aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2011-04-20 18:22:45 +0000
committerPeter Maydell <peter.maydell@linaro.org>2011-04-20 18:22:45 +0000
commit31567416d6a126589e18885d81dc04154bea3bd3 (patch)
tree4a5cd6bcdf9c9b4e5209ad706115520915bb0c87
parentec444452b8753a372de30b22d9b4765a799db612 (diff)
target-arm: Support v6 barriers in linux-user modecp15-barriers
ARMv6 implemented various operations as special cases of cp15 accesses which are true instructions in v7; this includes barriers (DMB, DSB, ISB). Catch this special case at translate time, so that it works in linux-user mode (which doesn't provide a functional get_cp15 helper) as well as system mode. Includes minor cleanup of the existing cases, and moving the check to before the "OK in user mode?" test, since we know all these instructions are OK. Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--target-arm/translate.c30
1 files changed, 21 insertions, 9 deletions
diff --git a/target-arm/translate.c b/target-arm/translate.c
index e1bda57e81..4b695cb48e 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -2530,14 +2530,15 @@ static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
/* cdp */
return 1;
}
- if (IS_USER(s) && !cp15_user_ok(insn)) {
- return 1;
- }
- /* Pre-v7 versions of the architecture implemented WFI via coprocessor
- * instructions rather than a separate instruction.
+ /* We special case a number of cp15 instructions which were used
+ * for things which are real instructions in ARMv7. This allows
+ * them to work in linux-user mode which doesn't provide functional
+ * get_cp15/set_cp15 helpers, and is more efficient anyway.
+ * These are all OK in both user and system mode.
*/
- if ((insn & 0x0fff0fff) == 0x0e070f90) {
+ switch ((insn & 0x0fff0fff)) {
+ case 0x0e070f90:
/* 0,c7,c0,4: Standard v6 WFI (also used in some pre-v6 cores).
* In v7, this must NOP.
*/
@@ -2547,9 +2548,7 @@ static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
s->is_jmp = DISAS_WFI;
}
return 0;
- }
-
- if ((insn & 0x0fff0fff) == 0x0e070f58) {
+ case 0x0e070f58:
/* 0,c7,c8,2: Not all pre-v6 cores implemented this WFI,
* so this is slightly over-broad.
*/
@@ -2563,6 +2562,19 @@ static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
* In particular, on v7 and some v6 cores this is one of
* the VA-PA registers.
*/
+ break;
+ case 0x0e070f95: /* 0,c7,c5,4 : ISB */
+ case 0x0e070f9a: /* 0,c7,c10,4: DSB */
+ case 0x0e070fba: /* 0,c7,c10,5: DMB */
+ case 0x0e070f3d: /* 0,c7,c13,1: prefetch-by-MVA in v6, NOP in v7 */
+ if (arm_feature(env, ARM_FEATURE_V6)) {
+ return 0;
+ }
+ break;
+ }
+
+ if (IS_USER(s) && !cp15_user_ok(insn)) {
+ return 1;
}
rd = (insn >> 12) & 0xf;