]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/mips/cp1.c
2002-05-01 Chris Demetriou <cgd@broadcom.com>
[thirdparty/binutils-gdb.git] / sim / mips / cp1.c
1 /*> cp1.c <*/
2 /* Floating Point Support for gdb MIPS simulators
3
4 This file is part of the MIPS sim
5
6 THIS SOFTWARE IS NOT COPYRIGHTED
7
8 Cygnus offers the following for use in the public domain. Cygnus
9 makes no warranty with regard to the software or it's performance
10 and the user accepts the software "AS IS" with all faults.
11
12 CYGNUS DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO
13 THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15
16 (Originally, this code was in interp.c)
17 */
18
19 #include "sim-main.h"
20 #include "sim-fpu.h"
21
22 /* Within cp1.c we refer to sim_cpu directly. */
23 #define CPU cpu
24 #define SD sd
25
26 /*-- FPU support routines ---------------------------------------------------*/
27
28 /* Numbers are held in normalized form. The SINGLE and DOUBLE binary
29 formats conform to ANSI/IEEE Std 754-1985. */
30 /* SINGLE precision floating:
31 * seeeeeeeefffffffffffffffffffffff
32 * s = 1bit = sign
33 * e = 8bits = exponent
34 * f = 23bits = fraction
35 */
36 /* SINGLE precision fixed:
37 * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
38 * s = 1bit = sign
39 * i = 31bits = integer
40 */
41 /* DOUBLE precision floating:
42 * seeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffff
43 * s = 1bit = sign
44 * e = 11bits = exponent
45 * f = 52bits = fraction
46 */
47 /* DOUBLE precision fixed:
48 * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
49 * s = 1bit = sign
50 * i = 63bits = integer
51 */
52
53 /* Explicit QNaN values used when value required: */
54 #define FPQNaN_SINGLE (0x7FBFFFFF)
55 #define FPQNaN_WORD (0x7FFFFFFF)
56 #define FPQNaN_DOUBLE ((((uword64) 0x7FF7FFFF) << 32) | 0xFFFFFFFF)
57 #define FPQNaN_LONG ((((uword64) 0x7FFFFFFF) << 32) | 0xFFFFFFFF)
58
59 static const char *fpu_format_name (FP_formats fmt);
60 #ifdef DEBUG
61 static const char *fpu_rounding_mode_name (int rm);
62 #endif
63
64 uword64
65 value_fpr (SIM_DESC sd,
66 sim_cpu *cpu,
67 address_word cia,
68 int fpr,
69 FP_formats fmt)
70 {
71 uword64 value = 0;
72 int err = 0;
73
74 /* Treat unused register values, as fixed-point 64bit values: */
75 if ((fmt == fmt_uninterpreted) || (fmt == fmt_unknown))
76 {
77 #if 1
78 /* If request to read data as "uninterpreted", then use the current
79 encoding: */
80 fmt = FPR_STATE[fpr];
81 #else
82 fmt = fmt_long;
83 #endif
84 }
85
86 /* For values not yet accessed, set to the desired format: */
87 if (FPR_STATE[fpr] == fmt_uninterpreted)
88 {
89 FPR_STATE[fpr] = fmt;
90 #ifdef DEBUG
91 printf ("DBG: Register %d was fmt_uninterpreted. Now %s\n", fpr,
92 fpu_format_name (fmt));
93 #endif /* DEBUG */
94 }
95 if (fmt != FPR_STATE[fpr])
96 {
97 sim_io_eprintf (sd, "FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",
98 fpr, fpu_format_name (FPR_STATE[fpr]),
99 fpu_format_name (fmt), pr_addr (cia));
100 FPR_STATE[fpr] = fmt_unknown;
101 }
102
103 if (FPR_STATE[fpr] == fmt_unknown)
104 {
105 /* Set QNaN value: */
106 switch (fmt)
107 {
108 case fmt_single:
109 value = FPQNaN_SINGLE;
110 break;
111
112 case fmt_double:
113 value = FPQNaN_DOUBLE;
114 break;
115
116 case fmt_word:
117 value = FPQNaN_WORD;
118 break;
119
120 case fmt_long:
121 value = FPQNaN_LONG;
122 break;
123
124 default:
125 err = -1;
126 break;
127 }
128 }
129 else if (SizeFGR () == 64)
130 {
131 switch (fmt)
132 {
133 case fmt_single:
134 case fmt_word:
135 value = (FGR[fpr] & 0xFFFFFFFF);
136 break;
137
138 case fmt_uninterpreted:
139 case fmt_double:
140 case fmt_long:
141 value = FGR[fpr];
142 break;
143
144 default:
145 err = -1;
146 break;
147 }
148 }
149 else
150 {
151 switch (fmt)
152 {
153 case fmt_single:
154 case fmt_word:
155 value = (FGR[fpr] & 0xFFFFFFFF);
156 break;
157
158 case fmt_uninterpreted:
159 case fmt_double:
160 case fmt_long:
161 if ((fpr & 1) == 0)
162 {
163 /* even registers only */
164 #ifdef DEBUG
165 printf ("DBG: ValueFPR: FGR[%d] = %s, FGR[%d] = %s\n",
166 fpr + 1, pr_uword64 ((uword64) FGR[fpr+1]),
167 fpr, pr_uword64 ((uword64) FGR[fpr]));
168 #endif
169 value = ((((uword64) FGR[fpr+1]) << 32)
170 | (FGR[fpr] & 0xFFFFFFFF));
171 }
172 else
173 {
174 SignalException (ReservedInstruction, 0);
175 }
176 break;
177
178 default :
179 err = -1;
180 break;
181 }
182 }
183
184 if (err)
185 SignalExceptionSimulatorFault ("Unrecognised FP format in ValueFPR ()");
186
187 #ifdef DEBUG
188 printf ("DBG: ValueFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR () = %d\n",
189 fpr, fpu_format_name (fmt), pr_uword64 (value), pr_addr (cia),
190 SizeFGR ());
191 #endif /* DEBUG */
192
193 return (value);
194 }
195
196 void
197 store_fpr (SIM_DESC sd,
198 sim_cpu *cpu,
199 address_word cia,
200 int fpr,
201 FP_formats fmt,
202 uword64 value)
203 {
204 int err = 0;
205
206 #ifdef DEBUG
207 printf ("DBG: StoreFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR () = %d, \n",
208 fpr, fpu_format_name (fmt), pr_uword64 (value), pr_addr (cia),
209 SizeFGR ());
210 #endif /* DEBUG */
211
212 if (SizeFGR () == 64)
213 {
214 switch (fmt)
215 {
216 case fmt_uninterpreted_32:
217 fmt = fmt_uninterpreted;
218 case fmt_single :
219 case fmt_word :
220 if (STATE_VERBOSE_P (SD))
221 sim_io_eprintf (SD,
222 "Warning: PC 0x%s: interp.c store_fpr DEADCODE\n",
223 pr_addr (cia));
224 FGR[fpr] = (((uword64) 0xDEADC0DE << 32) | (value & 0xFFFFFFFF));
225 FPR_STATE[fpr] = fmt;
226 break;
227
228 case fmt_uninterpreted_64:
229 fmt = fmt_uninterpreted;
230 case fmt_uninterpreted:
231 case fmt_double :
232 case fmt_long :
233 FGR[fpr] = value;
234 FPR_STATE[fpr] = fmt;
235 break;
236
237 default :
238 FPR_STATE[fpr] = fmt_unknown;
239 err = -1;
240 break;
241 }
242 }
243 else
244 {
245 switch (fmt)
246 {
247 case fmt_uninterpreted_32:
248 fmt = fmt_uninterpreted;
249 case fmt_single :
250 case fmt_word :
251 FGR[fpr] = (value & 0xFFFFFFFF);
252 FPR_STATE[fpr] = fmt;
253 break;
254
255 case fmt_uninterpreted_64:
256 fmt = fmt_uninterpreted;
257 case fmt_uninterpreted:
258 case fmt_double :
259 case fmt_long :
260 if ((fpr & 1) == 0)
261 {
262 /* even register number only */
263 FGR[fpr+1] = (value >> 32);
264 FGR[fpr] = (value & 0xFFFFFFFF);
265 FPR_STATE[fpr + 1] = fmt;
266 FPR_STATE[fpr] = fmt;
267 }
268 else
269 {
270 FPR_STATE[fpr] = fmt_unknown;
271 FPR_STATE[fpr + 1] = fmt_unknown;
272 SignalException (ReservedInstruction, 0);
273 }
274 break;
275
276 default :
277 FPR_STATE[fpr] = fmt_unknown;
278 err = -1;
279 break;
280 }
281 }
282
283 if (err)
284 SignalExceptionSimulatorFault ("Unrecognised FP format in StoreFPR ()");
285
286 #ifdef DEBUG
287 printf ("DBG: StoreFPR: fpr[%d] = 0x%s (format %s)\n",
288 fpr, pr_uword64 (FGR[fpr]), fpu_format_name (fmt));
289 #endif /* DEBUG */
290
291 return;
292 }
293
294 int
295 NaN (op, fmt)
296 uword64 op;
297 FP_formats fmt;
298 {
299 int boolean = 0;
300 switch (fmt)
301 {
302 case fmt_single:
303 case fmt_word:
304 {
305 sim_fpu wop;
306 sim_fpu_32to (&wop, op);
307 boolean = sim_fpu_is_nan (&wop);
308 break;
309 }
310 case fmt_double:
311 case fmt_long:
312 {
313 sim_fpu wop;
314 sim_fpu_64to (&wop, op);
315 boolean = sim_fpu_is_nan (&wop);
316 break;
317 }
318 default:
319 fprintf (stderr, "Bad switch\n");
320 abort ();
321 }
322
323 #ifdef DEBUG
324 printf ("DBG: NaN: returning %d for 0x%s (format = %s)\n",
325 boolean, pr_addr (op), fpu_format_name (fmt));
326 #endif /* DEBUG */
327
328 return (boolean);
329 }
330
331 int
332 Infinity (op, fmt)
333 uword64 op;
334 FP_formats fmt;
335 {
336 int boolean = 0;
337
338 #ifdef DEBUG
339 printf ("DBG: Infinity: format %s 0x%s\n",
340 fpu_format_name (fmt), pr_addr (op));
341 #endif /* DEBUG */
342
343 switch (fmt)
344 {
345 case fmt_single:
346 {
347 sim_fpu wop;
348 sim_fpu_32to (&wop, op);
349 boolean = sim_fpu_is_infinity (&wop);
350 break;
351 }
352 case fmt_double:
353 {
354 sim_fpu wop;
355 sim_fpu_64to (&wop, op);
356 boolean = sim_fpu_is_infinity (&wop);
357 break;
358 }
359 default:
360 printf ("DBG: TODO: unrecognised format (%s) for Infinity check\n",
361 fpu_format_name (fmt));
362 break;
363 }
364
365 #ifdef DEBUG
366 printf ("DBG: Infinity: returning %d for 0x%s (format = %s)\n",
367 boolean, pr_addr (op), fpu_format_name (fmt));
368 #endif /* DEBUG */
369
370 return (boolean);
371 }
372
373 int
374 Less (op1, op2, fmt)
375 uword64 op1;
376 uword64 op2;
377 FP_formats fmt;
378 {
379 int boolean = 0;
380
381 /* Argument checking already performed by the FPCOMPARE code */
382
383 #ifdef DEBUG
384 printf ("DBG: Less: %s: op1 = 0x%s : op2 = 0x%s\n",
385 fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
386 #endif /* DEBUG */
387
388 /* The format type should already have been checked: */
389 switch (fmt)
390 {
391 case fmt_single:
392 {
393 sim_fpu wop1;
394 sim_fpu wop2;
395 sim_fpu_32to (&wop1, op1);
396 sim_fpu_32to (&wop2, op2);
397 boolean = sim_fpu_is_lt (&wop1, &wop2);
398 break;
399 }
400 case fmt_double:
401 {
402 sim_fpu wop1;
403 sim_fpu wop2;
404 sim_fpu_64to (&wop1, op1);
405 sim_fpu_64to (&wop2, op2);
406 boolean = sim_fpu_is_lt (&wop1, &wop2);
407 break;
408 }
409 default:
410 fprintf (stderr, "Bad switch\n");
411 abort ();
412 }
413
414 #ifdef DEBUG
415 printf ("DBG: Less: returning %d (format = %s)\n",
416 boolean, fpu_format_name (fmt));
417 #endif /* DEBUG */
418
419 return (boolean);
420 }
421
422 int
423 Equal (op1, op2, fmt)
424 uword64 op1;
425 uword64 op2;
426 FP_formats fmt;
427 {
428 int boolean = 0;
429
430 /* Argument checking already performed by the FPCOMPARE code */
431
432 #ifdef DEBUG
433 printf ("DBG: Equal: %s: op1 = 0x%s : op2 = 0x%s\n",
434 fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
435 #endif /* DEBUG */
436
437 /* The format type should already have been checked: */
438 switch (fmt)
439 {
440 case fmt_single:
441 {
442 sim_fpu wop1;
443 sim_fpu wop2;
444 sim_fpu_32to (&wop1, op1);
445 sim_fpu_32to (&wop2, op2);
446 boolean = sim_fpu_is_eq (&wop1, &wop2);
447 break;
448 }
449 case fmt_double:
450 {
451 sim_fpu wop1;
452 sim_fpu wop2;
453 sim_fpu_64to (&wop1, op1);
454 sim_fpu_64to (&wop2, op2);
455 boolean = sim_fpu_is_eq (&wop1, &wop2);
456 break;
457 }
458 default:
459 fprintf (stderr, "Bad switch\n");
460 abort ();
461 }
462
463 #ifdef DEBUG
464 printf ("DBG: Equal: returning %d (format = %s)\n",
465 boolean, fpu_format_name (fmt));
466 #endif /* DEBUG */
467
468 return (boolean);
469 }
470
471 uword64
472 AbsoluteValue (op, fmt)
473 uword64 op;
474 FP_formats fmt;
475 {
476 uword64 result = 0;
477
478 #ifdef DEBUG
479 printf ("DBG: AbsoluteValue: %s: op = 0x%s\n",
480 fpu_format_name (fmt), pr_addr (op));
481 #endif /* DEBUG */
482
483 /* The format type should already have been checked: */
484 switch (fmt)
485 {
486 case fmt_single:
487 {
488 sim_fpu wop;
489 unsigned32 ans;
490 sim_fpu_32to (&wop, op);
491 sim_fpu_abs (&wop, &wop);
492 sim_fpu_to32 (&ans, &wop);
493 result = ans;
494 break;
495 }
496 case fmt_double:
497 {
498 sim_fpu wop;
499 unsigned64 ans;
500 sim_fpu_64to (&wop, op);
501 sim_fpu_abs (&wop, &wop);
502 sim_fpu_to64 (&ans, &wop);
503 result = ans;
504 break;
505 }
506 default:
507 fprintf (stderr, "Bad switch\n");
508 abort ();
509 }
510
511 return (result);
512 }
513
514 uword64
515 Negate (op, fmt)
516 uword64 op;
517 FP_formats fmt;
518 {
519 uword64 result = 0;
520
521 #ifdef DEBUG
522 printf ("DBG: Negate: %s: op = 0x%s\n",
523 fpu_format_name (fmt), pr_addr (op));
524 #endif /* DEBUG */
525
526 /* The format type should already have been checked: */
527 switch (fmt)
528 {
529 case fmt_single:
530 {
531 sim_fpu wop;
532 unsigned32 ans;
533 sim_fpu_32to (&wop, op);
534 sim_fpu_neg (&wop, &wop);
535 sim_fpu_to32 (&ans, &wop);
536 result = ans;
537 break;
538 }
539 case fmt_double:
540 {
541 sim_fpu wop;
542 unsigned64 ans;
543 sim_fpu_64to (&wop, op);
544 sim_fpu_neg (&wop, &wop);
545 sim_fpu_to64 (&ans, &wop);
546 result = ans;
547 break;
548 }
549 default:
550 fprintf (stderr, "Bad switch\n");
551 abort ();
552 }
553
554 return (result);
555 }
556
557 uword64
558 Add (op1, op2, fmt)
559 uword64 op1;
560 uword64 op2;
561 FP_formats fmt;
562 {
563 uword64 result = 0;
564
565 #ifdef DEBUG
566 printf ("DBG: Add: %s: op1 = 0x%s : op2 = 0x%s\n",
567 fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
568 #endif /* DEBUG */
569
570 /* The registers must specify FPRs valid for operands of type
571 "fmt". If they are not valid, the result is undefined. */
572
573 /* The format type should already have been checked: */
574 switch (fmt)
575 {
576 case fmt_single:
577 {
578 sim_fpu wop1;
579 sim_fpu wop2;
580 sim_fpu ans;
581 unsigned32 res;
582 sim_fpu_32to (&wop1, op1);
583 sim_fpu_32to (&wop2, op2);
584 sim_fpu_add (&ans, &wop1, &wop2);
585 sim_fpu_to32 (&res, &ans);
586 result = res;
587 break;
588 }
589 case fmt_double:
590 {
591 sim_fpu wop1;
592 sim_fpu wop2;
593 sim_fpu ans;
594 unsigned64 res;
595 sim_fpu_64to (&wop1, op1);
596 sim_fpu_64to (&wop2, op2);
597 sim_fpu_add (&ans, &wop1, &wop2);
598 sim_fpu_to64 (&res, &ans);
599 result = res;
600 break;
601 }
602 default:
603 fprintf (stderr, "Bad switch\n");
604 abort ();
605 }
606
607 #ifdef DEBUG
608 printf ("DBG: Add: returning 0x%s (format = %s)\n",
609 pr_addr (result), fpu_format_name (fmt));
610 #endif /* DEBUG */
611
612 return (result);
613 }
614
615 uword64
616 Sub (op1, op2, fmt)
617 uword64 op1;
618 uword64 op2;
619 FP_formats fmt;
620 {
621 uword64 result = 0;
622
623 #ifdef DEBUG
624 printf ("DBG: Sub: %s: op1 = 0x%s : op2 = 0x%s\n",
625 fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
626 #endif /* DEBUG */
627
628 /* The registers must specify FPRs valid for operands of type
629 "fmt". If they are not valid, the result is undefined. */
630
631 /* The format type should already have been checked: */
632 switch (fmt)
633 {
634 case fmt_single:
635 {
636 sim_fpu wop1;
637 sim_fpu wop2;
638 sim_fpu ans;
639 unsigned32 res;
640 sim_fpu_32to (&wop1, op1);
641 sim_fpu_32to (&wop2, op2);
642 sim_fpu_sub (&ans, &wop1, &wop2);
643 sim_fpu_to32 (&res, &ans);
644 result = res;
645 }
646 break;
647 case fmt_double:
648 {
649 sim_fpu wop1;
650 sim_fpu wop2;
651 sim_fpu ans;
652 unsigned64 res;
653 sim_fpu_64to (&wop1, op1);
654 sim_fpu_64to (&wop2, op2);
655 sim_fpu_sub (&ans, &wop1, &wop2);
656 sim_fpu_to64 (&res, &ans);
657 result = res;
658 }
659 break;
660 default:
661 fprintf (stderr, "Bad switch\n");
662 abort ();
663 }
664
665 #ifdef DEBUG
666 printf ("DBG: Sub: returning 0x%s (format = %s)\n",
667 pr_addr (result), fpu_format_name (fmt));
668 #endif /* DEBUG */
669
670 return (result);
671 }
672
673 uword64
674 Multiply (op1, op2, fmt)
675 uword64 op1;
676 uword64 op2;
677 FP_formats fmt;
678 {
679 uword64 result = 0;
680
681 #ifdef DEBUG
682 printf ("DBG: Multiply: %s: op1 = 0x%s : op2 = 0x%s\n",
683 fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
684 #endif /* DEBUG */
685
686 /* The registers must specify FPRs valid for operands of type
687 "fmt". If they are not valid, the result is undefined. */
688
689 /* The format type should already have been checked: */
690 switch (fmt)
691 {
692 case fmt_single:
693 {
694 sim_fpu wop1;
695 sim_fpu wop2;
696 sim_fpu ans;
697 unsigned32 res;
698 sim_fpu_32to (&wop1, op1);
699 sim_fpu_32to (&wop2, op2);
700 sim_fpu_mul (&ans, &wop1, &wop2);
701 sim_fpu_to32 (&res, &ans);
702 result = res;
703 break;
704 }
705 case fmt_double:
706 {
707 sim_fpu wop1;
708 sim_fpu wop2;
709 sim_fpu ans;
710 unsigned64 res;
711 sim_fpu_64to (&wop1, op1);
712 sim_fpu_64to (&wop2, op2);
713 sim_fpu_mul (&ans, &wop1, &wop2);
714 sim_fpu_to64 (&res, &ans);
715 result = res;
716 break;
717 }
718 default:
719 fprintf (stderr, "Bad switch\n");
720 abort ();
721 }
722
723 #ifdef DEBUG
724 printf ("DBG: Multiply: returning 0x%s (format = %s)\n",
725 pr_addr (result), fpu_format_name (fmt));
726 #endif /* DEBUG */
727
728 return (result);
729 }
730
731 uword64
732 Divide (op1, op2, fmt)
733 uword64 op1;
734 uword64 op2;
735 FP_formats fmt;
736 {
737 uword64 result = 0;
738
739 #ifdef DEBUG
740 printf ("DBG: Divide: %s: op1 = 0x%s : op2 = 0x%s\n",
741 fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
742 #endif /* DEBUG */
743
744 /* The registers must specify FPRs valid for operands of type
745 "fmt". If they are not valid, the result is undefined. */
746
747 /* The format type should already have been checked: */
748 switch (fmt)
749 {
750 case fmt_single:
751 {
752 sim_fpu wop1;
753 sim_fpu wop2;
754 sim_fpu ans;
755 unsigned32 res;
756 sim_fpu_32to (&wop1, op1);
757 sim_fpu_32to (&wop2, op2);
758 sim_fpu_div (&ans, &wop1, &wop2);
759 sim_fpu_to32 (&res, &ans);
760 result = res;
761 break;
762 }
763 case fmt_double:
764 {
765 sim_fpu wop1;
766 sim_fpu wop2;
767 sim_fpu ans;
768 unsigned64 res;
769 sim_fpu_64to (&wop1, op1);
770 sim_fpu_64to (&wop2, op2);
771 sim_fpu_div (&ans, &wop1, &wop2);
772 sim_fpu_to64 (&res, &ans);
773 result = res;
774 break;
775 }
776 default:
777 fprintf (stderr, "Bad switch\n");
778 abort ();
779 }
780
781 #ifdef DEBUG
782 printf ("DBG: Divide: returning 0x%s (format = %s)\n",
783 pr_addr (result), fpu_format_name (fmt));
784 #endif /* DEBUG */
785
786 return (result);
787 }
788
789 uword64 UNUSED
790 Recip (op, fmt)
791 uword64 op;
792 FP_formats fmt;
793 {
794 uword64 result = 0;
795
796 #ifdef DEBUG
797 printf ("DBG: Recip: %s: op = 0x%s\n",
798 fpu_format_name (fmt), pr_addr (op));
799 #endif /* DEBUG */
800
801 /* The registers must specify FPRs valid for operands of type
802 "fmt". If they are not valid, the result is undefined. */
803
804 /* The format type should already have been checked: */
805 switch (fmt)
806 {
807 case fmt_single:
808 {
809 sim_fpu wop;
810 sim_fpu ans;
811 unsigned32 res;
812 sim_fpu_32to (&wop, op);
813 sim_fpu_inv (&ans, &wop);
814 sim_fpu_to32 (&res, &ans);
815 result = res;
816 break;
817 }
818 case fmt_double:
819 {
820 sim_fpu wop;
821 sim_fpu ans;
822 unsigned64 res;
823 sim_fpu_64to (&wop, op);
824 sim_fpu_inv (&ans, &wop);
825 sim_fpu_to64 (&res, &ans);
826 result = res;
827 break;
828 }
829 default:
830 fprintf (stderr, "Bad switch\n");
831 abort ();
832 }
833
834 #ifdef DEBUG
835 printf ("DBG: Recip: returning 0x%s (format = %s)\n",
836 pr_addr (result), fpu_format_name (fmt));
837 #endif /* DEBUG */
838
839 return (result);
840 }
841
842 uword64
843 SquareRoot (op, fmt)
844 uword64 op;
845 FP_formats fmt;
846 {
847 uword64 result = 0;
848
849 #ifdef DEBUG
850 printf ("DBG: SquareRoot: %s: op = 0x%s\n",
851 fpu_format_name (fmt), pr_addr (op));
852 #endif /* DEBUG */
853
854 /* The registers must specify FPRs valid for operands of type
855 "fmt". If they are not valid, the result is undefined. */
856
857 /* The format type should already have been checked: */
858 switch (fmt)
859 {
860 case fmt_single:
861 {
862 sim_fpu wop;
863 sim_fpu ans;
864 unsigned32 res;
865 sim_fpu_32to (&wop, op);
866 sim_fpu_sqrt (&ans, &wop);
867 sim_fpu_to32 (&res, &ans);
868 result = res;
869 break;
870 }
871 case fmt_double:
872 {
873 sim_fpu wop;
874 sim_fpu ans;
875 unsigned64 res;
876 sim_fpu_64to (&wop, op);
877 sim_fpu_sqrt (&ans, &wop);
878 sim_fpu_to64 (&res, &ans);
879 result = res;
880 break;
881 }
882 default:
883 fprintf (stderr, "Bad switch\n");
884 abort ();
885 }
886
887 #ifdef DEBUG
888 printf ("DBG: SquareRoot: returning 0x%s (format = %s)\n",
889 pr_addr (result), fpu_format_name (fmt));
890 #endif /* DEBUG */
891
892 return (result);
893 }
894
895 #if 0
896 uword64
897 Max (uword64 op1,
898 uword64 op2,
899 FP_formats fmt)
900 {
901 int cmp;
902 unsigned64 result;
903
904 #ifdef DEBUG
905 printf ("DBG: Max: %s: op1 = 0x%s : op2 = 0x%s\n",
906 fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
907 #endif /* DEBUG */
908
909 /* The registers must specify FPRs valid for operands of type
910 "fmt". If they are not valid, the result is undefined. */
911
912 /* The format type should already have been checked: */
913 switch (fmt)
914 {
915 case fmt_single:
916 {
917 sim_fpu wop1;
918 sim_fpu wop2;
919 sim_fpu_32to (&wop1, op1);
920 sim_fpu_32to (&wop2, op2);
921 cmp = sim_fpu_cmp (&wop1, &wop2);
922 break;
923 }
924 case fmt_double:
925 {
926 sim_fpu wop1;
927 sim_fpu wop2;
928 sim_fpu_64to (&wop1, op1);
929 sim_fpu_64to (&wop2, op2);
930 cmp = sim_fpu_cmp (&wop1, &wop2);
931 break;
932 }
933 default:
934 fprintf (stderr, "Bad switch\n");
935 abort ();
936 }
937
938 switch (cmp)
939 {
940 case SIM_FPU_IS_SNAN:
941 case SIM_FPU_IS_QNAN:
942 result = op1;
943 case SIM_FPU_IS_NINF:
944 case SIM_FPU_IS_NNUMBER:
945 case SIM_FPU_IS_NDENORM:
946 case SIM_FPU_IS_NZERO:
947 result = op2; /* op1 - op2 < 0 */
948 case SIM_FPU_IS_PINF:
949 case SIM_FPU_IS_PNUMBER:
950 case SIM_FPU_IS_PDENORM:
951 case SIM_FPU_IS_PZERO:
952 result = op1; /* op1 - op2 > 0 */
953 default:
954 fprintf (stderr, "Bad switch\n");
955 abort ();
956 }
957
958 #ifdef DEBUG
959 printf ("DBG: Max: returning 0x%s (format = %s)\n",
960 pr_addr (result), fpu_format_name (fmt));
961 #endif /* DEBUG */
962
963 return (result);
964 }
965 #endif
966
967 #if 0
968 uword64
969 Min (uword64 op1,
970 uword64 op2,
971 FP_formats fmt)
972 {
973 int cmp;
974 unsigned64 result;
975
976 #ifdef DEBUG
977 printf ("DBG: Min: %s: op1 = 0x%s : op2 = 0x%s\n",
978 fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
979 #endif /* DEBUG */
980
981 /* The registers must specify FPRs valid for operands of type
982 "fmt". If they are not valid, the result is undefined. */
983
984 /* The format type should already have been checked: */
985 switch (fmt)
986 {
987 case fmt_single:
988 {
989 sim_fpu wop1;
990 sim_fpu wop2;
991 sim_fpu_32to (&wop1, op1);
992 sim_fpu_32to (&wop2, op2);
993 cmp = sim_fpu_cmp (&wop1, &wop2);
994 break;
995 }
996 case fmt_double:
997 {
998 sim_fpu wop1;
999 sim_fpu wop2;
1000 sim_fpu_64to (&wop1, op1);
1001 sim_fpu_64to (&wop2, op2);
1002 cmp = sim_fpu_cmp (&wop1, &wop2);
1003 break;
1004 }
1005 default:
1006 fprintf (stderr, "Bad switch\n");
1007 abort ();
1008 }
1009
1010 switch (cmp)
1011 {
1012 case SIM_FPU_IS_SNAN:
1013 case SIM_FPU_IS_QNAN:
1014 result = op1;
1015 case SIM_FPU_IS_NINF:
1016 case SIM_FPU_IS_NNUMBER:
1017 case SIM_FPU_IS_NDENORM:
1018 case SIM_FPU_IS_NZERO:
1019 result = op1; /* op1 - op2 < 0 */
1020 case SIM_FPU_IS_PINF:
1021 case SIM_FPU_IS_PNUMBER:
1022 case SIM_FPU_IS_PDENORM:
1023 case SIM_FPU_IS_PZERO:
1024 result = op2; /* op1 - op2 > 0 */
1025 default:
1026 fprintf (stderr, "Bad switch\n");
1027 abort ();
1028 }
1029
1030 #ifdef DEBUG
1031 printf ("DBG: Min: returning 0x%s (format = %s)\n",
1032 pr_addr (result), fpu_format_name (fmt));
1033 #endif /* DEBUG */
1034
1035 return (result);
1036 }
1037 #endif
1038
1039 uword64
1040 convert (SIM_DESC sd,
1041 sim_cpu *cpu,
1042 address_word cia,
1043 int rm,
1044 uword64 op,
1045 FP_formats from,
1046 FP_formats to)
1047 {
1048 sim_fpu wop;
1049 sim_fpu_round round;
1050 unsigned32 result32;
1051 unsigned64 result64;
1052
1053 #ifdef DEBUG
1054 #if 0 /* FIXME: doesn't compile */
1055 printf ("DBG: Convert: mode %s : op 0x%s : from %s : to %s : (PC = 0x%s)\n",
1056 fpu_rounding_mode_name (rm), pr_addr (op), fpu_format_name (from),
1057 fpu_format_name (to), pr_addr (IPC));
1058 #endif
1059 #endif /* DEBUG */
1060
1061 switch (rm)
1062 {
1063 case FP_RM_NEAREST:
1064 /* Round result to nearest representable value. When two
1065 representable values are equally near, round to the value
1066 that has a least significant bit of zero (i.e. is even). */
1067 round = sim_fpu_round_near;
1068 break;
1069 case FP_RM_TOZERO:
1070 /* Round result to the value closest to, and not greater in
1071 magnitude than, the result. */
1072 round = sim_fpu_round_zero;
1073 break;
1074 case FP_RM_TOPINF:
1075 /* Round result to the value closest to, and not less than,
1076 the result. */
1077 round = sim_fpu_round_up;
1078 break;
1079
1080 case FP_RM_TOMINF:
1081 /* Round result to the value closest to, and not greater than,
1082 the result. */
1083 round = sim_fpu_round_down;
1084 break;
1085 default:
1086 round = 0;
1087 fprintf (stderr, "Bad switch\n");
1088 abort ();
1089 }
1090
1091 /* Convert the input to sim_fpu internal format */
1092 switch (from)
1093 {
1094 case fmt_double:
1095 sim_fpu_64to (&wop, op);
1096 break;
1097 case fmt_single:
1098 sim_fpu_32to (&wop, op);
1099 break;
1100 case fmt_word:
1101 sim_fpu_i32to (&wop, op, round);
1102 break;
1103 case fmt_long:
1104 sim_fpu_i64to (&wop, op, round);
1105 break;
1106 default:
1107 fprintf (stderr, "Bad switch\n");
1108 abort ();
1109 }
1110
1111 /* Convert sim_fpu format into the output */
1112 /* The value WOP is converted to the destination format, rounding
1113 using mode RM. When the destination is a fixed-point format, then
1114 a source value of Infinity, NaN or one which would round to an
1115 integer outside the fixed point range then an IEEE Invalid
1116 Operation condition is raised. */
1117 switch (to)
1118 {
1119 case fmt_single:
1120 sim_fpu_round_32 (&wop, round, 0);
1121 sim_fpu_to32 (&result32, &wop);
1122 result64 = result32;
1123 break;
1124 case fmt_double:
1125 sim_fpu_round_64 (&wop, round, 0);
1126 sim_fpu_to64 (&result64, &wop);
1127 break;
1128 case fmt_word:
1129 sim_fpu_to32i (&result32, &wop, round);
1130 result64 = result32;
1131 break;
1132 case fmt_long:
1133 sim_fpu_to64i (&result64, &wop, round);
1134 break;
1135 default:
1136 result64 = 0;
1137 fprintf (stderr, "Bad switch\n");
1138 abort ();
1139 }
1140
1141 #ifdef DEBUG
1142 printf ("DBG: Convert: returning 0x%s (to format = %s)\n",
1143 pr_addr (result64), fpu_format_name (to));
1144 #endif /* DEBUG */
1145
1146 return (result64);
1147 }
1148
1149 static const char *
1150 fpu_format_name (FP_formats fmt)
1151 {
1152 switch (fmt)
1153 {
1154 case fmt_single:
1155 return "single";
1156 case fmt_double:
1157 return "double";
1158 case fmt_word:
1159 return "word";
1160 case fmt_long:
1161 return "long";
1162 case fmt_unknown:
1163 return "<unknown>";
1164 case fmt_uninterpreted:
1165 return "<uninterpreted>";
1166 case fmt_uninterpreted_32:
1167 return "<uninterpreted_32>";
1168 case fmt_uninterpreted_64:
1169 return "<uninterpreted_64>";
1170 default:
1171 return "<format error>";
1172 }
1173 }
1174
1175 #ifdef DEBUG
1176 static const char *
1177 fpu_rounding_mode_name (int rm)
1178 {
1179 switch (rm)
1180 {
1181 case FP_RM_NEAREST:
1182 return "Round";
1183 case FP_RM_TOZERO:
1184 return "Trunc";
1185 case FP_RM_TOPINF:
1186 return "Ceil";
1187 case FP_RM_TOMINF:
1188 return "Floor";
1189 default:
1190 return "<rounding mode error>";
1191 }
1192 }
1193 #endif /* DEBUG */