summaryrefslogtreecommitdiffstats
path: root/lib/libc/sparc64/fpu
diff options
context:
space:
mode:
authorjake <jake@FreeBSD.org>2002-04-27 21:56:28 +0000
committerjake <jake@FreeBSD.org>2002-04-27 21:56:28 +0000
commita1a94cce5c09be6d56eb4c83034f03ab93077bbe (patch)
treeef5f4b8e186ab8b15487aae5d54638610a6e672b /lib/libc/sparc64/fpu
parent60ee831d3e0478dd494c5dd9b27f019f1700ea71 (diff)
downloadFreeBSD-src-a1a94cce5c09be6d56eb4c83034f03ab93077bbe.zip
FreeBSD-src-a1a94cce5c09be6d56eb4c83034f03ab93077bbe.tar.gz
Emulate ldq and stq (load/store long double) instructions. GCC has started
using these to load long doubles, but they aren't implemented in hardware on (at least) UltraSPARC I and II machines. Emulate popc in the user trap handler as well. Re-arrange slightly to make support functions more accessible. Reviewed by: tmm
Diffstat (limited to 'lib/libc/sparc64/fpu')
-rw-r--r--lib/libc/sparc64/fpu/Makefile.inc2
-rw-r--r--lib/libc/sparc64/fpu/fpu.c106
-rw-r--r--lib/libc/sparc64/fpu/fpu_add.c3
-rw-r--r--lib/libc/sparc64/fpu/fpu_explode.c3
-rw-r--r--lib/libc/sparc64/fpu/fpu_extern.h5
-rw-r--r--lib/libc/sparc64/fpu/fpu_implode.c5
-rw-r--r--lib/libc/sparc64/fpu/fpu_subr.c5
7 files changed, 36 insertions, 93 deletions
diff --git a/lib/libc/sparc64/fpu/Makefile.inc b/lib/libc/sparc64/fpu/Makefile.inc
index a21672e..f311177 100644
--- a/lib/libc/sparc64/fpu/Makefile.inc
+++ b/lib/libc/sparc64/fpu/Makefile.inc
@@ -2,5 +2,7 @@
.PATH: ${.CURDIR}/../libc/sparc64/fpu/
+CFLAGS+= -I${.CURDIR}/sparc64/sys
+
SRCS+= fpu.c fpu_add.c fpu_compare.c fpu_div.c fpu_explode.c fpu_implode.c \
fpu_mul.c fpu_reg.S fpu_sqrt.c fpu_subr.c
diff --git a/lib/libc/sparc64/fpu/fpu.c b/lib/libc/sparc64/fpu/fpu.c
index a35238e..1092a67 100644
--- a/lib/libc/sparc64/fpu/fpu.c
+++ b/lib/libc/sparc64/fpu/fpu.c
@@ -87,7 +87,7 @@ __FBSDID("$FreeBSD$");
#include <machine/pcb.h>
#include <machine/tstate.h>
-#include "../sys/__sparc_utrap_private.h"
+#include "__sparc_utrap_private.h"
#include "fpu_emu.h"
#include "fpu_extern.h"
@@ -119,89 +119,52 @@ int __fpe_debug = 0;
#endif /* FPU_DEBUG */
static int __fpu_execute(struct utrapframe *, struct fpemu *, u_int32_t, u_long);
-static void utrap_write(char *);
-static void utrap_kill_self(int);
-
-/*
- * System call wrappers usable in an utrap environment.
- */
-static void
-utrap_write(char *str)
-{
- int berrno;
-
- berrno = errno;
- __sys_write(STDERR_FILENO, str, strlen(str));
- errno = berrno;
-}
-
-static void
-utrap_kill_self(sig)
-{
- int berrno;
-
- berrno = errno;
- __sys_kill(__sys_getpid(), sig);
- errno = berrno;
-}
-
-void
-__fpu_panic(char *msg)
-{
-
- utrap_write(msg);
- utrap_write("\n");
- utrap_kill_self(SIGKILL);
-}
/*
* Need to use an fpstate on the stack; we could switch, so we cannot safely
* modify the pcb one, it might get overwritten.
*/
-void
+int
__fpu_exception(struct utrapframe *uf)
{
struct fpemu fe;
u_long fsr, tstate;
u_int insn;
- int rv;
+ int sig;
fsr = uf->uf_fsr;
switch (FSR_GET_FTT(fsr)) {
case FSR_FTT_NONE:
- utrap_write("lost FPU trap type\n");
- return;
+ __utrap_write("lost FPU trap type\n");
+ return (0);
case FSR_FTT_IEEE:
- goto fatal;
+ return (SIGFPE);
case FSR_FTT_SEQERR:
- utrap_write("FPU sequence error\n");
- goto fatal;
+ __utrap_write("FPU sequence error\n");
+ return (SIGFPE);
case FSR_FTT_HWERR:
- utrap_write("FPU hardware error\n");
- goto fatal;
+ __utrap_write("FPU hardware error\n");
+ return (SIGFPE);
case FSR_FTT_UNFIN:
case FSR_FTT_UNIMP:
break;
default:
- utrap_write("unknown FPU error\n");
- goto fatal;
+ __utrap_write("unknown FPU error\n");
+ return (SIGFPE);
}
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))
- __fpu_panic("bogus FP fault");
+ __utrap_panic("bogus FP fault");
tstate = uf->uf_state;
- rv = __fpu_execute(uf, &fe, insn, tstate);
- if (rv != 0)
- utrap_kill_self(rv);
+ sig = __fpu_execute(uf, &fe, insn, tstate);
+ if (sig != 0)
+ return (sig);
__asm __volatile("ldx %0, %%fsr" : : "m" (fe.fe_fsr));
- return;
-fatal:
- utrap_kill_self(SIGFPE);
- return;
+ return (0);
}
#ifdef FPU_DEBUG
@@ -223,29 +186,6 @@ __fpu_dumpfpn(struct fpn *fp)
}
#endif
-static u_long
-fetch_reg(struct utrapframe *uf, int reg)
-{
- u_long offs;
- struct frame *frm;
-
- if (reg == IREG_G0)
- return (0);
- else if (reg < IREG_O0) /* global */
- return (uf->uf_global[reg]);
- else if (reg < IREG_L0) /* out */
- return (uf->uf_out[reg - IREG_O0]);
- else { /* local, in */
- /*
- * The in registers are immediately after the locals in
- * the frame.
- */
- frm = (struct frame *)(uf->uf_out[6] + SPOFF);
- return (frm->fr_local[reg - IREG_L0]);
- }
- __fpu_panic("fetch_reg: bogus register");
-}
-
static void
__fpu_mov(struct fpemu *fe, int type, int rd, int rs1, int rs2)
{
@@ -361,32 +301,32 @@ __fpu_execute(struct utrapframe *uf, struct fpemu *fe, u_int32_t insn, u_long ts
(tstate & TSTATE_XCC_MASK) >> (TSTATE_XCC_SHIFT));
return (0);
case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_Z)):
- reg = fetch_reg(uf, IF_F4_RS1(insn));
+ reg = __emul_fetch_reg(uf, IF_F4_RS1(insn));
if (reg == 0)
__fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2);
return (0);
case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_LEZ)):
- reg = fetch_reg(uf, IF_F4_RS1(insn));
+ reg = __emul_fetch_reg(uf, IF_F4_RS1(insn));
if (reg <= 0)
__fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2);
return (0);
case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_LZ)):
- reg = fetch_reg(uf, IF_F4_RS1(insn));
+ reg = __emul_fetch_reg(uf, IF_F4_RS1(insn));
if (reg < 0)
__fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2);
return (0);
case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_NZ)):
- reg = fetch_reg(uf, IF_F4_RS1(insn));
+ reg = __emul_fetch_reg(uf, IF_F4_RS1(insn));
if (reg != 0)
__fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2);
return (0);
case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_GZ)):
- reg = fetch_reg(uf, IF_F4_RS1(insn));
+ reg = __emul_fetch_reg(uf, IF_F4_RS1(insn));
if (reg > 0)
__fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2);
return (0);
case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_GEZ)):
- reg = fetch_reg(uf, IF_F4_RS1(insn));
+ reg = __emul_fetch_reg(uf, IF_F4_RS1(insn));
if (reg >= 0)
__fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2);
return (0);
diff --git a/lib/libc/sparc64/fpu/fpu_add.c b/lib/libc/sparc64/fpu/fpu_add.c
index e321e41..405b9b8 100644
--- a/lib/libc/sparc64/fpu/fpu_add.c
+++ b/lib/libc/sparc64/fpu/fpu_add.c
@@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
#include "fpu_arith.h"
#include "fpu_emu.h"
#include "fpu_extern.h"
+#include "__sparc_utrap_private.h"
struct fpn *
__fpu_add(fe)
@@ -198,7 +199,7 @@ __fpu_add(fe)
*/
#ifdef DIAGNOSTIC
if (x->fp_exp != y->fp_exp || r->fp_sticky)
- __fpu_panic("fpu_add");
+ __utrap_panic("fpu_add");
#endif
r->fp_sign = y->fp_sign;
FPU_SUBS(r3, 0, r3);
diff --git a/lib/libc/sparc64/fpu/fpu_explode.c b/lib/libc/sparc64/fpu/fpu_explode.c
index baa2da2..6967f5c 100644
--- a/lib/libc/sparc64/fpu/fpu_explode.c
+++ b/lib/libc/sparc64/fpu/fpu_explode.c
@@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
#include "fpu_arith.h"
#include "fpu_emu.h"
#include "fpu_extern.h"
+#include "__sparc_utrap_private.h"
/*
* N.B.: in all of the following, we assume the FP format is
@@ -278,7 +279,7 @@ __fpu_explode(fe, fp, type, reg)
break;
default:
- __fpu_panic("fpu_explode");
+ __utrap_panic("fpu_explode");
}
if (s == FPC_QNAN && (fp->fp_mant[0] & FP_QUIETBIT) == 0) {
diff --git a/lib/libc/sparc64/fpu/fpu_extern.h b/lib/libc/sparc64/fpu/fpu_extern.h
index fca0f06..f22c463 100644
--- a/lib/libc/sparc64/fpu/fpu_extern.h
+++ b/lib/libc/sparc64/fpu/fpu_extern.h
@@ -40,16 +40,13 @@
#ifndef _SPARC64_FPU_FPU_EXTERN_H_
#define _SPARC64_FPU_FPU_EXTERN_H_
-struct proc;
-struct fpstate;
struct utrapframe;
union instr;
struct fpemu;
struct fpn;
/* fpu.c */
-void __fpu_exception(struct utrapframe *tf);
-void __fpu_panic(char *msg);
+int __fpu_exception(struct utrapframe *tf);
/* fpu_add.c */
struct fpn *__fpu_add(struct fpemu *);
diff --git a/lib/libc/sparc64/fpu/fpu_implode.c b/lib/libc/sparc64/fpu/fpu_implode.c
index 27a826a..e1937a4 100644
--- a/lib/libc/sparc64/fpu/fpu_implode.c
+++ b/lib/libc/sparc64/fpu/fpu_implode.c
@@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
#include "fpu_arith.h"
#include "fpu_emu.h"
#include "fpu_extern.h"
+#include "__sparc_utrap_private.h"
static int round(struct fpemu *, struct fpn *);
static int toinf(struct fpemu *, int);
@@ -354,7 +355,7 @@ __fpu_ftos(fe, fp)
(void) __fpu_shr(fp, FP_NMANT - FP_NG - 1 - SNG_FRACBITS);
#ifdef DIAGNOSTIC
if ((fp->fp_mant[3] & SNG_EXP(1 << FP_NG)) == 0)
- __fpu_panic("fpu_ftos");
+ __utrap_panic("fpu_ftos");
#endif
if (round(fe, fp) && fp->fp_mant[3] == SNG_EXP(2))
exp++;
@@ -529,7 +530,7 @@ __fpu_implode(fe, fp, type, space)
break;
default:
- __fpu_panic("fpu_implode");
+ __utrap_panic("fpu_implode");
}
DPRINTF(FPE_REG, ("fpu_implode: %x %x %x %x\n",
space[0], space[1], space[2], space[3]));
diff --git a/lib/libc/sparc64/fpu/fpu_subr.c b/lib/libc/sparc64/fpu/fpu_subr.c
index 97300a3..7e6308f 100644
--- a/lib/libc/sparc64/fpu/fpu_subr.c
+++ b/lib/libc/sparc64/fpu/fpu_subr.c
@@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$");
#include "fpu_arith.h"
#include "fpu_emu.h"
#include "fpu_extern.h"
+#include "__sparc_utrap_private.h"
/*
* Shift the given number right rsh bits. Any bits that `fall off' will get
@@ -75,7 +76,7 @@ __fpu_shr(struct fpn *fp, int rsh)
#ifdef DIAGNOSTIC
if (rsh <= 0 || (fp->fp_class != FPC_NUM && !ISNAN(fp)))
- __fpu_panic("fpu_rightshift 1");
+ __utrap_panic("fpu_rightshift 1");
#endif
m0 = fp->fp_mant[0];
@@ -87,7 +88,7 @@ __fpu_shr(struct fpn *fp, int rsh)
if (rsh >= FP_NMANT) {
#ifdef DIAGNOSTIC
if ((m0 | m1 | m2 | m3) == 0)
- __fpu_panic("fpu_rightshift 2");
+ __utrap_panic("fpu_rightshift 2");
#endif
fp->fp_mant[0] = 0;
fp->fp_mant[1] = 0;
OpenPOWER on IntegriCloud