/*
- * 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
*
#define X(op, size) (op * 4 + size)
-#define SP (h8300hmode ? SL : SW)
+#define SP (h8300hmode && !h8300_normal_mode ? SL : SW)
#define h8_opcodes ops
#define DEFINE_TABLE
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
int h8300hmode = 0;
int h8300smode = 0;
+int h8300_normal_mode = 0;
int h8300sxmode = 0;
static int memory_size;
case L_32:
return SL;
case L_P:
- return h8300hmode ? SL : SW;
+ return (h8300hmode && !h8300_normal_mode)? SL : SW;
}
return 0;
}
static int
cmdline_location()
{
- if (h8300smode)
+ if (h8300smode && !h8300_normal_mode)
return 0xffff00L;
- else if (h8300hmode)
+ else if (h8300hmode && !h8300_normal_mode)
return 0x2ff00L;
else
return 0xff00L;
/* Find the exact opcode/arg combo. */
for (q = h8_opcodes; q->name; q++)
{
- op_type *nib = q->data.nib;
+ const op_type *nib = q->data.nib;
unsigned int len = 0;
if ((q->available == AV_H8SX && !h8300sxmode) ||
+ (q->available == AV_H8S && !h8300smode) ||
(q->available == AV_H8H && !h8300hmode))
continue;
+ cst[0] = cst[1] = cst[2] = 0;
+ reg[0] = reg[1] = reg[2] = 0;
+ rdisp[0] = rdisp[1] = rdisp[2] = 0;
+
while (1)
{
op_type looking_for = *nib;
(looking_for & MODE) == INDEXB ||
(looking_for & MODE) == INDEXW ||
(looking_for & MODE) == INDEXL)
-
{
switch (looking_for & SIZE)
{
case L_2:
cst[opnum] = thisnib & 3;
-
- /* DISP2 special treatment. */
- if ((looking_for & MODE) == DISP)
- {
- switch (OP_SIZE (q->how)) {
- default: break;
- case SW:
- cst[opnum] *= 2;
- break;
- case SL:
- cst[opnum] *= 4;
- break;
- }
- }
break;
case L_8:
cst[opnum] = SEXTCHAR (data[len / 2]);
(looking_for & SIZE) == L_16U)
{
cst[opnum] = (data[len / 2] << 8) + data[len / 2 + 1];
- if ((looking_for & SIZE) != L_16U)
+ /* Immediates are always unsigned. */
+ if ((looking_for & SIZE) != L_16U &&
+ (looking_for & MODE) != IMM)
cst[opnum] = (short) cst[opnum]; /* Sign extend. */
}
else if (looking_for & ABSJMP)
{
cst[opnum] = data[1];
}
+ else if ((looking_for & MODE) == VECIND)
+ {
+ if(h8300_normal_mode)
+ cst[opnum] = ((data[1] & 0x7f) + 0x80) * 2;
+ else
+ 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)
{
#endif
/* Fill in the args. */
{
- op_type *args = q->args.nib;
+ const op_type *args = q->args.nib;
int hadone = 0;
int nargs;
p->literal = 0;
if (OP_KIND (q->how) == O_JSR ||
OP_KIND (q->how) == O_JMP)
- if (lvalue (sd, p->type, p->reg, &p->type))
+ if (lvalue (sd, p->type, p->reg, (unsigned int *)&p->type))
goto end;
}
else if ((x & MODE) == ABS)
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->literal = cst[opnum];
if (OP_KIND (q->how) == O_JSR ||
OP_KIND (q->how) == O_JMP)
- if (lvalue (sd, p->type, p->reg, &p->type))
+ if (lvalue (sd, p->type, p->reg, (unsigned int *)&p->type))
goto end;
}
else if ((x & MODE) == PCREL)
p->type = X (OP_IMM, SP);
p->literal = cst[opnum];
}
- else if ((x & MODE) == INDEXB ||
- (x & MODE) == INDEXW ||
- (x & MODE) == INDEXL ||
- (x & MODE) == DISP)
+ else if ((x & MODE) == INDEXB)
{
- /* Use the instruction to determine
- the operand size. */
- switch (x & MODE) {
- case INDEXB:
- p->type = X (OP_INDEXB, OP_SIZE (q->how));
- break;
- case INDEXW:
- p->type = X (OP_INDEXW, OP_SIZE (q->how));
- break;
- case INDEXL:
- p->type = X (OP_INDEXL, OP_SIZE (q->how));
- break;
- case DISP:
- p->type = X (OP_DISP, OP_SIZE (q->how));
- break;
- }
-
+ p->type = X (OP_INDEXB, OP_SIZE (q->how));
+ p->literal = cst[opnum];
+ p->reg = rdisp[opnum];
+ }
+ else if ((x & MODE) == INDEXW)
+ {
+ p->type = X (OP_INDEXW, OP_SIZE (q->how));
+ p->literal = cst[opnum];
+ p->reg = rdisp[opnum];
+ }
+ else if ((x & MODE) == INDEXL)
+ {
+ p->type = X (OP_INDEXL, OP_SIZE (q->how));
p->literal = cst[opnum];
p->reg = rdisp[opnum];
}
+ else if ((x & MODE) == DISP)
+ {
+ /* Yuck -- special for mova args. */
+ if (strncmp (q->name, "mova", 4) == 0 &&
+ (x & SIZE) == L_2)
+ {
+ /* Mova can have a DISP2 dest, with an
+ INDEXB or INDEXW src. The multiplier
+ for the displacement value is determined
+ by the src operand, not by the insn. */
+
+ switch (OP_KIND (dst->src.type))
+ {
+ case OP_INDEXB:
+ p->type = X (OP_DISP, SB);
+ p->literal = cst[opnum];
+ break;
+ case OP_INDEXW:
+ p->type = X (OP_DISP, SW);
+ p->literal = cst[opnum] * 2;
+ break;
+ default:
+ goto fail;
+ }
+ }
+ else
+ {
+ p->type = X (OP_DISP, OP_SIZE (q->how));
+ p->literal = cst[opnum];
+ /* DISP2 is special. */
+ if ((x & SIZE) == L_2)
+ switch (OP_SIZE (q->how))
+ {
+ case SB: break;
+ case SW: p->literal *= 2; break;
+ case SL: p->literal *= 4; break;
+ }
+ }
+ p->reg = rdisp[opnum];
+ }
else if (x & CTRL)
{
switch (reg[opnum])
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++;
littleendian.i = 1;
- if (h8300smode)
+ if (h8300smode && !h8300_normal_mode)
memory_size = H8300S_MSIZE;
- else if (h8300hmode)
+ else if (h8300hmode && !h8300_normal_mode)
memory_size = H8300H_MSIZE;
else
memory_size = H8300_MSIZE;
goto end; \
if (fetch (sd, &code->src, &tmp)) \
goto end; \
- m = 1 << tmp; \
+ m = 1 << (tmp & 7); \
op; \
if (s) \
if (store (sd, &code->dst,ea)) \
}
/* 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. */
{
}
oldmask = h8_get_mask (sd);
- if (!h8300hmode)
+ if (!h8300hmode || h8300_normal_mode)
h8_set_mask (sd, 0xffff);
do
{
(mova/b, mova/w, mova/l).
4) Add literal value of 1st argument (src).
5) Store result in 3rd argument (op3).
+ */
+
+ /* Alas, since this is the only instruction with 3 arguments,
+ decode doesn't handle them very well. Some fix-up is required.
+ a) The size of dst is determined by whether src is
+ INDEXB or INDEXW. */
+
+ if (OP_KIND (code->src.type) == OP_INDEXB)
+ code->dst.type = X (OP_KIND (code->dst.type), SB);
+ else if (OP_KIND (code->src.type) == OP_INDEXW)
+ code->dst.type = X (OP_KIND (code->dst.type), SW);
+
+ /* b) If op3 == null, then this is the short form of the insn.
+ Dst is the dispreg of src, and op3 is the 32-bit form
+ of the same register.
*/
+
+ if (code->op3.type == 0)
+ {
+ /* Short form: src == INDEXB/INDEXW, dst == op3 == 0.
+ We get to compose dst and op3 as follows:
+
+ op3 is a 32-bit register, ID == src.reg.
+ dst is the same register, but 8 or 16 bits
+ depending on whether src is INDEXB or INDEXW.
+ */
+
+ code->op3.type = X (OP_REG, SL);
+ code->op3.reg = code->src.reg;
+ code->op3.literal = 0;
+
+ if (OP_KIND (code->src.type) == OP_INDEXB)
+ {
+ code->dst.type = X (OP_REG, SB);
+ code->dst.reg = code->op3.reg + 8;
+ }
+ else
+ code->dst.type = X (OP_REG, SW);
+ }
+
if (fetch (sd, &code->dst, &ea))
goto end;
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;
{
if (h8300smode)
h8_set_exr (sd, (trace << 7) | intMask);
- res = h8_get_exr (sd);
+ rd = h8_get_exr (sd);
}
else
goto illegal;
/* Setting char_ptr_size to the sizeof (char *) on the different
architectures. */
- if (h8300hmode || h8300smode)
+ if ((h8300hmode || h8300smode) && !h8300_normal_mode)
{
char_ptr_size = 4;
}
ind_arg_len = 0;
/* The size of the commandline argument. */
- ind_arg_len = strlen (h8_get_cmdline_arg (sd, i) + 1);
+ ind_arg_len = strlen (h8_get_cmdline_arg (sd, i)) + 1;
/* The total size of the command line string. */
size_cmdline += ind_arg_len;
for (i = 0; i < no_of_args; i++)
{
/* Saving the argv pointer. */
- if (h8300hmode || h8300smode)
+ if ((h8300hmode || h8300smode) && !h8300_normal_mode)
{
SET_MEMORY_L (argv_ptrs_location, argv_ptrs[i]);
}
/* Required by POSIX, Setting 0x0 at the end of the list of argv
pointers. */
- if (h8300hmode || h8300smode)
+ if ((h8300hmode || h8300smode) && !h8300_normal_mode)
{
SET_MEMORY_L (old_sp, 0x0);
}
/* Setting filename_ptr to first argument of open, */
/* and trying to get mode. */
- if (h8300sxmode || h8300hmode || h8300smode)
+ if ((h8300sxmode || h8300hmode || h8300smode) && !h8300_normal_mode)
{
filename_ptr = GET_L_REG (0);
mode = GET_MEMORY_L (h8_get_reg (sd, SP_REGNUM) + 4);
int read_return = 0; /* Return value from callback to
read. */
- fd = h8300hmode ? GET_L_REG (0) : GET_W_REG (0);
- buf_size = h8300hmode ? GET_L_REG (2) : GET_W_REG (2);
+ fd = (h8300hmode && !h8300_normal_mode) ? GET_L_REG (0) : GET_W_REG (0);
+ buf_size = (h8300hmode && !h8300_normal_mode) ? GET_L_REG (2) : GET_W_REG (2);
char_ptr = (char *) malloc (sizeof (char) * buf_size);
int write_return; /* Return value from callback to write. */
int i = 0; /* Loop counter */
- fd = h8300hmode ? GET_L_REG (0) : GET_W_REG (0);
- char_ptr = h8300hmode ? GET_L_REG (1) : GET_W_REG (1);
- len = h8300hmode ? GET_L_REG (2) : GET_W_REG (2);
+ fd = (h8300hmode && !h8300_normal_mode) ? GET_L_REG (0) : GET_W_REG (0);
+ char_ptr = (h8300hmode && !h8300_normal_mode) ? GET_L_REG (1) : GET_W_REG (1);
+ len = (h8300hmode && !h8300_normal_mode) ? GET_L_REG (2) : GET_W_REG (2);
/* Allocating space for the characters to be written. */
ptr = (char *) malloc (sizeof (char) * len);
int origin; /* Origin */
int lseek_return; /* Return value from callback to lseek. */
- fd = h8300hmode ? GET_L_REG (0) : GET_W_REG (0);
- offset = h8300hmode ? GET_L_REG (1) : GET_W_REG (1);
- origin = h8300hmode ? GET_L_REG (2) : GET_W_REG (2);
+ fd = (h8300hmode && !h8300_normal_mode) ? GET_L_REG (0) : GET_W_REG (0);
+ offset = (h8300hmode && !h8300_normal_mode) ? GET_L_REG (1) : GET_W_REG (1);
+ origin = (h8300hmode && !h8300_normal_mode) ? GET_L_REG (2) : GET_W_REG (2);
/* Callback lseek and return offset. */
lseek_return =
int fd; /* File descriptor */
int close_return; /* Return value from callback to close. */
- fd = h8300hmode ? GET_L_REG (0) : GET_W_REG (0);
+ fd = (h8300hmode && !h8300_normal_mode) ? GET_L_REG (0) : GET_W_REG (0);
/* Callback close and return. */
close_return = sim_callback->close (sim_callback, fd);
int stat_ptr; /* Pointer to stat record. */
char *temp_stat_ptr; /* Temporary stat_rec pointer. */
- fd = h8300hmode ? GET_L_REG (0) : GET_W_REG (0);
+ fd = (h8300hmode && !h8300_normal_mode) ? GET_L_REG (0) : GET_W_REG (0);
/* Setting stat_ptr to second argument of stat. */
- stat_ptr = h8300hmode ? GET_L_REG (1) : GET_W_REG (1);
+ stat_ptr = (h8300hmode && !h8300_normal_mode) ? GET_L_REG (1) : GET_W_REG (1);
/* Callback stat and return. */
fstat_return = sim_callback->fstat (sim_callback, fd, &stat_rec);
int i = 0; /* Loop Counter */
/* Setting filename_ptr to first argument of open. */
- filename_ptr = h8300hmode ? GET_L_REG (0) : GET_W_REG (0);
+ filename_ptr = (h8300hmode && !h8300_normal_mode) ? GET_L_REG (0) : GET_W_REG (0);
/* Trying to find the length of the filename. */
temp_char = GET_MEMORY_B (h8_get_reg (sd, 0));
/* Setting stat_ptr to second argument of stat. */
/* stat_ptr = h8_get_reg (sd, 1); */
- stat_ptr = h8300hmode ? GET_L_REG (1) : GET_W_REG (1);
+ stat_ptr = (h8300hmode && !h8300_normal_mode) ? GET_L_REG (1) : GET_W_REG (1);
/* Callback stat and return. */
stat_return =
if (fetch2 (sd, &code->dst, &rd))
goto end;
- if (code->src.type == X (OP_IMM, SB))
+ if (memcmp (&code->src, &code->dst, sizeof (code->src)) == 0)
+ ea = 1; /* unary op */
+ else /* binary op */
fetch (sd, &code->src, &ea);
- else
- ea = 1;
if (code->opcode == O (O_SHLL, SB))
{
if (fetch2 (sd, &code->dst, &rd))
goto end;
- if (code->src.type == X (OP_IMM, SW))
- fetch (sd, &code->src, &ea);
+ if (memcmp (&code->src, &code->dst, sizeof (code->src)) == 0)
+ ea = 1; /* unary op */
else
- ea = 1;
+ fetch (sd, &code->src, &ea);
if (code->opcode == O (O_SHLL, SW))
{
if (fetch2 (sd, &code->dst, &rd))
goto end;
- if (code->src.type == X (OP_IMM, SL))
- fetch (sd, &code->src, &ea);
+ if (memcmp (&code->src, &code->dst, sizeof (code->src)) == 0)
+ ea = 1; /* unary op */
else
- ea = 1;
+ fetch (sd, &code->src, &ea);
if (code->opcode == O (O_SHLL, SL))
{
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 && !h8300_normal_mode)
+ {
+ 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 && !h8300_normal_mode)
+ {
+ 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 && !h8300_normal_mode)
+ {
+ 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);
sim_engine_set_run_state (sd, sim_exited,
SIM_WEXITSTATUS (h8_get_reg (sd, 0)));
}
+#if 0
+ /* Unfortunately this won't really work, because
+ when we take a breakpoint trap, R0 has a "random",
+ user-defined value. Don't see any immediate solution. */
+ else if (SIM_WIFSTOPPED (h8_get_reg (sd, 0)))
+ {
+ /* Pass the stop signal up to gdb. */
+ sim_engine_set_run_state (sd, sim_stopped,
+ SIM_WSTOPSIG (h8_get_reg (sd, 0)));
+ }
+#endif
else
{
/* Treat it as a sigtrap. */
}
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);
+ if(h8300_normal_mode)
+ {
+ tmp -= 2;
+ SET_MEMORY_W (tmp, code->next_pc);
+ tmp -= 2;
+ SET_MEMORY_W (tmp, h8_get_ccr (sd));
+ }
+ else
+ {
+ 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);
+
+ if(h8300_normal_mode)
+ pc = GET_MEMORY_L (0x10 + res * 2); /* Vector addresses are 0x10,0x12,0x14 and 0x16 */
+ else
+ 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;
fetch (sd, &code->dst, &rd))
goto end;
- /* FIXME: is this the right place to be doing sign extend? */
- if (OP_KIND (code->src.type) == OP_IMM &&
- (ea & 8) != 0)
- ea |= 0xfff0;
- else
- ea = SEXTSHORT (ea);
-
+ ea = SEXTSHORT (ea);
res = SEXTSHORT (ea * SEXTSHORT (rd));
n = res & 0x8000;
fetch (sd, &code->dst, &rd))
goto end;
- /* FIXME: is this the right place to be doing sign extend? */
- if (OP_KIND (code->src.type) == OP_IMM &&
- (ea & 8) != 0)
- ea |= 0xfffffff0;
-
res = ea * rd;
n = res & 0x80000000;
fetch (sd, &code->dst, &rd))
goto end;
- /* FIXME: is this the right place to be doing sign extend? */
- if (OP_KIND (code->src.type) == OP_IMM &&
- (ea & 8) != 0)
- ea |= 0xfffffff0;
-
/* Compute upper 32 bits of the 64-bit result. */
res = (((long long) ea) * ((long long) rd)) >> 32;
fetch (sd, &code->dst, &rd))
goto end;
- /* FIXME: is this the right place to be doing sign extend? */
- if (OP_KIND (code->src.type) == OP_IMM &&
- (ea & 8) != 0)
- ea |= 0xfffffff0;
- else
- ea = SEXTCHAR (ea);
-
+ ea = SEXTCHAR (ea);
res = ea * SEXTCHAR (rd);
n = res & 0x8000;
fetch (sd, &code->dst, &rd))
goto end;
- /* FIXME: is this the right place to be doing sign extend? */
- if (OP_KIND (code->src.type) == OP_IMM &&
- (ea & 8) != 0)
- ea |= 0xfff0;
- else
- ea = SEXTSHORT (ea);
-
+ ea = SEXTSHORT (ea);
res = ea * SEXTSHORT (rd & 0xffff);
n = res & 0x80000000;
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))
fetch (sd, &code->dst, &rd))
goto end;
- /* FIXME: is this the right place to be doing sign extend? */
- if (OP_KIND (code->src.type) == OP_IMM &&
- (ea & 8) != 0)
- ea |= 0xfffffff0;
-
if (ea)
{
res = SEXTSHORT (rd) / SEXTSHORT (ea);
fetch (sd, &code->dst, &rd))
goto end;
- /* FIXME: is this the right place to be doing sign extend? */
- if (OP_KIND (code->src.type) == OP_IMM &&
- (ea & 8) != 0)
- ea |= 0xfffffff0;
-
if (ea)
{
res = rd / ea;
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 end;
rd = SEXTSHORT (rd);
-
- /* FIXME: is this the right place to be doing sign extend? */
- if (OP_KIND (code->src.type) == OP_IMM &&
- (ea & 8) != 0)
- ea |= 0xfffffff0;
- else
- ea = SEXTCHAR (ea);
+ ea = SEXTCHAR (ea);
if (ea)
{
fetch (sd, &code->dst, &rd))
goto end;
- /* FIXME: is this the right place to be doing sign extend? */
- if (OP_KIND (code->src.type) == OP_IMM &&
- (ea & 8) != 0)
- ea |= 0xfffffff0;
- else
- ea = SEXTSHORT (ea);
+ ea = SEXTSHORT (ea);
if (ea)
{
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) ||
switch (rn)
{
case PC_REGNUM:
- h8_set_pc (sd, intval);
+ if(h8300_normal_mode)
+ h8_set_pc (sd, shortval); /* PC for Normal mode is 2 bytes */
+ else
+ h8_set_pc (sd, intval);
break;
default:
(*sim_callback->printf_filtered) (sim_callback,
case EXR_REGNUM:
h8_set_exr (sd, intval);
break;
+ case SBR_REGNUM:
+ h8_set_sbr (sd, intval);
+ break;
+ case VBR_REGNUM:
+ h8_set_vbr (sd, intval);
+ break;
+ case MACH_REGNUM:
+ h8_set_mach (sd, intval);
+ break;
+ case MACL_REGNUM:
+ h8_set_macl (sd, intval);
+ break;
case CYCLE_REGNUM:
h8_set_cycles (sd, longval);
break;
case PC_REGNUM:
v = h8_get_pc (sd);
break;
+ case SBR_REGNUM:
+ v = h8_get_sbr (sd);
+ break;
+ case VBR_REGNUM:
+ v = h8_get_vbr (sd);
+ break;
+ case MACH_REGNUM:
+ v = h8_get_mach (sd);
+ break;
+ case MACL_REGNUM:
+ v = h8_get_macl (sd);
+ break;
case R0_REGNUM:
case R1_REGNUM:
case R2_REGNUM:
longreg = 1;
break;
}
- if (h8300hmode || longreg)
+ /* In Normal mode PC is 2 byte, but other registers are 4 byte */
+ if ((h8300hmode || longreg) && !(rn == PC_REGNUM && h8300_normal_mode))
{
buf[0] = v >> 24;
buf[1] = v >> 16;
FLAG is non-zero for the H8/300H. */
void
-set_h8300h (int h_flag, int s_flag, int sx_flag)
+set_h8300h (unsigned long machine)
{
/* FIXME: Much of the code in sim_load can be moved to sim_open.
This function being replaced by a sim_open:ARGV configuration
option. */
- h8300hmode = h_flag;
- h8300smode = s_flag;
- h8300sxmode = sx_flag;
+ h8300hmode = h8300smode = h8300sxmode = h8300_normal_mode = 0;
+
+ if (machine == bfd_mach_h8300sx || machine == bfd_mach_h8300sxn)
+ h8300sxmode = 1;
+
+ if (machine == bfd_mach_h8300s || machine == bfd_mach_h8300sn || h8300sxmode)
+ h8300smode = 1;
+
+ if (machine == bfd_mach_h8300h || machine == bfd_mach_h8300hn || h8300smode)
+ h8300hmode = 1;
+
+ if(machine == bfd_mach_h8300hn || machine == bfd_mach_h8300sn || machine == bfd_mach_h8300sxn)
+ h8300_normal_mode = 1;
}
/* Cover function of sim_state_free to free the cpu buffers as well. */
if (abfd != NULL)
prog_bfd = abfd;
else
- prog_bfd = bfd_openr (prog, "coff-h8300");
+ prog_bfd = bfd_openr (prog, NULL);
if (prog_bfd != NULL)
{
/* Set the cpu type. We ignore failure from bfd_check_format
and bfd_openr as sim_load_file checks too. */
if (bfd_check_format (prog_bfd, bfd_object))
{
- unsigned long mach = bfd_get_mach (prog_bfd);
-
- set_h8300h (mach == bfd_mach_h8300h ||
- mach == bfd_mach_h8300s ||
- mach == bfd_mach_h8300sx,
- mach == bfd_mach_h8300s ||
- mach == bfd_mach_h8300sx,
- mach == bfd_mach_h8300sx);
+ set_h8300h (bfd_get_mach (prog_bfd));
}
}
switching between H8/300 and H8/300H programs without exiting
gdb. */
- if (h8300smode)
+ if (h8300smode && !h8300_normal_mode)
memory_size = H8300S_MSIZE;
- else if (h8300hmode)
+ else if (h8300hmode && !h8300_normal_mode)
memory_size = H8300H_MSIZE;
else
memory_size = H8300_MSIZE;
calloc (sizeof (char), memory_size));
h8_set_cache_idx_buf (sd, (unsigned short *)
calloc (sizeof (short), memory_size));
+ sd->memory_size = memory_size;
h8_set_eightbit_buf (sd, (unsigned char *) calloc (sizeof (char), 256));
/* `msize' must be a power of two. */