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