changeset 1571:bbd1a5ee1075

* src/h8300h_stub.c Bcc d:16 trace miss fix. cleanup code. * src/h8300h_stub.c deleet async_breakpoint. rewrite single step support. * include/variant.inc add h8300_trap_adjust_pc macro.
author asl
date Tue, 06 Apr 2004 20:36:45 +0000
parents 391ff32e5af0
children 9be7d4ed9ac1
files packages/hal/h8300/h8300h/current/ChangeLog packages/hal/h8300/h8300h/current/include/variant.inc packages/hal/h8300/h8300h/current/src/h8300_h8300h.ld packages/hal/h8300/h8300h/current/src/h8300h_stub.c packages/hal/h8300/h8300h/current/src/var_misc.c
diffstat 5 files changed, 214 insertions(+), 147 deletions(-) [+]
line wrap: on
line diff
--- a/packages/hal/h8300/h8300h/current/ChangeLog
+++ b/packages/hal/h8300/h8300h/current/ChangeLog
@@ -1,3 +1,20 @@
+2003-03-17  Yoshinori Sato  <ysato@users.sourceforge.jp>
+
+	* src/h8300h_stub.c
+	Bcc d:16 trace miss fix.
+	cleanup code.
+
+2003-12-12  Yoshinori Sato  <ysato@users.sourceforge.jp>
+
+	* src/h8300h_stub.c
+	deleet async_breakpoint.
+	rewrite single step support.
+
+2003-12-08  Yoshinori Sato  <ysato@users.sourceforge.jp>
+
+	* include/variant.inc
+	add h8300_trap_adjust_pc macro.
+	
 2003-07-10  Nick Garnett  <nickg@balti.calivar.com>
 
 	* <general>: Added Yoshinori Sato's changes, see entries below,
--- a/packages/hal/h8300/h8300h/current/include/variant.inc
+++ b/packages/hal/h8300/h8300h/current/include/variant.inc
@@ -167,6 +167,12 @@
 	mov.b	r0h,ccr
 	.endm
 
+	.macro	h8300_trap_adjust_pc
+	mov.l	@(36:16,sp),er0
+	subs	#2,er0
+	mov.l	er0,@(36:16,sp)
+	.endm
+
 ##-----------------------------------------------------------------------------
 # Default interrupt decoding macros.
 
--- a/packages/hal/h8300/h8300h/current/src/h8300_h8300h.ld
+++ b/packages/hal/h8300/h8300h/current/src/h8300_h8300h.ld
@@ -45,11 +45,11 @@ ENTRY(CYG_LABEL_DEFN(_start))
 #ifdef EXTRAS
 INPUT(extras.o)
 #endif
-//#if (__GNUC__ >= 3)
-//GROUP(libtarget.a libgcc.a libsupc++.a)
-//#else
+#if (__GNUC__ >= 3)
+GROUP(libtarget.a libgcc.a libsupc++.a)
+#else
 GROUP(libtarget.a libgcc.a)
-//#endif
+#endif
 
 #define ALIGN_LMA 4
 #define FOLLOWING(_section_) AT ((LOADADDR (_section_) + SIZEOF (_section_) + ALIGN_LMA - 1) & ~ (ALIGN_LMA - 1))
@@ -95,7 +95,7 @@ GROUP(libtarget.a libgcc.a)
     { FORCE_OUTPUT; *(.gcc_except_table) } \
     > _region_
 
-#if defined(CYGHWR_HAL_H8300_VECTOR_ADDRESS)
+#if defined(CYGSEM_HAL_H8300_VECTOR_HOOK)
 #define SECTION_int_hook_table(_region_, _vma_, _lma_) \
     .int_hook_table CYGHWR_HAL_H8300_VECTOR_ADDRESS : _lma_ \
     { CYG_LABEL_DEFN(__int_hook_start) = ABSOLUTE (.); \
@@ -133,7 +133,7 @@ GROUP(libtarget.a libgcc.a)
 #define SECTION_bss(_region_, _vma_, _lma_) \
     .bss _vma_ : _lma_ \
     { CYG_LABEL_DEFN(__bss_start) = ABSOLUTE (.); \
-    *(.scommon) *(.dynbss) *(.bss) *(COMMON) \
+    *(.scommon) *(.dynbss) *(.bss.*) *(COMMON) \
     CYG_LABEL_DEFN(__bss_end) = ABSOLUTE (.); } \
     > _region_
 
--- a/packages/hal/h8300/h8300h/current/src/h8300h_stub.c
+++ b/packages/hal/h8300/h8300h/current/src/h8300h_stub.c
@@ -60,46 +60,19 @@
 #include <cyg/hal/hal_stub.h>
 #include <cyg/hal/hal_arch.h>
 #include <cyg/hal/hal_intr.h>
+#include <cyg/hal/hal_diag.h>
 
 #ifdef CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT
 #include <cyg/hal/dbg-threads-api.h>    // dbg_currthread_id
 #endif
 
-/*----------------------------------------------------------------------
- * Asynchronous interrupt support
- */
-
-typedef unsigned short t_inst;
-
-static struct
-{
-  t_inst *targetAddr;
-  t_inst savedInstr;
-} asyncBuffer;
-
-/* Called to asynchronously interrupt a running program.
-   Must be passed address of instruction interrupted.
-   This is typically called in response to a debug port
-   receive interrupt.
-*/
-
-void
-install_async_breakpoint(void *pc)
-{
-  asyncBuffer.targetAddr = pc;
-  asyncBuffer.savedInstr = *(t_inst *)pc;
-  *(t_inst *)pc = (t_inst)HAL_BREAKINST;
-  __instruction_cache(CACHE_FLUSH);
-  __data_cache(CACHE_FLUSH);
-}
-
 /*--------------------------------------------------------------------*/
 /* Given a trap value TRAP, return the corresponding signal. */
 
 int __computeSignal (unsigned int trap_number)
 {
     switch (trap_number) {
-    case 11:
+    case CYGNUM_HAL_VECTOR_TRAP3:
         return SIGTRAP;
     default:
         return SIGINT;
@@ -128,126 +101,199 @@ void set_pc (target_register_t pc)
 
 
 /*----------------------------------------------------------------------
- * Single-step support. Lifted from CygMon.
+ * Single-step support. 
  */
 
-#define NUM_SS_BPTS 2
-static target_register_t break_mem [NUM_SS_BPTS] = {0, 0};
-static unsigned short break_mem_data [NUM_SS_BPTS];
-
-/* Set a single-step breakpoint at ADDR.  Up to two such breakpoints
-   can be set; WHICH specifies which one to set (0 or 1).  */
+typedef struct {
+    unsigned short *addr;
+    unsigned short inst;
+} breakinfo;
 
-static void
-set_single_bp (int which, unsigned char *addr)
-{
-    if (break_mem[which] == 0) {
-        break_mem[which] = (target_register_t) addr;
-        break_mem_data[which] = *(unsigned short *)addr;
-        *(unsigned short *)addr = HAL_BREAKINST;
-    }
-}
+static breakinfo InstBuffer = {(unsigned short *)-1,0};
 
 /* Clear any single-step breakpoint(s) that may have been set.  */
 
 void __clear_single_step (void)
 {
-  int x;
-  for (x = 0; x < NUM_SS_BPTS; x++)
-    {
-        unsigned short* addr = (unsigned short *)break_mem[x];
-        if (addr) {
-            *addr = break_mem_data[x];
-            break_mem[x] = 0;
-        }
+    if ((long)InstBuffer.addr != -1L) {
+	*InstBuffer.addr = InstBuffer.inst;
+	InstBuffer.addr = (unsigned short *)-1;
     }
 }
 
+/* calculate next pc */
+
+enum jump_type{none,aabs,aind,ret,reg,relb,relw};
+
+/* opcode decode table define
+   ptn: opcode pattern
+   msk: opcode bitmask
+   len: instruction length (<0 next table index)
+   jmp: jump operation mode */
+
+struct optable {
+    unsigned char pattern;
+    unsigned char mask;
+    signed   char length;
+    char          type;
+} __attribute__((aligned(1),packed));
+
+#define OPTABLE(ptn,msk,len,jmp) {ptn,msk,len,jmp}
+
+const static struct optable optable_0[] = {
+    OPTABLE(0x00,0xff, 1,none), /* 0x00 */
+    OPTABLE(0x01,0xff,-1,none), /* 0x01 */
+    OPTABLE(0x02,0xfe, 1,none), /* 0x02-0x03 */
+    OPTABLE(0x04,0xee, 1,none), /* 0x04-0x05/0x14-0x15 */
+    OPTABLE(0x06,0xfe, 1,none), /* 0x06-0x07 */
+    OPTABLE(0x08,0xea, 1,none), /* 0x08-0x09/0x0c-0x0d/0x18-0x19/0x1c-0x1d */
+    OPTABLE(0x0a,0xee, 1,none), /* 0x0a-0x0b/0x1a-0x1b */
+    OPTABLE(0x0e,0xee, 1,none), /* 0x0e-0x0f/0x1e-0x1f */
+    OPTABLE(0x10,0xfc, 1,none), /* 0x10-0x13 */
+    OPTABLE(0x16,0xfe, 1,none), /* 0x16-0x17 */
+    OPTABLE(0x20,0xe0, 1,none), /* 0x20-0x3f */
+    OPTABLE(0x40,0xf0, 1,relb), /* 0x40-0x4f */
+    OPTABLE(0x50,0xfc, 1,none), /* 0x50-0x53 */
+    OPTABLE(0x54,0xfd, 1,ret ), /* 0x54/0x56 */
+    OPTABLE(0x55,0xff, 1,relb), /* 0x55 */
+    OPTABLE(0x57,0xff, 1,none), /* 0x57 */
+    OPTABLE(0x58,0xfb, 2,relw), /* 0x58/0x5c */
+    OPTABLE(0x59,0xfb, 1,reg ), /* 0x59/0x5b */
+    OPTABLE(0x5a,0xfb, 2,aabs), /* 0x5a/0x5e */
+    OPTABLE(0x5b,0xfb, 2,aind), /* 0x5b/0x5f */
+    OPTABLE(0x60,0xe8, 1,none), /* 0x60-0x67/0x70-0x77 */
+    OPTABLE(0x68,0xfa, 1,none), /* 0x68-0x69/0x6c-0x6d */
+    OPTABLE(0x6a,0xfe,-2,none), /* 0x6a-0x6b */
+    OPTABLE(0x6e,0xfe, 2,none), /* 0x6e-0x6f */
+    OPTABLE(0x78,0xff, 4,none), /* 0x78 */
+    OPTABLE(0x79,0xff, 2,none), /* 0x79 */
+    OPTABLE(0x7a,0xff, 3,none), /* 0x7a */
+    OPTABLE(0x7b,0xff, 2,none), /* 0x7b */
+    OPTABLE(0x7c,0xfc, 2,none), /* 0x7c-0x7f */
+    OPTABLE(0x80,0x80, 1,none), /* 0x80-0xff */
+};
+
+const static struct optable optable_1[] = {
+    OPTABLE(0x00,0xff,-3,none), /* 0x0100 */
+    OPTABLE(0x40,0xf0,-3,none), /* 0x0140-0x14f */
+    OPTABLE(0x80,0xf0, 1,none), /* 0x0180-0x018f */
+    OPTABLE(0xc0,0xc0, 2,none), /* 0x01c0-0x01ff */
+};
+
+const static struct optable optable_2[] = {
+    OPTABLE(0x00,0x20, 2,none), /* 0x6a0?/0x6a8?/0x6b0?/0x6b8? */
+    OPTABLE(0x20,0x20, 3,none), /* 0x6a2?/0x6aa?/0x6b2?/0x6ba? */
+};
+
+const static struct optable optable_3[] = {
+    OPTABLE(0x69,0xfb, 2,none), /* 0x010069/0x01006d/014069/0x01406d */
+    OPTABLE(0x6b,0xff,-4,none), /* 0x01006b/0x01406b */
+    OPTABLE(0x6f,0xff, 3,none), /* 0x01006f/0x01406f */
+    OPTABLE(0x78,0xff, 5,none), /* 0x010078/0x014078 */
+};
+
+const static struct optable optable_4[] = {
+    OPTABLE(0x00,0x78, 3,none), /* 0x0100690?/0x01006d0?/0140690/0x01406d0?/0x0100698?/0x01006d8?/0140698?/0x01406d8? */
+    OPTABLE(0x20,0x78, 4,none), /* 0x0100692?/0x01006d2?/0140692/0x01406d2?/0x010069a?/0x01006da?/014069a?/0x01406da? */
+};
+
+const static struct {
+    const struct optable *op;
+    int length;
+} optables[] = {
+    {optable_0,sizeof(optable_0)/sizeof(struct optable)},
+    {optable_1,sizeof(optable_1)/sizeof(struct optable)},
+    {optable_2,sizeof(optable_2)/sizeof(struct optable)},
+    {optable_3,sizeof(optable_3)/sizeof(struct optable)},
+    {optable_4,sizeof(optable_4)/sizeof(struct optable)},
+};
+
+const static unsigned char condmask[] = {
+    0x00,0x40,0x01,0x04,0x02,0x08,0x10,0x20
+};
+
+static int isbranch(int reson)
+{
+    unsigned char cond = get_register(CCR);
+    /* encode complex conditions */
+    /* B4: N^V
+       B5: Z|(N^V)
+       B6: C|Z */
+    __asm__("bld #3,%w0\n\t"
+	    "bxor #1,%w0\n\t"
+	    "bst #4,%w0\n\t"
+	    "bor #2,%w0\n\t"
+	    "bst #5,%w0\n\t"
+	    "bld #2,%w0\n\t"
+	    "bor #0,%w0\n\t"
+	    "bst #6,%w0\n\t"
+	    :"=&r"(cond):"g"(cond):"cc");
+    cond &= condmask[reson >> 1];
+    if (!(reson & 1))
+	return cond == 0;
+    else
+	return cond != 0;
+}
+
+static unsigned short *getnextpc(unsigned short *pc)
+{
+    const struct optable *op;
+    unsigned char *fetch_p;
+    unsigned char inst;
+    unsigned long addr;
+    unsigned long *sp;
+    int op_len;
+    op = optables[0].op;
+    op_len = optables[0].length;
+    fetch_p = (unsigned char *)pc;
+    inst = *fetch_p++;
+    do {
+	if ((inst & op->mask) == op->pattern) {
+	    if (op->length < 0) {
+		op = optables[-op->length].op;
+		op_len = optables[-op->length].length + 1;
+		inst = *fetch_p++;
+	    } else {
+		switch (op->type) {
+		case none:
+		    return pc + op->length;
+		case aabs:
+		    addr = *(unsigned long *)pc;
+		    return (unsigned short *)(addr & 0x00ffffff);
+		case aind:
+		    addr = *pc & 0xff;
+		    return (unsigned short *)(*(unsigned long *)addr);
+		case ret:
+		    sp = (unsigned long *)get_register(SP);
+		    return (unsigned short *)(*(sp+3) & 0x00ffffff);
+		case reg:
+		    addr = get_register((*pc >> 4) & 0x07);
+		    return (unsigned short *)addr;
+		case relb:
+		    if ((inst = 0x55) || isbranch(inst & 0x0f))
+			(unsigned char *)pc += (signed char)(*fetch_p);
+		    return pc+1; /* skip myself */
+		case relw:
+		    if ((inst = 0x5c) || isbranch((*fetch_p & 0xf0) >> 4))
+			(unsigned char *)pc += (signed short)(*(pc+1));
+		    return pc+2; /* skip myself */
+		}
+	    }
+	} else
+	    op++;
+    } while(--op_len > 0);
+    return NULL;
+}
+
 /* Set breakpoint(s) to simulate a single step from the current PC.  */
 
-const static unsigned char opcode_length0[]={
-  0x04,0x02,0x04,0x02,0x04,0x02,0x04,0x02,  /* 0x58 */
-  0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,  /* 0x60 */
-  0x02,0x02,0x11,0x11,0x02,0x02,0x04,0x04,  /* 0x68 */
-  0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,  /* 0x70 */
-  0x08,0x04,0x06,0x04,0x04,0x04,0x04,0x04   /* 0x78 */
-};
-
-const static unsigned char opcode_length1[]={
-  0x10,0x00,0x00,0x00,0x11,0x00,0x00,0x00,
-  0x02,0x00,0x00,0x00,0x04,0x04,0x00,0x04
-};
-
-static int insn_length(unsigned char *pc)
-{
-  if (*pc != 0x01 && (*pc < 0x58 || *pc>=0x80)) 
-    return 2;
-  else
-    switch (*pc) {
-      case 0x01:
-	switch (*(pc+1) & 0xf0) {
-	case 0x00:
-	  if (*(pc+2)== 0x78) {
-	    return 10;
-	  } else if (*(pc+2)== 0x6b) {
-	    return (*(pc+3) & 0x20)?8:6;
-	  } else {
-	    return (*(pc+2) & 0x02)?6:4;
-	  }
-	case 0x40:
-	  return (*(pc+2) & 0x02)?8:6;
-	default:
-	  return opcode_length1[*(pc+1)>>4];
-	}
-      case 0x6a:
-      case 0x6b:
-	return (*(pc+1) & 0x20)?6:4;
-      default:
-	return opcode_length0[*pc-0x58];
-    }
-}
-
 void __single_step (void)
 {
-  unsigned int pc = get_register (PC);
-  unsigned int next;
-  unsigned int opcode;
-
-  opcode = *(unsigned short *)pc;
-  next = pc + insn_length((unsigned char *)pc);
-  if (opcode == 0x5470) {
-    /* rts */ 
-    unsigned long *sp;
-    sp = (unsigned long *)get_register(SP);
-    next = *(sp+2) & 0x00ffffff;
-  } else if (((opcode & 0xf000) == 0x4000) || ((opcode & 0xff00) == 0x5500)) { 
-    /* b**:8 */
-    char dsp;
-    dsp = (opcode & 0xff);
-    set_single_bp(1,(unsigned char *)(pc+2+dsp));
-  } else if (((opcode & 0xff00) == 0x5800) || ((opcode & 0xff00) == 0x5c00)) { 
-    /* b**:16 */
-    short dsp;
-    dsp = *(short *)(pc+2);
-    set_single_bp(1,(unsigned char *)(pc+4+dsp));
-  } else if ((opcode & 0xfb00) != 0x5800) {
-    /* jmp / jsr */
-    int regs;
-    const short reg_tbl[]={ER0,ER1,ER2,ER3,ER4,ER5,ER6,SP};
-    switch(opcode & 0xfb00) {
-    case 0x5900:
-      regs = (opcode & 0x0070) >> 8;
-      next = get_register(reg_tbl[regs]);
-      break;
-    case 0x5a00:
-      next = *(unsigned long *)(pc) & 0x00ffffff;
-      break;
-    case 0x5b00:
-      next = *(unsigned long *)(opcode & 0xff);
-      break;
-    }
-  }
-  set_single_bp(0,(unsigned char *)next);
+    unsigned short *nextpc;
+    nextpc = getnextpc((unsigned short *)get_register(PC));
+    InstBuffer.addr = nextpc;
+    InstBuffer.inst = *nextpc;
+    *nextpc = HAL_BREAKINST;
 }
 
 void __install_breakpoints (void)
@@ -274,13 +320,11 @@ int
 
 
 /* Skip the current instruction. */
+/* only TRAPA instruction */
 
 void __skipinst (void)
 {
-    unsigned long pc = get_register (PC);
-
-    pc+=insn_length((unsigned char *)pc);
-    put_register (PC, (target_register_t) pc);
+    put_register (PC, get_register(PC) + 2);
 }
 
 #endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
--- a/packages/hal/h8300/h8300h/current/src/var_misc.c
+++ b/packages/hal/h8300/h8300h/current/src/var_misc.c
@@ -145,7 +145,7 @@ hal_interrupt_mask(int vector)
 	ier &= ~0x20;
 	HAL_WRITE_UINT16(CYGARC_TCSR,0xa500 | ier);
     } else {
-        if ((vector > 12) && regs->ier) {
+        if ((vector >= CYGNUM_HAL_INTERRUPT_EXTERNAL_0) && regs->ier) {
             HAL_READ_UINT8(regs->ier,ier);
 	    ier &= ~(regs->mask);
             HAL_WRITE_UINT8(regs->ier,ier);
@@ -168,7 +168,7 @@ hal_interrupt_unmask(int vector)
 	ier |= 0x20;
 	HAL_WRITE_UINT16(CYGARC_TCSR,0xa500 | ier);
     } else {
-        if ((vector > 12) && regs->ier) {
+        if ((vector >= CYGNUM_HAL_INTERRUPT_EXTERNAL_0) && regs->ier) {
             HAL_READ_UINT8(regs->ier,ier);
 	    ier |= regs->mask;
             HAL_WRITE_UINT8(regs->ier,ier);
@@ -194,7 +194,7 @@ hal_interrupt_acknowledge(int vector)
 	isr &= ~0x80;
 	HAL_WRITE_UINT16(CYGARC_TCSR,0xa500 | isr);
     } else {
-        if ((vector > 12) && regs->isr) {
+        if ((vector >= CYGNUM_HAL_INTERRUPT_EXTERNAL_0) && regs->isr) {
             HAL_READ_UINT8(regs->isr,isr);
 	    isr &= ~(regs->status);
             HAL_WRITE_UINT8(regs->isr,isr);