1*25c28e83SPiotr Jasiukajtis /*
2*25c28e83SPiotr Jasiukajtis * CDDL HEADER START
3*25c28e83SPiotr Jasiukajtis *
4*25c28e83SPiotr Jasiukajtis * The contents of this file are subject to the terms of the
5*25c28e83SPiotr Jasiukajtis * Common Development and Distribution License (the "License").
6*25c28e83SPiotr Jasiukajtis * You may not use this file except in compliance with the License.
7*25c28e83SPiotr Jasiukajtis *
8*25c28e83SPiotr Jasiukajtis * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*25c28e83SPiotr Jasiukajtis * or http://www.opensolaris.org/os/licensing.
10*25c28e83SPiotr Jasiukajtis * See the License for the specific language governing permissions
11*25c28e83SPiotr Jasiukajtis * and limitations under the License.
12*25c28e83SPiotr Jasiukajtis *
13*25c28e83SPiotr Jasiukajtis * When distributing Covered Code, include this CDDL HEADER in each
14*25c28e83SPiotr Jasiukajtis * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*25c28e83SPiotr Jasiukajtis * If applicable, add the following below this CDDL HEADER, with the
16*25c28e83SPiotr Jasiukajtis * fields enclosed by brackets "[]" replaced with your own identifying
17*25c28e83SPiotr Jasiukajtis * information: Portions Copyright [yyyy] [name of copyright owner]
18*25c28e83SPiotr Jasiukajtis *
19*25c28e83SPiotr Jasiukajtis * CDDL HEADER END
20*25c28e83SPiotr Jasiukajtis */
21*25c28e83SPiotr Jasiukajtis
22*25c28e83SPiotr Jasiukajtis /*
23*25c28e83SPiotr Jasiukajtis * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
24*25c28e83SPiotr Jasiukajtis */
25*25c28e83SPiotr Jasiukajtis /*
26*25c28e83SPiotr Jasiukajtis * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
27*25c28e83SPiotr Jasiukajtis * Use is subject to license terms.
28*25c28e83SPiotr Jasiukajtis */
29*25c28e83SPiotr Jasiukajtis
30*25c28e83SPiotr Jasiukajtis #if defined(__sparc)
31*25c28e83SPiotr Jasiukajtis #include <stdio.h>
32*25c28e83SPiotr Jasiukajtis #include <unistd.h>
33*25c28e83SPiotr Jasiukajtis #include <string.h>
34*25c28e83SPiotr Jasiukajtis #include <signal.h>
35*25c28e83SPiotr Jasiukajtis #include <siginfo.h>
36*25c28e83SPiotr Jasiukajtis #include <thread.h>
37*25c28e83SPiotr Jasiukajtis #include <ucontext.h>
38*25c28e83SPiotr Jasiukajtis #include <math.h>
39*25c28e83SPiotr Jasiukajtis #if defined(__SUNPRO_C)
40*25c28e83SPiotr Jasiukajtis #include <sunmath.h>
41*25c28e83SPiotr Jasiukajtis #endif
42*25c28e83SPiotr Jasiukajtis #include <fenv.h>
43*25c28e83SPiotr Jasiukajtis
44*25c28e83SPiotr Jasiukajtis #include "fenv_inlines.h"
45*25c28e83SPiotr Jasiukajtis #include "libm_inlines.h"
46*25c28e83SPiotr Jasiukajtis
47*25c28e83SPiotr Jasiukajtis #ifdef __sparcv9
48*25c28e83SPiotr Jasiukajtis
49*25c28e83SPiotr Jasiukajtis #define FPreg(X) &uap->uc_mcontext.fpregs.fpu_fr.fpu_regs[X]
50*25c28e83SPiotr Jasiukajtis
51*25c28e83SPiotr Jasiukajtis #define FPREG(X) &uap->uc_mcontext.fpregs.fpu_fr.fpu_dregs[(X>>1)| \
52*25c28e83SPiotr Jasiukajtis ((X&1)<<4)]
53*25c28e83SPiotr Jasiukajtis
54*25c28e83SPiotr Jasiukajtis #else
55*25c28e83SPiotr Jasiukajtis
56*25c28e83SPiotr Jasiukajtis #include <sys/procfs.h>
57*25c28e83SPiotr Jasiukajtis
58*25c28e83SPiotr Jasiukajtis #define FPxreg(X) &((prxregset_t*)uap->uc_mcontext.xrs.xrs_ptr)->pr_un.pr_v8p.pr_xfr.pr_regs[X]
59*25c28e83SPiotr Jasiukajtis
60*25c28e83SPiotr Jasiukajtis #define FPreg(X) &uap->uc_mcontext.fpregs.fpu_fr.fpu_regs[X]
61*25c28e83SPiotr Jasiukajtis
62*25c28e83SPiotr Jasiukajtis #define FPREG(X) ((X & 1)? FPxreg(X - 1) : FPreg(X))
63*25c28e83SPiotr Jasiukajtis
64*25c28e83SPiotr Jasiukajtis #endif /* __sparcv9 */
65*25c28e83SPiotr Jasiukajtis
66*25c28e83SPiotr Jasiukajtis #include "fex_handler.h"
67*25c28e83SPiotr Jasiukajtis
68*25c28e83SPiotr Jasiukajtis /* avoid dependence on libsunmath */
69*25c28e83SPiotr Jasiukajtis static enum fp_class_type
my_fp_classl(long double * a)70*25c28e83SPiotr Jasiukajtis my_fp_classl(long double *a)
71*25c28e83SPiotr Jasiukajtis {
72*25c28e83SPiotr Jasiukajtis int msw = *(int*)a & ~0x80000000;
73*25c28e83SPiotr Jasiukajtis
74*25c28e83SPiotr Jasiukajtis if (msw >= 0x7fff0000) {
75*25c28e83SPiotr Jasiukajtis if (((msw & 0xffff) | *(1+(int*)a) | *(2+(int*)a) | *(3+(int*)a)) == 0)
76*25c28e83SPiotr Jasiukajtis return fp_infinity;
77*25c28e83SPiotr Jasiukajtis else if (msw & 0x8000)
78*25c28e83SPiotr Jasiukajtis return fp_quiet;
79*25c28e83SPiotr Jasiukajtis else
80*25c28e83SPiotr Jasiukajtis return fp_signaling;
81*25c28e83SPiotr Jasiukajtis } else if (msw < 0x10000) {
82*25c28e83SPiotr Jasiukajtis if ((msw | *(1+(int*)a) | *(2+(int*)a) | *(3+(int*)a)) == 0)
83*25c28e83SPiotr Jasiukajtis return fp_zero;
84*25c28e83SPiotr Jasiukajtis else
85*25c28e83SPiotr Jasiukajtis return fp_subnormal;
86*25c28e83SPiotr Jasiukajtis } else
87*25c28e83SPiotr Jasiukajtis return fp_normal;
88*25c28e83SPiotr Jasiukajtis }
89*25c28e83SPiotr Jasiukajtis
90*25c28e83SPiotr Jasiukajtis /*
91*25c28e83SPiotr Jasiukajtis * Determine which type of invalid operation exception occurred
92*25c28e83SPiotr Jasiukajtis */
93*25c28e83SPiotr Jasiukajtis enum fex_exception
__fex_get_invalid_type(siginfo_t * sip,ucontext_t * uap)94*25c28e83SPiotr Jasiukajtis __fex_get_invalid_type(siginfo_t *sip, ucontext_t *uap)
95*25c28e83SPiotr Jasiukajtis {
96*25c28e83SPiotr Jasiukajtis unsigned instr, opf, rs1, rs2;
97*25c28e83SPiotr Jasiukajtis enum fp_class_type t1, t2;
98*25c28e83SPiotr Jasiukajtis
99*25c28e83SPiotr Jasiukajtis /* parse the instruction which caused the exception */
100*25c28e83SPiotr Jasiukajtis instr = uap->uc_mcontext.fpregs.fpu_q->FQu.fpq.fpq_instr;
101*25c28e83SPiotr Jasiukajtis opf = (instr >> 5) & 0x1ff;
102*25c28e83SPiotr Jasiukajtis rs1 = (instr >> 14) & 0x1f;
103*25c28e83SPiotr Jasiukajtis rs2 = instr & 0x1f;
104*25c28e83SPiotr Jasiukajtis
105*25c28e83SPiotr Jasiukajtis /* determine the classes of the operands */
106*25c28e83SPiotr Jasiukajtis switch (opf & 3) {
107*25c28e83SPiotr Jasiukajtis case 1: /* single */
108*25c28e83SPiotr Jasiukajtis t1 = fp_classf(*(float*)FPreg(rs1));
109*25c28e83SPiotr Jasiukajtis t2 = fp_classf(*(float*)FPreg(rs2));
110*25c28e83SPiotr Jasiukajtis break;
111*25c28e83SPiotr Jasiukajtis
112*25c28e83SPiotr Jasiukajtis case 2: /* double */
113*25c28e83SPiotr Jasiukajtis t1 = fp_class(*(double*)FPREG(rs1));
114*25c28e83SPiotr Jasiukajtis t2 = fp_class(*(double*)FPREG(rs2));
115*25c28e83SPiotr Jasiukajtis break;
116*25c28e83SPiotr Jasiukajtis
117*25c28e83SPiotr Jasiukajtis case 3: /* quad */
118*25c28e83SPiotr Jasiukajtis t1 = my_fp_classl((long double*)FPREG(rs1));
119*25c28e83SPiotr Jasiukajtis t2 = my_fp_classl((long double*)FPREG(rs2));
120*25c28e83SPiotr Jasiukajtis break;
121*25c28e83SPiotr Jasiukajtis
122*25c28e83SPiotr Jasiukajtis default: /* integer operands never cause an invalid operation */
123*25c28e83SPiotr Jasiukajtis return (enum fex_exception) -1;
124*25c28e83SPiotr Jasiukajtis }
125*25c28e83SPiotr Jasiukajtis
126*25c28e83SPiotr Jasiukajtis /* if rs2 is snan, return immediately */
127*25c28e83SPiotr Jasiukajtis if (t2 == fp_signaling)
128*25c28e83SPiotr Jasiukajtis return fex_inv_snan;
129*25c28e83SPiotr Jasiukajtis
130*25c28e83SPiotr Jasiukajtis /* determine the type of operation */
131*25c28e83SPiotr Jasiukajtis switch ((instr >> 19) & 0x183f) {
132*25c28e83SPiotr Jasiukajtis case 0x1034: /* add, subtract, multiply, divide, square root, convert */
133*25c28e83SPiotr Jasiukajtis switch (opf & 0x1fc) {
134*25c28e83SPiotr Jasiukajtis case 0x40:
135*25c28e83SPiotr Jasiukajtis case 0x44: /* add or subtract */
136*25c28e83SPiotr Jasiukajtis if (t1 == fp_signaling)
137*25c28e83SPiotr Jasiukajtis return fex_inv_snan;
138*25c28e83SPiotr Jasiukajtis else
139*25c28e83SPiotr Jasiukajtis return fex_inv_isi;
140*25c28e83SPiotr Jasiukajtis
141*25c28e83SPiotr Jasiukajtis case 0x48:
142*25c28e83SPiotr Jasiukajtis case 0x68:
143*25c28e83SPiotr Jasiukajtis case 0x6c: /* multiply */
144*25c28e83SPiotr Jasiukajtis if (t1 == fp_signaling)
145*25c28e83SPiotr Jasiukajtis return fex_inv_snan;
146*25c28e83SPiotr Jasiukajtis else
147*25c28e83SPiotr Jasiukajtis return fex_inv_zmi;
148*25c28e83SPiotr Jasiukajtis
149*25c28e83SPiotr Jasiukajtis case 0x4c: /* divide */
150*25c28e83SPiotr Jasiukajtis if (t1 == fp_signaling)
151*25c28e83SPiotr Jasiukajtis return fex_inv_snan;
152*25c28e83SPiotr Jasiukajtis else if (t1 == fp_zero)
153*25c28e83SPiotr Jasiukajtis return fex_inv_zdz;
154*25c28e83SPiotr Jasiukajtis else
155*25c28e83SPiotr Jasiukajtis return fex_inv_idi;
156*25c28e83SPiotr Jasiukajtis
157*25c28e83SPiotr Jasiukajtis case 0x28: /* square root */
158*25c28e83SPiotr Jasiukajtis return fex_inv_sqrt;
159*25c28e83SPiotr Jasiukajtis
160*25c28e83SPiotr Jasiukajtis case 0x80:
161*25c28e83SPiotr Jasiukajtis case 0xd0: /* convert to integer */
162*25c28e83SPiotr Jasiukajtis return fex_inv_int;
163*25c28e83SPiotr Jasiukajtis }
164*25c28e83SPiotr Jasiukajtis break;
165*25c28e83SPiotr Jasiukajtis
166*25c28e83SPiotr Jasiukajtis case 0x1035: /* compare */
167*25c28e83SPiotr Jasiukajtis if (t1 == fp_signaling)
168*25c28e83SPiotr Jasiukajtis return fex_inv_snan;
169*25c28e83SPiotr Jasiukajtis else
170*25c28e83SPiotr Jasiukajtis return fex_inv_cmp;
171*25c28e83SPiotr Jasiukajtis }
172*25c28e83SPiotr Jasiukajtis
173*25c28e83SPiotr Jasiukajtis return (enum fex_exception) -1;
174*25c28e83SPiotr Jasiukajtis }
175*25c28e83SPiotr Jasiukajtis
176*25c28e83SPiotr Jasiukajtis #ifdef __sparcv9
177*25c28e83SPiotr Jasiukajtis extern void _Qp_sqrt(long double *, const long double *);
178*25c28e83SPiotr Jasiukajtis #else
179*25c28e83SPiotr Jasiukajtis extern long double _Q_sqrt(long double);
180*25c28e83SPiotr Jasiukajtis #endif
181*25c28e83SPiotr Jasiukajtis
182*25c28e83SPiotr Jasiukajtis /*
183*25c28e83SPiotr Jasiukajtis * Get the operands, generate the default untrapped result with
184*25c28e83SPiotr Jasiukajtis * exceptions, and set a code indicating the type of operation
185*25c28e83SPiotr Jasiukajtis */
186*25c28e83SPiotr Jasiukajtis void
__fex_get_op(siginfo_t * sip,ucontext_t * uap,fex_info_t * info)187*25c28e83SPiotr Jasiukajtis __fex_get_op(siginfo_t *sip, ucontext_t *uap, fex_info_t *info)
188*25c28e83SPiotr Jasiukajtis {
189*25c28e83SPiotr Jasiukajtis unsigned long fsr;
190*25c28e83SPiotr Jasiukajtis unsigned instr, opf, rs1, rs2;
191*25c28e83SPiotr Jasiukajtis volatile int c;
192*25c28e83SPiotr Jasiukajtis
193*25c28e83SPiotr Jasiukajtis /* parse the instruction which caused the exception */
194*25c28e83SPiotr Jasiukajtis instr = uap->uc_mcontext.fpregs.fpu_q->FQu.fpq.fpq_instr;
195*25c28e83SPiotr Jasiukajtis opf = (instr >> 5) & 0x1ff;
196*25c28e83SPiotr Jasiukajtis rs1 = (instr >> 14) & 0x1f;
197*25c28e83SPiotr Jasiukajtis rs2 = instr & 0x1f;
198*25c28e83SPiotr Jasiukajtis
199*25c28e83SPiotr Jasiukajtis /* get the operands */
200*25c28e83SPiotr Jasiukajtis switch (opf & 3) {
201*25c28e83SPiotr Jasiukajtis case 0: /* integer */
202*25c28e83SPiotr Jasiukajtis info->op1.type = fex_nodata;
203*25c28e83SPiotr Jasiukajtis if (opf & 0x40) {
204*25c28e83SPiotr Jasiukajtis info->op2.type = fex_int;
205*25c28e83SPiotr Jasiukajtis info->op2.val.i = *(int*)FPreg(rs2);
206*25c28e83SPiotr Jasiukajtis }
207*25c28e83SPiotr Jasiukajtis else {
208*25c28e83SPiotr Jasiukajtis info->op2.type = fex_llong;
209*25c28e83SPiotr Jasiukajtis info->op2.val.l = *(long long*)FPREG(rs2);
210*25c28e83SPiotr Jasiukajtis }
211*25c28e83SPiotr Jasiukajtis break;
212*25c28e83SPiotr Jasiukajtis
213*25c28e83SPiotr Jasiukajtis case 1: /* single */
214*25c28e83SPiotr Jasiukajtis info->op1.type = info->op2.type = fex_float;
215*25c28e83SPiotr Jasiukajtis info->op1.val.f = *(float*)FPreg(rs1);
216*25c28e83SPiotr Jasiukajtis info->op2.val.f = *(float*)FPreg(rs2);
217*25c28e83SPiotr Jasiukajtis break;
218*25c28e83SPiotr Jasiukajtis
219*25c28e83SPiotr Jasiukajtis case 2: /* double */
220*25c28e83SPiotr Jasiukajtis info->op1.type = info->op2.type = fex_double;
221*25c28e83SPiotr Jasiukajtis info->op1.val.d = *(double*)FPREG(rs1);
222*25c28e83SPiotr Jasiukajtis info->op2.val.d = *(double*)FPREG(rs2);
223*25c28e83SPiotr Jasiukajtis break;
224*25c28e83SPiotr Jasiukajtis
225*25c28e83SPiotr Jasiukajtis case 3: /* quad */
226*25c28e83SPiotr Jasiukajtis info->op1.type = info->op2.type = fex_ldouble;
227*25c28e83SPiotr Jasiukajtis info->op1.val.q = *(long double*)FPREG(rs1);
228*25c28e83SPiotr Jasiukajtis info->op2.val.q = *(long double*)FPREG(rs2);
229*25c28e83SPiotr Jasiukajtis break;
230*25c28e83SPiotr Jasiukajtis }
231*25c28e83SPiotr Jasiukajtis
232*25c28e83SPiotr Jasiukajtis /* initialize res to the default untrapped result and ex to the
233*25c28e83SPiotr Jasiukajtis corresponding flags (assume trapping is disabled and flags
234*25c28e83SPiotr Jasiukajtis are clear) */
235*25c28e83SPiotr Jasiukajtis info->op = fex_other;
236*25c28e83SPiotr Jasiukajtis info->res.type = fex_nodata;
237*25c28e83SPiotr Jasiukajtis switch ((instr >> 19) & 0x183f) {
238*25c28e83SPiotr Jasiukajtis case 0x1035: /* compare */
239*25c28e83SPiotr Jasiukajtis info->op = fex_cmp;
240*25c28e83SPiotr Jasiukajtis switch (opf) {
241*25c28e83SPiotr Jasiukajtis case 0x51: /* compare single */
242*25c28e83SPiotr Jasiukajtis c = (info->op1.val.f == info->op2.val.f);
243*25c28e83SPiotr Jasiukajtis break;
244*25c28e83SPiotr Jasiukajtis
245*25c28e83SPiotr Jasiukajtis case 0x52: /* compare double */
246*25c28e83SPiotr Jasiukajtis c = (info->op1.val.d == info->op2.val.d);
247*25c28e83SPiotr Jasiukajtis break;
248*25c28e83SPiotr Jasiukajtis
249*25c28e83SPiotr Jasiukajtis case 0x53: /* compare quad */
250*25c28e83SPiotr Jasiukajtis c = (info->op1.val.q == info->op2.val.q);
251*25c28e83SPiotr Jasiukajtis break;
252*25c28e83SPiotr Jasiukajtis
253*25c28e83SPiotr Jasiukajtis case 0x55: /* compare single with exception */
254*25c28e83SPiotr Jasiukajtis c = (info->op1.val.f < info->op2.val.f);
255*25c28e83SPiotr Jasiukajtis break;
256*25c28e83SPiotr Jasiukajtis
257*25c28e83SPiotr Jasiukajtis case 0x56: /* compare double with exception */
258*25c28e83SPiotr Jasiukajtis c = (info->op1.val.d < info->op2.val.d);
259*25c28e83SPiotr Jasiukajtis break;
260*25c28e83SPiotr Jasiukajtis
261*25c28e83SPiotr Jasiukajtis case 0x57: /* compare quad with exception */
262*25c28e83SPiotr Jasiukajtis c = (info->op1.val.q < info->op2.val.q);
263*25c28e83SPiotr Jasiukajtis break;
264*25c28e83SPiotr Jasiukajtis }
265*25c28e83SPiotr Jasiukajtis break;
266*25c28e83SPiotr Jasiukajtis
267*25c28e83SPiotr Jasiukajtis case 0x1034: /* add, subtract, multiply, divide, square root, convert */
268*25c28e83SPiotr Jasiukajtis switch (opf) {
269*25c28e83SPiotr Jasiukajtis case 0x41: /* add single */
270*25c28e83SPiotr Jasiukajtis info->op = fex_add;
271*25c28e83SPiotr Jasiukajtis info->res.type = fex_float;
272*25c28e83SPiotr Jasiukajtis info->res.val.f = info->op1.val.f + info->op2.val.f;
273*25c28e83SPiotr Jasiukajtis break;
274*25c28e83SPiotr Jasiukajtis
275*25c28e83SPiotr Jasiukajtis case 0x42: /* add double */
276*25c28e83SPiotr Jasiukajtis info->op = fex_add;
277*25c28e83SPiotr Jasiukajtis info->res.type = fex_double;
278*25c28e83SPiotr Jasiukajtis info->res.val.d = info->op1.val.d + info->op2.val.d;
279*25c28e83SPiotr Jasiukajtis break;
280*25c28e83SPiotr Jasiukajtis
281*25c28e83SPiotr Jasiukajtis case 0x43: /* add quad */
282*25c28e83SPiotr Jasiukajtis info->op = fex_add;
283*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble;
284*25c28e83SPiotr Jasiukajtis info->res.val.q = info->op1.val.q + info->op2.val.q;
285*25c28e83SPiotr Jasiukajtis break;
286*25c28e83SPiotr Jasiukajtis
287*25c28e83SPiotr Jasiukajtis case 0x45: /* subtract single */
288*25c28e83SPiotr Jasiukajtis info->op = fex_sub;
289*25c28e83SPiotr Jasiukajtis info->res.type = fex_float;
290*25c28e83SPiotr Jasiukajtis info->res.val.f = info->op1.val.f - info->op2.val.f;
291*25c28e83SPiotr Jasiukajtis break;
292*25c28e83SPiotr Jasiukajtis
293*25c28e83SPiotr Jasiukajtis case 0x46: /* subtract double */
294*25c28e83SPiotr Jasiukajtis info->op = fex_sub;
295*25c28e83SPiotr Jasiukajtis info->res.type = fex_double;
296*25c28e83SPiotr Jasiukajtis info->res.val.d = info->op1.val.d - info->op2.val.d;
297*25c28e83SPiotr Jasiukajtis break;
298*25c28e83SPiotr Jasiukajtis
299*25c28e83SPiotr Jasiukajtis case 0x47: /* subtract quad */
300*25c28e83SPiotr Jasiukajtis info->op = fex_sub;
301*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble;
302*25c28e83SPiotr Jasiukajtis info->res.val.q = info->op1.val.q - info->op2.val.q;
303*25c28e83SPiotr Jasiukajtis break;
304*25c28e83SPiotr Jasiukajtis
305*25c28e83SPiotr Jasiukajtis case 0x49: /* multiply single */
306*25c28e83SPiotr Jasiukajtis info->op = fex_mul;
307*25c28e83SPiotr Jasiukajtis info->res.type = fex_float;
308*25c28e83SPiotr Jasiukajtis info->res.val.f = info->op1.val.f * info->op2.val.f;
309*25c28e83SPiotr Jasiukajtis break;
310*25c28e83SPiotr Jasiukajtis
311*25c28e83SPiotr Jasiukajtis case 0x4a: /* multiply double */
312*25c28e83SPiotr Jasiukajtis info->op = fex_mul;
313*25c28e83SPiotr Jasiukajtis info->res.type = fex_double;
314*25c28e83SPiotr Jasiukajtis info->res.val.d = info->op1.val.d * info->op2.val.d;
315*25c28e83SPiotr Jasiukajtis break;
316*25c28e83SPiotr Jasiukajtis
317*25c28e83SPiotr Jasiukajtis case 0x4b: /* multiply quad */
318*25c28e83SPiotr Jasiukajtis info->op = fex_mul;
319*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble;
320*25c28e83SPiotr Jasiukajtis info->res.val.q = info->op1.val.q * info->op2.val.q;
321*25c28e83SPiotr Jasiukajtis break;
322*25c28e83SPiotr Jasiukajtis
323*25c28e83SPiotr Jasiukajtis case 0x69: /* fsmuld */
324*25c28e83SPiotr Jasiukajtis info->op = fex_mul;
325*25c28e83SPiotr Jasiukajtis info->res.type = fex_double;
326*25c28e83SPiotr Jasiukajtis info->res.val.d = (double)info->op1.val.f * (double)info->op2.val.f;
327*25c28e83SPiotr Jasiukajtis break;
328*25c28e83SPiotr Jasiukajtis
329*25c28e83SPiotr Jasiukajtis case 0x6e: /* fdmulq */
330*25c28e83SPiotr Jasiukajtis info->op = fex_mul;
331*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble;
332*25c28e83SPiotr Jasiukajtis info->res.val.q = (long double)info->op1.val.d *
333*25c28e83SPiotr Jasiukajtis (long double)info->op2.val.d;
334*25c28e83SPiotr Jasiukajtis break;
335*25c28e83SPiotr Jasiukajtis
336*25c28e83SPiotr Jasiukajtis case 0x4d: /* divide single */
337*25c28e83SPiotr Jasiukajtis info->op = fex_div;
338*25c28e83SPiotr Jasiukajtis info->res.type = fex_float;
339*25c28e83SPiotr Jasiukajtis info->res.val.f = info->op1.val.f / info->op2.val.f;
340*25c28e83SPiotr Jasiukajtis break;
341*25c28e83SPiotr Jasiukajtis
342*25c28e83SPiotr Jasiukajtis case 0x4e: /* divide double */
343*25c28e83SPiotr Jasiukajtis info->op = fex_div;
344*25c28e83SPiotr Jasiukajtis info->res.type = fex_double;
345*25c28e83SPiotr Jasiukajtis info->res.val.d = info->op1.val.d / info->op2.val.d;
346*25c28e83SPiotr Jasiukajtis break;
347*25c28e83SPiotr Jasiukajtis
348*25c28e83SPiotr Jasiukajtis case 0x4f: /* divide quad */
349*25c28e83SPiotr Jasiukajtis info->op = fex_div;
350*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble;
351*25c28e83SPiotr Jasiukajtis info->res.val.q = info->op1.val.q / info->op2.val.q;
352*25c28e83SPiotr Jasiukajtis break;
353*25c28e83SPiotr Jasiukajtis
354*25c28e83SPiotr Jasiukajtis case 0x29: /* square root single */
355*25c28e83SPiotr Jasiukajtis info->op = fex_sqrt;
356*25c28e83SPiotr Jasiukajtis info->op1 = info->op2;
357*25c28e83SPiotr Jasiukajtis info->op2.type = fex_nodata;
358*25c28e83SPiotr Jasiukajtis info->res.type = fex_float;
359*25c28e83SPiotr Jasiukajtis info->res.val.f = sqrtf(info->op1.val.f);
360*25c28e83SPiotr Jasiukajtis break;
361*25c28e83SPiotr Jasiukajtis
362*25c28e83SPiotr Jasiukajtis case 0x2a: /* square root double */
363*25c28e83SPiotr Jasiukajtis info->op = fex_sqrt;
364*25c28e83SPiotr Jasiukajtis info->op1 = info->op2;
365*25c28e83SPiotr Jasiukajtis info->op2.type = fex_nodata;
366*25c28e83SPiotr Jasiukajtis info->res.type = fex_double;
367*25c28e83SPiotr Jasiukajtis info->res.val.d = sqrt(info->op1.val.d);
368*25c28e83SPiotr Jasiukajtis break;
369*25c28e83SPiotr Jasiukajtis
370*25c28e83SPiotr Jasiukajtis case 0x2b: /* square root quad */
371*25c28e83SPiotr Jasiukajtis info->op = fex_sqrt;
372*25c28e83SPiotr Jasiukajtis info->op1 = info->op2;
373*25c28e83SPiotr Jasiukajtis info->op2.type = fex_nodata;
374*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble;
375*25c28e83SPiotr Jasiukajtis #ifdef __sparcv9
376*25c28e83SPiotr Jasiukajtis _Qp_sqrt(&info->res.val.q, &info->op1.val.q);
377*25c28e83SPiotr Jasiukajtis #else
378*25c28e83SPiotr Jasiukajtis info->res.val.q = _Q_sqrt(info->op1.val.q);
379*25c28e83SPiotr Jasiukajtis #endif
380*25c28e83SPiotr Jasiukajtis break;
381*25c28e83SPiotr Jasiukajtis
382*25c28e83SPiotr Jasiukajtis default: /* conversions */
383*25c28e83SPiotr Jasiukajtis info->op = fex_cnvt;
384*25c28e83SPiotr Jasiukajtis info->op1 = info->op2;
385*25c28e83SPiotr Jasiukajtis info->op2.type = fex_nodata;
386*25c28e83SPiotr Jasiukajtis switch (opf) {
387*25c28e83SPiotr Jasiukajtis case 0xd1: /* convert single to int */
388*25c28e83SPiotr Jasiukajtis info->res.type = fex_int;
389*25c28e83SPiotr Jasiukajtis info->res.val.i = (int) info->op1.val.f;
390*25c28e83SPiotr Jasiukajtis break;
391*25c28e83SPiotr Jasiukajtis
392*25c28e83SPiotr Jasiukajtis case 0xd2: /* convert double to int */
393*25c28e83SPiotr Jasiukajtis info->res.type = fex_int;
394*25c28e83SPiotr Jasiukajtis info->res.val.i = (int) info->op1.val.d;
395*25c28e83SPiotr Jasiukajtis break;
396*25c28e83SPiotr Jasiukajtis
397*25c28e83SPiotr Jasiukajtis case 0xd3: /* convert quad to int */
398*25c28e83SPiotr Jasiukajtis info->res.type = fex_int;
399*25c28e83SPiotr Jasiukajtis info->res.val.i = (int) info->op1.val.q;
400*25c28e83SPiotr Jasiukajtis break;
401*25c28e83SPiotr Jasiukajtis
402*25c28e83SPiotr Jasiukajtis case 0x81: /* convert single to long long */
403*25c28e83SPiotr Jasiukajtis info->res.type = fex_llong;
404*25c28e83SPiotr Jasiukajtis info->res.val.l = (long long) info->op1.val.f;
405*25c28e83SPiotr Jasiukajtis break;
406*25c28e83SPiotr Jasiukajtis
407*25c28e83SPiotr Jasiukajtis case 0x82: /* convert double to long long */
408*25c28e83SPiotr Jasiukajtis info->res.type = fex_llong;
409*25c28e83SPiotr Jasiukajtis info->res.val.l = (long long) info->op1.val.d;
410*25c28e83SPiotr Jasiukajtis break;
411*25c28e83SPiotr Jasiukajtis
412*25c28e83SPiotr Jasiukajtis case 0x83: /* convert quad to long long */
413*25c28e83SPiotr Jasiukajtis info->res.type = fex_llong;
414*25c28e83SPiotr Jasiukajtis info->res.val.l = (long long) info->op1.val.q;
415*25c28e83SPiotr Jasiukajtis break;
416*25c28e83SPiotr Jasiukajtis
417*25c28e83SPiotr Jasiukajtis case 0xc4: /* convert int to single */
418*25c28e83SPiotr Jasiukajtis info->res.type = fex_float;
419*25c28e83SPiotr Jasiukajtis info->res.val.f = (float) info->op1.val.i;
420*25c28e83SPiotr Jasiukajtis break;
421*25c28e83SPiotr Jasiukajtis
422*25c28e83SPiotr Jasiukajtis case 0x84: /* convert long long to single */
423*25c28e83SPiotr Jasiukajtis info->res.type = fex_float;
424*25c28e83SPiotr Jasiukajtis info->res.val.f = (float) info->op1.val.l;
425*25c28e83SPiotr Jasiukajtis break;
426*25c28e83SPiotr Jasiukajtis
427*25c28e83SPiotr Jasiukajtis case 0x88: /* convert long long to double */
428*25c28e83SPiotr Jasiukajtis info->res.type = fex_double;
429*25c28e83SPiotr Jasiukajtis info->res.val.d = (double) info->op1.val.l;
430*25c28e83SPiotr Jasiukajtis break;
431*25c28e83SPiotr Jasiukajtis
432*25c28e83SPiotr Jasiukajtis case 0xc6: /* convert double to single */
433*25c28e83SPiotr Jasiukajtis info->res.type = fex_float;
434*25c28e83SPiotr Jasiukajtis info->res.val.f = (float) info->op1.val.d;
435*25c28e83SPiotr Jasiukajtis break;
436*25c28e83SPiotr Jasiukajtis
437*25c28e83SPiotr Jasiukajtis case 0xc7: /* convert quad to single */
438*25c28e83SPiotr Jasiukajtis info->res.type = fex_float;
439*25c28e83SPiotr Jasiukajtis info->res.val.f = (float) info->op1.val.q;
440*25c28e83SPiotr Jasiukajtis break;
441*25c28e83SPiotr Jasiukajtis
442*25c28e83SPiotr Jasiukajtis case 0xc9: /* convert single to double */
443*25c28e83SPiotr Jasiukajtis info->res.type = fex_double;
444*25c28e83SPiotr Jasiukajtis info->res.val.d = (double) info->op1.val.f;
445*25c28e83SPiotr Jasiukajtis break;
446*25c28e83SPiotr Jasiukajtis
447*25c28e83SPiotr Jasiukajtis case 0xcb: /* convert quad to double */
448*25c28e83SPiotr Jasiukajtis info->res.type = fex_double;
449*25c28e83SPiotr Jasiukajtis info->res.val.d = (double) info->op1.val.q;
450*25c28e83SPiotr Jasiukajtis break;
451*25c28e83SPiotr Jasiukajtis
452*25c28e83SPiotr Jasiukajtis case 0xcd: /* convert single to quad */
453*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble;
454*25c28e83SPiotr Jasiukajtis info->res.val.q = (long double) info->op1.val.f;
455*25c28e83SPiotr Jasiukajtis break;
456*25c28e83SPiotr Jasiukajtis
457*25c28e83SPiotr Jasiukajtis case 0xce: /* convert double to quad */
458*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble;
459*25c28e83SPiotr Jasiukajtis info->res.val.q = (long double) info->op1.val.d;
460*25c28e83SPiotr Jasiukajtis break;
461*25c28e83SPiotr Jasiukajtis }
462*25c28e83SPiotr Jasiukajtis }
463*25c28e83SPiotr Jasiukajtis break;
464*25c28e83SPiotr Jasiukajtis }
465*25c28e83SPiotr Jasiukajtis __fenv_getfsr(&fsr);
466*25c28e83SPiotr Jasiukajtis info->flags = (int)__fenv_get_ex(fsr);
467*25c28e83SPiotr Jasiukajtis __fenv_set_ex(fsr, 0);
468*25c28e83SPiotr Jasiukajtis __fenv_setfsr(&fsr);
469*25c28e83SPiotr Jasiukajtis }
470*25c28e83SPiotr Jasiukajtis
471*25c28e83SPiotr Jasiukajtis /*
472*25c28e83SPiotr Jasiukajtis * Store the specified result; if no result is given but the exception
473*25c28e83SPiotr Jasiukajtis * is underflow or overflow, supply the default trapped result
474*25c28e83SPiotr Jasiukajtis */
475*25c28e83SPiotr Jasiukajtis void
__fex_st_result(siginfo_t * sip,ucontext_t * uap,fex_info_t * info)476*25c28e83SPiotr Jasiukajtis __fex_st_result(siginfo_t *sip, ucontext_t *uap, fex_info_t *info)
477*25c28e83SPiotr Jasiukajtis {
478*25c28e83SPiotr Jasiukajtis unsigned instr, opf, rs1, rs2, rd;
479*25c28e83SPiotr Jasiukajtis long double qscl;
480*25c28e83SPiotr Jasiukajtis double dscl;
481*25c28e83SPiotr Jasiukajtis float fscl;
482*25c28e83SPiotr Jasiukajtis
483*25c28e83SPiotr Jasiukajtis /* parse the instruction which caused the exception */
484*25c28e83SPiotr Jasiukajtis instr = uap->uc_mcontext.fpregs.fpu_q->FQu.fpq.fpq_instr;
485*25c28e83SPiotr Jasiukajtis opf = (instr >> 5) & 0x1ff;
486*25c28e83SPiotr Jasiukajtis rs1 = (instr >> 14) & 0x1f;
487*25c28e83SPiotr Jasiukajtis rs2 = instr & 0x1f;
488*25c28e83SPiotr Jasiukajtis rd = (instr >> 25) & 0x1f;
489*25c28e83SPiotr Jasiukajtis
490*25c28e83SPiotr Jasiukajtis /* if the instruction is a compare, just set fcc to unordered */
491*25c28e83SPiotr Jasiukajtis if (((instr >> 19) & 0x183f) == 0x1035) {
492*25c28e83SPiotr Jasiukajtis if (rd == 0)
493*25c28e83SPiotr Jasiukajtis uap->uc_mcontext.fpregs.fpu_fsr |= 0xc00;
494*25c28e83SPiotr Jasiukajtis else {
495*25c28e83SPiotr Jasiukajtis #ifdef __sparcv9
496*25c28e83SPiotr Jasiukajtis uap->uc_mcontext.fpregs.fpu_fsr |= (3l << ((rd << 1) + 30));
497*25c28e83SPiotr Jasiukajtis #else
498*25c28e83SPiotr Jasiukajtis ((prxregset_t*)uap->uc_mcontext.xrs.xrs_ptr)->pr_un.pr_v8p.pr_xfsr |= (3 << ((rd - 1) << 1));
499*25c28e83SPiotr Jasiukajtis #endif
500*25c28e83SPiotr Jasiukajtis }
501*25c28e83SPiotr Jasiukajtis return;
502*25c28e83SPiotr Jasiukajtis }
503*25c28e83SPiotr Jasiukajtis
504*25c28e83SPiotr Jasiukajtis /* if there is no result available, try to generate the untrapped
505*25c28e83SPiotr Jasiukajtis default */
506*25c28e83SPiotr Jasiukajtis if (info->res.type == fex_nodata) {
507*25c28e83SPiotr Jasiukajtis /* set scale factors for exponent wrapping */
508*25c28e83SPiotr Jasiukajtis switch (sip->si_code) {
509*25c28e83SPiotr Jasiukajtis case FPE_FLTOVF:
510*25c28e83SPiotr Jasiukajtis fscl = 1.262177448e-29f; /* 2^-96 */
511*25c28e83SPiotr Jasiukajtis dscl = 6.441148769597133308e-232; /* 2^-768 */
512*25c28e83SPiotr Jasiukajtis qscl = 8.778357852076208839765066529179033145e-3700l;/* 2^-12288 */
513*25c28e83SPiotr Jasiukajtis break;
514*25c28e83SPiotr Jasiukajtis
515*25c28e83SPiotr Jasiukajtis case FPE_FLTUND:
516*25c28e83SPiotr Jasiukajtis fscl = 7.922816251e+28f; /* 2^96 */
517*25c28e83SPiotr Jasiukajtis dscl = 1.552518092300708935e+231; /* 2^768 */
518*25c28e83SPiotr Jasiukajtis qscl = 1.139165225263043370845938579315932009e+3699l;/* 2^12288 */
519*25c28e83SPiotr Jasiukajtis break;
520*25c28e83SPiotr Jasiukajtis
521*25c28e83SPiotr Jasiukajtis default:
522*25c28e83SPiotr Jasiukajtis /* user may have blown away the default result by mistake,
523*25c28e83SPiotr Jasiukajtis so try to regenerate it */
524*25c28e83SPiotr Jasiukajtis (void) __fex_get_op(sip, uap, info);
525*25c28e83SPiotr Jasiukajtis if (info->res.type != fex_nodata)
526*25c28e83SPiotr Jasiukajtis goto stuff;
527*25c28e83SPiotr Jasiukajtis /* couldn't do it */
528*25c28e83SPiotr Jasiukajtis return;
529*25c28e83SPiotr Jasiukajtis }
530*25c28e83SPiotr Jasiukajtis
531*25c28e83SPiotr Jasiukajtis /* get the operands */
532*25c28e83SPiotr Jasiukajtis switch (opf & 3) {
533*25c28e83SPiotr Jasiukajtis case 1: /* single */
534*25c28e83SPiotr Jasiukajtis info->op1.val.f = *(float*)FPreg(rs1);
535*25c28e83SPiotr Jasiukajtis info->op2.val.f = *(float*)FPreg(rs2);
536*25c28e83SPiotr Jasiukajtis break;
537*25c28e83SPiotr Jasiukajtis
538*25c28e83SPiotr Jasiukajtis case 2: /* double */
539*25c28e83SPiotr Jasiukajtis info->op1.val.d = *(double*)FPREG(rs1);
540*25c28e83SPiotr Jasiukajtis info->op2.val.d = *(double*)FPREG(rs2);
541*25c28e83SPiotr Jasiukajtis break;
542*25c28e83SPiotr Jasiukajtis
543*25c28e83SPiotr Jasiukajtis case 3: /* quad */
544*25c28e83SPiotr Jasiukajtis info->op1.val.q = *(long double*)FPREG(rs1);
545*25c28e83SPiotr Jasiukajtis info->op2.val.q = *(long double*)FPREG(rs2);
546*25c28e83SPiotr Jasiukajtis break;
547*25c28e83SPiotr Jasiukajtis }
548*25c28e83SPiotr Jasiukajtis
549*25c28e83SPiotr Jasiukajtis /* generate the wrapped result */
550*25c28e83SPiotr Jasiukajtis switch (opf) {
551*25c28e83SPiotr Jasiukajtis case 0x41: /* add single */
552*25c28e83SPiotr Jasiukajtis info->res.type = fex_float;
553*25c28e83SPiotr Jasiukajtis info->res.val.f = fscl * (fscl * info->op1.val.f +
554*25c28e83SPiotr Jasiukajtis fscl * info->op2.val.f);
555*25c28e83SPiotr Jasiukajtis break;
556*25c28e83SPiotr Jasiukajtis
557*25c28e83SPiotr Jasiukajtis case 0x42: /* add double */
558*25c28e83SPiotr Jasiukajtis info->res.type = fex_double;
559*25c28e83SPiotr Jasiukajtis info->res.val.d = dscl * (dscl * info->op1.val.d +
560*25c28e83SPiotr Jasiukajtis dscl * info->op2.val.d);
561*25c28e83SPiotr Jasiukajtis break;
562*25c28e83SPiotr Jasiukajtis
563*25c28e83SPiotr Jasiukajtis case 0x43: /* add quad */
564*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble;
565*25c28e83SPiotr Jasiukajtis info->res.val.q = qscl * (qscl * info->op1.val.q +
566*25c28e83SPiotr Jasiukajtis qscl * info->op2.val.q);
567*25c28e83SPiotr Jasiukajtis break;
568*25c28e83SPiotr Jasiukajtis
569*25c28e83SPiotr Jasiukajtis case 0x45: /* subtract single */
570*25c28e83SPiotr Jasiukajtis info->res.type = fex_float;
571*25c28e83SPiotr Jasiukajtis info->res.val.f = fscl * (fscl * info->op1.val.f -
572*25c28e83SPiotr Jasiukajtis fscl * info->op2.val.f);
573*25c28e83SPiotr Jasiukajtis break;
574*25c28e83SPiotr Jasiukajtis
575*25c28e83SPiotr Jasiukajtis case 0x46: /* subtract double */
576*25c28e83SPiotr Jasiukajtis info->res.type = fex_double;
577*25c28e83SPiotr Jasiukajtis info->res.val.d = dscl * (dscl * info->op1.val.d -
578*25c28e83SPiotr Jasiukajtis dscl * info->op2.val.d);
579*25c28e83SPiotr Jasiukajtis break;
580*25c28e83SPiotr Jasiukajtis
581*25c28e83SPiotr Jasiukajtis case 0x47: /* subtract quad */
582*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble;
583*25c28e83SPiotr Jasiukajtis info->res.val.q = qscl * (qscl * info->op1.val.q -
584*25c28e83SPiotr Jasiukajtis qscl * info->op2.val.q);
585*25c28e83SPiotr Jasiukajtis break;
586*25c28e83SPiotr Jasiukajtis
587*25c28e83SPiotr Jasiukajtis case 0x49: /* multiply single */
588*25c28e83SPiotr Jasiukajtis info->res.type = fex_float;
589*25c28e83SPiotr Jasiukajtis info->res.val.f = (fscl * info->op1.val.f) *
590*25c28e83SPiotr Jasiukajtis (fscl * info->op2.val.f);
591*25c28e83SPiotr Jasiukajtis break;
592*25c28e83SPiotr Jasiukajtis
593*25c28e83SPiotr Jasiukajtis case 0x4a: /* multiply double */
594*25c28e83SPiotr Jasiukajtis info->res.type = fex_double;
595*25c28e83SPiotr Jasiukajtis info->res.val.d = (dscl * info->op1.val.d) *
596*25c28e83SPiotr Jasiukajtis (dscl * info->op2.val.d);
597*25c28e83SPiotr Jasiukajtis break;
598*25c28e83SPiotr Jasiukajtis
599*25c28e83SPiotr Jasiukajtis case 0x4b: /* multiply quad */
600*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble;
601*25c28e83SPiotr Jasiukajtis info->res.val.q = (qscl * info->op1.val.q) *
602*25c28e83SPiotr Jasiukajtis (qscl * info->op2.val.q);
603*25c28e83SPiotr Jasiukajtis break;
604*25c28e83SPiotr Jasiukajtis
605*25c28e83SPiotr Jasiukajtis case 0x4d: /* divide single */
606*25c28e83SPiotr Jasiukajtis info->res.type = fex_float;
607*25c28e83SPiotr Jasiukajtis info->res.val.f = (fscl * info->op1.val.f) /
608*25c28e83SPiotr Jasiukajtis (info->op2.val.f / fscl);
609*25c28e83SPiotr Jasiukajtis break;
610*25c28e83SPiotr Jasiukajtis
611*25c28e83SPiotr Jasiukajtis case 0x4e: /* divide double */
612*25c28e83SPiotr Jasiukajtis info->res.type = fex_double;
613*25c28e83SPiotr Jasiukajtis info->res.val.d = (dscl * info->op1.val.d) /
614*25c28e83SPiotr Jasiukajtis (info->op2.val.d / dscl);
615*25c28e83SPiotr Jasiukajtis break;
616*25c28e83SPiotr Jasiukajtis
617*25c28e83SPiotr Jasiukajtis case 0x4f: /* divide quad */
618*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble;
619*25c28e83SPiotr Jasiukajtis info->res.val.q = (qscl * info->op1.val.q) /
620*25c28e83SPiotr Jasiukajtis (info->op2.val.q / qscl);
621*25c28e83SPiotr Jasiukajtis break;
622*25c28e83SPiotr Jasiukajtis
623*25c28e83SPiotr Jasiukajtis case 0xc6: /* convert double to single */
624*25c28e83SPiotr Jasiukajtis info->res.type = fex_float;
625*25c28e83SPiotr Jasiukajtis info->res.val.f = (float) (fscl * (fscl * info->op1.val.d));
626*25c28e83SPiotr Jasiukajtis break;
627*25c28e83SPiotr Jasiukajtis
628*25c28e83SPiotr Jasiukajtis case 0xc7: /* convert quad to single */
629*25c28e83SPiotr Jasiukajtis info->res.type = fex_float;
630*25c28e83SPiotr Jasiukajtis info->res.val.f = (float) (fscl * (fscl * info->op1.val.q));
631*25c28e83SPiotr Jasiukajtis break;
632*25c28e83SPiotr Jasiukajtis
633*25c28e83SPiotr Jasiukajtis case 0xcb: /* convert quad to double */
634*25c28e83SPiotr Jasiukajtis info->res.type = fex_double;
635*25c28e83SPiotr Jasiukajtis info->res.val.d = (double) (dscl * (dscl * info->op1.val.q));
636*25c28e83SPiotr Jasiukajtis break;
637*25c28e83SPiotr Jasiukajtis }
638*25c28e83SPiotr Jasiukajtis
639*25c28e83SPiotr Jasiukajtis if (info->res.type == fex_nodata)
640*25c28e83SPiotr Jasiukajtis /* couldn't do it */
641*25c28e83SPiotr Jasiukajtis return;
642*25c28e83SPiotr Jasiukajtis }
643*25c28e83SPiotr Jasiukajtis
644*25c28e83SPiotr Jasiukajtis stuff:
645*25c28e83SPiotr Jasiukajtis /* stick the result in the destination */
646*25c28e83SPiotr Jasiukajtis if (opf & 0x80) { /* conversion */
647*25c28e83SPiotr Jasiukajtis if (opf & 0x10) { /* result is an int */
648*25c28e83SPiotr Jasiukajtis switch (info->res.type) {
649*25c28e83SPiotr Jasiukajtis case fex_llong:
650*25c28e83SPiotr Jasiukajtis info->res.val.i = (int) info->res.val.l;
651*25c28e83SPiotr Jasiukajtis break;
652*25c28e83SPiotr Jasiukajtis
653*25c28e83SPiotr Jasiukajtis case fex_float:
654*25c28e83SPiotr Jasiukajtis info->res.val.i = (int) info->res.val.f;
655*25c28e83SPiotr Jasiukajtis break;
656*25c28e83SPiotr Jasiukajtis
657*25c28e83SPiotr Jasiukajtis case fex_double:
658*25c28e83SPiotr Jasiukajtis info->res.val.i = (int) info->res.val.d;
659*25c28e83SPiotr Jasiukajtis break;
660*25c28e83SPiotr Jasiukajtis
661*25c28e83SPiotr Jasiukajtis case fex_ldouble:
662*25c28e83SPiotr Jasiukajtis info->res.val.i = (int) info->res.val.q;
663*25c28e83SPiotr Jasiukajtis break;
664*25c28e83SPiotr Jasiukajtis
665*25c28e83SPiotr Jasiukajtis default:
666*25c28e83SPiotr Jasiukajtis break;
667*25c28e83SPiotr Jasiukajtis }
668*25c28e83SPiotr Jasiukajtis *(int*)FPreg(rd) = info->res.val.i;
669*25c28e83SPiotr Jasiukajtis return;
670*25c28e83SPiotr Jasiukajtis }
671*25c28e83SPiotr Jasiukajtis
672*25c28e83SPiotr Jasiukajtis switch (opf & 0xc) {
673*25c28e83SPiotr Jasiukajtis case 0: /* result is long long */
674*25c28e83SPiotr Jasiukajtis switch (info->res.type) {
675*25c28e83SPiotr Jasiukajtis case fex_int:
676*25c28e83SPiotr Jasiukajtis info->res.val.l = (long long) info->res.val.i;
677*25c28e83SPiotr Jasiukajtis break;
678*25c28e83SPiotr Jasiukajtis
679*25c28e83SPiotr Jasiukajtis case fex_float:
680*25c28e83SPiotr Jasiukajtis info->res.val.l = (long long) info->res.val.f;
681*25c28e83SPiotr Jasiukajtis break;
682*25c28e83SPiotr Jasiukajtis
683*25c28e83SPiotr Jasiukajtis case fex_double:
684*25c28e83SPiotr Jasiukajtis info->res.val.l = (long long) info->res.val.d;
685*25c28e83SPiotr Jasiukajtis break;
686*25c28e83SPiotr Jasiukajtis
687*25c28e83SPiotr Jasiukajtis case fex_ldouble:
688*25c28e83SPiotr Jasiukajtis info->res.val.l = (long long) info->res.val.q;
689*25c28e83SPiotr Jasiukajtis break;
690*25c28e83SPiotr Jasiukajtis
691*25c28e83SPiotr Jasiukajtis default:
692*25c28e83SPiotr Jasiukajtis break;
693*25c28e83SPiotr Jasiukajtis }
694*25c28e83SPiotr Jasiukajtis *(long long*)FPREG(rd) = info->res.val.l;
695*25c28e83SPiotr Jasiukajtis break;
696*25c28e83SPiotr Jasiukajtis
697*25c28e83SPiotr Jasiukajtis case 0x4: /* result is float */
698*25c28e83SPiotr Jasiukajtis switch (info->res.type) {
699*25c28e83SPiotr Jasiukajtis case fex_int:
700*25c28e83SPiotr Jasiukajtis info->res.val.f = (float) info->res.val.i;
701*25c28e83SPiotr Jasiukajtis break;
702*25c28e83SPiotr Jasiukajtis
703*25c28e83SPiotr Jasiukajtis case fex_llong:
704*25c28e83SPiotr Jasiukajtis info->res.val.f = (float) info->res.val.l;
705*25c28e83SPiotr Jasiukajtis break;
706*25c28e83SPiotr Jasiukajtis
707*25c28e83SPiotr Jasiukajtis case fex_double:
708*25c28e83SPiotr Jasiukajtis info->res.val.f = (float) info->res.val.d;
709*25c28e83SPiotr Jasiukajtis break;
710*25c28e83SPiotr Jasiukajtis
711*25c28e83SPiotr Jasiukajtis case fex_ldouble:
712*25c28e83SPiotr Jasiukajtis info->res.val.f = (float) info->res.val.q;
713*25c28e83SPiotr Jasiukajtis break;
714*25c28e83SPiotr Jasiukajtis
715*25c28e83SPiotr Jasiukajtis default:
716*25c28e83SPiotr Jasiukajtis break;
717*25c28e83SPiotr Jasiukajtis }
718*25c28e83SPiotr Jasiukajtis *(float*)FPreg(rd) = info->res.val.f;
719*25c28e83SPiotr Jasiukajtis break;
720*25c28e83SPiotr Jasiukajtis
721*25c28e83SPiotr Jasiukajtis case 0x8: /* result is double */
722*25c28e83SPiotr Jasiukajtis switch (info->res.type) {
723*25c28e83SPiotr Jasiukajtis case fex_int:
724*25c28e83SPiotr Jasiukajtis info->res.val.d = (double) info->res.val.i;
725*25c28e83SPiotr Jasiukajtis break;
726*25c28e83SPiotr Jasiukajtis
727*25c28e83SPiotr Jasiukajtis case fex_llong:
728*25c28e83SPiotr Jasiukajtis info->res.val.d = (double) info->res.val.l;
729*25c28e83SPiotr Jasiukajtis break;
730*25c28e83SPiotr Jasiukajtis
731*25c28e83SPiotr Jasiukajtis case fex_float:
732*25c28e83SPiotr Jasiukajtis info->res.val.d = (double) info->res.val.f;
733*25c28e83SPiotr Jasiukajtis break;
734*25c28e83SPiotr Jasiukajtis
735*25c28e83SPiotr Jasiukajtis case fex_ldouble:
736*25c28e83SPiotr Jasiukajtis info->res.val.d = (double) info->res.val.q;
737*25c28e83SPiotr Jasiukajtis break;
738*25c28e83SPiotr Jasiukajtis
739*25c28e83SPiotr Jasiukajtis default:
740*25c28e83SPiotr Jasiukajtis break;
741*25c28e83SPiotr Jasiukajtis }
742*25c28e83SPiotr Jasiukajtis *(double*)FPREG(rd) = info->res.val.d;
743*25c28e83SPiotr Jasiukajtis break;
744*25c28e83SPiotr Jasiukajtis
745*25c28e83SPiotr Jasiukajtis case 0xc: /* result is long double */
746*25c28e83SPiotr Jasiukajtis switch (info->res.type) {
747*25c28e83SPiotr Jasiukajtis case fex_int:
748*25c28e83SPiotr Jasiukajtis info->res.val.q = (long double) info->res.val.i;
749*25c28e83SPiotr Jasiukajtis break;
750*25c28e83SPiotr Jasiukajtis
751*25c28e83SPiotr Jasiukajtis case fex_llong:
752*25c28e83SPiotr Jasiukajtis info->res.val.q = (long double) info->res.val.l;
753*25c28e83SPiotr Jasiukajtis break;
754*25c28e83SPiotr Jasiukajtis
755*25c28e83SPiotr Jasiukajtis case fex_float:
756*25c28e83SPiotr Jasiukajtis info->res.val.q = (long double) info->res.val.f;
757*25c28e83SPiotr Jasiukajtis break;
758*25c28e83SPiotr Jasiukajtis
759*25c28e83SPiotr Jasiukajtis case fex_double:
760*25c28e83SPiotr Jasiukajtis info->res.val.q = (long double) info->res.val.d;
761*25c28e83SPiotr Jasiukajtis break;
762*25c28e83SPiotr Jasiukajtis
763*25c28e83SPiotr Jasiukajtis default:
764*25c28e83SPiotr Jasiukajtis break;
765*25c28e83SPiotr Jasiukajtis }
766*25c28e83SPiotr Jasiukajtis *(long double*)FPREG(rd) = info->res.val.q;
767*25c28e83SPiotr Jasiukajtis break;
768*25c28e83SPiotr Jasiukajtis }
769*25c28e83SPiotr Jasiukajtis return;
770*25c28e83SPiotr Jasiukajtis }
771*25c28e83SPiotr Jasiukajtis
772*25c28e83SPiotr Jasiukajtis if ((opf & 0xf0) == 0x60) { /* fsmuld, fdmulq */
773*25c28e83SPiotr Jasiukajtis switch (opf & 0xc0) {
774*25c28e83SPiotr Jasiukajtis case 0x8: /* result is double */
775*25c28e83SPiotr Jasiukajtis switch (info->res.type) {
776*25c28e83SPiotr Jasiukajtis case fex_int:
777*25c28e83SPiotr Jasiukajtis info->res.val.d = (double) info->res.val.i;
778*25c28e83SPiotr Jasiukajtis break;
779*25c28e83SPiotr Jasiukajtis
780*25c28e83SPiotr Jasiukajtis case fex_llong:
781*25c28e83SPiotr Jasiukajtis info->res.val.d = (double) info->res.val.l;
782*25c28e83SPiotr Jasiukajtis break;
783*25c28e83SPiotr Jasiukajtis
784*25c28e83SPiotr Jasiukajtis case fex_float:
785*25c28e83SPiotr Jasiukajtis info->res.val.d = (double) info->res.val.f;
786*25c28e83SPiotr Jasiukajtis break;
787*25c28e83SPiotr Jasiukajtis
788*25c28e83SPiotr Jasiukajtis case fex_ldouble:
789*25c28e83SPiotr Jasiukajtis info->res.val.d = (double) info->res.val.q;
790*25c28e83SPiotr Jasiukajtis break;
791*25c28e83SPiotr Jasiukajtis
792*25c28e83SPiotr Jasiukajtis default:
793*25c28e83SPiotr Jasiukajtis break;
794*25c28e83SPiotr Jasiukajtis }
795*25c28e83SPiotr Jasiukajtis *(double*)FPREG(rd) = info->res.val.d;
796*25c28e83SPiotr Jasiukajtis break;
797*25c28e83SPiotr Jasiukajtis
798*25c28e83SPiotr Jasiukajtis case 0xc: /* result is long double */
799*25c28e83SPiotr Jasiukajtis switch (info->res.type) {
800*25c28e83SPiotr Jasiukajtis case fex_int:
801*25c28e83SPiotr Jasiukajtis info->res.val.q = (long double) info->res.val.i;
802*25c28e83SPiotr Jasiukajtis break;
803*25c28e83SPiotr Jasiukajtis
804*25c28e83SPiotr Jasiukajtis case fex_llong:
805*25c28e83SPiotr Jasiukajtis info->res.val.q = (long double) info->res.val.l;
806*25c28e83SPiotr Jasiukajtis break;
807*25c28e83SPiotr Jasiukajtis
808*25c28e83SPiotr Jasiukajtis case fex_float:
809*25c28e83SPiotr Jasiukajtis info->res.val.q = (long double) info->res.val.f;
810*25c28e83SPiotr Jasiukajtis break;
811*25c28e83SPiotr Jasiukajtis
812*25c28e83SPiotr Jasiukajtis case fex_double:
813*25c28e83SPiotr Jasiukajtis info->res.val.q = (long double) info->res.val.d;
814*25c28e83SPiotr Jasiukajtis break;
815*25c28e83SPiotr Jasiukajtis
816*25c28e83SPiotr Jasiukajtis default:
817*25c28e83SPiotr Jasiukajtis break;
818*25c28e83SPiotr Jasiukajtis }
819*25c28e83SPiotr Jasiukajtis *(long double*)FPREG(rd) = info->res.val.q;
820*25c28e83SPiotr Jasiukajtis break;
821*25c28e83SPiotr Jasiukajtis }
822*25c28e83SPiotr Jasiukajtis return;
823*25c28e83SPiotr Jasiukajtis }
824*25c28e83SPiotr Jasiukajtis
825*25c28e83SPiotr Jasiukajtis switch (opf & 3) { /* other arithmetic op */
826*25c28e83SPiotr Jasiukajtis case 1: /* result is float */
827*25c28e83SPiotr Jasiukajtis switch (info->res.type) {
828*25c28e83SPiotr Jasiukajtis case fex_int:
829*25c28e83SPiotr Jasiukajtis info->res.val.f = (float) info->res.val.i;
830*25c28e83SPiotr Jasiukajtis break;
831*25c28e83SPiotr Jasiukajtis
832*25c28e83SPiotr Jasiukajtis case fex_llong:
833*25c28e83SPiotr Jasiukajtis info->res.val.f = (float) info->res.val.l;
834*25c28e83SPiotr Jasiukajtis break;
835*25c28e83SPiotr Jasiukajtis
836*25c28e83SPiotr Jasiukajtis case fex_double:
837*25c28e83SPiotr Jasiukajtis info->res.val.f = (float) info->res.val.d;
838*25c28e83SPiotr Jasiukajtis break;
839*25c28e83SPiotr Jasiukajtis
840*25c28e83SPiotr Jasiukajtis case fex_ldouble:
841*25c28e83SPiotr Jasiukajtis info->res.val.f = (float) info->res.val.q;
842*25c28e83SPiotr Jasiukajtis break;
843*25c28e83SPiotr Jasiukajtis
844*25c28e83SPiotr Jasiukajtis default:
845*25c28e83SPiotr Jasiukajtis break;
846*25c28e83SPiotr Jasiukajtis }
847*25c28e83SPiotr Jasiukajtis *(float*)FPreg(rd) = info->res.val.f;
848*25c28e83SPiotr Jasiukajtis break;
849*25c28e83SPiotr Jasiukajtis
850*25c28e83SPiotr Jasiukajtis case 2: /* result is double */
851*25c28e83SPiotr Jasiukajtis switch (info->res.type) {
852*25c28e83SPiotr Jasiukajtis case fex_int:
853*25c28e83SPiotr Jasiukajtis info->res.val.d = (double) info->res.val.i;
854*25c28e83SPiotr Jasiukajtis break;
855*25c28e83SPiotr Jasiukajtis
856*25c28e83SPiotr Jasiukajtis case fex_llong:
857*25c28e83SPiotr Jasiukajtis info->res.val.d = (double) info->res.val.l;
858*25c28e83SPiotr Jasiukajtis break;
859*25c28e83SPiotr Jasiukajtis
860*25c28e83SPiotr Jasiukajtis case fex_float:
861*25c28e83SPiotr Jasiukajtis info->res.val.d = (double) info->res.val.f;
862*25c28e83SPiotr Jasiukajtis break;
863*25c28e83SPiotr Jasiukajtis
864*25c28e83SPiotr Jasiukajtis case fex_ldouble:
865*25c28e83SPiotr Jasiukajtis info->res.val.d = (double) info->res.val.q;
866*25c28e83SPiotr Jasiukajtis break;
867*25c28e83SPiotr Jasiukajtis
868*25c28e83SPiotr Jasiukajtis default:
869*25c28e83SPiotr Jasiukajtis break;
870*25c28e83SPiotr Jasiukajtis }
871*25c28e83SPiotr Jasiukajtis *(double*)FPREG(rd) = info->res.val.d;
872*25c28e83SPiotr Jasiukajtis break;
873*25c28e83SPiotr Jasiukajtis
874*25c28e83SPiotr Jasiukajtis case 3: /* result is long double */
875*25c28e83SPiotr Jasiukajtis switch (info->res.type) {
876*25c28e83SPiotr Jasiukajtis case fex_int:
877*25c28e83SPiotr Jasiukajtis info->res.val.q = (long double) info->res.val.i;
878*25c28e83SPiotr Jasiukajtis break;
879*25c28e83SPiotr Jasiukajtis
880*25c28e83SPiotr Jasiukajtis case fex_llong:
881*25c28e83SPiotr Jasiukajtis info->res.val.q = (long double) info->res.val.l;
882*25c28e83SPiotr Jasiukajtis break;
883*25c28e83SPiotr Jasiukajtis
884*25c28e83SPiotr Jasiukajtis case fex_float:
885*25c28e83SPiotr Jasiukajtis info->res.val.q = (long double) info->res.val.f;
886*25c28e83SPiotr Jasiukajtis break;
887*25c28e83SPiotr Jasiukajtis
888*25c28e83SPiotr Jasiukajtis case fex_double:
889*25c28e83SPiotr Jasiukajtis info->res.val.q = (long double) info->res.val.d;
890*25c28e83SPiotr Jasiukajtis break;
891*25c28e83SPiotr Jasiukajtis
892*25c28e83SPiotr Jasiukajtis default:
893*25c28e83SPiotr Jasiukajtis break;
894*25c28e83SPiotr Jasiukajtis }
895*25c28e83SPiotr Jasiukajtis *(long double*)FPREG(rd) = info->res.val.q;
896*25c28e83SPiotr Jasiukajtis break;
897*25c28e83SPiotr Jasiukajtis }
898*25c28e83SPiotr Jasiukajtis }
899*25c28e83SPiotr Jasiukajtis #endif /* defined(__sparc) */
900