2003-07-18 Michael Snyder <msnyder@redhat.com>

* compile.c (decode): Enhancements for mova.
        Initialize cst, reg, and rdisp inside the loop, for each
        new instruction.  Defer correction of the disp2 values until
        later, and then adjust them by the size of the first operand,
        rather than the size of the instruction.
        (sim_resume): For mova, adjust the size of the second operand
        according to the type of the first operand (INDEXB vs. INDEXW).
        In cases where there is only one operand, the other two must
        both be composed on the fly.
This commit is contained in:
Michael Snyder 2003-07-29 21:03:39 +00:00
parent 83a27a96d4
commit f408565cc8
2 changed files with 110 additions and 37 deletions

View File

@ -1,3 +1,15 @@
2003-07-18 Michael Snyder <msnyder@redhat.com>
* compile.c (decode): Enhancements for mova.
Initialize cst, reg, and rdisp inside the loop, for each
new instruction. Defer correction of the disp2 values until
later, and then adjust them by the size of the first operand,
rather than the size of the instruction.
(sim_resume): For mova, adjust the size of the second operand
according to the type of the first operand (INDEXB vs. INDEXW).
In cases where there is only one operand, the other two must
both be composed on the fly.
2003-07-22 Michael Snyder <msnyder@redhat.com>
* compile.c (sim_resume): Revert 6-24 change, it does not

View File

@ -606,6 +606,10 @@ decode (SIM_DESC sd, int addr, unsigned char *data, decoded_inst *dst)
(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;
@ -770,26 +774,11 @@ decode (SIM_DESC sd, int addr, unsigned char *data, decoded_inst *dst)
(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]);
@ -1072,31 +1061,64 @@ decode (SIM_DESC sd, int addr, unsigned char *data, decoded_inst *dst)
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])
@ -1979,8 +2001,44 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
(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;
@ -3578,6 +3636,9 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
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. */