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


Reply via email to