#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
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;
(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]);
}
else if ((looking_for & MODE) == VECIND)
{
- /* FIXME: Multiplier should be 2 for "normal" mode. */
- cst[opnum] = ((data[1] & 0x7f) + 0x80) * 4;
+ 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)
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])
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;
}
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);
+ else
+ code->dst.type = X (OP_REG, SW);
+ }
+
if (fetch (sd, &code->dst, &ea))
goto end;
/* 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;
}
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 =
call:
tmp = h8_get_reg (sd, SP_REGNUM);
- if (h8300hmode)
+ if (h8300hmode && !h8300_normal_mode)
{
tmp -= 4;
SET_MEMORY_L (tmp, code->next_pc);
h8_set_exr (sd, GET_MEMORY_L (tmp));
tmp += 4;
}
- if (h8300hmode)
+ if (h8300hmode && !h8300_normal_mode)
{
h8_set_ccr (sd, GET_MEMORY_L (tmp));
tmp += 4;
rts:
tmp = h8_get_reg (sd, SP_REGNUM);
- if (h8300hmode)
+ if (h8300hmode && !h8300_normal_mode)
{
pc = GET_MEMORY_L (tmp);
tmp += 4;
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. */
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);
-
+ 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;
h8_set_reg (sd, SP_REGNUM, tmp);
- /* FIXME: "normal" mode should use 2-byte ptrs. */
- pc = GET_MEMORY_L (0x20 + res * 4);
+ 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):
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,
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;
This function being replaced by a sim_open:ARGV configuration
option. */
+ h8300hmode = h8300smode = h8300sxmode = h8300_normal_mode = 0;
+
if (machine == bfd_mach_h8300sx || machine == bfd_mach_h8300sxn)
h8300sxmode = 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
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;