summaryrefslogtreecommitdiffstats
path: root/linux-user
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2016-03-04 11:30:19 +0000
committerTimothy Pearson <tpearson@raptorengineering.com>2019-11-29 19:49:12 -0600
commitb0eb8f684731a7811a7db4a48dcd36b4c7125292 (patch)
tree7cd7506fecc8bef43dab96713bf7efc7913426ae /linux-user
parent919beba0a8322834d9b8c79de617e5ed0c872d64 (diff)
downloadhqemu-b0eb8f684731a7811a7db4a48dcd36b4c7125292.zip
hqemu-b0eb8f684731a7811a7db4a48dcd36b4c7125292.tar.gz
linux-user: arm: handle CPSR.E correctly in strex emulation
Now that CPSR.E is set correctly, prepare for when setend will be able to change it; bswap data in and out of strex manually by comparing SCTLR.B, CPSR.E and TARGET_WORDS_BIGENDIAN (we do not have the luxury of using TCGMemOps). Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> [ PC changes: * Moved SCTLR/CPSR logic to arm_cpu_data_is_big_endian ] Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/main.c50
1 files changed, 43 insertions, 7 deletions
diff --git a/linux-user/main.c b/linux-user/main.c
index 8827d27..6581344 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -461,6 +461,38 @@ void cpu_loop(CPUX86State *env)
__r; \
})
+#define get_user_data_u32(x, gaddr, env) \
+ ({ abi_long __r = get_user_u32((x), (gaddr)); \
+ if (!__r && arm_cpu_bswap_data(env)) { \
+ (x) = bswap32(x); \
+ } \
+ __r; \
+ })
+
+#define get_user_data_u16(x, gaddr, env) \
+ ({ abi_long __r = get_user_u16((x), (gaddr)); \
+ if (!__r && arm_cpu_bswap_data(env)) { \
+ (x) = bswap16(x); \
+ } \
+ __r; \
+ })
+
+#define put_user_data_u32(x, gaddr, env) \
+ ({ typeof(x) __x = (x); \
+ if (arm_cpu_bswap_data(env)) { \
+ __x = bswap32(__x); \
+ } \
+ put_user_u32(__x, (gaddr)); \
+ })
+
+#define put_user_data_u16(x, gaddr, env) \
+ ({ typeof(x) __x = (x); \
+ if (arm_cpu_bswap_data(env)) { \
+ __x = bswap16(__x); \
+ } \
+ put_user_u16(__x, (gaddr)); \
+ })
+
#ifdef TARGET_ABI32
/* Commpage handling -- there is no commpage for AArch64 */
@@ -620,11 +652,11 @@ static int do_strex(CPUARMState *env)
segv = get_user_u8(val, addr);
break;
case 1:
- segv = get_user_u16(val, addr);
+ segv = get_user_data_u16(val, addr, env);
break;
case 2:
case 3:
- segv = get_user_u32(val, addr);
+ segv = get_user_data_u32(val, addr, env);
break;
default:
abort();
@@ -635,12 +667,16 @@ static int do_strex(CPUARMState *env)
}
if (size == 3) {
uint32_t valhi;
- segv = get_user_u32(valhi, addr + 4);
+ segv = get_user_data_u32(valhi, addr + 4, env);
if (segv) {
env->exception.vaddress = addr + 4;
goto done;
}
- val = deposit64(val, 32, 32, valhi);
+ if (arm_cpu_bswap_data(env)) {
+ val = deposit64((uint64_t)valhi, 32, 32, val);
+ } else {
+ val = deposit64(val, 32, 32, valhi);
+ }
}
if (val != env->exclusive_val) {
goto fail;
@@ -652,11 +688,11 @@ static int do_strex(CPUARMState *env)
segv = put_user_u8(val, addr);
break;
case 1:
- segv = put_user_u16(val, addr);
+ segv = put_user_data_u16(val, addr, env);
break;
case 2:
case 3:
- segv = put_user_u32(val, addr);
+ segv = put_user_data_u32(val, addr, env);
break;
}
if (segv) {
@@ -665,7 +701,7 @@ static int do_strex(CPUARMState *env)
}
if (size == 3) {
val = env->regs[(env->exclusive_info >> 12) & 0xf];
- segv = put_user_u32(val, addr + 4);
+ segv = put_user_data_u32(val, addr + 4, env);
if (segv) {
env->exception.vaddress = addr + 4;
goto done;
OpenPOWER on IntegriCloud