Don't set CPSR.E for BE32 linux-user mode. As linux-user mode models BE32, using normal BE (and system mode will not), a special case is needed for user-mode where if sctlr.b is set, the CPU identifies as BE.
Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com> --- linux-user/main.c | 2 -- target-arm/cpu.h | 12 +++++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/linux-user/main.c b/linux-user/main.c index d481458..60375fb 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -4496,8 +4496,6 @@ int main(int argc, char **argv, char **envp) env->uncached_cpsr |= CPSR_E; } else { env->cp15.sctlr_el[1] |= SCTLR_B; - /* We model BE32 as regular BE, so set CPSR_E */ - env->uncached_cpsr |= CPSR_E; } #endif } diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 3edd56b..96b1e99 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -1812,7 +1812,17 @@ static bool arm_cpu_is_big_endian(CPUARMState *env) /* In 32bit endianness is determined by looking at CPSR's E bit */ if (!is_a64(env)) { - return (env->uncached_cpsr & CPSR_E) ? 1 : 0; + return +#ifdef CONFIG_USER_ONLY + /* In user mode, BE32 data accesses are just modelled as + * regular BE access. In system mode, BE32 is modelled as + * little endian, with the appropriate address translations on + * non-word accesses. So sctlr.b only affects overall + * endianness in user mode + */ + arm_sctlr_b(env) || +#endif + ((env->uncached_cpsr & CPSR_E) ? 1 : 0); } cur_el = arm_current_el(env); -- 1.9.1