* armemu.h (WRITEDESTB): New macro.
authorAlexandre Oliva <aoliva@redhat.com>
Tue, 4 Jul 2000 06:35:36 +0000 (06:35 +0000)
committerAlexandre Oliva <aoliva@redhat.com>
Tue, 4 Jul 2000 06:35:36 +0000 (06:35 +0000)
* armemu.c (ARMul_Emulate26, bl): Use WriteR15Branch() to
modify PC.  Moved the existing logic...
(WriteR15Branch): ... here.  New function.
(WriteR15, WriteSR15): Drop the two least significant bits.
(LoadSMult): Use WriteR15Branch() to modify PC.
(LoadMult): Use WRITEDESTB() instead of WRITEDEST().

sim/arm/ChangeLog
sim/arm/armemu.c
sim/arm/armemu.h

index 1b3a557bc0a3c54f28744dd5388ab052fde31021..526b49d05ef7ec1f859fed18b7936aee19e1fcbd 100644 (file)
@@ -1,5 +1,13 @@
 2000-07-04  Alexandre Oliva  <aoliva@redhat.com>
 
+       * armemu.h (WRITEDESTB): New macro.
+       * armemu.c (ARMul_Emulate26, bl): Use WriteR15Branch() to
+       modify PC.  Moved the existing logic...
+       (WriteR15Branch): ... here.  New function.
+       (WriteR15, WriteSR15): Drop the two least significant bits.
+       (LoadSMult): Use WriteR15Branch() to modify PC.
+       (LoadMult): Use WRITEDESTB() instead of WRITEDEST().
+
        * armemu.h (GETSPSR): Call ARMul_GetSPSR().
        * armsupp.c (ARMul_CPSRAltered): Zero out bits as they're
        extracted from state->Cpsr, but preserve the unused bits.
index 373ec7284733feac3e25a8b0d5d39d375661234a..2fc0eda5f573935e6b3a0b96444717ec33f9dc64 100644 (file)
@@ -24,6 +24,7 @@ static ARMword GetDPRegRHS (ARMul_State * state, ARMword instr);
 static ARMword GetDPSRegRHS (ARMul_State * state, ARMword instr);
 static void WriteR15 (ARMul_State * state, ARMword src);
 static void WriteSR15 (ARMul_State * state, ARMword src);
+static void WriteR15Branch (ARMul_State * state, ARMword src);
 static ARMword GetLSRegRHS (ARMul_State * state, ARMword instr);
 static ARMword GetLS7RHS (ARMul_State * state, ARMword instr);
 static unsigned LoadWord (ARMul_State * state, ARMword instr,
@@ -1082,35 +1083,8 @@ ARMul_Emulate26 (register ARMul_State * state)
 #ifdef MODET
              if (BITS (4, 27) == 0x12FFF1)
                {               /* BX */
-                 /* Branch to the address in RHSReg. If bit0 of
-                    destination address is 1 then switch to Thumb mode: */
-                 ARMword addr = state->Reg[RHSReg];
-
-                 /* If we read the PC then the bottom bit is clear */
-                 if (RHSReg == 15)
-                   addr &= ~1;
-
-                 /* Enable this for a helpful bit of debugging when
-                    GDB is not yet fully working... 
-                    fprintf (stderr, "BX at %x to %x (go %s)\n",
-                    state->Reg[15], addr, (addr & 1) ? "thumb": "arm" ); */
-
-                 if (addr & (1 << 0))
-                   {           /* Thumb bit */
-                     SETT;
-                     state->Reg[15] = addr & 0xfffffffe;
-                     /* NOTE: The other CPSR flag setting blocks do not
-                        seem to update the state->Cpsr state, but just do
-                        the explicit flag. The copy from the seperate
-                        flags to the register must happen later. */
-                     FLUSHPIPE;
-                   }
-                 else
-                   {
-                     CLEART;
-                     state->Reg[15] = addr & 0xfffffffc;
-                     FLUSHPIPE;
-                   }
+                 WriteR15Branch (state, state->Reg[RHSReg]);
+                 break;
                }
 #endif
              if (DESTReg == 15)
@@ -3128,11 +3102,14 @@ GetDPSRegRHS (ARMul_State * state, ARMword instr)
 static void
 WriteR15 (ARMul_State * state, ARMword src)
 {
-  /* The ARM documentation implies (but doe snot state) that the bottom bit of the PC is never set */
+  /* The ARM documentation states that the two least significant bits
+     are discarded when setting PC, except in the cases handled by
+     WriteR15Branch() below.  */
+  src &= 0xfffffffc;
 #ifdef MODE32
-  state->Reg[15] = src & PCBITS & ~0x1;
+  state->Reg[15] = src & PCBITS;
 #else
-  state->Reg[15] = (src & R15PCBITS & ~0x1) | ECC | ER15INT | EMODE;
+  state->Reg[15] = (src & R15PCBITS) | ECC | ER15INT | EMODE;
   ARMul_R15Altered (state);
 #endif
   FLUSHPIPE;
@@ -3145,6 +3122,7 @@ WriteR15 (ARMul_State * state, ARMword src)
 static void
 WriteSR15 (ARMul_State * state, ARMword src)
 {
+  src &= 0xfffffffc;
 #ifdef MODE32
   state->Reg[15] = src & PCBITS;
   if (state->Bank > 0)
@@ -3162,6 +3140,29 @@ WriteSR15 (ARMul_State * state, ARMword src)
   FLUSHPIPE;
 }
 
+/* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
+   will switch to Thumb mode if the least significant bit is set. */
+
+static void
+WriteR15Branch (ARMul_State * state, ARMword src)
+{
+#ifdef MODET
+  if (src & 1)
+    {          /* Thumb bit */
+      SETT;
+      state->Reg[15] = src & 0xfffffffe;
+    }
+  else
+    {
+      CLEART;
+      state->Reg[15] = src & 0xfffffffc;
+    }
+  FLUSHPIPE;
+#else
+  WriteR15 (state, src);
+#endif
+}
+
 /***************************************************************************\
 * This routine evaluates most Load and Store register RHS's.  It is         *
 * intended to be called from the macro LSRegRHS, which filters the          *
@@ -3249,7 +3250,7 @@ LoadWord (ARMul_State * state, ARMword instr, ARMword address)
     }
   if (address & 3)
     dest = ARMul_Align (state, address, dest);
-  WRITEDEST (dest);
+  WRITEDESTB (dest);
   ARMul_Icycles (state, 1, 0L);
 
   return (DESTReg != LHSReg);
@@ -3471,10 +3472,7 @@ LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase)
 
   if (BIT (15) && !state->Aborted)
     {                          /* PC is in the reg list */
-#ifdef MODE32
-      state->Reg[15] = PC;
-#endif
-      FLUSHPIPE;
+      WriteR15Branch(state, PC);
     }
 
   ARMul_Icycles (state, 1, 0L);        /* to write back the final register */
index da7fb2b429a008d05e6fd780728296648e72cf25..ad89294ffac020f98531b415333ad6a68006d595 100644 (file)
@@ -332,6 +332,11 @@ extern ARMword isize;
                          ARMul_NegZero(state, d) ; \
                          }
 
+#define WRITEDESTB(d) if (DESTReg == 15) \
+                        WriteR15Branch(state, d) ; \
+                     else \
+                          DEST = d
+
 #define BYTETOBUS(data) ((data & 0xff) | \
                         ((data & 0xff) << 8) | \
                         ((data & 0xff) << 16) | \