This is the mail archive of the gdb-patches@sourceware.cygnus.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

sh-stub.c SH4 & SCIF support


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



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]