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 * 9 * All advertising materials mentioning features or use of this software 10 * must display the following acknowledgement: 11 * This product includes software developed by the University of 12 * California, Lawrence Berkeley Laboratory. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 3. All advertising materials mentioning features or use of this software 23 * must display the following acknowledgement: 24 * This product includes software developed by the University of 25 * California, Berkeley and its contributors. 26 * 4. Neither the name of the University nor the names of its contributors 27 * may be used to endorse or promote products derived from this software 28 * without specific prior written permission. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 40 * SUCH DAMAGE. 41 */ 42/*- 43 * Copyright 2001 by Thomas Moestl <tmm@FreeBSD.org>. All rights reserved. 44 * 45 * Redistribution and use in source and binary forms, with or without 46 * modification, are permitted provided that the following conditions 47 * are met: 48 * 1. Redistributions of source code must retain the above copyright 49 * notice, this list of conditions and the following disclaimer. 50 * 2. Redistributions in binary form must reproduce the above copyright 51 * notice, this list of conditions and the following disclaimer in the 52 * documentation and/or other materials provided with the distribution. 53 * 54 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 55 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 56 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 57 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 58 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 59 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 60 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 61 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 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 * 9 * All advertising materials mentioning features or use of this software 10 * must display the following acknowledgement: 11 * This product includes software developed by the University of 12 * California, Lawrence Berkeley Laboratory. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 3. All advertising materials mentioning features or use of this software 23 * must display the following acknowledgement: 24 * This product includes software developed by the University of 25 * California, Berkeley and its contributors. 26 * 4. Neither the name of the University nor the names of its contributors 27 * may be used to endorse or promote products derived from this software 28 * without specific prior written permission. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 40 * SUCH DAMAGE. 41 */ 42/*- 43 * Copyright 2001 by Thomas Moestl <tmm@FreeBSD.org>. All rights reserved. 44 * 45 * Redistribution and use in source and binary forms, with or without 46 * modification, are permitted provided that the following conditions 47 * are met: 48 * 1. Redistributions of source code must retain the above copyright 49 * notice, this list of conditions and the following disclaimer. 50 * 2. Redistributions in binary form must reproduce the above copyright 51 * notice, this list of conditions and the following disclaimer in the 52 * documentation and/or other materials provided with the distribution. 53 * 54 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 55 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 56 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 57 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 58 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 59 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 60 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 61 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 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 95587 2002-04-27 21:56:28Z jake $");
| 70__FBSDID("$FreeBSD: head/lib/libc/sparc64/fpu/fpu.c 96422 2002-05-11 21:20:05Z 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 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 */ 99#define X1(x) x 100#define X2(x) x,x 101#define X4(x) x,x,x,x 102#define X8(x) X4(x),X4(x) 103#define X16(x) X8(x),X8(x) 104 105static char cx_to_trapx[] = { 106 X1(FSR_NX), 107 X2(FSR_DZ), 108 X4(FSR_UF), 109 X8(FSR_OF), 110 X16(FSR_NV) 111}; 112 113#ifdef FPU_DEBUG 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); 122 123/* 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 */ 127int 128__fpu_exception(struct utrapframe *uf) 129{ 130 struct fpemu fe; 131 u_long fsr, tstate; 132 u_int insn; 133 int sig; 134 135 fsr = uf->uf_fsr; 136 137 switch (FSR_GET_FTT(fsr)) { 138 case FSR_FTT_NONE: 139 __utrap_write("lost FPU trap type\n"); 140 return (0); 141 case FSR_FTT_IEEE: 142 return (SIGFPE); 143 case FSR_FTT_SEQERR: 144 __utrap_write("FPU sequence error\n"); 145 return (SIGFPE); 146 case FSR_FTT_HWERR: 147 __utrap_write("FPU hardware error\n"); 148 return (SIGFPE); 149 case FSR_FTT_UNFIN: 150 case FSR_FTT_UNIMP: 151 break; 152 default: 153 __utrap_write("unknown FPU error\n"); 154 return (SIGFPE); 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)) 161 __utrap_panic("bogus FP fault"); 162 tstate = uf->uf_state; 163 sig = __fpu_execute(uf, &fe, insn, tstate); 164 if (sig != 0) 165 return (sig); 166 __asm __volatile("ldx %0, %%fsr" : : "m" (fe.fe_fsr)); 167 return (0); 168} 169 170#ifdef FPU_DEBUG 171/* 172 * Dump a `fpn' structure. 173 */ 174void 175__fpu_dumpfpn(struct fpn *fp) 176{ 177 static char *class[] = { 178 "SNAN", "QNAN", "ZERO", "NUM", "INF" 179 }; 180 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
| 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 "__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 */ 99#define X1(x) x 100#define X2(x) x,x 101#define X4(x) x,x,x,x 102#define X8(x) X4(x),X4(x) 103#define X16(x) X8(x),X8(x) 104 105static char cx_to_trapx[] = { 106 X1(FSR_NX), 107 X2(FSR_DZ), 108 X4(FSR_UF), 109 X8(FSR_OF), 110 X16(FSR_NV) 111}; 112 113#ifdef FPU_DEBUG 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); 122 123/* 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 */ 127int 128__fpu_exception(struct utrapframe *uf) 129{ 130 struct fpemu fe; 131 u_long fsr, tstate; 132 u_int insn; 133 int sig; 134 135 fsr = uf->uf_fsr; 136 137 switch (FSR_GET_FTT(fsr)) { 138 case FSR_FTT_NONE: 139 __utrap_write("lost FPU trap type\n"); 140 return (0); 141 case FSR_FTT_IEEE: 142 return (SIGFPE); 143 case FSR_FTT_SEQERR: 144 __utrap_write("FPU sequence error\n"); 145 return (SIGFPE); 146 case FSR_FTT_HWERR: 147 __utrap_write("FPU hardware error\n"); 148 return (SIGFPE); 149 case FSR_FTT_UNFIN: 150 case FSR_FTT_UNIMP: 151 break; 152 default: 153 __utrap_write("unknown FPU error\n"); 154 return (SIGFPE); 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)) 161 __utrap_panic("bogus FP fault"); 162 tstate = uf->uf_state; 163 sig = __fpu_execute(uf, &fe, insn, tstate); 164 if (sig != 0) 165 return (sig); 166 __asm __volatile("ldx %0, %%fsr" : : "m" (fe.fe_fsr)); 167 return (0); 168} 169 170#ifdef FPU_DEBUG 171/* 172 * Dump a `fpn' structure. 173 */ 174void 175__fpu_dumpfpn(struct fpn *fp) 176{ 177 static char *class[] = { 178 "SNAN", "QNAN", "ZERO", "NUM", "INF" 179 }; 180 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
|
| 189static int opmask[] = {0, 0, 1, 3}; 190 191/* Decode 5 bit register field depending on the type. */ 192#define RN_DECODE(tp, rn) \ 193 ((tp == FTYPE_DBL || tp == FTYPE_EXT ? INSFPdq_RN((rn)) : (rn)) & \ 194 ~opmask[tp]) 195 196/* Operand size in 32-bit registers. */ 197#define OPSZ(tp) ((tp) == FTYPE_LNG ? 2 : (1 << (tp))) 198 199/* 200 * Helper for forming the below case statements. Build only the op3 and opf 201 * field of the instruction, these are the only ones that need to match. 202 */ 203#define FOP(op3, opf) \ 204 ((op3) << IF_F3_OP3_SHIFT | (opf) << IF_F3_OPF_SHIFT) 205 206/* 207 * Implement a move operation for all supported operand types. The additional 208 * nand and xor parameters will be applied to the upper 32 bit word of the 209 * source operand. This allows to implement fabs and fneg (for fp operands 210 * only!) using this functions, too, by passing (1 << 31) for one of the 211 * parameters, and 0 for the other. 212 */
|
189static void
| 213static void
|
190__fpu_mov(struct fpemu *fe, int type, int rd, int rs1, int rs2)
| 214__fpu_mov(struct fpemu *fe, int type, int rd, int rs2, u_int32_t nand, 215 u_int32_t xor)
|
191{
| 216{
|
| 217 u_int64_t tmp64; 218 u_int32_t *p32;
|
192 int i; 193
| 219 int i; 220
|
194 i = 1 << type; 195 __fpu_setreg(rd++, rs1); 196 while (--i) 197 __fpu_setreg(rd++, __fpu_getreg(++rs2));
| 221 if (type == FTYPE_INT || type == FTYPE_SNG) 222 __fpu_setreg(rd, (__fpu_getreg(rs2) & ~nand) ^ xor); 223 else { 224 /* 225 * Need to use the double versions to be able to access 226 * the upper 32 fp registers. 227 */ 228 for (i = 0; i < OPSZ(type); i += 2, rd += 2, rs2 += 2) { 229 tmp64 = __fpu_getreg64(rs2); 230 if (i == 0) 231 tmp64 = (tmp64 & ~((u_int64_t)nand << 32)) ^ 232 ((u_int64_t)xor << 32); 233 __fpu_setreg64(rd, tmp64); 234 } 235 }
|
198} 199 200static __inline void
| 236} 237 238static __inline void
|
201__fpu_ccmov(struct fpemu *fe, int type, int rd, int rs1, int rs2,
| 239__fpu_ccmov(struct fpemu *fe, int type, int rd, int rs2,
|
202 u_int32_t insn, int fcc) 203{ 204 205 if (IF_F4_COND(insn) == fcc)
| 240 u_int32_t insn, int fcc) 241{ 242 243 if (IF_F4_COND(insn) == fcc)
|
206 __fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2);
| 244 __fpu_mov(fe, type, rd, rs2, 0, 0);
|
207} 208 209static int 210__fpu_cmpck(struct fpemu *fe) 211{ 212 u_long fsr; 213 int cx; 214 215 /* 216 * The only possible exception here is NV; catch it 217 * early and get out, as there is no result register. 218 */ 219 cx = fe->fe_cx; 220 fsr = fe->fe_fsr | (cx << FSR_CEXC_SHIFT); 221 if (cx != 0) { 222 if (fsr & (FSR_NV << FSR_TEM_SHIFT)) { 223 fe->fe_fsr = (fsr & ~FSR_FTT_MASK) | 224 FSR_FTT(FSR_FTT_IEEE); 225 return (SIGFPE); 226 } 227 fsr |= FSR_NV << FSR_AEXC_SHIFT; 228 } 229 fe->fe_fsr = fsr; 230 return (0); 231} 232
| 245} 246 247static int 248__fpu_cmpck(struct fpemu *fe) 249{ 250 u_long fsr; 251 int cx; 252 253 /* 254 * The only possible exception here is NV; catch it 255 * early and get out, as there is no result register. 256 */ 257 cx = fe->fe_cx; 258 fsr = fe->fe_fsr | (cx << FSR_CEXC_SHIFT); 259 if (cx != 0) { 260 if (fsr & (FSR_NV << FSR_TEM_SHIFT)) { 261 fe->fe_fsr = (fsr & ~FSR_FTT_MASK) | 262 FSR_FTT(FSR_FTT_IEEE); 263 return (SIGFPE); 264 } 265 fsr |= FSR_NV << FSR_AEXC_SHIFT; 266 } 267 fe->fe_fsr = fsr; 268 return (0); 269} 270
|
233static int opmask[] = {0, 0, 1, 3}; 234
| |
235/*
| 271/*
|
236 * Helper for forming the below case statements. Build only the op3 and opf 237 * field of the instruction, these are the only that need to match. 238 */ 239#define FOP(op3, opf) \ 240 ((op3) << IF_F3_OP3_SHIFT | (opf) << IF_F3_OPF_SHIFT) 241 242/*
| |
243 * Execute an FPU instruction (one that runs entirely in the FPU; not 244 * FBfcc or STF, for instance). On return, fe->fe_fs->fs_fsr will be 245 * modified to reflect the setting the hardware would have left. 246 * 247 * Note that we do not catch all illegal opcodes, so you can, for instance, 248 * multiply two integers this way. 249 */ 250static int 251__fpu_execute(struct utrapframe *uf, struct fpemu *fe, u_int32_t insn, u_long tstate) 252{ 253 struct fpn *fp; 254 int opf, rs1, rs2, rd, type, mask, cx, cond; 255 u_long reg, fsr; 256 u_int space[4];
| 272 * Execute an FPU instruction (one that runs entirely in the FPU; not 273 * FBfcc or STF, for instance). On return, fe->fe_fs->fs_fsr will be 274 * modified to reflect the setting the hardware would have left. 275 * 276 * Note that we do not catch all illegal opcodes, so you can, for instance, 277 * multiply two integers this way. 278 */ 279static int 280__fpu_execute(struct utrapframe *uf, struct fpemu *fe, u_int32_t insn, u_long tstate) 281{ 282 struct fpn *fp; 283 int opf, rs1, rs2, rd, type, mask, cx, cond; 284 u_long reg, fsr; 285 u_int space[4];
|
| 286 int i;
|
257 258 /* 259 * `Decode' and execute instruction. Start with no exceptions. 260 * The type of any opf opcode is in the bottom two bits, so we 261 * squish them out here. 262 */ 263 opf = insn & (IF_MASK(IF_F3_OP3_SHIFT, IF_F3_OP3_BITS) | 264 IF_MASK(IF_F3_OPF_SHIFT + 2, IF_F3_OPF_BITS - 2)); 265 type = IF_F3_OPF(insn) & 3;
| 287 288 /* 289 * `Decode' and execute instruction. Start with no exceptions. 290 * The type of any opf opcode is in the bottom two bits, so we 291 * squish them out here. 292 */ 293 opf = insn & (IF_MASK(IF_F3_OP3_SHIFT, IF_F3_OP3_BITS) | 294 IF_MASK(IF_F3_OPF_SHIFT + 2, IF_F3_OPF_BITS - 2)); 295 type = IF_F3_OPF(insn) & 3;
|
266 mask = opmask[type]; 267 rs1 = IF_F3_RS1(insn) & ~mask; 268 rs2 = IF_F3_RS2(insn) & ~mask; 269 rd = IF_F3_RD(insn) & ~mask;
| 296 rs1 = RN_DECODE(type, IF_F3_RS1(insn)); 297 rs2 = RN_DECODE(type, IF_F3_RS2(insn)); 298 rd = RN_DECODE(type, IF_F3_RD(insn));
|
270 cond = 0; 271#ifdef notdef
| 299 cond = 0; 300#ifdef notdef
|
272 if ((rs1 | rs2 | rd) & mask)
| 301 if ((rs1 | rs2 | rd) & opmask[type])
|
273 return (SIGILL); 274#endif 275 fsr = fe->fe_fsr; 276 fe->fe_fsr &= ~FSR_CEXC_MASK; 277 fe->fe_cx = 0; 278 switch (opf) { 279 case FOP(INS2_FPop2, INSFP2_FMOV_CC(IFCC_FCC(0))):
| 302 return (SIGILL); 303#endif 304 fsr = fe->fe_fsr; 305 fe->fe_fsr &= ~FSR_CEXC_MASK; 306 fe->fe_cx = 0; 307 switch (opf) { 308 case FOP(INS2_FPop2, INSFP2_FMOV_CC(IFCC_FCC(0))):
|
280 __fpu_ccmov(fe, type, rd, __fpu_getreg(rs2), rs2, insn, 281 FSR_GET_FCC0(fsr));
| 309 __fpu_ccmov(fe, type, rd, rs2, insn, FSR_GET_FCC0(fsr));
|
282 return (0); 283 case FOP(INS2_FPop2, INSFP2_FMOV_CC(IFCC_FCC(1))):
| 310 return (0); 311 case FOP(INS2_FPop2, INSFP2_FMOV_CC(IFCC_FCC(1))):
|
284 __fpu_ccmov(fe, type, rd, __fpu_getreg(rs2), rs2, insn, 285 FSR_GET_FCC1(fsr));
| 312 __fpu_ccmov(fe, type, rd, rs2, insn, FSR_GET_FCC1(fsr));
|
286 return (0); 287 case FOP(INS2_FPop2, INSFP2_FMOV_CC(IFCC_FCC(2))):
| 313 return (0); 314 case FOP(INS2_FPop2, INSFP2_FMOV_CC(IFCC_FCC(2))):
|
288 __fpu_ccmov(fe, type, rd, __fpu_getreg(rs2), rs2, insn, 289 FSR_GET_FCC2(fsr));
| 315 __fpu_ccmov(fe, type, rd, rs2, insn, FSR_GET_FCC2(fsr));
|
290 return (0); 291 case FOP(INS2_FPop2, INSFP2_FMOV_CC(IFCC_FCC(3))):
| 316 return (0); 317 case FOP(INS2_FPop2, INSFP2_FMOV_CC(IFCC_FCC(3))):
|
292 __fpu_ccmov(fe, type, rd, __fpu_getreg(rs2), rs2, insn, 293 FSR_GET_FCC3(fsr));
| 318 __fpu_ccmov(fe, type, rd, rs2, insn, FSR_GET_FCC3(fsr));
|
294 return (0); 295 case FOP(INS2_FPop2, INSFP2_FMOV_CC(IFCC_ICC)):
| 319 return (0); 320 case FOP(INS2_FPop2, INSFP2_FMOV_CC(IFCC_ICC)):
|
296 __fpu_ccmov(fe, type, rd, __fpu_getreg(rs2), rs2, insn,
| 321 __fpu_ccmov(fe, type, rd, rs2, insn,
|
297 (tstate & TSTATE_ICC_MASK) >> TSTATE_ICC_SHIFT); 298 return (0); 299 case FOP(INS2_FPop2, INSFP2_FMOV_CC(IFCC_XCC)):
| 322 (tstate & TSTATE_ICC_MASK) >> TSTATE_ICC_SHIFT); 323 return (0); 324 case FOP(INS2_FPop2, INSFP2_FMOV_CC(IFCC_XCC)):
|
300 __fpu_ccmov(fe, type, rd, __fpu_getreg(rs2), rs2, insn,
| 325 __fpu_ccmov(fe, type, rd, rs2, insn,
|
301 (tstate & TSTATE_XCC_MASK) >> (TSTATE_XCC_SHIFT)); 302 return (0); 303 case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_Z)): 304 reg = __emul_fetch_reg(uf, IF_F4_RS1(insn)); 305 if (reg == 0)
| 326 (tstate & TSTATE_XCC_MASK) >> (TSTATE_XCC_SHIFT)); 327 return (0); 328 case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_Z)): 329 reg = __emul_fetch_reg(uf, IF_F4_RS1(insn)); 330 if (reg == 0)
|
306 __fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2);
| 331 __fpu_mov(fe, type, rd, rs2, 0, 0);
|
307 return (0); 308 case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_LEZ)): 309 reg = __emul_fetch_reg(uf, IF_F4_RS1(insn)); 310 if (reg <= 0)
| 332 return (0); 333 case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_LEZ)): 334 reg = __emul_fetch_reg(uf, IF_F4_RS1(insn)); 335 if (reg <= 0)
|
311 __fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2);
| 336 __fpu_mov(fe, type, rd, rs2, 0, 0);
|
312 return (0); 313 case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_LZ)): 314 reg = __emul_fetch_reg(uf, IF_F4_RS1(insn)); 315 if (reg < 0)
| 337 return (0); 338 case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_LZ)): 339 reg = __emul_fetch_reg(uf, IF_F4_RS1(insn)); 340 if (reg < 0)
|
316 __fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2);
| 341 __fpu_mov(fe, type, rd, rs2, 0, 0);
|
317 return (0); 318 case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_NZ)): 319 reg = __emul_fetch_reg(uf, IF_F4_RS1(insn)); 320 if (reg != 0)
| 342 return (0); 343 case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_NZ)): 344 reg = __emul_fetch_reg(uf, IF_F4_RS1(insn)); 345 if (reg != 0)
|
321 __fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2);
| 346 __fpu_mov(fe, type, rd, rs2, 0, 0);
|
322 return (0); 323 case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_GZ)): 324 reg = __emul_fetch_reg(uf, IF_F4_RS1(insn)); 325 if (reg > 0)
| 347 return (0); 348 case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_GZ)): 349 reg = __emul_fetch_reg(uf, IF_F4_RS1(insn)); 350 if (reg > 0)
|
326 __fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2);
| 351 __fpu_mov(fe, type, rd, rs2, 0, 0);
|
327 return (0); 328 case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_GEZ)): 329 reg = __emul_fetch_reg(uf, IF_F4_RS1(insn)); 330 if (reg >= 0)
| 352 return (0); 353 case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_GEZ)): 354 reg = __emul_fetch_reg(uf, IF_F4_RS1(insn)); 355 if (reg >= 0)
|
331 __fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2);
| 356 __fpu_mov(fe, type, rd, rs2, 0, 0);
|
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)); 338 case FOP(INS2_FPop2, INSFP2_FCMPE): 339 __fpu_explode(fe, &fe->fe_f1, type, rs1); 340 __fpu_explode(fe, &fe->fe_f2, type, rs2); 341 __fpu_compare(fe, 1, IF_F3_CC(insn)); 342 return (__fpu_cmpck(fe)); 343 case FOP(INS2_FPop1, INSFP1_FMOV): /* these should all be pretty obvious */
| 357 return (0); 358 case FOP(INS2_FPop2, INSFP2_FCMP): 359 __fpu_explode(fe, &fe->fe_f1, type, rs1); 360 __fpu_explode(fe, &fe->fe_f2, type, rs2); 361 __fpu_compare(fe, 0, IF_F3_CC(insn)); 362 return (__fpu_cmpck(fe)); 363 case FOP(INS2_FPop2, INSFP2_FCMPE): 364 __fpu_explode(fe, &fe->fe_f1, type, rs1); 365 __fpu_explode(fe, &fe->fe_f2, type, rs2); 366 __fpu_compare(fe, 1, IF_F3_CC(insn)); 367 return (__fpu_cmpck(fe)); 368 case FOP(INS2_FPop1, INSFP1_FMOV): /* these should all be pretty obvious */
|
344 __fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2);
| 369 __fpu_mov(fe, type, rd, rs2, 0, 0);
|
345 return (0); 346 case FOP(INS2_FPop1, INSFP1_FNEG):
| 370 return (0); 371 case FOP(INS2_FPop1, INSFP1_FNEG):
|
347 __fpu_mov(fe, type, rd, __fpu_getreg(rs2) ^ (1 << 31), rs2);
| 372 __fpu_mov(fe, type, rd, rs2, 0, (1 << 31));
|
348 return (0); 349 case FOP(INS2_FPop1, INSFP1_FABS):
| 373 return (0); 374 case FOP(INS2_FPop1, INSFP1_FABS):
|
350 __fpu_mov(fe, type, rd, __fpu_getreg(rs2) & ~(1 << 31), rs2);
| 375 __fpu_mov(fe, type, rd, rs2, (1 << 31), 0);
|
351 return (0); 352 case FOP(INS2_FPop1, INSFP1_FSQRT): 353 __fpu_explode(fe, &fe->fe_f1, type, rs2); 354 fp = __fpu_sqrt(fe); 355 break; 356 case FOP(INS2_FPop1, INSFP1_FADD): 357 __fpu_explode(fe, &fe->fe_f1, type, rs1); 358 __fpu_explode(fe, &fe->fe_f2, type, rs2); 359 fp = __fpu_add(fe); 360 break; 361 case FOP(INS2_FPop1, INSFP1_FSUB): 362 __fpu_explode(fe, &fe->fe_f1, type, rs1); 363 __fpu_explode(fe, &fe->fe_f2, type, rs2); 364 fp = __fpu_sub(fe); 365 break; 366 case FOP(INS2_FPop1, INSFP1_FMUL): 367 __fpu_explode(fe, &fe->fe_f1, type, rs1); 368 __fpu_explode(fe, &fe->fe_f2, type, rs2); 369 fp = __fpu_mul(fe); 370 break; 371 case FOP(INS2_FPop1, INSFP1_FDIV): 372 __fpu_explode(fe, &fe->fe_f1, type, rs1); 373 __fpu_explode(fe, &fe->fe_f2, type, rs2); 374 fp = __fpu_div(fe); 375 break; 376 case FOP(INS2_FPop1, INSFP1_FsMULd): 377 case FOP(INS2_FPop1, INSFP1_FdMULq): 378 if (type == FTYPE_EXT) 379 return (SIGILL); 380 __fpu_explode(fe, &fe->fe_f1, type, rs1); 381 __fpu_explode(fe, &fe->fe_f2, type, rs2); 382 type++; /* single to double, or double to quad */ 383 /* 384 * Recalculate rd (the old type applied for the source regs 385 * only, the target one has a different size). 386 */
| 376 return (0); 377 case FOP(INS2_FPop1, INSFP1_FSQRT): 378 __fpu_explode(fe, &fe->fe_f1, type, rs2); 379 fp = __fpu_sqrt(fe); 380 break; 381 case FOP(INS2_FPop1, INSFP1_FADD): 382 __fpu_explode(fe, &fe->fe_f1, type, rs1); 383 __fpu_explode(fe, &fe->fe_f2, type, rs2); 384 fp = __fpu_add(fe); 385 break; 386 case FOP(INS2_FPop1, INSFP1_FSUB): 387 __fpu_explode(fe, &fe->fe_f1, type, rs1); 388 __fpu_explode(fe, &fe->fe_f2, type, rs2); 389 fp = __fpu_sub(fe); 390 break; 391 case FOP(INS2_FPop1, INSFP1_FMUL): 392 __fpu_explode(fe, &fe->fe_f1, type, rs1); 393 __fpu_explode(fe, &fe->fe_f2, type, rs2); 394 fp = __fpu_mul(fe); 395 break; 396 case FOP(INS2_FPop1, INSFP1_FDIV): 397 __fpu_explode(fe, &fe->fe_f1, type, rs1); 398 __fpu_explode(fe, &fe->fe_f2, type, rs2); 399 fp = __fpu_div(fe); 400 break; 401 case FOP(INS2_FPop1, INSFP1_FsMULd): 402 case FOP(INS2_FPop1, INSFP1_FdMULq): 403 if (type == FTYPE_EXT) 404 return (SIGILL); 405 __fpu_explode(fe, &fe->fe_f1, type, rs1); 406 __fpu_explode(fe, &fe->fe_f2, type, rs2); 407 type++; /* single to double, or double to quad */ 408 /* 409 * Recalculate rd (the old type applied for the source regs 410 * only, the target one has a different size). 411 */
|
387 mask = opmask[type]; 388 rd = IF_F3_RD(insn) & ~mask;
| 412 rd = RN_DECODE(type, IF_F3_RD(insn));
|
389 fp = __fpu_mul(fe); 390 break; 391 case FOP(INS2_FPop1, INSFP1_FxTOs): 392 case FOP(INS2_FPop1, INSFP1_FxTOd): 393 case FOP(INS2_FPop1, INSFP1_FxTOq): 394 type = FTYPE_LNG; 395 __fpu_explode(fe, fp = &fe->fe_f1, type, rs2); 396 /* sneaky; depends on instruction encoding */ 397 type = (IF_F3_OPF(insn) >> 2) & 3;
| 413 fp = __fpu_mul(fe); 414 break; 415 case FOP(INS2_FPop1, INSFP1_FxTOs): 416 case FOP(INS2_FPop1, INSFP1_FxTOd): 417 case FOP(INS2_FPop1, INSFP1_FxTOq): 418 type = FTYPE_LNG; 419 __fpu_explode(fe, fp = &fe->fe_f1, type, rs2); 420 /* sneaky; depends on instruction encoding */ 421 type = (IF_F3_OPF(insn) >> 2) & 3;
|
398 mask = opmask[type]; 399 rd = IF_F3_RD(insn) & ~mask;
| 422 rd = RN_DECODE(type, IF_F3_RD(insn));
|
400 break; 401 case FOP(INS2_FPop1, INSFP1_FTOx): 402 __fpu_explode(fe, fp = &fe->fe_f1, type, rs2); 403 type = FTYPE_LNG; 404 mask = 1; /* needs 2 registers */ 405 rd = IF_F3_RD(insn) & ~mask; 406 break; 407 case FOP(INS2_FPop1, INSFP1_FTOs): 408 case FOP(INS2_FPop1, INSFP1_FTOd): 409 case FOP(INS2_FPop1, INSFP1_FTOq): 410 case FOP(INS2_FPop1, INSFP1_FTOi): 411 __fpu_explode(fe, fp = &fe->fe_f1, type, rs2); 412 /* sneaky; depends on instruction encoding */ 413 type = (IF_F3_OPF(insn) >> 2) & 3;
| 423 break; 424 case FOP(INS2_FPop1, INSFP1_FTOx): 425 __fpu_explode(fe, fp = &fe->fe_f1, type, rs2); 426 type = FTYPE_LNG; 427 mask = 1; /* needs 2 registers */ 428 rd = IF_F3_RD(insn) & ~mask; 429 break; 430 case FOP(INS2_FPop1, INSFP1_FTOs): 431 case FOP(INS2_FPop1, INSFP1_FTOd): 432 case FOP(INS2_FPop1, INSFP1_FTOq): 433 case FOP(INS2_FPop1, INSFP1_FTOi): 434 __fpu_explode(fe, fp = &fe->fe_f1, type, rs2); 435 /* sneaky; depends on instruction encoding */ 436 type = (IF_F3_OPF(insn) >> 2) & 3;
|
414 mask = opmask[type]; 415 rd = IF_F3_RD(insn) & ~mask;
| 437 rd = RN_DECODE(type, IF_F3_RD(insn));
|
416 break; 417 default: 418 return (SIGILL); 419 } 420 421 /* 422 * ALU operation is complete. Collapse the result and then check 423 * for exceptions. If we got any, and they are enabled, do not 424 * alter the destination register, just stop with an exception. 425 * Otherwise set new current exceptions and accrue. 426 */ 427 __fpu_implode(fe, fp, type, space); 428 cx = fe->fe_cx; 429 if (cx != 0) { 430 mask = (fsr >> FSR_TEM_SHIFT) & FSR_TEM_MASK; 431 if (cx & mask) { 432 /* not accrued??? */ 433 fsr = (fsr & ~FSR_FTT_MASK) | 434 FSR_FTT(FSR_FTT_IEEE) | 435 FSR_CEXC(cx_to_trapx[(cx & mask) - 1]); 436 return (SIGFPE); 437 } 438 fsr |= (cx << FSR_CEXC_SHIFT) | (cx << FSR_AEXC_SHIFT); 439 } 440 fe->fe_fsr = fsr;
| 438 break; 439 default: 440 return (SIGILL); 441 } 442 443 /* 444 * ALU operation is complete. Collapse the result and then check 445 * for exceptions. If we got any, and they are enabled, do not 446 * alter the destination register, just stop with an exception. 447 * Otherwise set new current exceptions and accrue. 448 */ 449 __fpu_implode(fe, fp, type, space); 450 cx = fe->fe_cx; 451 if (cx != 0) { 452 mask = (fsr >> FSR_TEM_SHIFT) & FSR_TEM_MASK; 453 if (cx & mask) { 454 /* not accrued??? */ 455 fsr = (fsr & ~FSR_FTT_MASK) | 456 FSR_FTT(FSR_FTT_IEEE) | 457 FSR_CEXC(cx_to_trapx[(cx & mask) - 1]); 458 return (SIGFPE); 459 } 460 fsr |= (cx << FSR_CEXC_SHIFT) | (cx << FSR_AEXC_SHIFT); 461 } 462 fe->fe_fsr = fsr;
|
441 __fpu_setreg(rd, space[0]); 442 if (type >= FTYPE_DBL || type == FTYPE_LNG) { 443 __fpu_setreg(rd + 1, space[1]); 444 if (type > FTYPE_DBL) { 445 __fpu_setreg(rd + 2, space[2]); 446 __fpu_setreg(rd + 3, space[3]);
| 463 if (type == FTYPE_INT || type == FTYPE_SNG) 464 __fpu_setreg(rd, space[0]); 465 else { 466 for (i = 0; i < OPSZ(type); i += 2) { 467 __fpu_setreg64(rd + i, ((u_int64_t)space[i] << 32) | 468 space[i + 1]);
|
447 } 448 } 449 return (0); /* success */ 450}
| 469 } 470 } 471 return (0); /* success */ 472}
|