This is the mail archive of the
gdb-patches@sourceware.cygnus.com
mailing list for the GDB project.
sh-stub.c SH4 & SCIF support
- To: gdb-patches@sourceware.cygnus.com
- Subject: sh-stub.c SH4 & SCIF support
- From: Toshiyasu Morita <tm@netcom.com>
- Date: Wed, 19 May 1999 15:39:23 -0700 (PDT)
I've hacked some SH4 and SCIF support into the sh-stub.c file.
This requires some hacking to actually use, since the SH4 interrupts
arrive on only three vectors, and you need to manually "fan-out" the
interrupts to separate vectors so you can grab just the ones needed for
debugging (trapa).
Also, there are some cache writeback/invalidates which need to be added
for this code to be used with the caches enabled. I have the code, but
haven't had the time to do this.
Toshi
Wed May 19 14:19:33 1999 Toshiyasu Morita (tm@netcom.com)
sh-stub.c (computeSignal, handleError, handleDebugException,
SCIF_*, etc) : Add support for SH4 and SH4 SCIF.
*** sh-stub.c.1 Fri Apr 23 13:33:29 1999
--- sh-stub.c Wed May 19 14:29:06 1999
***************
*** 5,10 ****
--- 5,20 ----
*/
+ /*
+ * Note:
+ *
+ * The SH4 has separate I/D caches, so if data is written
+ * then the data cache should be written back and the instruction cache
+ * invalidated in case code was changed.
+ *
+ * This isn't done yet.
+ */
+
/* This is originally based on an m68k software stub written by Glenn
Engel at HP, but has changed quite a bit.
***************
*** 179,190 ****
--- 189,220 ----
* BUFMAX defines the maximum number of characters in inbound/outbound
* buffers. At least NUMREGBYTES*2 are needed for register packets.
*/
+
#define BUFMAX 1024
/*
* Number of bytes for registers
+ *
+ * SH4 has these registers:
+ *
+ * 0: r0, r1, r2, r3, r4, r5, r6, r7,
+ * 8: r8, r9, r10, r11, r12, r13, r14, r15,
+ * 16: pc, pr,
+ * 18: gbr, vbr,
+ * 20: macl, mach
+ * 22: sr, fpul, fpscr
+ * 25: fr0, fr1, fr2, fr3, fr4, fr5, fr6, fr7,
+ * 33: fr8, fr9, fr10, fr11, fr12, fr13, fr14, fr15,
+ * 41: ssr, spc,
+ * 43: r0b0, r1b0, r2b0, r3b0, r4b0, r5b0, r6b0, r7b0,
+ * 51: r0b1, r1b1, r2b1, r3b1, r4b1, r5b1, r6b1, r7b1
*/
+
+ #ifdef __SH4__
+ #define NUMREGBYTES (59 * 4)
+ #else
#define NUMREGBYTES 112 /* 92 */
+ #endif
/*
* typedef
*************** int remote_debug;
*** 259,264 ****
--- 289,310 ----
/* jump buffer used for setjmp/longjmp */
jmp_buf remcomEnv;
+ #ifdef __sh4__
+ enum regnames
+ {
+ R0, R1, R2, R3, R4, R5, R6, R7,
+ R8, R9, R10, R11, R12, R13, R14, R15,
+ PC, PR,
+ GBR, VBR,
+ MACL, MACH,
+ SR, FPUL, FPSCR,
+ FR0, FR1, FR2, FR3, FR4, FR5, FR6, FR7,
+ FR8, FR9, FR10, FR11, FR12, FR13, FR14, FR15,
+ SSR, SPC,
+ R0B0, R1B0, R2B0, R3B0, R4B0, R5B0, R6B0, R7B0,
+ R0B1, R1B1, R2B1, R3B1, R4B1, R5B1, R6B1, R7B1
+ };
+ #else
enum regnames
{
R0, R1, R2, R3, R4, R5, R6, R7,
*************** enum regnames
*** 266,271 ****
--- 312,318 ----
R15, PC, PR, GBR, VBR, MACH, MACL, SR,
TICKS, STALLS, CYCLES, INSTS, PLR
};
+ #endif
typedef struct
{
*************** handle_buserror (void)
*** 507,550 ****
longjmp (remcomEnv, 1);
}
- /*
- * this function takes the SH-1 exception number and attempts to
- * translate this number into a unix compatible signal value
- */
- static int
- computeSignal (int exceptionVector)
- {
- int sigval;
- switch (exceptionVector)
- {
- case INVALID_INSN_VEC:
- sigval = 4;
- break;
- case INVALID_SLOT_VEC:
- sigval = 4;
- break;
- case CPU_BUS_ERROR_VEC:
- sigval = 10;
- break;
- case DMA_BUS_ERROR_VEC:
- sigval = 10;
- break;
- case NMI_VEC:
- sigval = 2;
- break;
-
- case TRAP_VEC:
- case USER_VEC:
- sigval = 5;
- break;
-
- default:
- sigval = 7; /* "software generated"*/
- break;
- }
- return (sigval);
- }
-
void
doSStep (void)
{
--- 554,559 ----
*************** breakpoint (void)
*** 818,838 ****
/**** Processor-specific routines start here ****/
/* Note:
! The Hitachi SH family uses two exception architectures:
!
! SH1 & SH2:
!
! These processors utilize an exception vector table.
! Exceptions are vectored to the address stored at VBR + (exception_num * 4)
! SH3, SH3E, & SH4:
! These processors have fixed entry points relative to the VBR for
! various exception classes.
! */
! #if defined(__sh1__) || defined(__sh2__)
/* SH1/SH2 exception vector table format */
--- 827,885 ----
/**** Processor-specific routines start here ****/
/* Note:
+ *
+ * The Hitachi SH family uses two exception architectures:
+ *
+ * SH1 & SH2:
+ *
+ * These processors utilize an exception vector table.
+ * Exceptions are vectored to the address stored at VBR + (exception_num * 4)
+ *
+ * SH3, SH3E, & SH4:
+ *
+ * These processors have fixed entry points relative to the VBR for
+ * various exception classes.
+ */
! #if defined(__sh1__) || defined(__sh2__)
! /*
! * this function takes the SH-1 exception number and attempts to
! * translate this number into a unix compatible signal value
! */
! static int
! computeSignal (int exceptionVector)
! {
! int sigval;
! switch (exceptionVector)
! {
! case INVALID_INSN_VEC:
! sigval = 4;
! break;
! case INVALID_SLOT_VEC:
! sigval = 4;
! break;
! case CPU_BUS_ERROR_VEC:
! sigval = 10;
! break;
! case DMA_BUS_ERROR_VEC:
! sigval = 10;
! break;
! case NMI_VEC:
! sigval = 2;
! break;
! case TRAP_VEC:
! case USER_VEC:
! sigval = 5;
! break;
! default:
! sigval = 7; /* "software generated"*/
! break;
! }
! return (sigval);
! }
/* SH1/SH2 exception vector table format */
*************** void
*** 1576,1581 ****
--- 1623,1873 ----
handleError (char theSSR)
{
SSR1 &= ~(SCI_ORER | SCI_PER | SCI_FER);
+ }
+
+ #endif
+
+ #if defined(__sh4__) || defined(__SH4_SINGLE_ONLY__)
+
+ static int computeSignal(int exception_num)
+
+ {
+ switch (exception_num) {
+
+ case 0x180: /* General illegal instruction exception */
+ case 0x0e0: /* Instruction address error */
+ case 0x820; /* Slot illegal instruction exception */
+
+ return SIGILL; /* Illegal instruction */
+
+ case 0x120: /* FPU exception */
+
+ return SIGFPE; /* Floating point exception */
+
+ case 0x0e0: /* Data address error (read) */
+ case 0x100: /* Data address error (write) */
+
+ return SIGBUS; /* Bus error */
+
+ case 0x160: /* Unconditional trap (TRAPA) */
+
+ return SIGTRAP;
+ }
+
+ return SIGHUP;
+ }
+
+ /*
+ * The SH4 has a pretty nasty interrupt structure,
+ * so we just ask the host OS for the registers.
+ */
+
+ void handle_debug_exception(int exception_num)
+
+ {
+ get_gdb_registers(registers);
+
+ gdb_handle_exception(exception_num);
+
+ set_gdb_registers(registers);
+ }
+
+
+ #define ALIGN4 __attribute__ ((__aligned__(4)))
+
+ /* SH4 SCIF registers */
+
+ typedef struct {
+
+ unsigned short scsmr2 ALIGN4; /* 0xffe80000 */
+ unsigned char scbrr2 ALIGN4; /* 0xffe80004 */
+ unsigned short scscr2 ALIGN4; /* 0xffe80008 */
+ unsigned char scftdr2 ALIGN4; /* 0xffe8000c */
+ unsigned short scfsr2 ALIGN4; /* 0xffe80010 */
+ unsigned char scfrdr2 ALIGN4; /* 0xffe80014 */
+ unsigned short scfcr2 ALIGN4; /* 0xffe80018 */
+ unsigned short scfdr2 ALIGN4; /* 0xffe8001c */
+ unsigned short scsptr2 ALIGN4; /* 0xffe80020 */
+ unsigned short sclsr2 ALIGN4; /* 0xffe80024 */
+
+ } SCIF;
+
+ volatile SCIF *scif = 0xffe80000;
+
+ /*
+ * static void SCIF_Calc_Baud_Rate(int baud_rate, int *scbrr2, int *divisor)
+ *
+ * Calculates the magic values to write to the SCIF for baud rate selection
+ */
+
+ static void SCIF_Calc_Baud_Rate(int baud_rate, int *scbrr2, int *divisor)
+
+ {
+ int i, denom;
+ float value;
+ float table[4] = {32.f, 128.f, 512.f, 2048.f};
+
+ for (i=0; i<4; i++) {
+
+ #if 0
+ value = ((50.f / (table[i] * baud_rate)) * 1000000.f) - 1.f;
+ #else
+ denom = table[i] * baud_rate;
+ value = (50000000.f + (denom >> 1)) / denom - 1;
+ #endif
+
+ if ((value > 1.f) && (value < 256.f))
+ break;
+ }
+
+ *divisor = i;
+ *scbrr2 = (int)value;
+ }
+
+ /*
+ * static void SCIF_Set_Parameters(int baud_rate, int data_bits, char parity, int stop_bits)
+ *
+ * Sets SCIF parameters for baud rate, data bits & parity
+ */
+
+ static void SCIF_Set_Parameters(int baud_rate, int data_bits, char parity, int stop_bits)
+
+ {
+ int scsmr2 = 0, scbrr2, divisor;
+
+ if ((data_bits != 7) && (data_bits != 8))
+ Codescape_printf("SCIF_Set_Parameters(): data_bits must be 7 or 8\n");
+
+ if ((parity != 'n') && (parity != 'o') && (parity != 'e'))
+ Codescape_printf("SCIF_Set_Parameters(): parity must be 'n', 'o', or 'e'\n");
+
+ if ((stop_bits != 1) && (stop_bits != 2))
+ Codescape_printf("SCIF_Set_Parameters(): stop_bits must be 1 or 2\n");
+
+ if (data_bits == 7)
+ scsmr2 |= 0x40;
+
+ if (parity == 'e')
+ scsmr2 |= 0x20;
+
+ if (parity == 'o')
+ scsmr2 |= 0x30;
+
+ if (stop_bits == 2)
+ scsmr2 |= 0x08;
+
+ SCIF_Calc_Baud_Rate(baud_rate, &scbrr2, &divisor);
+
+ scif->scsmr2 = scsmr2 | divisor;
+ scif->scbrr2 = scbrr2;
+ }
+
+ /*
+ * int getDebugChar(void)
+ *
+ * Blocking character receive.
+ */
+
+ char getDebugChar(void)
+
+ {
+ int value, sclsr2, scfsr2;
+
+ sclsr2 = scif->sclsr2;
+ scfsr2 = scif->scfsr2;
+
+ if (sclsr2 & 0x01) /* Check for overrun */
+ scif->sclsr2 = (sclsr2 &= ~1);
+
+ if (scfsr2 & 0x80) /* Check for framing/parity error */
+ scif->scfsr2 = (scfsr2 &= ~0x80);
+
+ if (scfsr2 & 0x10) /* Check for break */
+ scif->scfsr2 = (scfsr2 &= ~0x10);
+
+ while (!(scif->scfdr2 & 0x1f)) /* Wait for a character */
+ ;
+
+ value = *(unsigned char *)&scif->scfrdr2;
+ scif->scfsr2 &= ~2;
+ scif->sclsr2 = sclsr2 & ~0x01;
+
+ return value;
+ }
+
+ /*
+ * int putDebugChar(char data)
+ *
+ * Non-blocking character send.
+ *
+ * Returns space left in FIFO.
+ */
+
+ int putDebugChar(char data)
+
+ {
+ while (!(scif->scfsr2 & 0x20))
+ ;
+
+ scif->scftdr2 = data;
+ scif->scfsr2 &= ~0x60;
+
+ return 0x10 - ((scif->scfdr2 >> 8) & 0x1f);
+ }
+
+ /*
+ * void init_serial(int baud_rate)
+ *
+ * Initialize the SCIF to a baud rate.
+ */
+
+ /*
+ * Initialization flowchart:
+ *
+ * 1. Clear TE and RE bits in SCSCR2 to 0
+ *
+ * 2. Set TFRST and RFRST bits in SCFCR2 to 1
+ *
+ * 3. Set CKE1 bit in SCSCR2 (leaving TE and RE bits cleared to 0)
+ *
+ * 4. Set data transfer format in SCSMR2
+ *
+ * 5. Set value in SCBRR2
+ *
+ * 6. Wait at least 1 bit period
+ *
+ * 7. Set RTRG1-0, TTRG1-0, and MCE in SCFCR2
+ * Clear TFRST and RFRST bits to 0
+ *
+ * 8. Set TE and RE bits in SCSCR2 to 1
+ * Set RIE and TIE bits
+ */
+
+ void init_serial(int baud_rate)
+
+ {
+ volatile int i;
+
+ scif->scscr2 = 0x0000; /* 1. Clear TE and RE bits */
+ scif->scfcr2 = 0x0006; /* 2. Set TFRST and RFRTS bits */
+ scif->scscr2 = 0x0000; /* 3. Set CKE1 bit */
+
+ SCIF_Set_Parameters(baud_rate, 8, 'n', 1);
+ /* 4,5. Set SCSMR2 & SCBRR2 */
+
+ for (i=0; i<10000000; i++)
+ __asm__ volatile ("nop");
+
+ scif->scfcr2 = 0x38; /* 7. Set RTRG, TTRG, and MCE */
+ /* Clear TFRST and RFRST */
+
+ scif->scscr2 = 0x0030; /* 8. Set TE, RE, RIE and TIE bits */
+ scif->scsptr2 = 0x00;
+
+ for (i=0; i<10000000; i++)
+ __asm__ volatile ("nop");
+
+ scif->scfsr2 &= ~0x20;
}
#endif