fpu.c (94254) | fpu.c (95587) |
---|---|
1/* 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This software was developed by the Computer Systems Engineering group 6 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 7 * contributed to Berkeley. 8 * --- 53 unchanged lines hidden (view full) --- 62 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 63 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 64 * 65 * @(#)fpu.c 8.1 (Berkeley) 6/11/93 66 * $NetBSD: fpu.c,v 1.11 2000/12/06 01:47:50 mrg Exp $ 67 */ 68 69#include <sys/cdefs.h> | 1/* 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This software was developed by the Computer Systems Engineering group 6 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 7 * contributed to Berkeley. 8 * --- 53 unchanged lines hidden (view full) --- 62 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 63 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 64 * 65 * @(#)fpu.c 8.1 (Berkeley) 6/11/93 66 * $NetBSD: fpu.c,v 1.11 2000/12/06 01:47:50 mrg Exp $ 67 */ 68 69#include <sys/cdefs.h> |
70__FBSDID("$FreeBSD: head/lib/libc/sparc64/fpu/fpu.c 94254 2002-04-09 00:57:23Z jake $"); | 70__FBSDID("$FreeBSD: head/lib/libc/sparc64/fpu/fpu.c 95587 2002-04-27 21:56:28Z jake $"); |
71 72#include <sys/param.h> 73 74#include "namespace.h" 75#include <errno.h> 76#include <unistd.h> 77#include <signal.h> 78#include <stdlib.h> 79#include "un-namespace.h" 80#include "libc_private.h" 81 82#include <machine/emul.h> 83#include <machine/fp.h> 84#include <machine/frame.h> 85#include <machine/fsr.h> 86#include <machine/instr.h> 87#include <machine/pcb.h> 88#include <machine/tstate.h> 89 | 71 72#include <sys/param.h> 73 74#include "namespace.h" 75#include <errno.h> 76#include <unistd.h> 77#include <signal.h> 78#include <stdlib.h> 79#include "un-namespace.h" 80#include "libc_private.h" 81 82#include <machine/emul.h> 83#include <machine/fp.h> 84#include <machine/frame.h> 85#include <machine/fsr.h> 86#include <machine/instr.h> 87#include <machine/pcb.h> 88#include <machine/tstate.h> 89 |
90#include "../sys/__sparc_utrap_private.h" | 90#include "__sparc_utrap_private.h" |
91#include "fpu_emu.h" 92#include "fpu_extern.h" 93 94/* 95 * Translate current exceptions into `first' exception. The 96 * bits go the wrong way for ffs() (0x10 is most important, etc). 97 * There are only 5, so do it the obvious way. 98 */ --- 15 unchanged lines hidden (view full) --- 114#ifdef FPU_DEBUG_MASK 115int __fpe_debug = FPU_DEBUG_MASK; 116#else 117int __fpe_debug = 0; 118#endif 119#endif /* FPU_DEBUG */ 120 121static int __fpu_execute(struct utrapframe *, struct fpemu *, u_int32_t, u_long); | 91#include "fpu_emu.h" 92#include "fpu_extern.h" 93 94/* 95 * Translate current exceptions into `first' exception. The 96 * bits go the wrong way for ffs() (0x10 is most important, etc). 97 * There are only 5, so do it the obvious way. 98 */ --- 15 unchanged lines hidden (view full) --- 114#ifdef FPU_DEBUG_MASK 115int __fpe_debug = FPU_DEBUG_MASK; 116#else 117int __fpe_debug = 0; 118#endif 119#endif /* FPU_DEBUG */ 120 121static int __fpu_execute(struct utrapframe *, struct fpemu *, u_int32_t, u_long); |
122static void utrap_write(char *); 123static void utrap_kill_self(int); | |
124 125/* | 122 123/* |
126 * System call wrappers usable in an utrap environment. 127 */ 128static void 129utrap_write(char *str) 130{ 131 int berrno; 132 133 berrno = errno; 134 __sys_write(STDERR_FILENO, str, strlen(str)); 135 errno = berrno; 136} 137 138static void 139utrap_kill_self(sig) 140{ 141 int berrno; 142 143 berrno = errno; 144 __sys_kill(__sys_getpid(), sig); 145 errno = berrno; 146} 147 148void 149__fpu_panic(char *msg) 150{ 151 152 utrap_write(msg); 153 utrap_write("\n"); 154 utrap_kill_self(SIGKILL); 155} 156 157/* | |
158 * Need to use an fpstate on the stack; we could switch, so we cannot safely 159 * modify the pcb one, it might get overwritten. 160 */ | 124 * Need to use an fpstate on the stack; we could switch, so we cannot safely 125 * modify the pcb one, it might get overwritten. 126 */ |
161void | 127int |
162__fpu_exception(struct utrapframe *uf) 163{ 164 struct fpemu fe; 165 u_long fsr, tstate; 166 u_int insn; | 128__fpu_exception(struct utrapframe *uf) 129{ 130 struct fpemu fe; 131 u_long fsr, tstate; 132 u_int insn; |
167 int rv; | 133 int sig; |
168 169 fsr = uf->uf_fsr; 170 171 switch (FSR_GET_FTT(fsr)) { 172 case FSR_FTT_NONE: | 134 135 fsr = uf->uf_fsr; 136 137 switch (FSR_GET_FTT(fsr)) { 138 case FSR_FTT_NONE: |
173 utrap_write("lost FPU trap type\n"); 174 return; | 139 __utrap_write("lost FPU trap type\n"); 140 return (0); |
175 case FSR_FTT_IEEE: | 141 case FSR_FTT_IEEE: |
176 goto fatal; | 142 return (SIGFPE); |
177 case FSR_FTT_SEQERR: | 143 case FSR_FTT_SEQERR: |
178 utrap_write("FPU sequence error\n"); 179 goto fatal; | 144 __utrap_write("FPU sequence error\n"); 145 return (SIGFPE); |
180 case FSR_FTT_HWERR: | 146 case FSR_FTT_HWERR: |
181 utrap_write("FPU hardware error\n"); 182 goto fatal; | 147 __utrap_write("FPU hardware error\n"); 148 return (SIGFPE); |
183 case FSR_FTT_UNFIN: 184 case FSR_FTT_UNIMP: 185 break; 186 default: | 149 case FSR_FTT_UNFIN: 150 case FSR_FTT_UNIMP: 151 break; 152 default: |
187 utrap_write("unknown FPU error\n"); 188 goto fatal; | 153 __utrap_write("unknown FPU error\n"); 154 return (SIGFPE); |
189 } 190 191 fe.fe_fsr = fsr & ~FSR_FTT_MASK; 192 insn = *(u_int32_t *)uf->uf_pc; 193 if (IF_OP(insn) != IOP_MISC || (IF_F3_OP3(insn) != INS2_FPop1 && 194 IF_F3_OP3(insn) != INS2_FPop2)) | 155 } 156 157 fe.fe_fsr = fsr & ~FSR_FTT_MASK; 158 insn = *(u_int32_t *)uf->uf_pc; 159 if (IF_OP(insn) != IOP_MISC || (IF_F3_OP3(insn) != INS2_FPop1 && 160 IF_F3_OP3(insn) != INS2_FPop2)) |
195 __fpu_panic("bogus FP fault"); | 161 __utrap_panic("bogus FP fault"); |
196 tstate = uf->uf_state; | 162 tstate = uf->uf_state; |
197 rv = __fpu_execute(uf, &fe, insn, tstate); 198 if (rv != 0) 199 utrap_kill_self(rv); | 163 sig = __fpu_execute(uf, &fe, insn, tstate); 164 if (sig != 0) 165 return (sig); |
200 __asm __volatile("ldx %0, %%fsr" : : "m" (fe.fe_fsr)); | 166 __asm __volatile("ldx %0, %%fsr" : : "m" (fe.fe_fsr)); |
201 return; 202fatal: 203 utrap_kill_self(SIGFPE); 204 return; | 167 return (0); |
205} 206 207#ifdef FPU_DEBUG 208/* 209 * Dump a `fpn' structure. 210 */ 211void 212__fpu_dumpfpn(struct fpn *fp) --- 5 unchanged lines hidden (view full) --- 218 printf("%s %c.%x %x %x %xE%d", class[fp->fp_class + 2], 219 fp->fp_sign ? '-' : ' ', 220 fp->fp_mant[0], fp->fp_mant[1], 221 fp->fp_mant[2], fp->fp_mant[3], 222 fp->fp_exp); 223} 224#endif 225 | 168} 169 170#ifdef FPU_DEBUG 171/* 172 * Dump a `fpn' structure. 173 */ 174void 175__fpu_dumpfpn(struct fpn *fp) --- 5 unchanged lines hidden (view full) --- 181 printf("%s %c.%x %x %x %xE%d", class[fp->fp_class + 2], 182 fp->fp_sign ? '-' : ' ', 183 fp->fp_mant[0], fp->fp_mant[1], 184 fp->fp_mant[2], fp->fp_mant[3], 185 fp->fp_exp); 186} 187#endif 188 |
226static u_long 227fetch_reg(struct utrapframe *uf, int reg) 228{ 229 u_long offs; 230 struct frame *frm; 231 232 if (reg == IREG_G0) 233 return (0); 234 else if (reg < IREG_O0) /* global */ 235 return (uf->uf_global[reg]); 236 else if (reg < IREG_L0) /* out */ 237 return (uf->uf_out[reg - IREG_O0]); 238 else { /* local, in */ 239 /* 240 * The in registers are immediately after the locals in 241 * the frame. 242 */ 243 frm = (struct frame *)(uf->uf_out[6] + SPOFF); 244 return (frm->fr_local[reg - IREG_L0]); 245 } 246 __fpu_panic("fetch_reg: bogus register"); 247} 248 | |
249static void 250__fpu_mov(struct fpemu *fe, int type, int rd, int rs1, int rs2) 251{ 252 int i; 253 254 i = 1 << type; 255 __fpu_setreg(rd++, rs1); 256 while (--i) --- 99 unchanged lines hidden (view full) --- 356 __fpu_ccmov(fe, type, rd, __fpu_getreg(rs2), rs2, insn, 357 (tstate & TSTATE_ICC_MASK) >> TSTATE_ICC_SHIFT); 358 return (0); 359 case FOP(INS2_FPop2, INSFP2_FMOV_CC(IFCC_XCC)): 360 __fpu_ccmov(fe, type, rd, __fpu_getreg(rs2), rs2, insn, 361 (tstate & TSTATE_XCC_MASK) >> (TSTATE_XCC_SHIFT)); 362 return (0); 363 case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_Z)): | 189static void 190__fpu_mov(struct fpemu *fe, int type, int rd, int rs1, int rs2) 191{ 192 int i; 193 194 i = 1 << type; 195 __fpu_setreg(rd++, rs1); 196 while (--i) --- 99 unchanged lines hidden (view full) --- 296 __fpu_ccmov(fe, type, rd, __fpu_getreg(rs2), rs2, insn, 297 (tstate & TSTATE_ICC_MASK) >> TSTATE_ICC_SHIFT); 298 return (0); 299 case FOP(INS2_FPop2, INSFP2_FMOV_CC(IFCC_XCC)): 300 __fpu_ccmov(fe, type, rd, __fpu_getreg(rs2), rs2, insn, 301 (tstate & TSTATE_XCC_MASK) >> (TSTATE_XCC_SHIFT)); 302 return (0); 303 case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_Z)): |
364 reg = fetch_reg(uf, IF_F4_RS1(insn)); | 304 reg = __emul_fetch_reg(uf, IF_F4_RS1(insn)); |
365 if (reg == 0) 366 __fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2); 367 return (0); 368 case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_LEZ)): | 305 if (reg == 0) 306 __fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2); 307 return (0); 308 case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_LEZ)): |
369 reg = fetch_reg(uf, IF_F4_RS1(insn)); | 309 reg = __emul_fetch_reg(uf, IF_F4_RS1(insn)); |
370 if (reg <= 0) 371 __fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2); 372 return (0); 373 case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_LZ)): | 310 if (reg <= 0) 311 __fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2); 312 return (0); 313 case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_LZ)): |
374 reg = fetch_reg(uf, IF_F4_RS1(insn)); | 314 reg = __emul_fetch_reg(uf, IF_F4_RS1(insn)); |
375 if (reg < 0) 376 __fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2); 377 return (0); 378 case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_NZ)): | 315 if (reg < 0) 316 __fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2); 317 return (0); 318 case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_NZ)): |
379 reg = fetch_reg(uf, IF_F4_RS1(insn)); | 319 reg = __emul_fetch_reg(uf, IF_F4_RS1(insn)); |
380 if (reg != 0) 381 __fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2); 382 return (0); 383 case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_GZ)): | 320 if (reg != 0) 321 __fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2); 322 return (0); 323 case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_GZ)): |
384 reg = fetch_reg(uf, IF_F4_RS1(insn)); | 324 reg = __emul_fetch_reg(uf, IF_F4_RS1(insn)); |
385 if (reg > 0) 386 __fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2); 387 return (0); 388 case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_GEZ)): | 325 if (reg > 0) 326 __fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2); 327 return (0); 328 case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_GEZ)): |
389 reg = fetch_reg(uf, IF_F4_RS1(insn)); | 329 reg = __emul_fetch_reg(uf, IF_F4_RS1(insn)); |
390 if (reg >= 0) 391 __fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2); 392 return (0); 393 case FOP(INS2_FPop2, INSFP2_FCMP): 394 __fpu_explode(fe, &fe->fe_f1, type, rs1); 395 __fpu_explode(fe, &fe->fe_f2, type, rs2); 396 __fpu_compare(fe, 0, IF_F3_CC(insn)); 397 return (__fpu_cmpck(fe)); --- 113 unchanged lines hidden --- | 330 if (reg >= 0) 331 __fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2); 332 return (0); 333 case FOP(INS2_FPop2, INSFP2_FCMP): 334 __fpu_explode(fe, &fe->fe_f1, type, rs1); 335 __fpu_explode(fe, &fe->fe_f2, type, rs2); 336 __fpu_compare(fe, 0, IF_F3_CC(insn)); 337 return (__fpu_cmpck(fe)); --- 113 unchanged lines hidden --- |