Deleted Added
full compact
fpu.c (95587) fpu.c (96422)
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}