[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v2 07/18] linux-user: arm: handle CPSR.E correctly i
From: |
Peter Crosthwaite |
Subject: |
[Qemu-devel] [PATCH v2 07/18] linux-user: arm: handle CPSR.E correctly in strex emulation |
Date: |
Tue, 1 Mar 2016 22:56:11 -0800 |
From: Paolo Bonzini <address@hidden>
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 <address@hidden>
[ PC changes:
* Moved SCTLR/CPSR logic to arm_cpu_data_is_big_endian
]
Signed-off-by: Peter Crosthwaite <address@hidden>
---
Changed since v1:
Removed SCTLR logic from bwap_data()
linux-user/main.c | 50 +++++++++++++++++++++++++++++++++++++++++++-------
target-arm/cpu.h | 11 +++++++++++
2 files changed, 54 insertions(+), 7 deletions(-)
diff --git a/linux-user/main.c b/linux-user/main.c
index 510b3b7..2b1e755 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -451,6 +451,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 */
@@ -610,11 +642,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();
@@ -625,12 +657,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;
@@ -642,11 +678,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) {
@@ -655,7 +691,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;
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index ab0ea92..cbf171c 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -2102,6 +2102,17 @@ static inline int fp_exception_el(CPUARMState *env)
return 0;
}
+#ifdef CONFIG_USER_ONLY
+static inline bool arm_cpu_bswap_data(CPUARMState *env)
+{
+ return
+#ifdef TARGET_WORDS_BIGENDIAN
+ 1 ^
+#endif
+ arm_cpu_data_is_big_endian(env);
+}
+#endif
+
static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
target_ulong *cs_base, int *flags)
{
--
1.9.1
- [Qemu-devel] [PATCH v2 00/18] ARM big-endian and setend support, Peter Crosthwaite, 2016/03/02
- [Qemu-devel] [PATCH v2 01/18] linux-user: arm: fix coding style for some linux-user signal functions, Peter Crosthwaite, 2016/03/02
- [Qemu-devel] [PATCH v2 02/18] linux-user: arm: pass env to get_user_code_*, Peter Crosthwaite, 2016/03/02
- [Qemu-devel] [PATCH v2 04/18] target-arm: cpu: Move cpu_is_big_endian to header, Peter Crosthwaite, 2016/03/02
- [Qemu-devel] [PATCH v2 03/18] target-arm: implement SCTLR.B, drop bswap_code, Peter Crosthwaite, 2016/03/02
- [Qemu-devel] [PATCH v2 05/18] arm: cpu: handle BE32 user-mode as BE, Peter Crosthwaite, 2016/03/02
- [Qemu-devel] [PATCH v2 06/18] linux-user: arm: set CPSR.E/SCTLR.E0E correctly for BE mode, Peter Crosthwaite, 2016/03/02
- [Qemu-devel] [PATCH v2 07/18] linux-user: arm: handle CPSR.E correctly in strex emulation,
Peter Crosthwaite <=
- [Qemu-devel] [PATCH v2 08/18] target-arm: implement SCTLR.EE, Peter Crosthwaite, 2016/03/02
- [Qemu-devel] [PATCH v2 10/18] target-arm: introduce disas flag for endianness, Peter Crosthwaite, 2016/03/02
- [Qemu-devel] [PATCH v2 09/18] target-arm: pass DisasContext to gen_aa32_ld*/st*, Peter Crosthwaite, 2016/03/02
- [Qemu-devel] [PATCH v2 11/18] target-arm: a64: Add endianness support, Peter Crosthwaite, 2016/03/02
- [Qemu-devel] [PATCH v2 12/18] target-arm: introduce tbflag for endianness, Peter Crosthwaite, 2016/03/02
- [Qemu-devel] [PATCH v2 13/18] target-arm: implement setend, Peter Crosthwaite, 2016/03/02
- [Qemu-devel] [PATCH v2 15/18] loader: add API to load elf header, Peter Crosthwaite, 2016/03/02
- [Qemu-devel] [PATCH v2 16/18] loader: load_elf(): Add doc comment, Peter Crosthwaite, 2016/03/02