Add support for the SDIV and UDIV instructions to the ARM simulator.
authorJens Bauer <jens@plustv.dk>
Tue, 15 Dec 2020 12:40:35 +0000 (12:40 +0000)
committerNick Clifton <nickc@redhat.com>
Tue, 15 Dec 2020 12:40:35 +0000 (12:40 +0000)
* armemu.c (handle_v6_insn): Add support for SDIV and UDIV.
* thumbemu.c (handle_T2_insn): Likewise.

sim/arm/ChangeLog
sim/arm/armemu.c
sim/arm/thumbemu.c
sim/arm/wrapper.c

index 92dfabadad08e621521b6e4494cf800c22a24f8d..64171d65c0de572a1555fb9ce25b51b950b6b774 100644 (file)
@@ -1,3 +1,12 @@
+2020-12-15  Nick Clifton  <nickc@redhat.com>
+
+       * wrapper.c (sim_create_inferior): Accept some more ARM machine numbers.
+
+2020-12-15  Jens Bauer <jens@plustv.dk>
+
+       * armemu.c (handle_v6_insn): Add support for SDIV and UDIV.
+       * thumbemu.c (handle_T2_insn): Likewise.
+
 2020-10-20  Dr. David Alan Gilbert  <dgilbert@redhat.com>
 
        * armos.c (SWIread): Fix printf format.
index 3a72277683e62b40f367e50e29815e98cd9d4891..922c2e498db9c3b52b048a00debd9708b85e92fe 100644 (file)
@@ -915,6 +915,68 @@ handle_v6_insn (ARMul_State * state, ARMword instr)
       }
       return 1;
 
+    case 0x71:
+    case 0x73:
+      {
+       ARMword valn, valm;
+       /* SDIV<c> <Rd>,<Rn>,<Rm>
+          UDIV<c> <Rd>,<Rn>,<Rm>
+          instr[31,28] = cond
+          instr[27,20] = 0111 0001 (SDIV), 0111 0011 (UDIV)
+          instr[21,21] = sign
+          instr[19,16] = Rn
+          instr[15,12] = 1111
+          instr[11, 8] = Rd
+          instr[ 7, 4] = 1111
+          instr[ 3, 0] = Rm    */
+       /* These bit-positions are confusing!
+           instr[15,12] = Rd
+          instr[11, 8] = 1111  */
+
+#if 0  /* This is what I would expect:  */
+       Rn = BITS (16, 19);
+       Rd = BITS (8, 11);
+       Rm = BITS (0, 3);
+#else  /* This seem to work:  */
+       Rd = BITS (16, 19);
+       Rm = BITS (8, 11);
+       Rn = BITS (0, 3);
+#endif
+       if (Rn == 15 || Rd == 15 || Rm == 15
+           || Rn == 13 || Rd == 13 || Rm == 13)
+         {
+           ARMul_UndefInstr (state, instr);
+           state->Emulate = FALSE;
+           break;
+         }
+
+       valn = state->Reg[Rn];
+       valm = state->Reg[Rm];
+
+       if (valm == 0)
+         {
+#if 0  
+           /* Exceptions: UsageFault, address 20
+              Note: UsageFault is for Cortex-M; I don't know what it would be on non-Cortex-M.  */
+           ARMul_Abort (state, address);
+#endif
+           printf ("Unhandled v6 insn: %cDIV divide by zero exception\n", "SU"[BIT(21)]);
+         }
+       else
+         {
+           if(BIT(21))
+             {
+               val = valn / valm;
+             }
+           else
+             {
+               val = ((ARMsword)valn / (ARMsword)valm);
+             }
+           state->Reg[Rd] = val;
+         }
+       return 1;
+      }
+
     case 0x7c:
     case 0x7d:
       {
@@ -963,7 +1025,6 @@ handle_v6_insn (ARMul_State * state, ARMword instr)
          }
        return 1;
       }
-
     case 0x7b:
     case 0x7a: /* SBFX<c> <Rd>,<Rn>,#<lsb>,#<width>.  */
       {
index 72929c76b524803eadb49493f3875d4b1404218a..fa70d5bfcfbf994f48a7953b5a979c2204df68a0 100644 (file)
@@ -1759,26 +1759,60 @@ handle_T2_insn (ARMul_State * state,
        break;
       }
 
-    case 0xDC: // SMULL
-      tASSERT (tBIT (4) == 0);
-      tASSERT (ntBITS (4, 7) == 0);
-      * ainstr = 0xE0C00090;
-      * ainstr |= (ntBITS (8, 11) << 16); // RdHi
-      * ainstr |= (ntBITS (12, 15) << 12); // RdLo
-      * ainstr |= (ntBITS (0, 3) << 8); // Rm
-      * ainstr |= tBITS (0, 3); // Rn
-      * pvalid = t_decoded;
+    case 0xDC:
+      if (tBIT (4) == 0 && ntBITS (4, 7) == 0)
+       {
+         // SMULL
+         * ainstr = 0xE0C00090;
+         * ainstr |= (ntBITS (8, 11) << 16); // RdHi
+         * ainstr |= (ntBITS (12, 15) << 12); // RdLo
+         * ainstr |= (ntBITS (0, 3) << 8); // Rm
+         * ainstr |= tBITS (0, 3); // Rn
+         * pvalid = t_decoded;
+       }
+      else if (tBIT (4) == 1 && ntBITS (4, 7) == 0xF)
+       {
+         // SDIV
+         * ainstr = 0xE710F010;
+         * ainstr |= (ntBITS (8, 11) << 16); // Rd
+         * ainstr |= (ntBITS (0, 3) << 8);   // Rm
+         * ainstr |= tBITS (0, 3); // Rn
+         * pvalid = t_decoded;
+       }
+      else
+       {
+         fprintf (stderr, "(op = %x) ", tBITS (5,12));
+         tASSERT (0);
+         return;
+       }
       break;
 
-    case 0xDD: // UMULL
-      tASSERT (tBIT (4) == 0);
-      tASSERT (ntBITS (4, 7) == 0);
-      * ainstr = 0xE0800090;
-      * ainstr |= (ntBITS (8, 11) << 16); // RdHi
-      * ainstr |= (ntBITS (12, 15) << 12); // RdLo
-      * ainstr |= (ntBITS (0, 3) << 8); // Rm
-      * ainstr |= tBITS (0, 3); // Rn
-      * pvalid = t_decoded;
+    case 0xDD:
+      if (tBIT (4) == 0 && ntBITS (4, 7) == 0)
+       {
+         // UMULL
+         * ainstr = 0xE0800090;
+         * ainstr |= (ntBITS (8, 11) << 16); // RdHi
+         * ainstr |= (ntBITS (12, 15) << 12); // RdLo
+         * ainstr |= (ntBITS (0, 3) << 8); // Rm
+         * ainstr |= tBITS (0, 3); // Rn
+         * pvalid = t_decoded;
+       }
+      else if (tBIT (4) == 1 && ntBITS (4, 7) == 0xF)
+       {
+         // UDIV
+         * ainstr = 0xE730F010;
+         * ainstr |= (ntBITS (8, 11) << 16); // Rd
+         * ainstr |= (ntBITS (0, 3) << 8);   // Rm
+         * ainstr |= tBITS (0, 3); // Rn
+         * pvalid = t_decoded;
+       }
+      else
+       {
+         fprintf (stderr, "(op = %x) ", tBITS (5,12));
+         tASSERT (0);
+         return;
+       }
       break;
 
     case 0xDF: // UMLAL
@@ -1896,6 +1930,7 @@ handle_v6_thumb_insn (ARMul_State * state,
     case 0xEB80: // SUB
     case 0xEBC0: // RSB
     case 0xFA80: // UADD, SEL
+    case 0xFBC0: // UMULL, SMULL, SDIV, UDIV
       handle_T2_insn (state, tinstr, next_instr, pc, ainstr, pvalid);
       return;
 
index 68f8242288f19dd4170e2160140c69b88d429353..cc18498151223369eb3eeeeaa6e518497972dba2 100644 (file)
@@ -241,6 +241,14 @@ sim_create_inferior (SIM_DESC sd ATTRIBUTE_UNUSED,
       ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop | ARM_v6_Prop);
       break;
 
+#if 1
+    case bfd_mach_arm_6T2:
+    case bfd_mach_arm_7:
+    case bfd_mach_arm_7EM:
+      ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop | ARM_v6_Prop);
+      break;
+#endif
+
     case bfd_mach_arm_XScale:
       ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop | ARM_XScale_Prop | ARM_v6_Prop);
       break;