aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sim/arm/ChangeLog8
-rw-r--r--sim/arm/armemu.c72
-rw-r--r--sim/arm/armemu.h5
3 files changed, 48 insertions, 37 deletions
diff --git a/sim/arm/ChangeLog b/sim/arm/ChangeLog
index 1b3a557..526b49d 100644
--- a/sim/arm/ChangeLog
+++ b/sim/arm/ChangeLog
@@ -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.
diff --git a/sim/arm/armemu.c b/sim/arm/armemu.c
index 373ec72..2fc0eda 100644
--- a/sim/arm/armemu.c
+++ b/sim/arm/armemu.c
@@ -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 */
diff --git a/sim/arm/armemu.h b/sim/arm/armemu.h
index da7fb2b..ad89294 100644
--- a/sim/arm/armemu.h
+++ b/sim/arm/armemu.h
@@ -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) | \