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