gdb: Convert language la_value_print field to a method
[deliverable/binutils-gdb.git] / sim / arm / armemu.c
index d535a4e90752a1199344f6515759e1b890ee4465..3a72277683e62b40f367e50e29815e98cd9d4891 100644 (file)
@@ -6,12 +6,12 @@
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation; either version 3 of the License, or
     (at your option) any later version.
+
     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
+
     You should have received a copy of the GNU General Public License
     along with this program; if not, see <http://www.gnu.org/licenses/>.  */
 
@@ -48,17 +48,6 @@ static void     Handle_Store_Double (ARMul_State *, ARMword);
 #define LDEFAULT  (0)          /* default : do nothing */
 #define LSCC      (1)          /* set condition codes on result */
 
-#ifdef NEED_UI_LOOP_HOOK
-/* How often to run the ui_loop update, when in use.  */
-#define UI_LOOP_POLL_INTERVAL 0x32000
-
-/* Counter for the ui_loop_hook update.  */
-static long ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL;
-
-/* Actual hook to call to run through gdb's gui event loop.  */
-extern int (*deprecated_ui_loop_hook) (int);
-#endif /* NEED_UI_LOOP_HOOK */
-
 extern int stop_simulator;
 
 /* Short-hand macros for LDR/STR.  */
@@ -272,9 +261,15 @@ extern int stop_simulator;
 /* Attempt to emulate an ARMv6 instruction.
    Returns non-zero upon success.  */
 
+#ifdef MODE32
 static int
 handle_v6_insn (ARMul_State * state, ARMword instr)
 {
+  ARMword val;
+  ARMword Rd;
+  ARMword Rm;
+  ARMword Rn;
+
   switch (BITS (20, 27))
     {
 #if 0
@@ -290,29 +285,427 @@ handle_v6_insn (ARMul_State * state, ARMword instr)
     case 0x1d: printf ("Unhandled v6 insn: ldrexb\n"); break;
     case 0x1e: printf ("Unhandled v6 insn: strexh\n"); break;
     case 0x1f: printf ("Unhandled v6 insn: ldrexh\n"); break;
-    case 0x30: printf ("Unhandled v6 insn: movw\n"); break;
     case 0x32: printf ("Unhandled v6 insn: nop/sev/wfe/wfi/yield\n"); break;
-    case 0x34: printf ("Unhandled v6 insn: movt\n"); break;
     case 0x3f: printf ("Unhandled v6 insn: rbit\n"); break;
 #endif
     case 0x61: printf ("Unhandled v6 insn: sadd/ssub\n"); break;
-    case 0x62: printf ("Unhandled v6 insn: qadd/qsub\n"); break;
     case 0x63: printf ("Unhandled v6 insn: shadd/shsub\n"); break;
-    case 0x65: printf ("Unhandled v6 insn: uadd/usub\n"); break;
-    case 0x66: printf ("Unhandled v6 insn: uqadd/uqsub\n"); break;
-    case 0x67: printf ("Unhandled v6 insn: uhadd/uhsub\n"); break;
-    case 0x68: printf ("Unhandled v6 insn: pkh/sxtab/selsxtb\n"); break;
     case 0x6c: printf ("Unhandled v6 insn: uxtb16/uxtab16\n"); break;
     case 0x70: printf ("Unhandled v6 insn: smuad/smusd/smlad/smlsd\n"); break;
     case 0x74: printf ("Unhandled v6 insn: smlald/smlsld\n"); break;
     case 0x75: printf ("Unhandled v6 insn: smmla/smmls/smmul\n"); break;
     case 0x78: printf ("Unhandled v6 insn: usad/usada8\n"); break;
-    case 0x7a: printf ("Unhandled v6 insn: usbfx\n"); break;
-    case 0x7c: printf ("Unhandled v6 insn: bfc/bfi\n"); break;
+
+    case 0x30:
+      {
+       /* MOVW<c> <Rd>,#<imm16>
+          instr[31,28] = cond
+          instr[27,20] = 0011 0000
+          instr[19,16] = imm4
+          instr[15,12] = Rd
+          instr[11, 0] = imm12.  */
+       Rd = BITS (12, 15);
+       val = (BITS (16, 19) << 12) | BITS (0, 11);
+       state->Reg[Rd] = val;
+       return 1;
+      }
+
+    case 0x34:
+      {
+       /* MOVT<c> <Rd>,#<imm16>
+          instr[31,28] = cond
+          instr[27,20] = 0011 0100
+          instr[19,16] = imm4
+          instr[15,12] = Rd
+          instr[11, 0] = imm12.  */
+       Rd = BITS (12, 15);
+       val = (BITS (16, 19) << 12) | BITS (0, 11);
+       state->Reg[Rd] &= 0xFFFF;
+       state->Reg[Rd] |= val << 16;
+       return 1;
+      }
+
+    case 0x62:
+      {
+       ARMword val1;
+       ARMword val2;
+       ARMsword n, m, r;
+       int i;
+
+       Rd = BITS (12, 15);
+       Rn = BITS (16, 19);
+       Rm = BITS (0, 3);
+
+       if (Rd == 15 || Rn == 15 || Rm == 15)
+         break;
+
+       val1 = state->Reg[Rn];
+       val2 = state->Reg[Rm];
+
+       switch (BITS (4, 11))
+         {
+         case 0xF1: /* QADD16<c> <Rd>,<Rn>,<Rm>.  */
+           state->Reg[Rd] = 0;
+
+           for (i = 0; i < 32; i+= 16)
+             {
+               n = (val1 >> i) & 0xFFFF;
+               if (n & 0x8000)
+                 n |= -(1 << 16);
+
+               m = (val2 >> i) & 0xFFFF;
+               if (m & 0x8000)
+                 m |= -(1 << 16);
+
+               r = n + m;
+
+               if (r > 0x7FFF)
+                 r = 0x7FFF;
+               else if (r < -(0x8000))
+                 r = - 0x8000;
+
+               state->Reg[Rd] |= (r & 0xFFFF) << i;
+             } 
+           return 1;
+
+         case 0xF3: /* QASX<c> <Rd>,<Rn>,<Rm>.  */
+           n = val1 & 0xFFFF;
+           if (n & 0x8000)
+             n |= -(1 << 16);
+
+           m = (val2 >> 16) & 0xFFFF;
+           if (m & 0x8000)
+             m |= -(1 << 16);
+
+           r = n - m;
+
+           if (r > 0x7FFF)
+             r = 0x7FFF;
+           else if (r < -(0x8000))
+             r = - 0x8000;
+
+           state->Reg[Rd] = (r & 0xFFFF);
+
+           n = (val1 >> 16) & 0xFFFF;
+           if (n & 0x8000)
+             n |= -(1 << 16);
+
+           m = val2 & 0xFFFF;
+           if (m & 0x8000)
+             m |= -(1 << 16);
+
+           r = n + m;
+
+           if (r > 0x7FFF)
+             r = 0x7FFF;
+           else if (r < -(0x8000))
+             r = - 0x8000;
+
+           state->Reg[Rd] |= (r & 0xFFFF) << 16;
+           return 1;
+
+         case 0xF5: /* QSAX<c> <Rd>,<Rn>,<Rm>.  */
+           n = val1 & 0xFFFF;
+           if (n & 0x8000)
+             n |= -(1 << 16);
+
+           m = (val2 >> 16) & 0xFFFF;
+           if (m & 0x8000)
+             m |= -(1 << 16);
+
+           r = n + m;
+
+           if (r > 0x7FFF)
+             r = 0x7FFF;
+           else if (r < -(0x8000))
+             r = - 0x8000;
+
+           state->Reg[Rd] = (r & 0xFFFF);
+
+           n = (val1 >> 16) & 0xFFFF;
+           if (n & 0x8000)
+             n |= -(1 << 16);
+
+           m = val2 & 0xFFFF;
+           if (m & 0x8000)
+             m |= -(1 << 16);
+
+           r = n - m;
+
+           if (r > 0x7FFF)
+             r = 0x7FFF;
+           else if (r < -(0x8000))
+             r = - 0x8000;
+
+           state->Reg[Rd] |= (r & 0xFFFF) << 16;
+           return 1;
+
+         case 0xF7: /* QSUB16<c> <Rd>,<Rn>,<Rm>.  */
+           state->Reg[Rd] = 0;
+
+           for (i = 0; i < 32; i+= 16)
+             {
+               n = (val1 >> i) & 0xFFFF;
+               if (n & 0x8000)
+                 n |= -(1 << 16);
+
+               m = (val2 >> i) & 0xFFFF;
+               if (m & 0x8000)
+                 m |= -(1 << 16);
+
+               r = n - m;
+
+               if (r > 0x7FFF)
+                 r = 0x7FFF;
+               else if (r < -(0x8000))
+                 r = - 0x8000;
+
+               state->Reg[Rd] |= (r & 0xFFFF) << i;
+             } 
+           return 1;
+
+         case 0xF9: /* QADD8<c> <Rd>,<Rn>,<Rm>.  */
+           state->Reg[Rd] = 0;
+
+           for (i = 0; i < 32; i+= 8)
+             {
+               n = (val1 >> i) & 0xFF;
+               if (n & 0x80)
+                 n |= - (1 << 8);
+
+               m = (val2 >> i) & 0xFF;
+               if (m & 0x80)
+                 m |= - (1 << 8);
+
+               r = n + m;
+
+               if (r > 127)
+                 r = 127;
+               else if (r < -128)
+                 r = -128;
+
+               state->Reg[Rd] |= (r & 0xFF) << i;
+             } 
+           return 1;
+
+         case 0xFF: /* QSUB8<c> <Rd>,<Rn>,<Rm>.  */
+           state->Reg[Rd] = 0;
+
+           for (i = 0; i < 32; i+= 8)
+             {
+               n = (val1 >> i) & 0xFF;
+               if (n & 0x80)
+                 n |= - (1 << 8);
+
+               m = (val2 >> i) & 0xFF;
+               if (m & 0x80)
+                 m |= - (1 << 8);
+
+               r = n - m;
+
+               if (r > 127)
+                 r = 127;
+               else if (r < -128)
+                 r = -128;
+
+               state->Reg[Rd] |= (r & 0xFF) << i;
+             } 
+           return 1;
+
+         default:
+           break;
+         }
+       break;
+      }
+
+    case 0x65:
+      {
+       ARMword valn;
+       ARMword valm;
+       ARMword res1, res2, res3, res4;
+
+       /* U{ADD|SUB}{8|16}<c> <Rd>, <Rn>, <Rm>
+          instr[31,28] = cond
+          instr[27,20] = 0110 0101
+          instr[19,16] = Rn
+          instr[15,12] = Rd
+          instr[11, 8] = 1111
+          instr[ 7, 4] = opcode: UADD8 (1001), UADD16 (0001), USUB8 (1111), USUB16 (0111)
+          instr[ 3, 0] = Rm.  */
+       if (BITS (8, 11) != 0xF)
+         break;
+
+       Rn = BITS (16, 19);
+       Rd = BITS (12, 15);
+       Rm = BITS (0, 3);
+
+       if (Rn == 15 || Rd == 15 || Rm == 15)
+         {
+           ARMul_UndefInstr (state, instr);
+           state->Emulate = FALSE;
+           break;
+         }
+
+       valn = state->Reg[Rn];
+       valm = state->Reg[Rm];
+       
+       switch (BITS (4, 7))
+         {
+         case 1:  /* UADD16.  */
+           res1 = (valn & 0xFFFF) + (valm & 0xFFFF);
+           if (res1 > 0xFFFF)
+             state->Cpsr |= (GE0 | GE1);
+           else
+             state->Cpsr &= ~ (GE0 | GE1);
+
+           res2 = (valn >> 16) + (valm >> 16);
+           if (res2 > 0xFFFF)
+             state->Cpsr |= (GE2 | GE3);
+           else
+             state->Cpsr &= ~ (GE2 | GE3);
+
+           state->Reg[Rd] = (res1 & 0xFFFF) | (res2 << 16);
+           return 1;
+
+         case 7:  /* USUB16.  */
+           res1 = (valn & 0xFFFF) - (valm & 0xFFFF);
+           if (res1 & 0x800000)
+             state->Cpsr |= (GE0 | GE1);
+           else
+             state->Cpsr &= ~ (GE0 | GE1);
+
+           res2 = (valn >> 16) - (valm >> 16);
+           if (res2 & 0x800000)
+             state->Cpsr |= (GE2 | GE3);
+           else
+             state->Cpsr &= ~ (GE2 | GE3);
+
+           state->Reg[Rd] = (res1 & 0xFFFF) | (res2 << 16);
+           return 1;
+
+         case 9:  /* UADD8.  */
+           res1 = (valn & 0xFF) + (valm & 0xFF);
+           if (res1 > 0xFF)
+             state->Cpsr |= GE0;
+           else
+             state->Cpsr &= ~ GE0;
+
+           res2 = ((valn >> 8) & 0xFF) + ((valm >> 8) & 0xFF);
+           if (res2 > 0xFF)
+             state->Cpsr |= GE1;
+           else
+             state->Cpsr &= ~ GE1;
+
+           res3 = ((valn >> 16) & 0xFF) + ((valm >> 16) & 0xFF);
+           if (res3 > 0xFF)
+             state->Cpsr |= GE2;
+           else
+             state->Cpsr &= ~ GE2;
+
+           res4 = (valn >> 24) + (valm >> 24);
+           if (res4 > 0xFF)
+             state->Cpsr |= GE3;
+           else
+             state->Cpsr &= ~ GE3;
+
+           state->Reg[Rd] = (res1 & 0xFF) | ((res2 << 8) & 0xFF00)
+             | ((res3 << 16) & 0xFF0000) | (res4 << 24);
+           return 1;
+
+         case 15: /* USUB8.  */
+           res1 = (valn & 0xFF) - (valm & 0xFF);
+           if (res1 & 0x800000)
+             state->Cpsr |= GE0;
+           else
+             state->Cpsr &= ~ GE0;
+
+           res2 = ((valn >> 8) & 0XFF) - ((valm >> 8) & 0xFF);
+           if (res2 & 0x800000)
+             state->Cpsr |= GE1;
+           else
+             state->Cpsr &= ~ GE1;
+
+           res3 = ((valn >> 16) & 0XFF) - ((valm >> 16) & 0xFF);
+           if (res3 & 0x800000)
+             state->Cpsr |= GE2;
+           else
+             state->Cpsr &= ~ GE2;
+
+           res4 = (valn >> 24) - (valm >> 24) ;
+           if (res4 & 0x800000)
+             state->Cpsr |= GE3;
+           else
+             state->Cpsr &= ~ GE3;
+
+           state->Reg[Rd] = (res1 & 0xFF) | ((res2 << 8) & 0xFF00)
+             | ((res3 << 16) & 0xFF0000) | (res4 << 24);
+           return 1;
+
+         default:
+           break;
+         }
+       break;
+      }
+
+    case 0x68:
+      {
+       ARMword res;
+
+       /* PKHBT<c> <Rd>,<Rn>,<Rm>{,LSL #<imm>}
+          PKHTB<c> <Rd>,<Rn>,<Rm>{,ASR #<imm>}
+          SXTAB16<c> <Rd>,<Rn>,<Rm>{,<rotation>}
+          SXTB16<c> <Rd>,<Rm>{,<rotation>}
+          SEL<c> <Rd>,<Rn>,<Rm>
+
+          instr[31,28] = cond
+          instr[27,20] = 0110 1000
+          instr[19,16] = Rn
+          instr[15,12] = Rd
+          instr[11, 7] = imm5 (PKH), 11111 (SEL), rr000 (SXTAB16 & SXTB16),
+          instr[6]     = tb (PKH), 0 (SEL), 1 (SXT)
+          instr[5]     = opcode: PKH (0), SEL/SXT (1)
+          instr[4]     = 1
+          instr[ 3, 0] = Rm.  */
+
+       if (BIT (4) != 1)
+         break;
+
+       if (BIT (5) == 0)
+         {
+           /* FIXME: Add implementation of PKH.  */
+           fprintf (stderr, "PKH: NOT YET IMPLEMENTED\n");
+           ARMul_UndefInstr (state, instr);
+           break;
+         }
+
+       if (BIT (6) == 1)
+         {
+           /* FIXME: Add implementation of SXT.  */
+           fprintf (stderr, "SXT: NOT YET IMPLEMENTED\n");
+           ARMul_UndefInstr (state, instr);
+           break;
+         }
+
+       Rn = BITS (16, 19);
+       Rd = BITS (12, 15);
+       Rm = BITS (0, 3);
+       if (Rn == 15 || Rm == 15 || Rd == 15)
+         {
+           ARMul_UndefInstr (state, instr);
+           state->Emulate = FALSE;
+           break;
+         }
+
+       res  = (state->Reg[(state->Cpsr & GE0) ? Rn : Rm]) & 0xFF;
+       res |= (state->Reg[(state->Cpsr & GE1) ? Rn : Rm]) & 0xFF00;
+       res |= (state->Reg[(state->Cpsr & GE2) ? Rn : Rm]) & 0xFF0000;
+       res |= (state->Reg[(state->Cpsr & GE3) ? Rn : Rm]) & 0xFF000000;
+       state->Reg[Rd] = res;
+       return 1;
+      }
 
     case 0x6a:
       {
-       ARMword Rm;
        int ror = -1;
 
        switch (BITS (4, 11))
@@ -326,6 +719,7 @@ handle_v6_insn (ARMul_State * state, ARMword instr)
          case 0xf3:
            printf ("Unhandled v6 insn: ssat\n");
            return 0;
+
          default:
            break;
          }
@@ -355,9 +749,8 @@ handle_v6_insn (ARMul_State * state, ARMword instr)
 
     case 0x6b:
       {
-       ARMword Rm;
        int ror = -1;
-         
+
        switch (BITS (4, 11))
          {
          case 0x07: ror = 0; break;
@@ -365,9 +758,57 @@ handle_v6_insn (ARMul_State * state, ARMword instr)
          case 0x87: ror = 16; break;
          case 0xc7: ror = 24; break;
 
+         case 0xf3:
+           {
+             /* REV<c> <Rd>,<Rm>
+                instr[31,28] = cond
+                instr[27,20] = 0110 1011
+                instr[19,16] = 1111
+                instr[15,12] = Rd
+                instr[11, 4] = 1111 0011
+                instr[ 3, 0] = Rm.  */
+             if (BITS (16, 19) != 0xF)
+               break;
+
+             Rd = BITS (12, 15);
+             Rm = BITS (0, 3);
+             if (Rd == 15 || Rm == 15)
+               {
+                 ARMul_UndefInstr (state, instr);
+                 state->Emulate = FALSE;
+                 break;
+               }
+
+             val = state->Reg[Rm] << 24;
+             val |= ((state->Reg[Rm] << 8) & 0xFF0000);
+             val |= ((state->Reg[Rm] >> 8) & 0xFF00);
+             val |= ((state->Reg[Rm] >> 24));
+             state->Reg[Rd] = val;
+             return 1;
+           }
+
          case 0xfb:
-           printf ("Unhandled v6 insn: rev\n");
-           return 0;
+           {
+             /* REV16<c> <Rd>,<Rm>.  */
+             if (BITS (16, 19) != 0xF)
+               break;
+
+             Rd = BITS (12, 15);
+             Rm = BITS (0, 3);
+             if (Rd == 15 || Rm == 15)
+               {
+                 ARMul_UndefInstr (state, instr);
+                 state->Emulate = FALSE;
+                 break;
+               }
+
+             val = 0;
+             val |= ((state->Reg[Rm] >> 8) & 0x00FF00FF);
+             val |= ((state->Reg[Rm] << 8) & 0xFF00FF00);
+             state->Reg[Rd] = val;
+             return 1;
+           }
+
          default:
            break;
          }
@@ -390,9 +831,8 @@ handle_v6_insn (ARMul_State * state, ARMword instr)
 
     case 0x6e:
       {
-       ARMword Rm;
        int ror = -1;
-         
+
        switch (BITS (4, 11))
          {
          case 0x07: ror = 0; break;
@@ -404,6 +844,7 @@ handle_v6_insn (ARMul_State * state, ARMword instr)
          case 0xf3:
            printf ("Unhandled v6 insn: usat\n");
            return 0;
+
          default:
            break;
          }
@@ -421,7 +862,7 @@ handle_v6_insn (ARMul_State * state, ARMword instr)
        Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFF);
 
        if (BITS (16, 19) == 0xf)
-          /* UXTB */
+         /* UXTB */
          state->Reg[BITS (12, 15)] = Rm;
        else
          /* UXTAB */
@@ -431,9 +872,9 @@ handle_v6_insn (ARMul_State * state, ARMword instr)
 
     case 0x6f:
       {
-       ARMword Rm;
+       int i;
        int ror = -1;
-         
+
        switch (BITS (4, 11))
          {
          case 0x07: ror = 0; break;
@@ -441,9 +882,21 @@ handle_v6_insn (ARMul_State * state, ARMword instr)
          case 0x87: ror = 16; break;
          case 0xc7: ror = 24; break;
 
+         case 0xf3: /* RBIT */
+           if (BITS (16, 19) != 0xF)
+             break;
+           Rd = BITS (12, 15);
+           state->Reg[Rd] = 0;
+           Rm = state->Reg[BITS (0, 3)];
+           for (i = 0; i < 32; i++)
+             if (Rm & (1 << i))
+               state->Reg[Rd] |= (1 << (31 - i));
+           return 1;
+
          case 0xfb:
            printf ("Unhandled v6 insn: revsh\n");
            return 0;
+
          default:
            break;
          }
@@ -457,13 +910,138 @@ handle_v6_insn (ARMul_State * state, ARMword instr)
          /* UXT */
          state->Reg[BITS (12, 15)] = Rm;
        else
+         /* UXTAH */
+         state->Reg[BITS (12, 15)] = state->Reg [BITS (16, 19)] + Rm;
+      }
+      return 1;
+
+    case 0x7c:
+    case 0x7d:
+      {
+       int lsb;
+       int msb;
+       ARMword mask;
+
+       /* BFC<c> <Rd>,#<lsb>,#<width>
+          BFI<c> <Rd>,<Rn>,#<lsb>,#<width>
+
+          instr[31,28] = cond
+          instr[27,21] = 0111 110
+          instr[20,16] = msb
+          instr[15,12] = Rd
+          instr[11, 7] = lsb
+          instr[ 6, 4] = 001 1111
+          instr[ 3, 0] = Rn (BFI) / 1111 (BFC).  */
+
+       if (BITS (4, 6) != 0x1)
+         break;
+
+       Rd = BITS (12, 15);
+       if (Rd == 15)
          {
-           /* UXTAH */
-           state->Reg[BITS (12, 15)] = state->Reg [BITS (16, 19)] + Rm;
+           ARMul_UndefInstr (state, instr);
+           state->Emulate = FALSE;
+         }
+
+       lsb = BITS (7, 11);
+       msb = BITS (16, 20);
+       if (lsb > msb)
+         {
+           ARMul_UndefInstr (state, instr);
+           state->Emulate = FALSE;
          }
-       }
-      return 1;
 
+       mask = -(1 << lsb);
+       mask &= ~(-(1 << (msb + 1)));
+       state->Reg[Rd] &= ~ mask;
+
+       Rn = BITS (0, 3);
+       if (Rn != 0xF)
+         {
+           ARMword val = state->Reg[Rn] & ~(-(1 << ((msb + 1) - lsb)));
+           state->Reg[Rd] |= val << lsb;
+         }
+       return 1;
+      }
+
+    case 0x7b:
+    case 0x7a: /* SBFX<c> <Rd>,<Rn>,#<lsb>,#<width>.  */
+      {
+       int lsb;
+       int widthm1;
+       ARMsword sval;
+
+       if (BITS (4, 6) != 0x5)
+         break;
+
+       Rd = BITS (12, 15);
+       if (Rd == 15)
+         {
+           ARMul_UndefInstr (state, instr);
+           state->Emulate = FALSE;
+         }
+
+       Rn = BITS (0, 3);
+       if (Rn == 15)
+         {
+           ARMul_UndefInstr (state, instr);
+           state->Emulate = FALSE;
+         }
+
+       lsb = BITS (7, 11);
+       widthm1 = BITS (16, 20);
+
+       sval = state->Reg[Rn];
+       sval <<= (31 - (lsb + widthm1));
+       sval >>= (31 - widthm1);
+       state->Reg[Rd] = sval;
+       
+       return 1;
+      }
+
+    case 0x7f:
+    case 0x7e:
+      {
+       int lsb;
+       int widthm1;
+
+       /* UBFX<c> <Rd>,<Rn>,#<lsb>,#<width>
+          instr[31,28] = cond
+          instr[27,21] = 0111 111
+          instr[20,16] = widthm1
+          instr[15,12] = Rd
+          instr[11, 7] = lsb
+          instr[ 6, 4] = 101
+          instr[ 3, 0] = Rn.  */
+
+       if (BITS (4, 6) != 0x5)
+         break;
+
+       Rd = BITS (12, 15);
+       if (Rd == 15)
+         {
+           ARMul_UndefInstr (state, instr);
+           state->Emulate = FALSE;
+         }
+
+       Rn = BITS (0, 3);
+       if (Rn == 15)
+         {
+           ARMul_UndefInstr (state, instr);
+           state->Emulate = FALSE;
+         }
+
+       lsb = BITS (7, 11);
+       widthm1 = BITS (16, 20);
+
+       val = state->Reg[Rn];
+       val >>= lsb;
+       val &= ~(-(1 << (widthm1 + 1)));
+
+       state->Reg[Rd] = val;
+       
+       return 1;
+      }
 #if 0
     case 0x84: printf ("Unhandled v6 insn: srs\n"); break;
 #endif
@@ -473,12 +1051,94 @@ handle_v6_insn (ARMul_State * state, ARMword instr)
   printf ("Unhandled v6 insn: UNKNOWN: %08x\n", instr);
   return 0;
 }
+#endif
 
-/* EMULATION of ARM6.  */
+static void
+handle_VFP_move (ARMul_State * state, ARMword instr)
+{
+  switch (BITS (20, 27))
+    {
+    case 0xC4:
+    case 0xC5:
+      switch (BITS (4, 11))
+       {
+       case 0xA1:
+       case 0xA3:
+         {
+           /* VMOV two core <-> two VFP single precision.  */
+           int sreg = (BITS (0, 3) << 1) | BIT (5);
 
-/* The PC pipeline value depends on whether ARM
-   or Thumb instructions are being executed.  */
-ARMword isize;
+           if (BIT (20))
+             {
+               state->Reg[BITS (12, 15)] = VFP_uword (sreg);
+               state->Reg[BITS (16, 19)] = VFP_uword (sreg + 1);
+             }
+           else
+             {
+               VFP_uword (sreg)     = state->Reg[BITS (12, 15)];
+               VFP_uword (sreg + 1) = state->Reg[BITS (16, 19)];
+             }
+         }
+         break;
+
+       case 0xB1:
+       case 0xB3:
+         {
+           /* VMOV two core <-> VFP double precision.  */
+           int dreg = BITS (0, 3) | (BIT (5) << 4);
+
+           if (BIT (20))
+             {
+               if (trace)
+                 fprintf (stderr, " VFP: VMOV: r%d r%d <= d%d\n",
+                          BITS (12, 15), BITS (16, 19), dreg);
+
+               state->Reg[BITS (12, 15)] = VFP_dword (dreg);
+               state->Reg[BITS (16, 19)] = VFP_dword (dreg) >> 32;
+             }
+           else
+             {
+               VFP_dword (dreg) = state->Reg[BITS (16, 19)];
+               VFP_dword (dreg) <<= 32;
+               VFP_dword (dreg) |= state->Reg[BITS (12, 15)];
+
+               if (trace)
+                 fprintf (stderr, " VFP: VMOV: d%d <= r%d r%d : %g\n",
+                          dreg, BITS (16, 19), BITS (12, 15),
+                          VFP_dval (dreg));
+             }
+         }
+         break;
+
+       default:
+         fprintf (stderr, "SIM: VFP: Unimplemented move insn %x\n", BITS (20, 27));
+         break;
+       }
+      break;
+
+    case 0xe0:
+    case 0xe1:
+      /* VMOV single core <-> VFP single precision.  */
+      if (BITS (0, 6) != 0x10 || BITS (8, 11) != 0xA)
+       fprintf (stderr, "SIM: VFP: Unimplemented move insn %x\n", BITS (20, 27));
+      else
+       {
+         int sreg = (BITS (16, 19) << 1) | BIT (7);
+
+         if (BIT (20))
+           state->Reg[DESTReg] = VFP_uword (sreg);
+         else
+           VFP_uword (sreg) = state->Reg[DESTReg];
+       }
+      break;
+
+    default:
+      fprintf (stderr, "SIM: VFP: Unimplemented move insn %x\n", BITS (20, 27));
+      return;
+    }
+}
+
+/* EMULATION of ARM6.  */
 
 ARMword
 #ifdef MODE32
@@ -629,7 +1289,6 @@ ARMul_Emulate26 (ARMul_State * state)
 
       if (state->CallDebug > 0)
        {
-         instr = ARMul_Debug (state, pc, instr);
          if (state->Emulate < ONCE)
            {
              state->NextInstr = RESUME;
@@ -712,9 +1371,9 @@ ARMul_Emulate26 (ARMul_State * state)
              if (BITS (25, 27) == 5) /* BLX(1) */
                {
                  ARMword dest;
-                 
+
                  state->Reg[14] = pc + 4;
-                 
+
                  /* Force entry into Thumb mode.  */
                  dest = pc + 8 + 1;
                  if (BIT (23))
@@ -817,10 +1476,11 @@ ARMul_Emulate26 (ARMul_State * state)
              else
                {
                  ARMword cp14r1;
-                 int do_int = 0;
+                 int do_int;
 
                  state->CP14R0_CCD = -1;
 check_PMUintr:
+                 do_int = 0;
                  cp14r0 |= ARMul_CP14_R0_FLAG2;
                  (void) state->CPWrite[14] (state, 0, cp14r0);
 
@@ -883,7 +1543,7 @@ check_PMUintr:
                      ARMword temp = GetLS7RHS (state, instr);
                      ARMword temp2 = BIT (23) ? LHS + temp : LHS - temp;
                      ARMword addr = BIT (24) ? temp2 : LHS;
-                     
+
                      if (BIT (12))
                        ARMul_UndefInstr (state, instr);
                      else if (addr & 7)
@@ -892,7 +1552,7 @@ check_PMUintr:
                      else
                        {
                          int wb = BIT (21) || (! BIT (24));
-                         
+
                          state->Reg[BITS (12, 15)] =
                            ARMul_LoadWordN (state, addr);
                          state->Reg[BITS (12, 15) + 1] =
@@ -1464,7 +2124,7 @@ check_PMUintr:
                      ARMword op1 = state->Reg[BITS (0, 3)];
                      ARMword op2 = state->Reg[BITS (8, 11)];
                      ARMword Rn = state->Reg[BITS (12, 15)];
-                     
+
                      if (BIT (5))
                        op1 >>= 16;
                      if (BIT (6))
@@ -1476,7 +2136,7 @@ check_PMUintr:
                      if (op2 & 0x8000)
                        op2 -= 65536;
                      op1 *= op2;
-                     
+
                      if (AddOverflow (op1, Rn, op1 + Rn))
                        SETS;
                      state->Reg[BITS (16, 19)] = op1 + Rn;
@@ -1546,6 +2206,11 @@ check_PMUintr:
                }
              else
                {
+#ifdef MODE32
+                 if (state->is_v6
+                     && handle_v6_insn (state, instr))
+                   break;
+#endif
                  UNDEF_Test;
                }
              break;
@@ -1619,7 +2284,7 @@ check_PMUintr:
                      if (BIT (5) == 0)
                        {
                          ARMword Rn = state->Reg[BITS (12, 15)];
-                         
+
                          if (AddOverflow (result, Rn, result + Rn))
                            SETS;
                          result += Rn;
@@ -1712,6 +2377,11 @@ check_PMUintr:
 #endif
                  ARMul_FixCPSR (state, instr, temp);
                }
+#ifdef MODE32
+             else if (state->is_v6
+                      && handle_v6_insn (state, instr))
+               break;
+#endif
              else
                UNDEF_Test;
 
@@ -1842,6 +2512,11 @@ check_PMUintr:
                  UNDEF_MRSPC;
                  DEST = GETSPSR (state->Bank);
                }
+#ifdef MODE32
+             else if (state->is_v6
+                      && handle_v6_insn (state, instr))
+               break;
+#endif
              else
                UNDEF_Test;
 
@@ -1978,6 +2653,11 @@ check_PMUintr:
                }
              else
                {
+#ifdef MODE32
+                 if (state->is_v6
+                     && handle_v6_insn (state, instr))
+                   break;
+#endif
                  UNDEF_Test;
                }
              break;
@@ -2333,6 +3013,11 @@ check_PMUintr:
              break;
 
            case 0x30:          /* MOVW immed */
+#ifdef MODE32
+             if (state->is_v6
+                 && handle_v6_insn (state, instr))
+               break;
+#endif
              dest = BITS (0, 11);
              dest |= (BITS (16, 19) << 12);
              WRITEDEST (dest);
@@ -2363,6 +3048,11 @@ check_PMUintr:
              if (DESTReg == 15)
                /* MSR immed to CPSR.  */
                ARMul_FixCPSR (state, instr, DPImmRHS);
+#ifdef MODE32
+             else if (state->is_v6
+                      && handle_v6_insn (state, instr))
+               break;
+#endif
              else
                UNDEF_Test;
              break;
@@ -2388,6 +3078,12 @@ check_PMUintr:
              break;
 
            case 0x34:          /* MOVT immed */
+#ifdef MODE32
+             if (state->is_v6
+                 && handle_v6_insn (state, instr))
+               break;
+#endif
+             DEST &= 0xFFFF;
              dest  = BITS (0, 11);
              dest |= (BITS (16, 19) << 12);
              DEST |= (dest << 16);
@@ -2430,6 +3126,11 @@ check_PMUintr:
            case 0x36:          /* CMN immed and MSR immed to SPSR */
              if (DESTReg == 15)
                ARMul_FixSPSR (state, instr, DPImmRHS);
+#ifdef MODE32
+             else if (state->is_v6
+                      && handle_v6_insn (state, instr))
+               break;
+#endif
              else
                UNDEF_Test;
              break;
@@ -2747,6 +3448,11 @@ check_PMUintr:
            case 0x60:          /* Store Word, No WriteBack, Post Dec, Reg.  */
              if (BIT (4))
                {
+#ifdef MODE32
+                 if (state->is_v6
+                     && handle_v6_insn (state, instr))
+                   break;
+#endif
                  ARMul_UndefInstr (state, instr);
                  break;
                }
@@ -2828,6 +3534,11 @@ check_PMUintr:
            case 0x64:          /* Store Byte, No WriteBack, Post Dec, Reg.  */
              if (BIT (4))
                {
+#ifdef MODE32
+                 if (state->is_v6
+                     && handle_v6_insn (state, instr))
+                   break;
+#endif
                  ARMul_UndefInstr (state, instr);
                  break;
                }
@@ -2929,6 +3640,11 @@ check_PMUintr:
            case 0x69:          /* Load Word, No WriteBack, Post Inc, Reg.  */
              if (BIT (4))
                {
+#ifdef MODE32
+                 if (state->is_v6
+                     && handle_v6_insn (state, instr))
+                   break;
+#endif
                  ARMul_UndefInstr (state, instr);
                  break;
                }
@@ -3010,6 +3726,11 @@ check_PMUintr:
            case 0x6d:          /* Load Byte, No WriteBack, Post Inc, Reg.  */
              if (BIT (4))
                {
+#ifdef MODE32
+                 if (state->is_v6
+                     && handle_v6_insn (state, instr))
+                   break;
+#endif
                  ARMul_UndefInstr (state, instr);
                  break;
                }
@@ -3086,6 +3807,11 @@ check_PMUintr:
            case 0x71:          /* Load Word, No WriteBack, Pre Dec, Reg.  */
              if (BIT (4))
                {
+#ifdef MODE32
+                 if (state->is_v6
+                     && handle_v6_insn (state, instr))
+                   break;
+#endif
                  ARMul_UndefInstr (state, instr);
                  break;
                }
@@ -3095,6 +3821,11 @@ check_PMUintr:
            case 0x72:          /* Store Word, WriteBack, Pre Dec, Reg.  */
              if (BIT (4))
                {
+#ifdef MODE32
+                 if (state->is_v6
+                     && handle_v6_insn (state, instr))
+                   break;
+#endif
                  ARMul_UndefInstr (state, instr);
                  break;
                }
@@ -3110,6 +3841,11 @@ check_PMUintr:
            case 0x73:          /* Load Word, WriteBack, Pre Dec, Reg.  */
              if (BIT (4))
                {
+#ifdef MODE32
+                 if (state->is_v6
+                     && handle_v6_insn (state, instr))
+                   break;
+#endif
                  ARMul_UndefInstr (state, instr);
                  break;
                }
@@ -3153,6 +3889,11 @@ check_PMUintr:
            case 0x76:          /* Store Byte, WriteBack, Pre Dec, Reg.  */
              if (BIT (4))
                {
+#ifdef MODE32
+                 if (state->is_v6
+                     && handle_v6_insn (state, instr))
+                   break;
+#endif
                  ARMul_UndefInstr (state, instr);
                  break;
                }
@@ -3168,6 +3909,11 @@ check_PMUintr:
            case 0x77:          /* Load Byte, WriteBack, Pre Dec, Reg.  */
              if (BIT (4))
                {
+#ifdef MODE32
+                 if (state->is_v6
+                     && handle_v6_insn (state, instr))
+                   break;
+#endif
                  ARMul_UndefInstr (state, instr);
                  break;
                }
@@ -3197,6 +3943,11 @@ check_PMUintr:
            case 0x79:          /* Load Word, No WriteBack, Pre Inc, Reg.  */
              if (BIT (4))
                {
+#ifdef MODE32
+                 if (state->is_v6
+                     && handle_v6_insn (state, instr))
+                   break;
+#endif
                  ARMul_UndefInstr (state, instr);
                  break;
                }
@@ -3226,6 +3977,11 @@ check_PMUintr:
            case 0x7b:          /* Load Word, WriteBack, Pre Inc, Reg.  */
              if (BIT (4))
                {
+#ifdef MODE32
+                 if (state->is_v6
+                     && handle_v6_insn (state, instr))
+                   break;
+#endif
                  ARMul_UndefInstr (state, instr);
                  break;
                }
@@ -3255,6 +4011,11 @@ check_PMUintr:
            case 0x7d:          /* Load Byte, No WriteBack, Pre Inc, Reg.  */
              if (BIT (4))
                {
+#ifdef MODE32
+                 if (state->is_v6
+                     && handle_v6_insn (state, instr))
+                   break;
+#endif
                  ARMul_UndefInstr (state, instr);
                  break;
                }
@@ -3264,6 +4025,11 @@ check_PMUintr:
            case 0x7e:          /* Store Byte, WriteBack, Pre Inc, Reg.  */
              if (BIT (4))
                {
+#ifdef MODE32
+                 if (state->is_v6
+                     && handle_v6_insn (state, instr))
+                   break;
+#endif
                  ARMul_UndefInstr (state, instr);
                  break;
                }
@@ -3287,6 +4053,11 @@ check_PMUintr:
                      if (!ARMul_OSHandleSWI (state, SWI_Breakpoint))
                        ARMul_Abort (state, ARMul_SWIV);
                    }
+#ifdef MODE32
+                 else if (state->is_v6
+                          && handle_v6_insn (state, instr))
+                   break;
+#endif
                  else
                    ARMul_UndefInstr (state, instr);
                  break;
@@ -3521,8 +4292,10 @@ check_PMUintr:
            case 0xc4:
              if (state->is_v5)
                {
+                 if (CPNum == 10 || CPNum == 11)
+                   handle_VFP_move (state, instr);
                  /* Reading from R15 is UNPREDICTABLE.  */
-                 if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
+                 else if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
                    ARMul_UndefInstr (state, instr);
                  /* Is access to coprocessor 0 allowed ?  */
                  else if (! CP_ACCESS_ALLOWED (state, CPNum))
@@ -3548,11 +4321,11 @@ check_PMUintr:
                    }
                  else
                    /* FIXME: Not sure what to do for other v5 processors.  */
-                   ARMul_UndefInstr (state, instr);                
+                   ARMul_UndefInstr (state, instr);
                  break;
                }
              /* Drop through.  */
-             
+
            case 0xc0:          /* Store , No WriteBack , Post Dec.  */
              ARMul_STC (state, instr, LHS);
              break;
@@ -3560,8 +4333,10 @@ check_PMUintr:
            case 0xc5:
              if (state->is_v5)
                {
+                 if (CPNum == 10 || CPNum == 11)
+                   handle_VFP_move (state, instr);
                  /* Writes to R15 are UNPREDICATABLE.  */
-                 if (DESTReg == 15 || LHSReg == 15)
+                 else if (DESTReg == 15 || LHSReg == 15)
                    ARMul_UndefInstr (state, instr);
                  /* Is access to the coprocessor allowed ?  */
                  else if (! CP_ACCESS_ALLOWED (state, CPNum))
@@ -3794,8 +4569,10 @@ check_PMUintr:
            case 0xee:
              if (BIT (4))
                {
+                 if (CPNum == 10 || CPNum == 11)
+                   handle_VFP_move (state, instr);
                  /* MCR.  */
-                 if (DESTReg == 15)
+                 else if (DESTReg == 15)
                    {
                      UNDEF_MCRPC;
 #ifdef MODE32
@@ -3825,17 +4602,69 @@ check_PMUintr:
            case 0xef:
              if (BIT (4))
                {
-                 /* MRC */
-                 temp = ARMul_MRC (state, instr);
-                 if (DESTReg == 15)
+                 if (CPNum == 10 || CPNum == 11)
                    {
-                     ASSIGNN ((temp & NBIT) != 0);
-                     ASSIGNZ ((temp & ZBIT) != 0);
-                     ASSIGNC ((temp & CBIT) != 0);
-                     ASSIGNV ((temp & VBIT) != 0);
+                     switch (BITS (20, 27))
+                       {
+                       case 0xEF:
+                         if (BITS (16, 19) == 0x1
+                             && BITS (0, 11) == 0xA10)
+                           {
+                             /* VMRS  */
+                             if (DESTReg == 15)
+                               {
+                                 ARMul_SetCPSR (state, (state->FPSCR & 0xF0000000)
+                                                | (ARMul_GetCPSR (state) & 0x0FFFFFFF));
+
+                                 if (trace)
+                                   fprintf (stderr, " VFP: VMRS: set flags to %c%c%c%c\n",
+                                            ARMul_GetCPSR (state) & NBIT ? 'N' : '-',
+                                            ARMul_GetCPSR (state) & ZBIT ? 'Z' : '-',
+                                            ARMul_GetCPSR (state) & CBIT ? 'C' : '-',
+                                            ARMul_GetCPSR (state) & VBIT ? 'V' : '-');
+                               }
+                             else
+                               {
+                                 state->Reg[DESTReg] = state->FPSCR;
+
+                                 if (trace)
+                                   fprintf (stderr, " VFP: VMRS: r%d = %x\n", DESTReg, state->Reg[DESTReg]);
+                               }
+                           }
+                         else
+                           fprintf (stderr, "SIM: VFP: Unimplemented: Compare op\n");
+                         break;
+
+                       case 0xE0:
+                       case 0xE1:
+                         /* VMOV reg <-> single precision.  */
+                         if (BITS (0,6) != 0x10 || BITS (8,11) != 0xA)
+                           fprintf (stderr, "SIM: VFP: Unimplemented: move op\n");
+                         else if (BIT (20))
+                           state->Reg[BITS (12, 15)] = VFP_uword (BITS (16, 19) << 1 | BIT (7));
+                         else
+                           VFP_uword (BITS (16, 19) << 1 | BIT (7)) = state->Reg[BITS (12, 15)];
+                         break;
+
+                       default:
+                         fprintf (stderr, "SIM: VFP: Unimplemented: CDP op\n");
+                         break;
+                       }
                    }
                  else
-                   DEST = temp;
+                   {
+                     /* MRC */
+                     temp = ARMul_MRC (state, instr);
+                     if (DESTReg == 15)
+                       {
+                         ASSIGNN ((temp & NBIT) != 0);
+                         ASSIGNZ ((temp & ZBIT) != 0);
+                         ASSIGNC ((temp & CBIT) != 0);
+                         ASSIGNV ((temp & VBIT) != 0);
+                       }
+                     else
+                       DEST = temp;
+                   }
                }
              else
                /* CDP Part 2.  */
@@ -3879,14 +4708,6 @@ check_PMUintr:
     donext:
 #endif
 
-#ifdef NEED_UI_LOOP_HOOK
-      if (deprecated_ui_loop_hook != NULL && ui_loop_hook_counter-- < 0)
-       {
-         ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL;
-         deprecated_ui_loop_hook (0);
-       }
-#endif /* NEED_UI_LOOP_HOOK */
-
       if (state->Emulate == ONCE)
        state->Emulate = STOP;
       /* If we have changed mode, allow the PC to advance before stopping.  */
@@ -4410,7 +5231,7 @@ Handle_Load_Double (ARMul_State * state, ARMword instr)
   ARMword addr_reg;
   ARMword write_back  = BIT (21);
   ARMword immediate   = BIT (22);
-  ARMword add_to_base = BIT (23);        
+  ARMword add_to_base = BIT (23);
   ARMword pre_indexed = BIT (24);
   ARMword offset;
   ARMword addr;
@@ -4418,7 +5239,7 @@ Handle_Load_Double (ARMul_State * state, ARMword instr)
   ARMword base;
   ARMword value1;
   ARMword value2;
-  
+
   BUSUSEDINCPCS;
 
   /* If the writeback bit is set, the pre-index bit must be clear.  */
@@ -4427,13 +5248,13 @@ Handle_Load_Double (ARMul_State * state, ARMword instr)
       ARMul_UndefInstr (state, instr);
       return;
     }
-  
+
   /* Extract the base address register.  */
   addr_reg = LHSReg;
-  
+
   /* Extract the destination register and check it.  */
   dest_reg = DESTReg;
-  
+
   /* Destination register must be even.  */
   if ((dest_reg & 1)
     /* Destination register cannot be LR.  */
@@ -4454,15 +5275,18 @@ Handle_Load_Double (ARMul_State * state, ARMword instr)
     sum = base + offset;
   else
     sum = base - offset;
-  
+
   /* If this is a pre-indexed mode use the sum.  */
   if (pre_indexed)
     addr = sum;
   else
     addr = base;
 
+  if (state->is_v6 && (addr & 0x3) == 0)
+    /* Word alignment is enough for v6.  */
+    ;
   /* The address must be aligned on a 8 byte boundary.  */
-  if (addr & 0x7)
+  else if (addr & 0x7)
     {
 #ifdef ABORTS
       ARMul_DATAABORT (addr);
@@ -4493,17 +5317,17 @@ Handle_Load_Double (ARMul_State * state, ARMword instr)
       TAKEABORT;
       return;
     }
-  
+
   ARMul_Icycles (state, 2, 0L);
 
   /* Store the values.  */
   state->Reg[dest_reg] = value1;
   state->Reg[dest_reg + 1] = value2;
-  
+
   /* Do the post addressing and writeback.  */
   if (! pre_indexed)
     addr = sum;
-  
+
   if (! pre_indexed || write_back)
     state->Reg[addr_reg] = addr;
 }
@@ -4517,7 +5341,7 @@ Handle_Store_Double (ARMul_State * state, ARMword instr)
   ARMword addr_reg;
   ARMword write_back  = BIT (21);
   ARMword immediate   = BIT (22);
-  ARMword add_to_base = BIT (23);        
+  ARMword add_to_base = BIT (23);
   ARMword pre_indexed = BIT (24);
   ARMword offset;
   ARMword addr;
@@ -4532,20 +5356,20 @@ Handle_Store_Double (ARMul_State * state, ARMword instr)
       ARMul_UndefInstr (state, instr);
       return;
     }
-  
+
   /* Extract the base address register.  */
   addr_reg = LHSReg;
-  
+
   /* Base register cannot be PC.  */
   if (addr_reg == 15)
     {
       ARMul_UndefInstr (state, instr);
       return;
     }
-  
+
   /* Extract the source register.  */
   src_reg = DESTReg;
-  
+
   /* Source register must be even.  */
   if (src_reg & 1)
     {
@@ -4564,7 +5388,7 @@ Handle_Store_Double (ARMul_State * state, ARMword instr)
     sum = base + offset;
   else
     sum = base - offset;
-  
+
   /* If this is a pre-indexed mode use the sum.  */
   if (pre_indexed)
     addr = sum;
@@ -4596,17 +5420,17 @@ Handle_Store_Double (ARMul_State * state, ARMword instr)
   /* Load the words.  */
   ARMul_StoreWordN (state, addr, state->Reg[src_reg]);
   ARMul_StoreWordN (state, addr + 4, state->Reg[src_reg + 1]);
-  
+
   if (state->Aborted)
     {
       TAKEABORT;
       return;
     }
-  
+
   /* Do the post addressing and writeback.  */
   if (! pre_indexed)
     addr = sum;
-  
+
   if (! pre_indexed || write_back)
     state->Reg[addr_reg] = addr;
 }
@@ -5003,7 +5827,7 @@ StoreSMult (ARMul_State * state,
 
   for (temp = 0; !BIT (temp); temp++)
     ;  /* N cycle first.  */
-  
+
 #ifdef MODE32
   ARMul_StoreWordN (state, address, state->Reg[temp++]);
 #else
@@ -5109,9 +5933,7 @@ Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc)
       && nRdLo != 15
       && nRs   != 15
       && nRm   != 15
-      && nRdHi != nRdLo
-      && nRdHi != nRm
-      && nRdLo != nRm)
+      && nRdHi != nRdLo)
     {
       /* Intermediate results.  */
       ARMword lo, mid1, mid2, hi;
@@ -5119,6 +5941,15 @@ Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc)
       ARMword Rs = state->Reg[nRs];
       int sign = 0;
 
+#ifdef MODE32
+      if (state->is_v6)
+       ;
+      else
+#endif
+       /* BAD code can trigger this result.  So only complain if debugging.  */
+       if (state->Debug && (nRdHi == nRm || nRdLo == nRm))
+         fprintf (stderr, "sim: MULTIPLY64 - INVALID ARGUMENTS: %d %d %d\n",
+                  nRdHi, nRdLo, nRm);
       if (msigned)
        {
          /* Compute sign of result and adjust operands if necessary.  */
@@ -5163,7 +5994,7 @@ Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc)
       state->Reg[nRdLo] = RdLo;
       state->Reg[nRdHi] = RdHi;
     }
-  else
+  else if (state->Debug)
     fprintf (stderr, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
 
   if (scc)
This page took 0.039906 seconds and 4 git commands to generate.