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