2 * Copyright (c) 2010 by Peter Jeremy <peterjeremy@acm.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
23 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
29 #include <sys/param.h>
35 #include "__sparc_utrap_private.h"
36 #include "fpu_extern.h"
39 static u_long ireg[32];
42 __utrap_panic(const char *msg)
45 fprintf(stderr, "panic: %s\n", msg);
49 void __utrap_write(const char *msg)
52 fprintf(stderr, "%s", msg);
56 __emul_fetch_reg(struct utrapframe *uf, int reg)
62 typedef unsigned char int8;
63 typedef unsigned int int32;
64 typedef unsigned long int64;
65 typedef unsigned int float32;
66 typedef unsigned long float64;
68 unsigned long high, low;
70 typedef unsigned long flag;
72 struct utrapframe utf;
74 u_int32_t __fpreg[64];
76 static __inline float128
77 __fpu_getreg128(int r)
81 v.high = ((u_int64_t)__fpreg[r] << 32 | (u_int64_t)__fpreg[r + 1]);
82 v.low = ((u_int64_t)__fpreg[r + 2] << 32 | (u_int64_t)__fpreg[r + 3]);
87 __fpu_setreg128(int r, float128 v)
90 __fpreg[r] = (u_int32_t)(v.high >> 32);
91 __fpreg[r + 1] = (u_int32_t)v.high;
92 __fpreg[r + 2] = (u_int32_t)(v.low >> 32);
93 __fpreg[r + 3] = (u_int32_t)v.low;
97 -------------------------------------------------------------------------------
98 Clears the system's IEC/IEEE floating-point exception flags. Returns the
99 previous value of the flags.
100 -------------------------------------------------------------------------------
105 int8 syst_float_flags_clear(void)
109 flags = (utf.uf_fsr & FE_ALL_EXCEPT) >> 5;
110 utf.uf_fsr &= ~(u_long)FE_ALL_EXCEPT;
115 emul_trap(const u_int *insn, u_long mask)
117 u_int32_t savreg[64];
120 for (i = 0; i < 64; i++)
121 savreg[i] = __fpreg[i];
123 utf.uf_fsr = (utf.uf_fsr & ~FSR_FTT_MASK) |
124 (FSR_FTT_UNFIN << FSR_FTT_SHIFT);
125 utf.uf_pc = (u_long)insn;
126 if (__fpu_exception(&utf) == 0)
127 __asm("stx %%fsr,%0" : "=m" (utf.uf_fsr));
129 for (i = 0; i < 64; i++) {
130 if (!(mask & (1UL << i)) && savreg[i] != __fpreg[i]) {
131 fprintf(stderr, "### %2d %08x != %08x\n",
132 i, savreg[i], __fpreg[i]);
137 extern u_int insn_int32_to_float32;
138 extern u_int insn_int32_to_float64;
139 extern u_int insn_int32_to_float128;
140 extern u_int insn_int64_to_float32;
141 extern u_int insn_int64_to_float64;
142 extern u_int insn_int64_to_float128;
143 extern u_int insn_float32_to_int32_round_to_zero;
144 extern u_int insn_float32_to_int64_round_to_zero;
145 extern u_int insn_float32_to_float64;
146 extern u_int insn_float32_to_float128;
147 extern u_int insn_float32_add;
148 extern u_int insn_float32_sub;
149 extern u_int insn_float32_mul;
150 extern u_int insn_float32_div;
151 extern u_int insn_float32_sqrt;
152 extern u_int insn_float32_cmp;
153 extern u_int insn_float32_cmpe;
154 extern u_int insn_float64_to_int32_round_to_zero;
155 extern u_int insn_float64_to_int64_round_to_zero;
156 extern u_int insn_float64_to_float32;
157 extern u_int insn_float64_to_float128;
158 extern u_int insn_float64_add;
159 extern u_int insn_float64_sub;
160 extern u_int insn_float64_mul;
161 extern u_int insn_float64_div;
162 extern u_int insn_float64_sqrt;
163 extern u_int insn_float64_cmp;
164 extern u_int insn_float64_cmpe;
165 extern u_int insn_float128_to_int32_round_to_zero;
166 extern u_int insn_float128_to_int64_round_to_zero;
167 extern u_int insn_float128_to_float32;
168 extern u_int insn_float128_to_float64;
169 extern u_int insn_float128_add;
170 extern u_int insn_float128_sub;
171 extern u_int insn_float128_mul;
172 extern u_int insn_float128_div;
173 extern u_int insn_float128_sqrt;
174 extern u_int insn_float128_cmp;
175 extern u_int insn_float128_cmpe;
178 syst_int32_to_float32(int32 a)
182 emul_trap(&insn_int32_to_float32, 0x1UL);
183 return (__fpu_getreg(0));
187 syst_int32_to_float64(int32 a)
191 emul_trap(&insn_int32_to_float64, 0x3UL);
192 return (__fpu_getreg64(0));
196 syst_int32_to_float128(int32 a)
200 emul_trap(&insn_int32_to_float128, 0xfUL);
201 return (__fpu_getreg128(0));
205 syst_int64_to_float32(int64 a)
208 __fpu_setreg64(0, a);
209 emul_trap(&insn_int64_to_float32, 0x1UL);
210 return (__fpu_getreg(0));
214 syst_int64_to_float64(int64 a)
217 __fpu_setreg64(0, a);
218 emul_trap(&insn_int64_to_float64, 0x3UL);
219 return (__fpu_getreg64(0));
224 syst_int64_to_float128(int64 a)
227 __fpu_setreg64(0, a);
228 emul_trap(&insn_int64_to_float128, 0xfUL);
229 return (__fpu_getreg128(0));
233 syst_float32_to_int32_round_to_zero(float32 a)
237 emul_trap(&insn_float32_to_int32_round_to_zero, 0x1UL);
238 return (__fpu_getreg(0));
242 syst_float32_to_int64_round_to_zero(float32 a)
246 emul_trap(&insn_float32_to_int64_round_to_zero, 0x3UL);
247 return (__fpu_getreg64(0));
251 syst_float32_to_float64(float32 a)
255 emul_trap(&insn_float32_to_float64, 0x3UL);
256 return (__fpu_getreg64(0));
260 syst_float32_to_float128(float32 a)
264 emul_trap(&insn_float32_to_float128, 0xfUL);
265 return (__fpu_getreg128(0));
269 syst_float32_add(float32 a, float32 b)
274 emul_trap(&insn_float32_add, 0x1UL);
275 return (__fpu_getreg(0));
279 syst_float32_sub(float32 a, float32 b)
284 emul_trap(&insn_float32_sub, 0x1UL);
285 return (__fpu_getreg(0));
289 syst_float32_mul(float32 a, float32 b)
294 emul_trap(&insn_float32_mul, 0x1UL);
295 return (__fpu_getreg(0));
299 syst_float32_div(float32 a, float32 b)
304 emul_trap(&insn_float32_div, 0x1UL);
305 return (__fpu_getreg(0));
309 syst_float32_sqrt(float32 a)
313 emul_trap(&insn_float32_sqrt, 0x1UL);
314 return (__fpu_getreg(0));
317 flag syst_float32_eq(float32 a, float32 b)
323 emul_trap(&insn_float32_cmp, 0x0UL);
324 __asm __volatile("mov 0,%0; move %%fcc0,1,%0" : "=r" (r));
328 flag syst_float32_le(float32 a, float32 b)
334 emul_trap(&insn_float32_cmpe, 0x0UL);
335 __asm __volatile("mov 0,%0; movle %%fcc0,1,%0" : "=r" (r));
339 flag syst_float32_lt(float32 a, float32 b)
345 emul_trap(&insn_float32_cmpe, 0x0UL);
346 __asm __volatile("mov 0,%0; movl %%fcc0,1,%0" : "=r" (r));
350 flag syst_float32_eq_signaling(float32 a, float32 b)
356 emul_trap(&insn_float32_cmpe, 0x0UL);
357 __asm __volatile("mov 0,%0; move %%fcc0,1,%0" : "=r" (r));
361 flag syst_float32_le_quiet(float32 a, float32 b)
367 emul_trap(&insn_float32_cmp, 0x0UL);
368 __asm __volatile("mov 0,%0; movle %%fcc0,1,%0" : "=r" (r));
372 flag syst_float32_lt_quiet(float32 a, float32 b)
378 emul_trap(&insn_float32_cmp, 0x0UL);
379 __asm __volatile("mov 0,%0; movl %%fcc0,1,%0" : "=r" (r));
384 syst_float64_to_int32_round_to_zero(float64 a)
387 __fpu_setreg64(0, a);
388 emul_trap(&insn_float64_to_int32_round_to_zero, 0x1UL);
389 return (__fpu_getreg(0));
393 syst_float64_to_int64_round_to_zero(float64 a)
396 __fpu_setreg64(0, a);
397 emul_trap(&insn_float64_to_int64_round_to_zero, 0x3UL);
398 return (__fpu_getreg64(0));
402 syst_float64_to_float32(float64 a)
405 __fpu_setreg64(0, a);
406 emul_trap(&insn_float64_to_float32, 0x1UL);
407 return (__fpu_getreg(0));
411 syst_float64_to_float128(float64 a)
414 __fpu_setreg64(0, a);
415 emul_trap(&insn_float64_to_float128, 0xfUL);
416 return (__fpu_getreg128(0));
420 syst_float64_add(float64 a, float64 b)
423 __fpu_setreg64(0, a);
424 __fpu_setreg64(2, b);
425 emul_trap(&insn_float64_add, 0x3UL);
426 return (__fpu_getreg64(0));
430 syst_float64_sub(float64 a, float64 b)
433 __fpu_setreg64(0, a);
434 __fpu_setreg64(2, b);
435 emul_trap(&insn_float64_sub, 0x3UL);
436 return (__fpu_getreg64(0));
440 syst_float64_mul(float64 a, float64 b)
443 __fpu_setreg64(0, a);
444 __fpu_setreg64(2, b);
445 emul_trap(&insn_float64_mul, 0x3UL);
446 return (__fpu_getreg64(0));
450 syst_float64_div(float64 a, float64 b)
453 __fpu_setreg64(0, a);
454 __fpu_setreg64(2, b);
455 emul_trap(&insn_float64_div, 0x3UL);
456 return (__fpu_getreg64(0));
460 syst_float64_sqrt(float64 a)
463 __fpu_setreg64(0, a);
464 emul_trap(&insn_float64_sqrt, 0x3UL);
465 return (__fpu_getreg64(0));
468 flag syst_float64_eq(float64 a, float64 b)
472 __fpu_setreg64(0, a);
473 __fpu_setreg64(2, b);
474 emul_trap(&insn_float64_cmp, 0x0UL);
475 __asm __volatile("mov 0,%0; move %%fcc0,1,%0" : "=r" (r));
479 flag syst_float64_le(float64 a, float64 b)
483 __fpu_setreg64(0, a);
484 __fpu_setreg64(2, b);
485 emul_trap(&insn_float64_cmpe, 0x0UL);
486 __asm __volatile("mov 0,%0; movle %%fcc0,1,%0" : "=r" (r));
490 flag syst_float64_lt(float64 a, float64 b)
494 __fpu_setreg64(0, a);
495 __fpu_setreg64(2, b);
496 emul_trap(&insn_float64_cmpe, 0x0UL);
497 __asm __volatile("mov 0,%0; movl %%fcc0,1,%0" : "=r" (r));
501 flag syst_float64_eq_signaling(float64 a, float64 b)
505 __fpu_setreg64(0, a);
506 __fpu_setreg64(2, b);
507 emul_trap(&insn_float64_cmpe, 0x0UL);
508 __asm __volatile("mov 0,%0; move %%fcc0,1,%0" : "=r" (r));
512 flag syst_float64_le_quiet(float64 a, float64 b)
516 __fpu_setreg64(0, a);
517 __fpu_setreg64(2, b);
518 emul_trap(&insn_float64_cmp, 0x0UL);
519 __asm __volatile("mov 0,%0; movle %%fcc0,1,%0" : "=r" (r));
523 flag syst_float64_lt_quiet(float64 a, float64 b)
527 __fpu_setreg64(0, a);
528 __fpu_setreg64(2, b);
529 emul_trap(&insn_float64_cmp, 0x0UL);
530 __asm __volatile("mov 0,%0; movl %%fcc0,1,%0" : "=r" (r));
535 syst_float128_to_int32_round_to_zero(float128 a)
538 __fpu_setreg128(0, a);
539 emul_trap(&insn_float128_to_int32_round_to_zero, 0x1UL);
540 return (__fpu_getreg(0));
544 syst_float128_to_int64_round_to_zero(float128 a)
547 __fpu_setreg128(0, a);
548 emul_trap(&insn_float128_to_int64_round_to_zero, 0x3UL);
549 return (__fpu_getreg64(0));
553 syst_float128_to_float32(float128 a)
556 __fpu_setreg128(0, a);
557 emul_trap(&insn_float128_to_float32, 0x1UL);
558 return (__fpu_getreg(0));
562 syst_float128_to_float64(float128 a)
565 __fpu_setreg128(0, a);
566 emul_trap(&insn_float128_to_float64, 0x3UL);
567 return (__fpu_getreg64(0));
571 syst_float128_add(float128 a, float128 b)
574 __fpu_setreg128(0, a);
575 __fpu_setreg128(4, b);
576 emul_trap(&insn_float128_add, 0xfUL);
577 return (__fpu_getreg128(0));
581 syst_float128_sub(float128 a, float128 b)
584 __fpu_setreg128(0, a);
585 __fpu_setreg128(4, b);
586 emul_trap(&insn_float128_sub, 0xfUL);
587 return (__fpu_getreg128(0));
591 syst_float128_mul(float128 a, float128 b)
594 __fpu_setreg128(0, a);
595 __fpu_setreg128(4, b);
596 emul_trap(&insn_float128_mul, 0xfUL);
597 return (__fpu_getreg128(0));
601 syst_float128_div(float128 a, float128 b)
604 __fpu_setreg128(0, a);
605 __fpu_setreg128(4, b);
606 emul_trap(&insn_float128_div, 0xfUL);
607 return (__fpu_getreg128(0));
611 syst_float128_sqrt(float128 a)
614 __fpu_setreg128(0, a);
615 emul_trap(&insn_float128_sqrt, 0xfUL);
616 return (__fpu_getreg128(0));
619 flag syst_float128_eq(float128 a, float128 b)
623 __fpu_setreg128(0, a);
624 __fpu_setreg128(4, b);
625 emul_trap(&insn_float128_cmp, 0x0UL);
626 __asm __volatile("mov 0,%0; move %%fcc0,1,%0" : "=r" (r));
630 flag syst_float128_le(float128 a, float128 b)
634 __fpu_setreg128(0, a);
635 __fpu_setreg128(4, b);
636 emul_trap(&insn_float128_cmpe, 0x0UL);
637 __asm __volatile("mov 0,%0; movle %%fcc0,1,%0" : "=r" (r));
641 flag syst_float128_lt(float128 a, float128 b)
645 __fpu_setreg128(0, a);
646 __fpu_setreg128(4, b);
647 emul_trap(&insn_float128_cmpe, 0x0UL);
648 __asm __volatile("mov 0,%0; movl %%fcc0,1,%0" : "=r" (r));
652 flag syst_float128_eq_signaling(float128 a, float128 b)
656 __fpu_setreg128(0, a);
657 __fpu_setreg128(4, b);
658 emul_trap(&insn_float128_cmpe, 0x0UL);
659 __asm __volatile("mov 0,%0; move %%fcc0,1,%0" : "=r" (r));
663 flag syst_float128_le_quiet(float128 a, float128 b)
667 __fpu_setreg128(0, a);
668 __fpu_setreg128(4, b);
669 emul_trap(&insn_float128_cmp, 0x0UL);
670 __asm __volatile("mov 0,%0; movle %%fcc0,1,%0" : "=r" (r));
674 flag syst_float128_lt_quiet(float128 a, float128 b)
678 __fpu_setreg128(0, a);
679 __fpu_setreg128(4, b);
680 emul_trap(&insn_float128_cmp, 0x0UL);
681 __asm __volatile("mov 0,%0; movl %%fcc0,1,%0" : "=r" (r));
687 -------------------------------------------------------------------------------
688 Sets the system's IEC/IEEE floating-point rounding mode.
689 -------------------------------------------------------------------------------
691 void syst_float_set_rounding_mode(int8 roundingMode)
694 utf.uf_fsr &= ~FSR_RD_MASK;
695 utf.uf_fsr |= FSR_RD((unsigned int)roundingMode & 0x03);
699 -------------------------------------------------------------------------------
701 -------------------------------------------------------------------------------
703 void syst_float_set_rounding_precision(int8 precision)