gdb, testsuite: Fix return value in gdb.base/foll-fork.exp
[binutils-gdb.git] / sim / rx / fpu.c
blobdb7ee794942fd00e58ca26bef2acd9b345b8426e
1 /* fpu.c --- FPU emulator for stand-alone RX simulator.
3 Copyright (C) 2008-2024 Free Software Foundation, Inc.
4 Contributed by Red Hat, Inc.
6 This file is part of the GNU simulators.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 /* This must come before any other includes. */
22 #include "defs.h"
24 #include <stdio.h>
25 #include <stdlib.h>
27 #include "cpu.h"
28 #include "fpu.h"
30 /* FPU encodings are as follows:
32 S EXPONENT MANTISSA
33 1 12345678 12345678901234567890123
35 0 00000000 00000000000000000000000 +0
36 1 00000000 00000000000000000000000 -0
38 X 00000000 00000000000000000000001 Denormals
39 X 00000000 11111111111111111111111
41 X 00000001 XXXXXXXXXXXXXXXXXXXXXXX Normals
42 X 11111110 XXXXXXXXXXXXXXXXXXXXXXX
44 0 11111111 00000000000000000000000 +Inf
45 1 11111111 00000000000000000000000 -Inf
47 X 11111111 0XXXXXXXXXXXXXXXXXXXXXX SNaN (X != 0)
48 X 11111111 1XXXXXXXXXXXXXXXXXXXXXX QNaN (X != 0)
52 #define trace 0
53 #define tprintf if (trace) printf
55 /* Some magic numbers. */
56 #define PLUS_MAX 0x7f7fffffUL
57 #define MINUS_MAX 0xff7fffffUL
58 #define PLUS_INF 0x7f800000UL
59 #define MINUS_INF 0xff800000UL
60 #define PLUS_ZERO 0x00000000UL
61 #define MINUS_ZERO 0x80000000UL
63 #define FP_RAISE(e) fp_raise(FPSWBITS_C##e)
64 static void
65 fp_raise (int mask)
67 regs.r_fpsw |= mask;
68 if (mask != FPSWBITS_CE)
70 if (regs.r_fpsw & (mask << FPSW_CESH))
71 regs.r_fpsw |= (mask << FPSW_CFSH);
72 if (regs.r_fpsw & FPSWBITS_FMASK)
73 regs.r_fpsw |= FPSWBITS_FSUM;
74 else
75 regs.r_fpsw &= ~FPSWBITS_FSUM;
79 /* We classify all numbers as one of these. They correspond to the
80 rows/colums in the exception tables. */
81 typedef enum {
82 FP_NORMAL,
83 FP_PZERO,
84 FP_NZERO,
85 FP_PINFINITY,
86 FP_NINFINITY,
87 FP_DENORMAL,
88 FP_QNAN,
89 FP_SNAN
90 } FP_Type;
92 #if defined DEBUG0
93 static const char *fpt_names[] = {
94 "Normal", "+0", "-0", "+Inf", "-Inf", "Denormal", "QNaN", "SNaN"
96 #endif
98 #define EXP_BIAS 127
99 #define EXP_ZERO -127
100 #define EXP_INF 128
102 #define MANT_BIAS 0x00080000UL
104 typedef struct {
105 int exp;
106 unsigned int mant; /* 24 bits */
107 char type;
108 char sign;
109 fp_t orig_value;
110 } FP_Parts;
112 static void
113 fp_explode (fp_t f, FP_Parts *p)
115 int exp, mant, sign;
117 exp = ((f & 0x7f800000UL) >> 23);
118 mant = f & 0x007fffffUL;
119 sign = f & 0x80000000UL;
120 /*printf("explode: %08x %x %2x %6x\n", f, sign, exp, mant);*/
122 p->sign = sign ? -1 : 1;
123 p->exp = exp - EXP_BIAS;
124 p->orig_value = f;
125 p->mant = mant | 0x00800000UL;
127 if (p->exp == EXP_ZERO)
129 if (regs.r_fpsw & FPSWBITS_DN)
130 mant = 0;
131 if (mant)
132 p->type = FP_DENORMAL;
133 else
135 p->mant = 0;
136 p->type = sign ? FP_NZERO : FP_PZERO;
139 else if (p->exp == EXP_INF)
141 if (mant == 0)
142 p->type = sign ? FP_NINFINITY : FP_PINFINITY;
143 else if (mant & 0x00400000UL)
144 p->type = FP_QNAN;
145 else
146 p->type = FP_SNAN;
148 else
149 p->type = FP_NORMAL;
152 static fp_t
153 fp_implode (FP_Parts *p)
155 int exp, mant;
157 exp = p->exp + EXP_BIAS;
158 mant = p->mant;
159 /*printf("implode: exp %d mant 0x%x\n", exp, mant);*/
160 if (p->type == FP_NORMAL)
162 while (mant
163 && exp > 0
164 && mant < 0x00800000UL)
166 mant <<= 1;
167 exp --;
169 while (mant > 0x00ffffffUL)
171 mant >>= 1;
172 exp ++;
174 if (exp < 0)
176 /* underflow */
177 exp = 0;
178 mant = 0;
179 FP_RAISE (E);
181 if (exp >= 255)
183 /* overflow */
184 exp = 255;
185 mant = 0;
186 FP_RAISE (O);
189 mant &= 0x007fffffUL;
190 exp &= 0xff;
191 mant |= exp << 23;
192 if (p->sign < 0)
193 mant |= 0x80000000UL;
195 return mant;
198 typedef union {
199 unsigned long long ll;
200 double d;
201 } U_d_ll;
203 static int checked_format = 0;
205 /* We assume a double format like this:
206 S[1] E[11] M[52]
209 static double
210 fp_to_double (FP_Parts *p)
212 U_d_ll u;
214 if (!checked_format)
216 u.d = 1.5;
217 if (u.ll != 0x3ff8000000000000ULL)
218 abort ();
219 u.d = -225;
220 if (u.ll != 0xc06c200000000000ULL)
221 abort ();
222 u.d = 10.1;
223 if (u.ll != 0x4024333333333333ULL)
224 abort ();
225 checked_format = 1;
228 u.ll = 0;
229 if (p->sign < 0)
230 u.ll |= (1ULL << 63);
231 /* Make sure a zero encoding stays a zero. */
232 if (p->exp != -EXP_BIAS)
233 u.ll |= ((unsigned long long)p->exp + 1023ULL) << 52;
234 u.ll |= (unsigned long long) (p->mant & 0x007fffffUL) << (52 - 23);
235 return u.d;
238 static void
239 double_to_fp (double d, FP_Parts *p)
241 int exp;
242 U_d_ll u;
243 int sign;
245 u.d = d;
247 sign = (u.ll & 0x8000000000000000ULL) ? 1 : 0;
248 exp = u.ll >> 52;
249 exp = (exp & 0x7ff);
251 if (exp == 0)
253 /* A generated denormal should show up as an underflow, not
254 here. */
255 if (sign)
256 fp_explode (MINUS_ZERO, p);
257 else
258 fp_explode (PLUS_ZERO, p);
259 return;
262 exp = exp - 1023;
263 if ((exp + EXP_BIAS) > 254)
265 FP_RAISE (O);
266 switch (regs.r_fpsw & FPSWBITS_RM)
268 case FPRM_NEAREST:
269 if (sign)
270 fp_explode (MINUS_INF, p);
271 else
272 fp_explode (PLUS_INF, p);
273 break;
274 case FPRM_ZERO:
275 if (sign)
276 fp_explode (MINUS_MAX, p);
277 else
278 fp_explode (PLUS_MAX, p);
279 break;
280 case FPRM_PINF:
281 if (sign)
282 fp_explode (MINUS_MAX, p);
283 else
284 fp_explode (PLUS_INF, p);
285 break;
286 case FPRM_NINF:
287 if (sign)
288 fp_explode (MINUS_INF, p);
289 else
290 fp_explode (PLUS_MAX, p);
291 break;
293 return;
295 if ((exp + EXP_BIAS) < 1)
297 if (sign)
298 fp_explode (MINUS_ZERO, p);
299 else
300 fp_explode (PLUS_ZERO, p);
301 FP_RAISE (U);
304 p->sign = sign ? -1 : 1;
305 p->exp = exp;
306 p->mant = u.ll >> (52-23) & 0x007fffffUL;
307 p->mant |= 0x00800000UL;
308 p->type = FP_NORMAL;
310 if (u.ll & 0x1fffffffULL)
312 switch (regs.r_fpsw & FPSWBITS_RM)
314 case FPRM_NEAREST:
315 if (u.ll & 0x10000000ULL)
316 p->mant ++;
317 break;
318 case FPRM_ZERO:
319 break;
320 case FPRM_PINF:
321 if (sign == 1)
322 p->mant ++;
323 break;
324 case FPRM_NINF:
325 if (sign == -1)
326 p->mant ++;
327 break;
329 FP_RAISE (X);
334 typedef enum {
335 eNR, /* Use the normal result. */
336 ePZ, eNZ, /* +- zero */
337 eSZ, /* signed zero - XOR signs of ops together. */
338 eRZ, /* +- zero depending on rounding mode. */
339 ePI, eNI, /* +- Infinity */
340 eSI, /* signed infinity - XOR signs of ops together. */
341 eQN, eSN, /* Quiet/Signalling NANs */
342 eIn, /* Invalid. */
343 eUn, /* Unimplemented. */
344 eDZ, /* Divide-by-zero. */
345 eLT, /* less than */
346 eGT, /* greater than */
347 eEQ, /* equal to */
348 } FP_ExceptionCases;
350 #if defined DEBUG0
351 static const char *ex_names[] = {
352 "NR", "PZ", "NZ", "SZ", "RZ", "PI", "NI", "SI", "QN", "SN", "IN", "Un", "DZ", "LT", "GT", "EQ"
354 #endif
356 /* This checks for all exceptional cases (not all FP exceptions) and
357 returns TRUE if it is providing the result in *c. If it returns
358 FALSE, the caller should do the "normal" operation. */
359 static int
360 check_exceptions (FP_Parts *a, FP_Parts *b, fp_t *c,
361 FP_ExceptionCases ex_tab[5][5],
362 FP_ExceptionCases *case_ret)
364 FP_ExceptionCases fpec;
366 if (a->type == FP_SNAN
367 || b->type == FP_SNAN)
368 fpec = eIn;
369 else if (a->type == FP_QNAN
370 || b->type == FP_QNAN)
371 fpec = eQN;
372 else if (a->type == FP_DENORMAL
373 || b->type == FP_DENORMAL)
374 fpec = eUn;
375 else
376 fpec = ex_tab[(int)(a->type)][(int)(b->type)];
378 /*printf("%s %s -> %s\n", fpt_names[(int)(a->type)], fpt_names[(int)(b->type)], ex_names[(int)(fpec)]);*/
380 if (case_ret)
381 *case_ret = fpec;
383 switch (fpec)
385 case eNR: /* Use the normal result. */
386 return 0;
388 case ePZ: /* + zero */
389 *c = 0x00000000;
390 return 1;
392 case eNZ: /* - zero */
393 *c = 0x80000000;
394 return 1;
396 case eSZ: /* signed zero */
397 *c = (a->sign == b->sign) ? PLUS_ZERO : MINUS_ZERO;
398 return 1;
400 case eRZ: /* +- zero depending on rounding mode. */
401 if ((regs.r_fpsw & FPSWBITS_RM) == FPRM_NINF)
402 *c = 0x80000000;
403 else
404 *c = 0x00000000;
405 return 1;
407 case ePI: /* + Infinity */
408 *c = 0x7F800000;
409 return 1;
411 case eNI: /* - Infinity */
412 *c = 0xFF800000;
413 return 1;
415 case eSI: /* sign Infinity */
416 *c = (a->sign == b->sign) ? PLUS_INF : MINUS_INF;
417 return 1;
419 case eQN: /* Quiet NANs */
420 if (a->type == FP_QNAN)
421 *c = a->orig_value;
422 else
423 *c = b->orig_value;
424 return 1;
426 case eSN: /* Signalling NANs */
427 if (a->type == FP_SNAN)
428 *c = a->orig_value;
429 else
430 *c = b->orig_value;
431 FP_RAISE (V);
432 return 1;
434 case eIn: /* Invalid. */
435 FP_RAISE (V);
436 if (a->type == FP_SNAN)
437 *c = a->orig_value | 0x00400000;
438 else if (b->type == FP_SNAN)
439 *c = b->orig_value | 0x00400000;
440 else
441 *c = 0x7fc00000;
442 return 1;
444 case eUn: /* Unimplemented. */
445 FP_RAISE (E);
446 return 1;
448 case eDZ: /* Division-by-zero. */
449 *c = (a->sign == b->sign) ? PLUS_INF : MINUS_INF;
450 FP_RAISE (Z);
451 return 1;
453 default:
454 return 0;
458 #define CHECK_EXCEPTIONS(FPPa, FPPb, fpc, ex_tab) \
459 if (check_exceptions (&FPPa, &FPPb, &fpc, ex_tab, 0)) \
460 return fpc;
462 /* For each operation, we have two tables of how nonnormal cases are
463 handled. The DN=0 case is first, followed by the DN=1 case, with
464 each table using the following layout: */
466 static FP_ExceptionCases ex_add_tab[5][5] = {
467 /* N +0 -0 +In -In */
468 { eNR, eNR, eNR, ePI, eNI }, /* Normal */
469 { eNR, ePZ, eRZ, ePI, eNI }, /* +0 */
470 { eNR, eRZ, eNZ, ePI, eNI }, /* -0 */
471 { ePI, ePI, ePI, ePI, eIn }, /* +Inf */
472 { eNI, eNI, eNI, eIn, eNI }, /* -Inf */
475 fp_t
476 rxfp_add (fp_t fa, fp_t fb)
478 FP_Parts a, b, c;
479 fp_t rv;
480 double da, db;
482 fp_explode (fa, &a);
483 fp_explode (fb, &b);
484 CHECK_EXCEPTIONS (a, b, rv, ex_add_tab);
486 da = fp_to_double (&a);
487 db = fp_to_double (&b);
488 tprintf("%g + %g = %g\n", da, db, da+db);
490 double_to_fp (da+db, &c);
491 rv = fp_implode (&c);
492 return rv;
495 static FP_ExceptionCases ex_sub_tab[5][5] = {
496 /* N +0 -0 +In -In */
497 { eNR, eNR, eNR, eNI, ePI }, /* Normal */
498 { eNR, eRZ, ePZ, eNI, ePI }, /* +0 */
499 { eNR, eNZ, eRZ, eNI, ePI }, /* -0 */
500 { ePI, ePI, ePI, eIn, ePI }, /* +Inf */
501 { eNI, eNI, eNI, eNI, eIn }, /* -Inf */
504 fp_t
505 rxfp_sub (fp_t fa, fp_t fb)
507 FP_Parts a, b, c;
508 fp_t rv;
509 double da, db;
511 fp_explode (fa, &a);
512 fp_explode (fb, &b);
513 CHECK_EXCEPTIONS (a, b, rv, ex_sub_tab);
515 da = fp_to_double (&a);
516 db = fp_to_double (&b);
517 tprintf("%g - %g = %g\n", da, db, da-db);
519 double_to_fp (da-db, &c);
520 rv = fp_implode (&c);
522 return rv;
525 static FP_ExceptionCases ex_mul_tab[5][5] = {
526 /* N +0 -0 +In -In */
527 { eNR, eNR, eNR, eSI, eSI }, /* Normal */
528 { eNR, ePZ, eNZ, eIn, eIn }, /* +0 */
529 { eNR, eNZ, ePZ, eIn, eIn }, /* -0 */
530 { eSI, eIn, eIn, ePI, eNI }, /* +Inf */
531 { eSI, eIn, eIn, eNI, ePI }, /* -Inf */
534 fp_t
535 rxfp_mul (fp_t fa, fp_t fb)
537 FP_Parts a, b, c;
538 fp_t rv;
539 double da, db;
541 fp_explode (fa, &a);
542 fp_explode (fb, &b);
543 CHECK_EXCEPTIONS (a, b, rv, ex_mul_tab);
545 da = fp_to_double (&a);
546 db = fp_to_double (&b);
547 tprintf("%g x %g = %g\n", da, db, da*db);
549 double_to_fp (da*db, &c);
550 rv = fp_implode (&c);
552 return rv;
555 static FP_ExceptionCases ex_div_tab[5][5] = {
556 /* N +0 -0 +In -In */
557 { eNR, eDZ, eDZ, eSZ, eSZ }, /* Normal */
558 { eSZ, eIn, eIn, ePZ, eNZ }, /* +0 */
559 { eSZ, eIn, eIn, eNZ, ePZ }, /* -0 */
560 { eSI, ePI, eNI, eIn, eIn }, /* +Inf */
561 { eSI, eNI, ePI, eIn, eIn }, /* -Inf */
564 fp_t
565 rxfp_div (fp_t fa, fp_t fb)
567 FP_Parts a, b, c;
568 fp_t rv;
569 double da, db;
571 fp_explode (fa, &a);
572 fp_explode (fb, &b);
573 CHECK_EXCEPTIONS (a, b, rv, ex_div_tab);
575 da = fp_to_double (&a);
576 db = fp_to_double (&b);
577 tprintf("%g / %g = %g\n", da, db, da/db);
579 double_to_fp (da/db, &c);
580 rv = fp_implode (&c);
582 return rv;
585 static FP_ExceptionCases ex_cmp_tab[5][5] = {
586 /* N +0 -0 +In -In */
587 { eNR, eNR, eNR, eLT, eGT }, /* Normal */
588 { eNR, eEQ, eEQ, eLT, eGT }, /* +0 */
589 { eNR, eEQ, eEQ, eLT, eGT }, /* -0 */
590 { eGT, eGT, eGT, eEQ, eGT }, /* +Inf */
591 { eLT, eLT, eLT, eLT, eEQ }, /* -Inf */
594 void
595 rxfp_cmp (fp_t fa, fp_t fb)
597 FP_Parts a, b;
598 fp_t c;
599 FP_ExceptionCases reason;
600 int flags = 0;
601 double da, db;
603 fp_explode (fa, &a);
604 fp_explode (fb, &b);
606 if (check_exceptions (&a, &b, &c, ex_cmp_tab, &reason))
608 if (reason == eQN)
610 /* Special case - incomparable. */
611 set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O, FLAGBIT_O);
612 return;
614 return;
617 switch (reason)
619 case eEQ:
620 flags = FLAGBIT_Z;
621 break;
622 case eLT:
623 flags = FLAGBIT_S;
624 break;
625 case eGT:
626 flags = 0;
627 break;
628 case eNR:
629 da = fp_to_double (&a);
630 db = fp_to_double (&b);
631 tprintf("fcmp: %g cmp %g\n", da, db);
632 if (da < db)
633 flags = FLAGBIT_S;
634 else if (da == db)
635 flags = FLAGBIT_Z;
636 else
637 flags = 0;
638 break;
639 default:
640 abort();
643 set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O, flags);
646 long
647 rxfp_ftoi (fp_t fa, int round_mode)
649 FP_Parts a;
650 fp_t rv;
651 int sign;
652 int whole_bits, frac_bits;
654 fp_explode (fa, &a);
655 sign = fa & 0x80000000UL;
657 switch (a.type)
659 case FP_NORMAL:
660 break;
661 case FP_PZERO:
662 case FP_NZERO:
663 return 0;
664 case FP_PINFINITY:
665 FP_RAISE (V);
666 return 0x7fffffffL;
667 case FP_NINFINITY:
668 FP_RAISE (V);
669 return 0x80000000L;
670 case FP_DENORMAL:
671 FP_RAISE (E);
672 return 0;
673 case FP_QNAN:
674 case FP_SNAN:
675 FP_RAISE (V);
676 return sign ? 0x80000000U : 0x7fffffff;
679 if (a.exp >= 31)
681 FP_RAISE (V);
682 return sign ? 0x80000000U : 0x7fffffff;
685 a.exp -= 23;
687 if (a.exp <= -25)
689 /* Less than 0.49999 */
690 frac_bits = a.mant;
691 whole_bits = 0;
693 else if (a.exp < 0)
695 frac_bits = a.mant << (32 + a.exp);
696 whole_bits = a.mant >> (-a.exp);
698 else
700 frac_bits = 0;
701 whole_bits = a.mant << a.exp;
704 if (frac_bits)
706 switch (round_mode & 3)
708 case FPRM_NEAREST:
709 if (frac_bits & 0x80000000UL)
710 whole_bits ++;
711 break;
712 case FPRM_ZERO:
713 break;
714 case FPRM_PINF:
715 if (!sign)
716 whole_bits ++;
717 break;
718 case FPRM_NINF:
719 if (sign)
720 whole_bits ++;
721 break;
725 rv = sign ? -whole_bits : whole_bits;
727 return rv;
730 fp_t
731 rxfp_itof (long fa, int round_mode)
733 fp_t rv;
734 int sign = 0;
735 unsigned int frac_bits;
736 volatile unsigned int whole_bits;
737 FP_Parts a = {0};
739 if (fa == 0)
740 return PLUS_ZERO;
742 if (fa < 0)
744 fa = -fa;
745 sign = 1;
746 a.sign = -1;
748 else
749 a.sign = 1;
751 whole_bits = fa;
752 a.exp = 31;
754 while (! (whole_bits & 0x80000000UL))
756 a.exp --;
757 whole_bits <<= 1;
759 frac_bits = whole_bits & 0xff;
760 whole_bits = whole_bits >> 8;
762 if (frac_bits)
764 /* We must round */
765 switch (round_mode & 3)
767 case FPRM_NEAREST:
768 if (frac_bits & 0x80)
769 whole_bits ++;
770 break;
771 case FPRM_ZERO:
772 break;
773 case FPRM_PINF:
774 if (!sign)
775 whole_bits ++;
776 break;
777 case FPRM_NINF:
778 if (sign)
779 whole_bits ++;
780 break;
784 a.mant = whole_bits;
785 if (whole_bits & 0xff000000UL)
787 a.mant >>= 1;
788 a.exp ++;
791 rv = fp_implode (&a);
792 return rv;