]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - tools/test/testfloat/sparc64/fpu_util.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / tools / test / testfloat / sparc64 / fpu_util.c
1 /*-
2  * Copyright (c) 2010 by Peter Jeremy <peterjeremy@acm.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
13  *
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.
24  */
25
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
28
29 #include <sys/param.h>
30
31 #include <math.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34
35 #include "__sparc_utrap_private.h"
36 #include "fpu_extern.h"
37 #include "fpu_reg.h"
38
39 static u_long   ireg[32];
40
41 void
42 __utrap_panic(const char *msg)
43 {
44
45         fprintf(stderr, "panic: %s\n", msg);
46         exit(1);
47 }
48
49 void __utrap_write(const char *msg)
50 {
51
52         fprintf(stderr, "%s", msg);
53 }
54
55 u_long
56 __emul_fetch_reg(struct utrapframe *uf, int reg)
57 {
58
59         return (ireg[reg]);
60 }
61
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;
67 typedef struct {
68         unsigned long high, low;
69 } float128;
70 typedef unsigned long flag;
71
72 struct utrapframe utf;
73
74 u_int32_t __fpreg[64];
75
76 static __inline float128
77 __fpu_getreg128(int r)
78 {
79         float128 v;
80
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]);
83         return (v);
84 }
85
86 static __inline void
87 __fpu_setreg128(int r, float128 v)
88 {
89
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;
94 }
95
96 /*
97 -------------------------------------------------------------------------------
98 Clears the system's IEC/IEEE floating-point exception flags.  Returns the
99 previous value of the flags.
100 -------------------------------------------------------------------------------
101 */
102 #include <fenv.h>
103 #include <ieeefp.h>
104
105 int8 syst_float_flags_clear(void)
106 {
107         int32 flags;
108
109         flags = (utf.uf_fsr & FE_ALL_EXCEPT) >> 5;
110         utf.uf_fsr &= ~(u_long)FE_ALL_EXCEPT;
111         return (flags);
112 }
113
114 static void
115 emul_trap(const u_int *insn, u_long mask)
116 {
117         u_int32_t savreg[64];
118         int i;
119
120         for (i = 0; i < 64; i++)
121             savreg[i] = __fpreg[i];
122
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));
128         
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]);
133                 }
134         }
135 }
136
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;
176
177 float32
178 syst_int32_to_float32(int32 a)
179 {
180
181         __fpu_setreg(0, a);
182         emul_trap(&insn_int32_to_float32, 0x1UL);
183         return (__fpu_getreg(0));
184 }
185
186 float64
187 syst_int32_to_float64(int32 a)
188 {
189
190         __fpu_setreg(0, a);
191         emul_trap(&insn_int32_to_float64, 0x3UL);
192         return (__fpu_getreg64(0));
193 }
194
195 float128
196 syst_int32_to_float128(int32 a)
197 {
198
199         __fpu_setreg(0, a);
200         emul_trap(&insn_int32_to_float128, 0xfUL);
201         return (__fpu_getreg128(0));
202 }
203
204 float32
205 syst_int64_to_float32(int64 a)
206 {
207
208         __fpu_setreg64(0, a);
209         emul_trap(&insn_int64_to_float32, 0x1UL);
210         return (__fpu_getreg(0));
211 }
212
213 float64
214 syst_int64_to_float64(int64 a)
215 {
216
217         __fpu_setreg64(0, a);
218         emul_trap(&insn_int64_to_float64, 0x3UL);
219         return (__fpu_getreg64(0));
220 }
221
222
223 float128
224 syst_int64_to_float128(int64 a)
225 {
226
227         __fpu_setreg64(0, a);
228         emul_trap(&insn_int64_to_float128, 0xfUL);
229         return (__fpu_getreg128(0));
230 }
231
232 int32
233 syst_float32_to_int32_round_to_zero(float32 a)
234 {
235
236         __fpu_setreg(0, a);
237         emul_trap(&insn_float32_to_int32_round_to_zero, 0x1UL);
238         return (__fpu_getreg(0));
239 }
240
241 int64
242 syst_float32_to_int64_round_to_zero(float32 a)
243 {
244
245         __fpu_setreg(0, a);
246         emul_trap(&insn_float32_to_int64_round_to_zero, 0x3UL);
247         return (__fpu_getreg64(0));
248 }
249
250 float64
251 syst_float32_to_float64(float32 a)
252 {
253
254         __fpu_setreg(0, a);
255         emul_trap(&insn_float32_to_float64, 0x3UL);
256         return (__fpu_getreg64(0));
257 }
258
259 float128
260 syst_float32_to_float128(float32 a)
261 {
262
263         __fpu_setreg(0, a);
264         emul_trap(&insn_float32_to_float128, 0xfUL);
265         return (__fpu_getreg128(0));
266 }
267
268 float32
269 syst_float32_add(float32 a, float32 b)
270 {
271
272         __fpu_setreg(0, a);
273         __fpu_setreg(1, b);
274         emul_trap(&insn_float32_add, 0x1UL);
275         return (__fpu_getreg(0));
276 }
277
278 float32
279 syst_float32_sub(float32 a, float32 b)
280 {
281
282         __fpu_setreg(0, a);
283         __fpu_setreg(1, b);
284         emul_trap(&insn_float32_sub, 0x1UL);
285         return (__fpu_getreg(0));
286 }
287
288 float32
289 syst_float32_mul(float32 a, float32 b)
290 {
291
292         __fpu_setreg(0, a);
293         __fpu_setreg(1, b);
294         emul_trap(&insn_float32_mul, 0x1UL);
295         return (__fpu_getreg(0));
296 }
297
298 float32
299 syst_float32_div(float32 a, float32 b)
300 {
301
302         __fpu_setreg(0, a);
303         __fpu_setreg(1, b);
304         emul_trap(&insn_float32_div, 0x1UL);
305         return (__fpu_getreg(0));
306 }
307
308 float32
309 syst_float32_sqrt(float32 a)
310 {
311
312         __fpu_setreg(0, a);
313         emul_trap(&insn_float32_sqrt, 0x1UL);
314         return (__fpu_getreg(0));
315 }
316
317 flag syst_float32_eq(float32 a, float32 b)
318 {
319         u_long r;
320
321         __fpu_setreg(0, a);
322         __fpu_setreg(1, b);
323         emul_trap(&insn_float32_cmp, 0x0UL);
324         __asm __volatile("mov 0,%0; move %%fcc0,1,%0" : "=r" (r));
325         return (r);
326 }
327
328 flag syst_float32_le(float32 a, float32 b)
329 {
330         u_long r;
331
332         __fpu_setreg(0, a);
333         __fpu_setreg(1, b);
334         emul_trap(&insn_float32_cmpe, 0x0UL);
335         __asm __volatile("mov 0,%0; movle %%fcc0,1,%0" : "=r" (r));
336         return (r);
337 }
338
339 flag syst_float32_lt(float32 a, float32 b)
340 {
341         u_long r;
342
343         __fpu_setreg(0, a);
344         __fpu_setreg(1, b);
345         emul_trap(&insn_float32_cmpe, 0x0UL);
346         __asm __volatile("mov 0,%0; movl %%fcc0,1,%0" : "=r" (r));
347         return (r);
348 }
349
350 flag syst_float32_eq_signaling(float32 a, float32 b)
351 {
352         u_long r;
353
354         __fpu_setreg(0, a);
355         __fpu_setreg(1, b);
356         emul_trap(&insn_float32_cmpe, 0x0UL);
357         __asm __volatile("mov 0,%0; move %%fcc0,1,%0" : "=r" (r));
358         return (r);
359 }
360
361 flag syst_float32_le_quiet(float32 a, float32 b)
362 {
363         u_long r;
364
365         __fpu_setreg(0, a);
366         __fpu_setreg(1, b);
367         emul_trap(&insn_float32_cmp, 0x0UL);
368         __asm __volatile("mov 0,%0; movle %%fcc0,1,%0" : "=r" (r));
369         return (r);
370 }
371
372 flag syst_float32_lt_quiet(float32 a, float32 b)
373 {
374         u_long r;
375
376         __fpu_setreg(0, a);
377         __fpu_setreg(1, b);
378         emul_trap(&insn_float32_cmp, 0x0UL);
379         __asm __volatile("mov 0,%0; movl %%fcc0,1,%0" : "=r" (r));
380         return (r);
381 }
382
383 int32
384 syst_float64_to_int32_round_to_zero(float64 a)
385 {
386
387         __fpu_setreg64(0, a);
388         emul_trap(&insn_float64_to_int32_round_to_zero, 0x1UL);
389         return (__fpu_getreg(0));
390 }
391
392 int64
393 syst_float64_to_int64_round_to_zero(float64 a)
394 {
395
396         __fpu_setreg64(0, a);
397         emul_trap(&insn_float64_to_int64_round_to_zero, 0x3UL);
398         return (__fpu_getreg64(0));
399 }
400
401 float32
402 syst_float64_to_float32(float64 a)
403 {
404
405         __fpu_setreg64(0, a);
406         emul_trap(&insn_float64_to_float32, 0x1UL);
407         return (__fpu_getreg(0));
408 }
409
410 float128
411 syst_float64_to_float128(float64 a)
412 {
413
414         __fpu_setreg64(0, a);
415         emul_trap(&insn_float64_to_float128, 0xfUL);
416         return (__fpu_getreg128(0));
417 }
418
419 float64
420 syst_float64_add(float64 a, float64 b)
421 {
422
423         __fpu_setreg64(0, a);
424         __fpu_setreg64(2, b);
425         emul_trap(&insn_float64_add, 0x3UL);
426         return (__fpu_getreg64(0));
427 }
428
429 float64
430 syst_float64_sub(float64 a, float64 b)
431 {
432
433         __fpu_setreg64(0, a);
434         __fpu_setreg64(2, b);
435         emul_trap(&insn_float64_sub, 0x3UL);
436         return (__fpu_getreg64(0));
437 }
438
439 float64
440 syst_float64_mul(float64 a, float64 b)
441 {
442
443         __fpu_setreg64(0, a);
444         __fpu_setreg64(2, b);
445         emul_trap(&insn_float64_mul, 0x3UL);
446         return (__fpu_getreg64(0));
447 }
448
449 float64
450 syst_float64_div(float64 a, float64 b)
451 {
452
453         __fpu_setreg64(0, a);
454         __fpu_setreg64(2, b);
455         emul_trap(&insn_float64_div, 0x3UL);
456         return (__fpu_getreg64(0));
457 }
458
459 float64
460 syst_float64_sqrt(float64 a)
461 {
462
463         __fpu_setreg64(0, a);
464         emul_trap(&insn_float64_sqrt, 0x3UL);
465         return (__fpu_getreg64(0));
466 }
467
468 flag syst_float64_eq(float64 a, float64 b)
469 {
470         u_long r;
471
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));
476         return (r);
477 }
478
479 flag syst_float64_le(float64 a, float64 b)
480 {
481         u_long r;
482
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));
487         return (r);
488 }
489
490 flag syst_float64_lt(float64 a, float64 b)
491 {
492         u_long r;
493
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));
498         return (r);
499 }
500
501 flag syst_float64_eq_signaling(float64 a, float64 b)
502 {
503         u_long r;
504
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));
509         return (r);
510 }
511
512 flag syst_float64_le_quiet(float64 a, float64 b)
513 {
514         u_long r;
515
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));
520         return (r);
521 }
522
523 flag syst_float64_lt_quiet(float64 a, float64 b)
524 {
525         u_long r;
526
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));
531         return (r);
532 }
533
534 int32
535 syst_float128_to_int32_round_to_zero(float128 a)
536 {
537
538         __fpu_setreg128(0, a);
539         emul_trap(&insn_float128_to_int32_round_to_zero, 0x1UL);
540         return (__fpu_getreg(0));
541 }
542
543 int64
544 syst_float128_to_int64_round_to_zero(float128 a)
545 {
546
547         __fpu_setreg128(0, a);
548         emul_trap(&insn_float128_to_int64_round_to_zero, 0x3UL);
549         return (__fpu_getreg64(0));
550 }
551
552 float32
553 syst_float128_to_float32(float128 a)
554 {
555
556         __fpu_setreg128(0, a);
557         emul_trap(&insn_float128_to_float32, 0x1UL);
558         return (__fpu_getreg(0));
559 }
560
561 float64
562 syst_float128_to_float64(float128 a)
563 {
564
565         __fpu_setreg128(0, a);
566         emul_trap(&insn_float128_to_float64, 0x3UL);
567         return (__fpu_getreg64(0));
568 }
569
570 float128
571 syst_float128_add(float128 a, float128 b)
572 {
573
574         __fpu_setreg128(0, a);
575         __fpu_setreg128(4, b);
576         emul_trap(&insn_float128_add, 0xfUL);
577         return (__fpu_getreg128(0));
578 }
579
580 float128
581 syst_float128_sub(float128 a, float128 b)
582 {
583
584         __fpu_setreg128(0, a);
585         __fpu_setreg128(4, b);
586         emul_trap(&insn_float128_sub, 0xfUL);
587         return (__fpu_getreg128(0));
588 }
589
590 float128
591 syst_float128_mul(float128 a, float128 b)
592 {
593
594         __fpu_setreg128(0, a);
595         __fpu_setreg128(4, b);
596         emul_trap(&insn_float128_mul, 0xfUL);
597         return (__fpu_getreg128(0));
598 }
599
600 float128
601 syst_float128_div(float128 a, float128 b)
602 {
603
604         __fpu_setreg128(0, a);
605         __fpu_setreg128(4, b);
606         emul_trap(&insn_float128_div, 0xfUL);
607         return (__fpu_getreg128(0));
608 }
609
610 float128
611 syst_float128_sqrt(float128 a)
612 {
613
614         __fpu_setreg128(0, a);
615         emul_trap(&insn_float128_sqrt, 0xfUL);
616         return (__fpu_getreg128(0));
617 }
618
619 flag syst_float128_eq(float128 a, float128 b)
620 {
621         u_long r;
622
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));
627         return (r);
628 }
629
630 flag syst_float128_le(float128 a, float128 b)
631 {
632         u_long r;
633
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));
638         return (r);
639 }
640
641 flag syst_float128_lt(float128 a, float128 b)
642 {
643         u_long r;
644
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));
649         return (r);
650 }
651
652 flag syst_float128_eq_signaling(float128 a, float128 b)
653 {
654         u_long r;
655
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));
660         return (r);
661 }
662
663 flag syst_float128_le_quiet(float128 a, float128 b)
664 {
665         u_long r;
666
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));
671         return (r);
672 }
673
674 flag syst_float128_lt_quiet(float128 a, float128 b)
675 {
676         u_long r;
677
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));
682         return (r);
683 }
684
685
686 /*
687 -------------------------------------------------------------------------------
688 Sets the system's IEC/IEEE floating-point rounding mode.
689 -------------------------------------------------------------------------------
690 */
691 void syst_float_set_rounding_mode(int8 roundingMode)
692 {
693
694         utf.uf_fsr &= ~FSR_RD_MASK;
695         utf.uf_fsr |= FSR_RD((unsigned int)roundingMode & 0x03);
696 }
697
698 /*
699 -------------------------------------------------------------------------------
700 Does nothing.
701 -------------------------------------------------------------------------------
702 */
703 void syst_float_set_rounding_precision(int8 precision)
704 {
705
706 }