summaryrefslogtreecommitdiffstats
path: root/lib/libc/sparc64
diff options
context:
space:
mode:
authortmm <tmm@FreeBSD.org>2002-03-11 03:18:17 +0000
committertmm <tmm@FreeBSD.org>2002-03-11 03:18:17 +0000
commitbef62c8ae4f38f6c19f75826cc852e95fe1dcd17 (patch)
tree030517175f5f142fc9fd099096c5c1603614a5a6 /lib/libc/sparc64
parentadd3c8c97251f8d1d096896098707aba73d84ae6 (diff)
downloadFreeBSD-src-bef62c8ae4f38f6c19f75826cc852e95fe1dcd17.zip
FreeBSD-src-bef62c8ae4f38f6c19f75826cc852e95fe1dcd17.tar.gz
Fix some bugs that would prevent %fsr to be set correctly, and add
support for fcmp and fcmpe instructions with a condition code specification other than %fcc0. This (primarily the first part) seems to fix a lot of problems that people were seeing, e.g. perl and gawk failures. Reported and analyzed by: wollman
Diffstat (limited to 'lib/libc/sparc64')
-rw-r--r--lib/libc/sparc64/fpu/fpu.c9
-rw-r--r--lib/libc/sparc64/fpu/fpu_compare.c20
-rw-r--r--lib/libc/sparc64/fpu/fpu_emu.h2
-rw-r--r--lib/libc/sparc64/fpu/fpu_extern.h2
4 files changed, 25 insertions, 8 deletions
diff --git a/lib/libc/sparc64/fpu/fpu.c b/lib/libc/sparc64/fpu/fpu.c
index c026f86..2c454e3 100644
--- a/lib/libc/sparc64/fpu/fpu.c
+++ b/lib/libc/sparc64/fpu/fpu.c
@@ -187,7 +187,7 @@ __fpu_exception(struct utrapframe *uf)
goto fatal;
}
- fe.fe_fsr = fsr;
+ fe.fe_fsr = fsr & ~FSR_FTT_MASK;
insn = *(u_int32_t *)uf->uf_pc;
if (IF_OP(insn) != IOP_MISC || (IF_F3_OP3(insn) != INS2_FPop1 &&
IF_F3_OP3(insn) != INS2_FPop2))
@@ -268,7 +268,8 @@ __fpu_ccmov(struct fpemu *fe, int type, int rd, int rs1, int rs2,
static int
__fpu_cmpck(struct fpemu *fe)
{
- int cx, fsr;
+ u_long fsr;
+ int cx;
/*
* The only possible exception here is NV; catch it
@@ -391,12 +392,12 @@ __fpu_execute(struct utrapframe *uf, struct fpemu *fe, u_int32_t insn, u_long ts
case FOP(INS2_FPop2, INSFP2_FCMP):
__fpu_explode(fe, &fe->fe_f1, type, rs1);
__fpu_explode(fe, &fe->fe_f2, type, rs2);
- __fpu_compare(fe, 0);
+ __fpu_compare(fe, 0, IF_F3_CC(insn));
return (__fpu_cmpck(fe));
case FOP(INS2_FPop2, INSFP2_FCMPE):
__fpu_explode(fe, &fe->fe_f1, type, rs1);
__fpu_explode(fe, &fe->fe_f2, type, rs2);
- __fpu_compare(fe, 1);
+ __fpu_compare(fe, 1, IF_F3_CC(insn));
return (__fpu_cmpck(fe));
case FOP(INS2_FPop1, INSFP1_FMOV): /* these should all be pretty obvious */
__fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2);
diff --git a/lib/libc/sparc64/fpu/fpu_compare.c b/lib/libc/sparc64/fpu/fpu_compare.c
index 6c83afc..5d63699 100644
--- a/lib/libc/sparc64/fpu/fpu_compare.c
+++ b/lib/libc/sparc64/fpu/fpu_compare.c
@@ -62,6 +62,21 @@
#include "fpu_emu.h"
#include "fpu_extern.h"
+static u_long fcc_nmask[] = {
+ ~FSR_FCC0_MASK,
+ ~FSR_FCC1_MASK,
+ ~FSR_FCC2_MASK,
+ ~FSR_FCC3_MASK
+};
+
+/* XXX: we don't use the FSR_FCCx macros here; it's much easier this way. */
+static int fcc_shift[] = {
+ FSR_FCC0_SHIFT,
+ FSR_FCC1_SHIFT,
+ FSR_FCC2_SHIFT,
+ FSR_FCC3_SHIFT
+};
+
/*
* Perform a compare instruction (with or without unordered exception).
* This updates the fcc field in the fsr.
@@ -78,7 +93,7 @@
* complete).
*/
void
-__fpu_compare(struct fpemu *fe, int cmpe)
+__fpu_compare(struct fpemu *fe, int cmpe, int fcc)
{
register struct fpn *a, *b;
register int cc;
@@ -160,5 +175,6 @@ __fpu_compare(struct fpemu *fe, int cmpe)
cc = diff(FSR_CC_GT);
done:
- fe->fe_fsr = (fe->fe_fsr & ~FSR_FCC0_MASK) | FSR_FCC0(cc);
+ fe->fe_fsr = (fe->fe_fsr & fcc_nmask[fcc]) |
+ ((u_long)cc << fcc_shift[fcc]);
}
diff --git a/lib/libc/sparc64/fpu/fpu_emu.h b/lib/libc/sparc64/fpu/fpu_emu.h
index e7c24cd..d08642b 100644
--- a/lib/libc/sparc64/fpu/fpu_emu.h
+++ b/lib/libc/sparc64/fpu/fpu_emu.h
@@ -156,7 +156,7 @@ struct fpn {
* Emulator state.
*/
struct fpemu {
- int fe_fsr; /* fsr copy (modified during op) */
+ u_long fe_fsr; /* fsr copy (modified during op) */
int fe_cx; /* exceptions */
struct fpn fe_f1; /* operand 1 */
struct fpn fe_f2; /* operand 2, if required */
diff --git a/lib/libc/sparc64/fpu/fpu_extern.h b/lib/libc/sparc64/fpu/fpu_extern.h
index 4d18ed4..862ca59 100644
--- a/lib/libc/sparc64/fpu/fpu_extern.h
+++ b/lib/libc/sparc64/fpu/fpu_extern.h
@@ -56,7 +56,7 @@ void __fpu_panic __P((char *msg));
struct fpn *__fpu_add __P((struct fpemu *));
/* fpu_compare.c */
-void __fpu_compare __P((struct fpemu *, int));
+void __fpu_compare __P((struct fpemu *, int, int));
/* fpu_div.c */
struct fpn *__fpu_div __P((struct fpemu *));
OpenPOWER on IntegriCloud