Module Name: src
Committed By: isaki
Date: Sat Dec 28 11:23:12 UTC 2024
Modified Files:
src/sys/arch/m68k/fpe: fpu_emulate.c
Log Message:
m68k/fpe: Reimplement and simplify test_cc().
This logic was analized by Y.Sugahara (in 2016).
Finally fputest.x(0.24.10.08) about fbcc fdbcc fscc (40960 tests) passed 100%!
To generate a diff of this commit:
cvs rdiff -u -r1.45 -r1.46 src/sys/arch/m68k/fpe/fpu_emulate.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/m68k/fpe/fpu_emulate.c
diff -u src/sys/arch/m68k/fpe/fpu_emulate.c:1.45 src/sys/arch/m68k/fpe/fpu_emulate.c:1.46
--- src/sys/arch/m68k/fpe/fpu_emulate.c:1.45 Sat Dec 28 11:15:11 2024
+++ src/sys/arch/m68k/fpe/fpu_emulate.c Sat Dec 28 11:23:12 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: fpu_emulate.c,v 1.45 2024/12/28 11:15:11 isaki Exp $ */
+/* $NetBSD: fpu_emulate.c,v 1.46 2024/12/28 11:23:12 isaki Exp $ */
/*
* Copyright (c) 1995 Gordon W. Ross
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fpu_emulate.c,v 1.45 2024/12/28 11:15:11 isaki Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fpu_emulate.c,v 1.46 2024/12/28 11:23:12 isaki Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -913,11 +913,10 @@ fpu_emul_arith(struct fpemu *fe, struct
static int
test_cc(struct fpemu *fe, int pred)
{
- int result, sig_bsun, invert;
+ int result, sig_bsun;
int fpsr;
fpsr = fe->fe_fpsr;
- invert = 0;
DPRINTF(("%s: fpsr=0x%08x\n", __func__, fpsr));
pred &= 0x3f; /* lowest 6 bits */
@@ -936,54 +935,56 @@ test_cc(struct fpemu *fe, int pred)
sig_bsun = 0;
}
- if (pred & 0x08) {
- DPRINTF(("Not "));
- /* predicate is "NOT ..." */
- pred ^= 0xf; /* invert */
- invert = -1;
- }
- switch (pred) {
- case 0: /* (Signaling) False */
- DPRINTF(("False"));
- result = 0;
- break;
- case 1: /* (Signaling) Equal */
- DPRINTF(("Equal"));
- result = -((fpsr & FPSR_ZERO) == FPSR_ZERO);
- break;
- case 2: /* Greater Than */
- DPRINTF(("GT"));
- result = -((fpsr & (FPSR_NAN|FPSR_ZERO|FPSR_NEG)) == 0);
- break;
- case 3: /* Greater or Equal */
- DPRINTF(("GE"));
- result = -((fpsr & FPSR_ZERO) ||
- (fpsr & (FPSR_NAN|FPSR_NEG)) == 0);
- break;
- case 4: /* Less Than */
- DPRINTF(("LT"));
- result = -((fpsr & (FPSR_NAN|FPSR_ZERO|FPSR_NEG)) == FPSR_NEG);
- break;
- case 5: /* Less or Equal */
- DPRINTF(("LE"));
- result = -((fpsr & FPSR_ZERO) ||
- ((fpsr & (FPSR_NAN|FPSR_NEG)) == FPSR_NEG));
- break;
- case 6: /* Greater or Less than */
- DPRINTF(("GLT"));
- result = -((fpsr & (FPSR_NAN|FPSR_ZERO)) == 0);
- break;
- case 7: /* Greater, Less or Equal */
- DPRINTF(("GLE"));
- result = -((fpsr & FPSR_NAN) == 0);
+ /*
+ * condition real 68882
+ * mnemonic in manual condition
+ * -------- ---------- ----------
+ * 0000 F 0 <- = ~NAN & 0 & ~Z | 0
+ * 0001 EQ Z <- = ~NAN & 0 | Z | 0
+ * 0010 OGT ~(NAN|Z|N) <- = ~NAN & ~N & ~Z | 0
+ * 0011 OGE Z|~(NAN|N) <- = ~NAN & ~N | Z | 0
+ * 0100 OLT N&~(NAN|Z) <- = ~NAN & N & ~Z | 0
+ * 0101 OLE Z|(N&~NAN) <- = ~NAN & N | Z | 0
+ * 0110 OGL ~(NAN|Z) <- = ~NAN & 1 & ~Z | 0
+ * 0111 OR ~NAN Z|~NAN = ~NAN & 1 | Z | 0
+ *
+ * 1000 UN NAN <- = 1 & 0 & ~Z | NAN
+ * 1001 UEQ NAN|Z <- = 1 & 0 | Z | NAN
+ * 1010 UGT NAN|~(N|Z) <- = 1 & ~N & ~Z | NAN
+ * 1011 UGE NAN|(Z|~N) <- = 1 & ~N | Z | NAN
+ * 1100 ULT NAN|(N&~Z) <- = 1 & N & ~Z | NAN
+ * 1101 ULE NAN|(Z|N) <- = 1 & N | Z | NAN
+ * 1110 NE ~Z NAN|(~Z) = 1 & 1 & ~Z | NAN
+ * 1111 T 1 <- = 1 & 1 | Z | NAN
+ */
+ if ((pred & 0x08) == 0) {
+ result = ((fpsr & FPSR_NAN) == 0);
+ } else {
+ result = 1;
+ }
+ switch (pred & 0x06) {
+ case 0x00: /* AND 0 */
+ result &= 0;
+ break;
+ case 0x02: /* AND ~N */
+ result &= ((fpsr & FPSR_NEG) == 0);
+ break;
+ case 0x04: /* AND N */
+ result &= ((fpsr & FPSR_NEG) != 0);
+ break;
+ case 0x06: /* AND 1 */
+ result &= 1;
break;
- default:
- /* invalid predicate */
- DPRINTF(("Invalid predicate\n"));
- return SIGILL;
}
- /* if the predicate is "NOT ...", then invert the result */
- result ^= invert;
+ if ((pred & 0x01) == 0) {
+ result &= ((fpsr & FPSR_ZERO) == 0);
+ } else {
+ result |= ((fpsr & FPSR_ZERO) != 0);
+ }
+ if ((pred & 0x08) != 0) {
+ result |= ((fpsr & FPSR_NAN) != 0);
+ }
+
DPRINTF(("=> %s (%d)\n", result ? "true" : "false", result));
/* if it's an IEEE unaware test and NAN is set, BSUN is set */
if (sig_bsun && (fpsr & FPSR_NAN)) {
@@ -997,7 +998,7 @@ test_cc(struct fpemu *fe, int pred)
/* put fpsr back */
fe->fe_fpframe->fpf_fpsr = fe->fe_fpsr = fpsr;
- return result;
+ return -result;
}
/*