(handle_v6_thumb_insn): New function.
authorNick Clifton <nickc@redhat.com>
Tue, 24 May 2005 15:30:38 +0000 (15:30 +0000)
committerNick Clifton <nickc@redhat.com>
Tue, 24 May 2005 15:30:38 +0000 (15:30 +0000)
(ARMul_ThumbDecode): Call handle_v6_thumb_insn() when an undefined instruction
  binary is encountered.

sim/arm/ChangeLog
sim/arm/thumbemu.c

index 1402584609bb2d9858d1d780e2f014fd6c08d253..e79141698aab065c7ad3d230121c7aea36031b79 100644 (file)
@@ -1,3 +1,9 @@
+2005-05-24  Nick Clifton  <nickc@redhat.com>
+
+       * thumbemu.c (handle_v6_thumb_insn): New function.
+       (ARMul_ThumbDecode): Call handle_v6_thumb_insn() when an undefined
+       instruction binary is encountered.
+
 2005-05-12  Nick Clifton  <nickc@redhat.com>
 
        * Update the address and phone number of the FSF organization in
index 0aa0f61fed08b88d5051dc5a810d2feea70dbc16..8707ca71a64b09a498750b5717d3ba551d7d9dc1 100644 (file)
@@ -31,20 +31,74 @@ existing ARM simulator.  */
 #include "armemu.h"
 #include "armos.h"
 
+/* Attempt to emulate an ARMv6 instruction.
+   Stores t_branch into PVALUE upon success or t_undefined otherwise.  */
+
+static void
+handle_v6_thumb_insn (ARMul_State * state,
+                     ARMword       tinstr,
+                     tdstate *     pvalid)
+{
+  ARMword Rd;
+  ARMword Rm;
+
+  if (! state->is_v6)
+    {
+      * pvalid = t_undefined;
+      return;
+    }
+
+  switch (tinstr & 0xFFC0)
+    {
+    case 0xb660: /* cpsie */
+    case 0xb670: /* cpsid */
+    case 0x4600: /* cpy */
+    case 0xba00: /* rev */
+    case 0xba40: /* rev16 */
+    case 0xbac0: /* revsh */
+    case 0xb650: /* setend */
+    default:  
+      printf ("Unhandled v6 thumb insn: %04x\n", tinstr);
+      * pvalid = t_undefined;
+      return;
+
+    case 0xb200: /* sxth */
+      Rm = state->Reg [(tinstr & 0x38) >> 3];
+      if (Rm & 0x8000)
+       state->Reg [(tinstr & 0x7)] = (Rm & 0xffff) | 0xffff0000;
+      else
+       state->Reg [(tinstr & 0x7)] = Rm & 0xffff;
+      break;
+    case 0xb240: /* sxtb */
+      Rm = state->Reg [(tinstr & 0x38) >> 3];
+      if (Rm & 0x80)
+       state->Reg [(tinstr & 0x7)] = (Rm & 0xff) | 0xffffff00;
+      else
+       state->Reg [(tinstr & 0x7)] = Rm & 0xff;
+      break;
+    case 0xb280: /* uxth */
+      Rm = state->Reg [(tinstr & 0x38) >> 3];
+      state->Reg [(tinstr & 0x7)] = Rm & 0xffff;
+      break;
+    case 0xb2c0: /* uxtb */
+      Rm = state->Reg [(tinstr & 0x38) >> 3];
+      state->Reg [(tinstr & 0x7)] = Rm & 0xff;
+      break;
+    }
+  /* Indicate that the instruction has been processed.  */
+  * pvalid = t_branch;
+}
+
 /* Decode a 16bit Thumb instruction.  The instruction is in the low
    16-bits of the tinstr field, with the following Thumb instruction
    held in the high 16-bits.  Passing in two Thumb instructions allows
    easier simulation of the special dual BL instruction.  */
 
-tdstate ARMul_ThumbDecode (state, pc, tinstr, ainstr)
-     ARMul_State *
-       state;
-     ARMword
-       pc;
-     ARMword
-       tinstr;
-     ARMword *
-       ainstr;
+tdstate
+ARMul_ThumbDecode (ARMul_State * state,
+                  ARMword       pc,
+                  ARMword       tinstr,
+                  ARMword *     ainstr)
 {
   tdstate valid = t_decoded;   /* default assumes a valid instruction */
   ARMword next_instr;
@@ -222,7 +276,7 @@ tdstate ARMul_ThumbDecode (state, pc, tinstr, ainstr)
            case 0x0:           /* UNDEFINED */
            case 0x4:           /* UNDEFINED */
            case 0x8:           /* UNDEFINED */
-             valid = t_undefined;
+             handle_v6_thumb_insn (state, tinstr, & valid);
              break;
            }
        }
@@ -370,7 +424,7 @@ tdstate ARMul_ThumbDecode (state, pc, tinstr, ainstr)
          /* Drop through.  */
        default:
          /* Everything else is an undefined instruction.  */
-         valid = t_undefined;
+         handle_v6_thumb_insn (state, tinstr, & valid);
          break;
        }
       break;
@@ -460,8 +514,9 @@ tdstate ARMul_ThumbDecode (state, pc, tinstr, ainstr)
            }
          valid = t_branch;
        }
-      else                     /* UNDEFINED : cc=1110(AL) uses different format */
-       valid = t_undefined;
+      else
+       /* UNDEFINED : cc=1110(AL) uses different format.  */
+       handle_v6_thumb_insn (state, tinstr, & valid);
       break;
     case 28:                   /* B */
       /* Format 18 */
@@ -476,7 +531,7 @@ tdstate ARMul_ThumbDecode (state, pc, tinstr, ainstr)
        {
          if (tinstr & 1)
            {
-             valid = t_undefined;
+             handle_v6_thumb_insn (state, tinstr, & valid);
              break;
            }
          /* Drop through.  */
@@ -499,8 +554,10 @@ tdstate ARMul_ThumbDecode (state, pc, tinstr, ainstr)
            break;
          }
        }
-      valid = t_undefined;
+
+      handle_v6_thumb_insn (state, tinstr, & valid);
       break;
+
     case 30:                   /* BL instruction 1 */
       /* Format 19 */
       /* There is no single ARM instruction equivalent for this Thumb