Module Name: src
Committed By: rin
Date: Wed Jul 15 09:36:35 UTC 2020
Modified Files:
src/sys/arch/powerpc/fpu: fpu_emu.c
Log Message:
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}.
To generate a diff of this commit:
cvs rdiff -u -r1.31 -r1.32 src/sys/arch/powerpc/fpu/fpu_emu.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/powerpc/fpu/fpu_emu.c
diff -u src/sys/arch/powerpc/fpu/fpu_emu.c:1.31 src/sys/arch/powerpc/fpu/fpu_emu.c:1.32
--- src/sys/arch/powerpc/fpu/fpu_emu.c:1.31 Wed Jul 15 09:22:26 2020
+++ src/sys/arch/powerpc/fpu/fpu_emu.c Wed Jul 15 09:36:35 2020
@@ -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 @@ FPU_EMU_EVCNT_DECL(fnmadd);
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 @@ fpu_execute(struct trapframe *tf, struct
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 @@ fpu_execute(struct trapframe *tf, struct
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 @@ fpu_execute(struct trapframe *tf, struct
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 @@ fpu_execute(struct trapframe *tf, struct
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 @@ fpu_execute(struct trapframe *tf, struct
/* 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;