powerpc ifetch endianness depends on MSR[LE] so it has to byteswap after cpu_ldl_code(). This corrects DSISR bits in alignment interrupts when running in little endian mode.
Signed-off-by: Nicholas Piggin <npig...@gmail.com> --- target/ppc/excp_helper.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 287659c74d..5f0e363363 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -133,6 +133,31 @@ static void dump_hcall(CPUPPCState *env) env->nip); } +/* Return true iff byteswap is needed in a scalar memop */ +static inline bool need_byteswap(CPUArchState *env) +{ +#if TARGET_BIG_ENDIAN + return !!(env->msr & ((target_ulong)1 << MSR_LE)); +#else + return !(env->msr & ((target_ulong)1 << MSR_LE)); +#endif +} + +static uint32_t ppc_ldl_code(CPUArchState *env, abi_ptr addr) +{ + uint32_t insn = cpu_ldl_code(env, addr); +#if TARGET_BIG_ENDIAN + if (env->msr & ((target_ulong)1 << MSR_LE)) { + insn = bswap32(insn); + } +#else + if (!(env->msr & ((target_ulong)1 << MSR_LE))) { + insn = bswap32(insn); + } +#endif + return insn; +} + static void ppc_excp_debug_sw_tlb(CPUPPCState *env, int excp) { const char *es; @@ -3097,7 +3122,7 @@ void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr, /* Restore state and reload the insn we executed, for filling in DSISR. */ cpu_restore_state(cs, retaddr); - insn = cpu_ldl_code(env, env->nip); + insn = ppc_ldl_code(env, env->nip); switch (env->mmu_model) { case POWERPC_MMU_SOFT_4xx: -- 2.37.2