aboutsummaryrefslogtreecommitdiff
path: root/sim
diff options
context:
space:
mode:
authorDavid McQuillan <dmcq@tao-group.com>2014-03-14 14:03:29 +0000
committerNick Clifton <nickc@redhat.com>2014-03-14 14:03:29 +0000
commitb9366cf3955d81e26537ea1932b183dbdf237361 (patch)
tree1f4e10e5525d8bd983a29f4f920b85620218bf30 /sim
parente5b98723a5f36c5bc32d465deefd20c334627f5a (diff)
downloadfsf-binutils-gdb-b9366cf3955d81e26537ea1932b183dbdf237361.zip
fsf-binutils-gdb-b9366cf3955d81e26537ea1932b183dbdf237361.tar.gz
fsf-binutils-gdb-b9366cf3955d81e26537ea1932b183dbdf237361.tar.bz2
Prevent writes to R15 via LDR or LDM from changing the ARM/Thumb state in pre-v5 architectures.
PR sim/8388 * armemu.c (WriteR15Load): New function. Determines if the state can be changed upon a write to R15. (LoadMult): Use WriteR15Load. * armemu.h (WRITEDESTB): Use WriteR15Load.
Diffstat (limited to 'sim')
-rw-r--r--sim/arm/ChangeLog8
-rw-r--r--sim/arm/armemu.c16
-rw-r--r--sim/arm/armemu.h2
3 files changed, 23 insertions, 3 deletions
diff --git a/sim/arm/ChangeLog b/sim/arm/ChangeLog
index 9910633..fe236cb 100644
--- a/sim/arm/ChangeLog
+++ b/sim/arm/ChangeLog
@@ -1,3 +1,11 @@
+2014-03-14 David McQuillan <dmcq@tao-group.com>
+
+ PR sim/8388
+ * armemu.c (WriteR15Load): New function. Determines if the state
+ can be changed upon a write to R15.
+ (LoadMult): Use WriteR15Load.
+ * armemu.h (WRITEDESTB): Use WriteR15Load.
+
2014-03-10 Mike Frysinger <vapier@gentoo.org>
* wrapper.c (sim_do_command): Add const to cmd.
diff --git a/sim/arm/armemu.c b/sim/arm/armemu.c
index 20a36bc..64c0146 100644
--- a/sim/arm/armemu.c
+++ b/sim/arm/armemu.c
@@ -1,7 +1,7 @@
/* armemu.c -- Main instruction emulation: ARM7 Instruction Emulator.
Copyright (C) 1994 Advanced RISC Machines Ltd.
Modifications to add arch. v4 support by <jsmith@cygnus.com>.
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
@@ -25,6 +25,7 @@ static ARMword GetDPSRegRHS (ARMul_State *, ARMword);
static void WriteR15 (ARMul_State *, ARMword);
static void WriteSR15 (ARMul_State *, ARMword);
static void WriteR15Branch (ARMul_State *, ARMword);
+static void WriteR15Load (ARMul_State *, ARMword);
static ARMword GetLSRegRHS (ARMul_State *, ARMword);
static ARMword GetLS7RHS (ARMul_State *, ARMword);
static unsigned LoadWord (ARMul_State *, ARMword, ARMword);
@@ -4212,6 +4213,17 @@ WriteR15Branch (ARMul_State * state, ARMword src)
#endif
}
+/* Before ARM_v5 LDR and LDM of pc did not change mode. */
+
+static void
+WriteR15Load (ARMul_State * state, ARMword src)
+{
+ if (state->is_v5)
+ WriteR15Branch (state, src);
+ else
+ WriteR15 (state, src);
+}
+
/* This routine evaluates most Load and Store register RHS's. It is
intended to be called from the macro LSRegRHS, which filters the
common case of an unshifted register with in line code. */
@@ -4724,7 +4736,7 @@ LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase)
if (BIT (15) && !state->Aborted)
/* PC is in the reg list. */
- WriteR15Branch (state, PC);
+ WriteR15Load (state, PC);
/* To write back the final register. */
ARMul_Icycles (state, 1, 0L);
diff --git a/sim/arm/armemu.h b/sim/arm/armemu.h
index 71bee27..d61c85a 100644
--- a/sim/arm/armemu.h
+++ b/sim/arm/armemu.h
@@ -402,7 +402,7 @@ extern ARMword isize;
do \
{ \
if (DESTReg == 15) \
- WriteR15Branch (state, d); \
+ WriteR15Load (state, d); \
else \
DEST = d; \
} \