From 49017bd8b4395ba380c45c2fc41f4353fc2f0f06 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 4 Mar 2016 11:30:18 +0000 Subject: linux-user: arm: pass env to get_user_code_* This matches the idiom used by get_user_data_* later in the series, and will help when bswap_code will be replaced by SCTLR.B. Reviewed-by: Peter Maydell Signed-off-by: Paolo Bonzini Signed-off-by: Peter Crosthwaite Signed-off-by: Peter Maydell --- linux-user/main.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'linux-user/main.c') diff --git a/linux-user/main.c b/linux-user/main.c index 700724effe..bcb9f66570 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -435,17 +435,17 @@ void cpu_loop(CPUX86State *env) #ifdef TARGET_ARM -#define get_user_code_u32(x, gaddr, doswap) \ +#define get_user_code_u32(x, gaddr, env) \ ({ abi_long __r = get_user_u32((x), (gaddr)); \ - if (!__r && (doswap)) { \ + if (!__r && (env)->bswap_code) { \ (x) = bswap32(x); \ } \ __r; \ }) -#define get_user_code_u16(x, gaddr, doswap) \ +#define get_user_code_u16(x, gaddr, env) \ ({ abi_long __r = get_user_u16((x), (gaddr)); \ - if (!__r && (doswap)) { \ + if (!__r && (env)->bswap_code) { \ (x) = bswap16(x); \ } \ __r; \ @@ -692,7 +692,7 @@ void cpu_loop(CPUARMState *env) /* we handle the FPU emulation here, as Linux */ /* we get the opcode */ /* FIXME - what to do if get_user() fails? */ - get_user_code_u32(opcode, env->regs[15], env->bswap_code); + get_user_code_u32(opcode, env->regs[15], env); rc = EmulateAll(opcode, &ts->fpa, env); if (rc == 0) { /* illegal instruction */ @@ -762,25 +762,23 @@ void cpu_loop(CPUARMState *env) if (trapnr == EXCP_BKPT) { if (env->thumb) { /* FIXME - what to do if get_user() fails? */ - get_user_code_u16(insn, env->regs[15], env->bswap_code); + get_user_code_u16(insn, env->regs[15], env); n = insn & 0xff; env->regs[15] += 2; } else { /* FIXME - what to do if get_user() fails? */ - get_user_code_u32(insn, env->regs[15], env->bswap_code); + get_user_code_u32(insn, env->regs[15], env); n = (insn & 0xf) | ((insn >> 4) & 0xff0); env->regs[15] += 4; } } else { if (env->thumb) { /* FIXME - what to do if get_user() fails? */ - get_user_code_u16(insn, env->regs[15] - 2, - env->bswap_code); + get_user_code_u16(insn, env->regs[15] - 2, env); n = insn & 0xff; } else { /* FIXME - what to do if get_user() fails? */ - get_user_code_u32(insn, env->regs[15] - 4, - env->bswap_code); + get_user_code_u32(insn, env->regs[15] - 4, env); n = insn & 0xffffff; } } -- cgit v1.2.3 From f9fd40ebe4f55e0048e002925b8d65e66d56e7a7 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 4 Mar 2016 11:30:19 +0000 Subject: target-arm: implement SCTLR.B, drop bswap_code bswap_code is a CPU property of sorts ("is the iside endianness the opposite way round to TARGET_WORDS_BIGENDIAN?") but it is not the actual CPU state involved here which is SCTLR.B (set for BE32 binaries, clear for BE8). Replace bswap_code with SCTLR.B, and pass that to arm_ld*_code. The next patches will make data fetches honor both SCTLR.B and CPSR.E appropriately. Signed-off-by: Paolo Bonzini [PC changes: * rebased on master (Jan 2016) * s/TARGET_USER_ONLY/CONFIG_USER_ONLY * Use bswap_code() for disas_set_info() instead of raw sctlr_b ] Signed-off-by: Peter Crosthwaite Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- linux-user/main.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'linux-user/main.c') diff --git a/linux-user/main.c b/linux-user/main.c index bcb9f66570..fe2a8dd6db 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -437,7 +437,7 @@ void cpu_loop(CPUX86State *env) #define get_user_code_u32(x, gaddr, env) \ ({ abi_long __r = get_user_u32((x), (gaddr)); \ - if (!__r && (env)->bswap_code) { \ + if (!__r && bswap_code(arm_sctlr_b(env))) { \ (x) = bswap32(x); \ } \ __r; \ @@ -445,7 +445,7 @@ void cpu_loop(CPUX86State *env) #define get_user_code_u16(x, gaddr, env) \ ({ abi_long __r = get_user_u16((x), (gaddr)); \ - if (!__r && (env)->bswap_code) { \ + if (!__r && bswap_code(arm_sctlr_b(env))) { \ (x) = bswap16(x); \ } \ __r; \ @@ -4449,11 +4449,15 @@ int main(int argc, char **argv, char **envp) for(i = 0; i < 16; i++) { env->regs[i] = regs->uregs[i]; } +#ifdef TARGET_WORDS_BIGENDIAN /* Enable BE8. */ if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4 && (info->elf_flags & EF_ARM_BE8)) { - env->bswap_code = 1; + /* nothing for now, CPSR.E not emulated yet */ + } else { + env->cp15.sctlr_el[1] |= SCTLR_B; } +#endif } #elif defined(TARGET_UNICORE32) { -- cgit v1.2.3 From 9c5a7460389e92d230362a983b5a4158d6a1cefe Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Fri, 4 Mar 2016 11:30:19 +0000 Subject: linux-user: arm: set CPSR.E/SCTLR.E0E correctly for BE mode If doing big-endian linux-user mode, set both the CPSR.E and SCTLR.E0E bits. This sets big-endian mode for data accesses. Signed-off-by: Peter Crosthwaite Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- linux-user/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'linux-user/main.c') diff --git a/linux-user/main.c b/linux-user/main.c index fe2a8dd6db..510b3b7740 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -4453,7 +4453,8 @@ int main(int argc, char **argv, char **envp) /* Enable BE8. */ if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4 && (info->elf_flags & EF_ARM_BE8)) { - /* nothing for now, CPSR.E not emulated yet */ + env->uncached_cpsr |= CPSR_E; + env->cp15.sctlr_el[1] |= SCTLR_E0E; } else { env->cp15.sctlr_el[1] |= SCTLR_B; } -- cgit v1.2.3 From c3ae85fc8f36b64fb73038214e4359f1e470d169 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 4 Mar 2016 11:30:19 +0000 Subject: 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 [ PC changes: * Moved SCTLR/CPSR logic to arm_cpu_data_is_big_endian ] Signed-off-by: Peter Crosthwaite Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- linux-user/main.c | 50 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 7 deletions(-) (limited to 'linux-user/main.c') diff --git a/linux-user/main.c b/linux-user/main.c index 510b3b7740..2b1e7552da 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; -- cgit v1.2.3