Table 3-1 of the e500mc, e5500 and e6500 reference manuals specifies that mtfsfi ignores W and mtfsf ignores W and L, behaving as if these fields were zero. The existing translation rejects W=1 without extended FPSCR support and honors L=1, which does not match these cores.
Add a processor behavior flag to ignore these fields without advertising extended FPSCR support. Keep the ordinary field mask and rounding-mode updates effective. Reference: - E500MCRM (Rev.3), section 3.1.1 https://www.nxp.com/docs/en/reference-manual/E500MCRM.pdf - E5500RM (Rev.4), section 3.1.1 https://www.nxp.com/webapp/Download?colCode=E5500RM - E6500RM (Rev.0), section 3.1.1 https://www.nxp.com/docs/en/reference-manual/E6500RM.pdf Signed-off-by: Bin Meng <[email protected]> --- target/ppc/cpu.h | 2 ++ target/ppc/cpu_init.c | 9 ++++++--- target/ppc/translate/fp-impl.c.inc | 6 ++++++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 78fa4653fb..edcb2ac5c7 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -844,6 +844,8 @@ enum { POWERPC_FLAG_BHRB = 0x01000000, /* Use PPE42-specific behavior */ POWERPC_FLAG_PPE42 = 0x02000000, + /* Treat FPSCR instruction W and L fields as zero */ + POWERPC_FLAG_FPSCR_IGNORE_WL = 0x04000000, }; /* diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 1c02354e11..f38a67208d 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -3188,7 +3188,8 @@ POWERPC_FAMILY(e500mc)(ObjectClass *oc, const void *data) /* FIXME: figure out the correct flag for e500mc */ pcc->bfd_mach = bfd_mach_ppc_e500; pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_DE | - POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK; + POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK | + POWERPC_FLAG_FPSCR_IGNORE_WL; } #ifdef TARGET_PPC64 @@ -3238,7 +3239,8 @@ POWERPC_FAMILY(e5500)(ObjectClass *oc, const void *data) /* FIXME: figure out the correct flag for e5500 */ pcc->bfd_mach = bfd_mach_ppc_e500; pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_DE | - POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK; + POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK | + POWERPC_FLAG_FPSCR_IGNORE_WL; } static void init_proc_e6500(CPUPPCState *env) @@ -3288,7 +3290,8 @@ POWERPC_FAMILY(e6500)(ObjectClass *oc, const void *data) pcc->bus_model = PPC_FLAGS_INPUT_BookE; pcc->bfd_mach = bfd_mach_ppc_e500; pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_DE | - POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_VRE; + POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_VRE | + POWERPC_FLAG_FPSCR_IGNORE_WL; } #endif diff --git a/target/ppc/translate/fp-impl.c.inc b/target/ppc/translate/fp-impl.c.inc index fef770368a..9937b2db50 100644 --- a/target/ppc/translate/fp-impl.c.inc +++ b/target/ppc/translate/fp-impl.c.inc @@ -592,6 +592,9 @@ static void gen_mtfsf(DisasContext *ctx) flm = FPFLM(ctx->opcode); l = FPL(ctx->opcode); w = FPW(ctx->opcode); + if (ctx->flags & POWERPC_FLAG_FPSCR_IGNORE_WL) { + l = w = 0; + } if (unlikely(w & !(ctx->insns_flags2 & PPC2_FPSCR_EXT_ISA205))) { gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); return; @@ -627,6 +630,9 @@ static void gen_mtfsfi(DisasContext *ctx) } w = FPW(ctx->opcode); bf = FPBF(ctx->opcode); + if (ctx->flags & POWERPC_FLAG_FPSCR_IGNORE_WL) { + w = 0; + } if (unlikely(w & !(ctx->insns_flags2 & PPC2_FPSCR_EXT_ISA205))) { gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); return; -- 2.53.0
