2003-07-18 Michael Snyder <msnyder@redhat.com>
authorMichael Snyder <msnyder@vmware.com>
Tue, 29 Jul 2003 21:03:39 +0000 (21:03 +0000)
committerMichael Snyder <msnyder@vmware.com>
Tue, 29 Jul 2003 21:03:39 +0000 (21:03 +0000)
        * 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.

sim/h8300/ChangeLog
sim/h8300/compile.c

index 1ff3d42c4b7893c7902c7244e30b6d2a5bfee821..3bd23ece655c081bce5244ef8c65f68b678fd159 100644 (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
index 904bdf7aa63ec8eda427232f1cd5895d1213ef99..a799d2bed8cca8bbd75d96d4db03a0f5f79c26cf 100644 (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.  */