diff options
author | Nicholas Piggin <npiggin@gmail.com> | 2023-06-20 23:10:41 +1000 |
---|---|---|
committer | Cédric Le Goater <clg@kaod.org> | 2023-06-25 22:41:30 +0200 |
commit | 888050cf519eb5995424cf415f4f8f269de96824 (patch) | |
tree | d6ff1489fd56e8fc9c586661014eeec74a634f96 /target/ppc | |
parent | 6b8a05373bf142fe5fd3839c3675da005bfc9b49 (diff) |
target/ppc: Fix instruction loading endianness in alignment interrupt
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.
Reviewed-by: Fabiano Rosas <farosas@suse.de>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Diffstat (limited to 'target/ppc')
-rw-r--r-- | target/ppc/excp_helper.c | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 12d8a7257b..a2801f6e6b 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -133,6 +133,26 @@ static void dump_hcall(CPUPPCState *env) env->nip); } +#ifdef CONFIG_TCG +/* Return true iff byteswap is needed to load instruction */ +static inline bool insn_need_byteswap(CPUArchState *env) +{ + /* SYSTEM builds TARGET_BIG_ENDIAN. Need to swap when MSR[LE] is set */ + return !!(env->msr & ((target_ulong)1 << MSR_LE)); +} + +static uint32_t ppc_ldl_code(CPUArchState *env, hwaddr addr) +{ + uint32_t insn = cpu_ldl_code(env, addr); + + if (insn_need_byteswap(env)) { + insn = bswap32(insn); + } + + return insn; +} +#endif + static void ppc_excp_debug_sw_tlb(CPUPPCState *env, int excp) { const char *es; @@ -3104,7 +3124,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: |