/*
- * Simulator for the Hitachi H8/300 architecture.
+ * Simulator for the Renesas (formerly Hitachi) H8/300 architecture.
*
* Written by Steve Chamberlain of Cygnus Support. sac@cygnus.com
*
h8_set_ccr (SD, (I << 7) | (UI << 6) | (H << 5) | (U << 4) \
| (N << 3) | (Z << 2) | (V << 1) | C)
+#define GETSR(SD) \
+ /* Get Status Register (flags). */ \
+ c = (h8_get_ccr (sd) >> 0) & 1; \
+ v = (h8_get_ccr (sd) >> 1) & 1; \
+ nz = !((h8_get_ccr (sd) >> 2) & 1); \
+ n = (h8_get_ccr (sd) >> 3) & 1; \
+ u = (h8_get_ccr (sd) >> 4) & 1; \
+ h = (h8_get_ccr (sd) >> 5) & 1; \
+ ui = ((h8_get_ccr (sd) >> 6) & 1); \
+ intMaskBit = (h8_get_ccr (sd) >> 7) & 1
+
+
#ifdef __CHAR_IS_SIGNED__
#define SEXTCHAR(x) ((char) (x))
#endif
unsigned int len = 0;
if ((q->available == AV_H8SX && !h8300sxmode) ||
+ (q->available == AV_H8S && !h8300smode) ||
(q->available == AV_H8H && !h8300hmode))
continue;
{
cst[opnum] = data[1];
}
+ else if ((looking_for & MODE) == VECIND)
+ {
+ /* FIXME: Multiplier should be 2 for "normal" mode. */
+ cst[opnum] = ((data[1] & 0x7f) + 0x80) * 4;
+ cst[opnum] += h8_get_vbr (sd); /* Add vector base reg. */
+ }
else if ((looking_for & SIZE) == L_32)
{
int i = len / 2;
cst[opnum] = data[len / 2] & 0xff;
}
}
+ else if ((looking_for & SIZE) == L_2)
+ {
+ cst[opnum] = thisnib & 3;
+ }
else if ((looking_for & SIZE) == L_3 ||
(looking_for & SIZE) == L_3NZ)
{
else
p->reg = ZERO_REGNUM;;
}
- else if ((x & MODE) == MEMIND)
+ else if ((x & MODE) == MEMIND ||
+ (x & MODE) == VECIND)
{
/* Size doesn't matter. */
p->type = X (OP_MEM, SB);
p->type = OP_EXR;
}
else
- printf ("Hmmmm %x...\n", x);
+ printf ("Hmmmm 0x%x...\n", x);
args++;
}
return;
}
else
- printf ("Don't understand %x \n", looking_for);
+ printf ("Don't understand 0x%x \n", looking_for);
}
len++;
}
/* Get Status Register (flags). */
- c = (h8_get_ccr (sd) >> 0) & 1;
- v = (h8_get_ccr (sd) >> 1) & 1;
- nz = !((h8_get_ccr (sd) >> 2) & 1);
- n = (h8_get_ccr (sd) >> 3) & 1;
- u = (h8_get_ccr (sd) >> 4) & 1;
- h = (h8_get_ccr (sd) >> 5) & 1;
- ui = ((h8_get_ccr (sd) >> 6) & 1);
- intMaskBit = (h8_get_ccr (sd) >> 7) & 1;
+ GETSR (sd);
if (h8300smode) /* Get exr. */
{
goto end;
goto just_flags_log32;
- case O (O_MOVMD, SB): /* movsd.b */
+ case O (O_MOVMD, SB): /* movmd.b */
ea = GET_W_REG (4);
if (ea == 0)
ea = 0x10000;
}
goto next;
- case O (O_MOVMD, SW): /* movsd.b */
+ case O (O_MOVMD, SW): /* movmd.w */
ea = GET_W_REG (4);
if (ea == 0)
ea = 0x10000;
}
goto next;
- case O (O_MOVMD, SL): /* movsd.b */
+ case O (O_MOVMD, SL): /* movmd.l */
ea = GET_W_REG (4);
if (ea == 0)
ea = 0x10000;
case O (O_JMP, SL):
case O (O_JMP, SB): /* jmp */
case O (O_JMP, SW):
- {
- fetch (sd, &code->src, &pc);
- goto end;
- }
+ fetch (sd, &code->src, &pc);
+ goto end;
case O (O_JSR, SN):
case O (O_JSR, SL):
case O (O_JSR, SB): /* jsr, jump to subroutine */
case O (O_JSR, SW):
- {
- int tmp;
- if (fetch (sd, &code->src, &pc))
- goto end;
- call:
- tmp = h8_get_reg (sd, SP_REGNUM);
+ if (fetch (sd, &code->src, &pc))
+ goto end;
+ call:
+ tmp = h8_get_reg (sd, SP_REGNUM);
- if (h8300hmode)
- {
- tmp -= 4;
- SET_MEMORY_L (tmp, code->next_pc);
- }
- else
- {
- tmp -= 2;
- SET_MEMORY_W (tmp, code->next_pc);
- }
- h8_set_reg (sd, SP_REGNUM, tmp);
+ if (h8300hmode)
+ {
+ tmp -= 4;
+ SET_MEMORY_L (tmp, code->next_pc);
+ }
+ else
+ {
+ tmp -= 2;
+ SET_MEMORY_W (tmp, code->next_pc);
+ }
+ h8_set_reg (sd, SP_REGNUM, tmp);
- goto end;
- }
+ goto end;
case O (O_BSR, SW):
case O (O_BSR, SL):
pc = code->next_pc + res;
goto call;
- case O (O_RTS, SN): /* rts, return from subroutine */
- {
- int tmp;
+ case O (O_RTE, SN): /* rte, return from exception */
+ rte:
+ /* Pops exr and ccr before pc -- otherwise identical to rts. */
+ tmp = h8_get_reg (sd, SP_REGNUM);
- tmp = h8_get_reg (sd, SP_REGNUM);
+ if (h8300smode) /* pop exr */
+ {
+ h8_set_exr (sd, GET_MEMORY_L (tmp));
+ tmp += 4;
+ }
+ if (h8300hmode)
+ {
+ h8_set_ccr (sd, GET_MEMORY_L (tmp));
+ tmp += 4;
+ pc = GET_MEMORY_L (tmp);
+ tmp += 4;
+ }
+ else
+ {
+ h8_set_ccr (sd, GET_MEMORY_W (tmp));
+ tmp += 2;
+ pc = GET_MEMORY_W (tmp);
+ tmp += 2;
+ }
- if (h8300hmode)
- {
- pc = GET_MEMORY_L (tmp);
- tmp += 4;
- }
- else
- {
- pc = GET_MEMORY_W (tmp);
- tmp += 2;
- }
+ GETSR (sd);
+ h8_set_reg (sd, SP_REGNUM, tmp);
+ goto end;
- h8_set_reg (sd, SP_REGNUM, tmp);
- goto end;
- }
+ case O (O_RTS, SN): /* rts, return from subroutine */
+ rts:
+ tmp = h8_get_reg (sd, SP_REGNUM);
+
+ if (h8300hmode)
+ {
+ pc = GET_MEMORY_L (tmp);
+ tmp += 4;
+ }
+ else
+ {
+ pc = GET_MEMORY_W (tmp);
+ tmp += 2;
+ }
+
+ h8_set_reg (sd, SP_REGNUM, tmp);
+ goto end;
case O (O_ILL, SB): /* illegal */
sim_engine_set_run_state (sd, sim_stopped, SIGILL);
}
goto end;
+ case O (O_TRAPA, SB): /* trapa */
+ if (fetch (sd, &code->src, &res))
+ goto end; /* res is vector number. */
+
+ tmp = h8_get_reg (sd, SP_REGNUM);
+ tmp -= 4;
+ SET_MEMORY_L (tmp, code->next_pc);
+ tmp -= 4;
+ SET_MEMORY_L (tmp, h8_get_ccr (sd));
+ intMaskBit = 1;
+ BUILDSR (sd);
+
+ if (h8300smode)
+ {
+ tmp -= 4;
+ SET_MEMORY_L (tmp, h8_get_exr (sd));
+ }
+
+ h8_set_reg (sd, SP_REGNUM, tmp);
+
+ /* FIXME: "normal" mode should use 2-byte ptrs. */
+ pc = GET_MEMORY_L (0x20 + res * 4);
+ goto end;
+
case O (O_BPT, SN):
sim_engine_set_run_state (sd, sim_stopped, SIGTRAP);
goto end;
goto next;
- case O (O_TAS, SB): /* tas, (test and set?) */
- if (!h8300smode || code->src.type != X (OP_REG, SL))
- goto illegal;
- switch (code->src.reg)
- {
- case R0_REGNUM:
- case R1_REGNUM:
- case R4_REGNUM:
- case R5_REGNUM:
- break;
- default:
- goto illegal;
- }
+ case O (O_TAS, SB): /* tas (test and set) */
+ if (!h8300sxmode) /* h8sx can use any register. */
+ switch (code->src.reg)
+ {
+ case R0_REGNUM:
+ case R1_REGNUM:
+ case R4_REGNUM:
+ case R5_REGNUM:
+ break;
+ default:
+ goto illegal;
+ }
+
if (fetch (sd, &code->src, &res))
goto end;
if (store (sd, &code->src, res | 0x80))
res = 0;
}
- if (store (sd, &code->dst, (res & 0xffff) | (tmp << 8)))
+ if (store (sd, &code->dst, (res & 0xff) | (tmp << 8)))
goto end;
goto next;
goto next;
case O (O_LDM, SL): /* ldm, load from memory */
+ case O (O_RTEL, SN): /* rte/l, ldm plus rte */
+ case O (O_RTSL, SN): /* rts/l, ldm plus rts */
{
int nregs, firstreg, i;
- nregs = GET_MEMORY_B (pc + 1);
- nregs >>= 4;
- nregs &= 0xf;
- firstreg = code->dst.reg;
- firstreg &= 0xf;
+ nregs = ((GET_MEMORY_B (pc + 1) >> 4) & 0xf);
+ firstreg = code->dst.reg & 0xf;
for (i = firstreg; i >= firstreg - nregs; i--)
{
h8_set_reg (sd, i, GET_MEMORY_L (h8_get_reg (sd, SP_REGNUM)));
h8_set_reg (sd, SP_REGNUM, h8_get_reg (sd, SP_REGNUM) + 4);
}
}
- goto next;
+ switch (code->opcode) {
+ case O (O_RTEL, SN):
+ goto rte;
+ case O (O_RTSL, SN):
+ goto rts;
+ case O (O_LDM, SL):
+ goto next;
+ default:
+ goto illegal;
+ }
case O (O_DAA, SB):
/* Decimal Adjust Addition. This is for BCD arithmetic. */
- res = GET_B_REG (code->src.reg);
+ res = GET_B_REG (code->src.reg); /* FIXME fetch? */
if (!c && (0 <= (res >> 4) && (res >> 4) <= 9) &&
!h && (0 <= (res & 0xf) && (res & 0xf) <= 9))
res = res; /* Value added == 0. */
code->dst.type == X (OP_CCR, SW))
{
h8_set_ccr (sd, res);
- /* Get Status Register (flags). */
- c = (h8_get_ccr (sd) >> 0) & 1;
- v = (h8_get_ccr (sd) >> 1) & 1;
- nz = !((h8_get_ccr (sd) >> 2) & 1);
- n = (h8_get_ccr (sd) >> 3) & 1;
- u = (h8_get_ccr (sd) >> 4) & 1;
- h = (h8_get_ccr (sd) >> 5) & 1;
- ui = ((h8_get_ccr (sd) >> 6) & 1);
- intMaskBit = (h8_get_ccr (sd) >> 7) & 1;
+ GETSR (sd);
}
else if (h8300smode &&
(code->dst.type == X (OP_EXR, SB) ||
init_pointers (sd);
switch (rn)
{
+ case PC_REGNUM:
+ h8_set_pc (sd, intval);
+ break;
default:
(*sim_callback->printf_filtered) (sim_callback,
"sim_store_register: bad regnum %d.\n",
case R7_REGNUM:
h8_set_reg (sd, rn, intval);
break;
- case PC_REGNUM:
- h8_set_pc (sd, intval);
- break;
case CCR_REGNUM:
h8_set_ccr (sd, intval);
break;
case CYCLE_REGNUM:
h8_set_cycles (sd, longval);
break;
+
case INST_REGNUM:
h8_set_insts (sd, longval);
break;
+
case TICK_REGNUM:
h8_set_ticks (sd, longval);
break;
This function being replaced by a sim_open:ARGV configuration
option. */
- if (machine == bfd_mach_h8300sx)
+ if (machine == bfd_mach_h8300sx || machine == bfd_mach_h8300sxn)
h8300sxmode = 1;
if (machine == bfd_mach_h8300s || machine == bfd_mach_h8300sn || h8300sxmode)