diff options
author | jake <jake@FreeBSD.org> | 2002-04-27 21:56:28 +0000 |
---|---|---|
committer | jake <jake@FreeBSD.org> | 2002-04-27 21:56:28 +0000 |
commit | a1a94cce5c09be6d56eb4c83034f03ab93077bbe (patch) | |
tree | ef5f4b8e186ab8b15487aae5d54638610a6e672b /lib/libc/sparc64/fpu | |
parent | 60ee831d3e0478dd494c5dd9b27f019f1700ea71 (diff) | |
download | FreeBSD-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.inc | 2 | ||||
-rw-r--r-- | lib/libc/sparc64/fpu/fpu.c | 106 | ||||
-rw-r--r-- | lib/libc/sparc64/fpu/fpu_add.c | 3 | ||||
-rw-r--r-- | lib/libc/sparc64/fpu/fpu_explode.c | 3 | ||||
-rw-r--r-- | lib/libc/sparc64/fpu/fpu_extern.h | 5 | ||||
-rw-r--r-- | lib/libc/sparc64/fpu/fpu_implode.c | 5 | ||||
-rw-r--r-- | lib/libc/sparc64/fpu/fpu_subr.c | 5 |
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; |