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;

Reply via email to