|
From: | Paolo Bonzini |
Subject: | Re: [Qemu-devel] [PATCH v2 4/8] linux-user: arm: handle CPSR.E correctly in strex emulation |
Date: | Fri, 30 May 2014 08:52:13 +0200 |
User-agent: | Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.5.0 |
Il 29/05/2014 22:21, Peter Maydell ha scritto:
On 29 May 2014 20:46, Paolo Bonzini <address@hidden> wrote: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 bswap_code to CPSR.E (we do not have the luxury of using TCGMemOps). Signed-off-by: Paolo Bonzini <address@hidden> --- linux-user/main.c | 50 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/linux-user/main.c b/linux-user/main.c index 8eb910a..b129a2b 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -449,6 +449,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 && (env)->bswap_code != !!((env)->uncached_cpsr & CPSR_E)) { \ + (x) = bswap32(x); \ + } \ + __r; \ + })This looks bogus. bswap_code doesn't have anything to do with whether data should be byteswapped. Consider the ARMv5 big-endian code, which qemu-armeb also supports: there both code and data are big-endian, and bswap_code is false. bswap_code should only be consulted for iside accesses.
This is correct. It is not very intuitive, but a XOR does exactly what we want.
For v3 I'll wrap it into an inline function like this: /* get_user and put_user respectivaly return and expect data according * to TARGET_WORDS_BIGENDIAN, but ldrex/strex emulation needs to take * into account CPSR.E too. It turns out that a XOR gives exactly the * required result: * * TARGET_WORDS_BIGENDIAN bswap_code CPSR.E need swap? * LE/LE no 0 0 no * LE/BE no 0 1 yes * BE8/LE yes 1 0 yes * BE8/BE yes 1 1 no * BE32/BE yes 0 0 no */ static inline bool swap_get_put_user(CPUARMState *env) { return env->bswap_code ^ !!(env->uncached_cpsr & CPSR_E); }The reason is that bswap_code is about more than just code endianness, it affects get_user as well. It more generally means "is the endianness given by TARGET_WORDS_BIGENDIAN the opposite of what we get at CPSR.E=0?", and it affects the setting of CPSR.E=1 in the signal handlers, as you pointed out in the review of patch 2. I'll prepend a patch that renames bswap_code to be8_user, since in the end BE8 binaries on qemu-armeb are the only case where it is true.
Instead, BE32 is handled incorrectly for TCG-generated accesses. I'll fix it for v3.
Paolo
[Prev in Thread] | Current Thread | [Next in Thread] |