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; } /*