Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/powerpc/fpu Try to fix FPSCR bits in the end of emu...



details:   https://anonhg.NetBSD.org/src/rev/addac978b8f9
branches:  trunk
changeset: 935993:addac978b8f9
user:      rin <rin%NetBSD.org@localhost>
date:      Wed Jul 15 09:36:35 2020 +0000

description:
Try to fix FPSCR bits in the end of emulation:

- FPSCR[FEX] is not a sticky bit.
- Turn on FPSCR[FEX] if the emulated instruction causes invalid operation,
  and invalid operation exception is not masked out.
- FPSCR[VX] is not a sticky bit, however it should be set when at least
  one of FPSCR[VXfoo] bits (they are sticky!) is set.
- FPSCR[FX] is a sticky bit, and it should be set if FPSCR is modified by
  instructions other than mtfsf{,i}.

diffstat:

 sys/arch/powerpc/fpu/fpu_emu.c |  24 +++++++++++++++---------
 1 files changed, 15 insertions(+), 9 deletions(-)

diffs (84 lines):

diff -r da21c63a1c0a -r addac978b8f9 sys/arch/powerpc/fpu/fpu_emu.c
--- a/sys/arch/powerpc/fpu/fpu_emu.c    Wed Jul 15 09:22:26 2020 +0000
+++ b/sys/arch/powerpc/fpu/fpu_emu.c    Wed Jul 15 09:36:35 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: fpu_emu.c,v 1.31 2020/07/15 09:22:26 rin Exp $ */
+/*     $NetBSD: fpu_emu.c,v 1.32 2020/07/15 09:36:35 rin Exp $ */
 
 /*
  * Copyright 2001 Wasabi Systems, Inc.
@@ -76,7 +76,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fpu_emu.c,v 1.31 2020/07/15 09:22:26 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fpu_emu.c,v 1.32 2020/07/15 09:36:35 rin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ddb.h"
@@ -147,7 +147,9 @@
                        FPSCR_VXZDZ|FPSCR_VXIMZ|FPSCR_VXVC|FPSCR_VXSOFT|\
                        FPSCR_VXSQRT|FPSCR_VXCVI)
 #define        FPSR_EX         (FPSCR_VE|FPSCR_OE|FPSCR_UE|FPSCR_ZE|FPSCR_XE)
-#define        FPSR_EXOP       (FPSR_EX_MSK&(~FPSR_EX))
+#define        FPSR_INV        (FPSCR_VXSNAN|FPSCR_VXISI|FPSCR_VXIDI|          \
+                       FPSCR_VXZDZ|FPSCR_VXIMZ|FPSCR_VXVC|FPSCR_VXSOFT|\
+                       FPSCR_VXSQRT|FPSCR_VXCVI)
 
 
 int fpe_debug = 0;
@@ -287,6 +289,7 @@
        int ra, rb, rc, rt, type, mask, fsr, cx, bf, setcr;
        unsigned int cond;
        struct fpreg *fs;
+       int mtfsf = 0;
 
        /* Setup work. */
        fp = NULL;
@@ -550,6 +553,7 @@
                                        sizeof(double));
                                break;
                        case    OPC63_MTFSFI:
+                               mtfsf = 1;
                                FPU_EMU_EVCNT_INCR(mtfsfi);
                                DPRINTF(FPE_INSN, ("fpu_execute: MTFSFI\n"));
                                rb >>= 1;
@@ -585,6 +589,7 @@
                                        sizeof(fs->fpscr));
                                break;
                        case    OPC63_MTFSF:
+                               mtfsf = 1;
                                FPU_EMU_EVCNT_INCR(mtfsf);
                                DPRINTF(FPE_INSN, ("fpu_execute: MTFSF\n"));
                                if ((rt = instr.i_xfl.i_flm) == -1)
@@ -769,11 +774,10 @@
        if (fp)
                fpu_implode(fe, fp, type, (u_int *)&fs->fpreg[rt]);
        cx = fe->fe_cx;
-       fsr = fe->fe_fpscr;
+       fsr = fe->fe_fpscr & ~(FPSCR_FEX|FPSCR_VX);
        if (cx != 0) {
-               fsr &= ~FPSCR_FX;
-               if ((cx^fsr)&FPSR_EX_MSK)
-                       fsr |= FPSCR_FX;
+               if (cx & FPSR_INV)
+                       cx |= FPSCR_VX;
                mask = fsr & FPSR_EX;
                mask <<= (25-3);
                if (cx & mask) 
@@ -782,11 +786,13 @@
                        /* Need to replace CC */
                        fsr &= ~FPSCR_FPRF;
                }
-               if (cx & (FPSR_EXOP))
-                       fsr |= FPSCR_VX;
                fsr |= cx;
                DPRINTF(FPE_INSN, ("fpu_execute: cx %x, fsr %x\n", cx, fsr));
        }
+       if (fsr & FPSR_INV)
+               fsr |= FPSCR_VX;
+       if (mtfsf == 0 && ((fsr ^ fe->fe_fpscr) & FPSR_EX_MSK))
+               fsr |= FPSCR_FX;
 
        if (cond) {
                cond = fsr & 0xf0000000;



Home | Main Index | Thread Index | Old Index