[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-arm] [PATCH] target-arm: Correctly handle 'sub pc, pc, 1' for ARMv
From: |
Peter Maydell |
Subject: |
[Qemu-arm] [PATCH] target-arm: Correctly handle 'sub pc, pc, 1' for ARMv6 |
Date: |
Tue, 20 Sep 2016 15:15:41 +0100 |
In the ARM v6 architecture, 'sub pc, pc, 1' is not an interworking
branch, so the computed new value is written to r15 as a normal
value. The architecture says that in this case, bits [1:0] of
the value written must be ignored if we are in ARM mode (or
bit [0] ignored if in Thumb mode); this is a change from the
ARMv4/v5 specification that behaviour is UNPREDICTABLE.
Use the correct mask on the PC value when doing a non-interworking
store to PC.
A popular library used on RaspberryPi uses this instruction
as part of a trick to determine whether it is running on
ARMv6 or ARMv7, and we were mishandling the sequence.
Fixes bug: https://bugs.launchpad.net/bugs/1625295
Reported-by: <address@hidden>
Signed-off-by: Peter Maydell <address@hidden>
---
target-arm/translate.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 693d4bc..8df24bf 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -180,7 +180,12 @@ static inline TCGv_i32 load_reg(DisasContext *s, int reg)
static void store_reg(DisasContext *s, int reg, TCGv_i32 var)
{
if (reg == 15) {
- tcg_gen_andi_i32(var, var, ~1);
+ /* In Thumb mode, we must ignore bit 0.
+ * In ARM mode, for ARMv4 and ARMv5, it is UNPREDICTABLE if bits [1:0]
+ * are not 0b00, but for ARMv6 and above, we must ignore bits [1:0].
+ * We choose to ignore [1:0] in ARM mode for all architecture versions.
+ */
+ tcg_gen_andi_i32(var, var, s->thumb ? ~1 : ~3);
s->is_jmp = DISAS_JUMP;
}
tcg_gen_mov_i32(cpu_R[reg], var);
--
2.7.4
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-arm] [PATCH] target-arm: Correctly handle 'sub pc, pc, 1' for ARMv6,
Peter Maydell <=