2002-03-19 Chris Demetriou <cgd@broadcom.com>
[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 #if defined(WARN_RESULT)
283 else
284 UndefinedResult ();
285 #endif /* WARN_RESULT */
286
287 if (err)
288 SignalExceptionSimulatorFault ("Unrecognised FP format in StoreFPR ()");
289
290 #ifdef DEBUG
291 printf ("DBG: StoreFPR: fpr[%d] = 0x%s (format %s)\n",
292 fpr, pr_uword64 (FGR[fpr]), fpu_format_name (fmt));
293 #endif /* DEBUG */
294
295 return;
296 }
297
298 int
299 NaN (op, fmt)
300 uword64 op;
301 FP_formats fmt;
302 {
303 int boolean = 0;
304 switch (fmt)
305 {
306 case fmt_single:
307 case fmt_word:
308 {
309 sim_fpu wop;
310 sim_fpu_32to (&wop, op);
311 boolean = sim_fpu_is_nan (&wop);
312 break;
313 }
314 case fmt_double:
315 case fmt_long:
316 {
317 sim_fpu wop;
318 sim_fpu_64to (&wop, op);
319 boolean = sim_fpu_is_nan (&wop);
320 break;
321 }
322 default:
323 fprintf (stderr, "Bad switch\n");
324 abort ();
325 }
326
327 #ifdef DEBUG
328 printf ("DBG: NaN: returning %d for 0x%s (format = %s)\n",
329 boolean, pr_addr (op), fpu_format_name (fmt));
330 #endif /* DEBUG */
331
332 return (boolean);
333 }
334
335 int
336 Infinity (op, fmt)
337 uword64 op;
338 FP_formats fmt;
339 {
340 int boolean = 0;
341
342 #ifdef DEBUG
343 printf ("DBG: Infinity: format %s 0x%s\n",
344 fpu_format_name (fmt), pr_addr (op));
345 #endif /* DEBUG */
346
347 switch (fmt)
348 {
349 case fmt_single:
350 {
351 sim_fpu wop;
352 sim_fpu_32to (&wop, op);
353 boolean = sim_fpu_is_infinity (&wop);
354 break;
355 }
356 case fmt_double:
357 {
358 sim_fpu wop;
359 sim_fpu_64to (&wop, op);
360 boolean = sim_fpu_is_infinity (&wop);
361 break;
362 }
363 default:
364 printf ("DBG: TODO: unrecognised format (%s) for Infinity check\n",
365 fpu_format_name (fmt));
366 break;
367 }
368
369 #ifdef DEBUG
370 printf ("DBG: Infinity: returning %d for 0x%s (format = %s)\n",
371 boolean, pr_addr (op), fpu_format_name (fmt));
372 #endif /* DEBUG */
373
374 return (boolean);
375 }
376
377 int
378 Less (op1, op2, fmt)
379 uword64 op1;
380 uword64 op2;
381 FP_formats fmt;
382 {
383 int boolean = 0;
384
385 /* Argument checking already performed by the FPCOMPARE code */
386
387 #ifdef DEBUG
388 printf ("DBG: Less: %s: op1 = 0x%s : op2 = 0x%s\n",
389 fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
390 #endif /* DEBUG */
391
392 /* The format type should already have been checked: */
393 switch (fmt)
394 {
395 case fmt_single:
396 {
397 sim_fpu wop1;
398 sim_fpu wop2;
399 sim_fpu_32to (&wop1, op1);
400 sim_fpu_32to (&wop2, op2);
401 boolean = sim_fpu_is_lt (&wop1, &wop2);
402 break;
403 }
404 case fmt_double:
405 {
406 sim_fpu wop1;
407 sim_fpu wop2;
408 sim_fpu_64to (&wop1, op1);
409 sim_fpu_64to (&wop2, op2);
410 boolean = sim_fpu_is_lt (&wop1, &wop2);
411 break;
412 }
413 default:
414 fprintf (stderr, "Bad switch\n");
415 abort ();
416 }
417
418 #ifdef DEBUG
419 printf ("DBG: Less: returning %d (format = %s)\n",
420 boolean, fpu_format_name (fmt));
421 #endif /* DEBUG */
422
423 return (boolean);
424 }
425
426 int
427 Equal (op1, op2, fmt)
428 uword64 op1;
429 uword64 op2;
430 FP_formats fmt;
431 {
432 int boolean = 0;
433
434 /* Argument checking already performed by the FPCOMPARE code */
435
436 #ifdef DEBUG
437 printf ("DBG: Equal: %s: op1 = 0x%s : op2 = 0x%s\n",
438 fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
439 #endif /* DEBUG */
440
441 /* The format type should already have been checked: */
442 switch (fmt)
443 {
444 case fmt_single:
445 {
446 sim_fpu wop1;
447 sim_fpu wop2;
448 sim_fpu_32to (&wop1, op1);
449 sim_fpu_32to (&wop2, op2);
450 boolean = sim_fpu_is_eq (&wop1, &wop2);
451 break;
452 }
453 case fmt_double:
454 {
455 sim_fpu wop1;
456 sim_fpu wop2;
457 sim_fpu_64to (&wop1, op1);
458 sim_fpu_64to (&wop2, op2);
459 boolean = sim_fpu_is_eq (&wop1, &wop2);
460 break;
461 }
462 default:
463 fprintf (stderr, "Bad switch\n");
464 abort ();
465 }
466
467 #ifdef DEBUG
468 printf ("DBG: Equal: returning %d (format = %s)\n",
469 boolean, fpu_format_name (fmt));
470 #endif /* DEBUG */
471
472 return (boolean);
473 }
474
475 uword64
476 AbsoluteValue (op, fmt)
477 uword64 op;
478 FP_formats fmt;
479 {
480 uword64 result = 0;
481
482 #ifdef DEBUG
483 printf ("DBG: AbsoluteValue: %s: op = 0x%s\n",
484 fpu_format_name (fmt), pr_addr (op));
485 #endif /* DEBUG */
486
487 /* The format type should already have been checked: */
488 switch (fmt)
489 {
490 case fmt_single:
491 {
492 sim_fpu wop;
493 unsigned32 ans;
494 sim_fpu_32to (&wop, op);
495 sim_fpu_abs (&wop, &wop);
496 sim_fpu_to32 (&ans, &wop);
497 result = ans;
498 break;
499 }
500 case fmt_double:
501 {
502 sim_fpu wop;
503 unsigned64 ans;
504 sim_fpu_64to (&wop, op);
505 sim_fpu_abs (&wop, &wop);
506 sim_fpu_to64 (&ans, &wop);
507 result = ans;
508 break;
509 }
510 default:
511 fprintf (stderr, "Bad switch\n");
512 abort ();
513 }
514
515 return (result);
516 }
517
518 uword64
519 Negate (op, fmt)
520 uword64 op;
521 FP_formats fmt;
522 {
523 uword64 result = 0;
524
525 #ifdef DEBUG
526 printf ("DBG: Negate: %s: op = 0x%s\n",
527 fpu_format_name (fmt), pr_addr (op));
528 #endif /* DEBUG */
529
530 /* The format type should already have been checked: */
531 switch (fmt)
532 {
533 case fmt_single:
534 {
535 sim_fpu wop;
536 unsigned32 ans;
537 sim_fpu_32to (&wop, op);
538 sim_fpu_neg (&wop, &wop);
539 sim_fpu_to32 (&ans, &wop);
540 result = ans;
541 break;
542 }
543 case fmt_double:
544 {
545 sim_fpu wop;
546 unsigned64 ans;
547 sim_fpu_64to (&wop, op);
548 sim_fpu_neg (&wop, &wop);
549 sim_fpu_to64 (&ans, &wop);
550 result = ans;
551 break;
552 }
553 default:
554 fprintf (stderr, "Bad switch\n");
555 abort ();
556 }
557
558 return (result);
559 }
560
561 uword64
562 Add (op1, op2, fmt)
563 uword64 op1;
564 uword64 op2;
565 FP_formats fmt;
566 {
567 uword64 result = 0;
568
569 #ifdef DEBUG
570 printf ("DBG: Add: %s: op1 = 0x%s : op2 = 0x%s\n",
571 fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
572 #endif /* DEBUG */
573
574 /* The registers must specify FPRs valid for operands of type
575 "fmt". If they are not valid, the result is undefined. */
576
577 /* The format type should already have been checked: */
578 switch (fmt)
579 {
580 case fmt_single:
581 {
582 sim_fpu wop1;
583 sim_fpu wop2;
584 sim_fpu ans;
585 unsigned32 res;
586 sim_fpu_32to (&wop1, op1);
587 sim_fpu_32to (&wop2, op2);
588 sim_fpu_add (&ans, &wop1, &wop2);
589 sim_fpu_to32 (&res, &ans);
590 result = res;
591 break;
592 }
593 case fmt_double:
594 {
595 sim_fpu wop1;
596 sim_fpu wop2;
597 sim_fpu ans;
598 unsigned64 res;
599 sim_fpu_64to (&wop1, op1);
600 sim_fpu_64to (&wop2, op2);
601 sim_fpu_add (&ans, &wop1, &wop2);
602 sim_fpu_to64 (&res, &ans);
603 result = res;
604 break;
605 }
606 default:
607 fprintf (stderr, "Bad switch\n");
608 abort ();
609 }
610
611 #ifdef DEBUG
612 printf ("DBG: Add: returning 0x%s (format = %s)\n",
613 pr_addr (result), fpu_format_name (fmt));
614 #endif /* DEBUG */
615
616 return (result);
617 }
618
619 uword64
620 Sub (op1, op2, fmt)
621 uword64 op1;
622 uword64 op2;
623 FP_formats fmt;
624 {
625 uword64 result = 0;
626
627 #ifdef DEBUG
628 printf ("DBG: Sub: %s: op1 = 0x%s : op2 = 0x%s\n",
629 fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
630 #endif /* DEBUG */
631
632 /* The registers must specify FPRs valid for operands of type
633 "fmt". If they are not valid, the result is undefined. */
634
635 /* The format type should already have been checked: */
636 switch (fmt)
637 {
638 case fmt_single:
639 {
640 sim_fpu wop1;
641 sim_fpu wop2;
642 sim_fpu ans;
643 unsigned32 res;
644 sim_fpu_32to (&wop1, op1);
645 sim_fpu_32to (&wop2, op2);
646 sim_fpu_sub (&ans, &wop1, &wop2);
647 sim_fpu_to32 (&res, &ans);
648 result = res;
649 }
650 break;
651 case fmt_double:
652 {
653 sim_fpu wop1;
654 sim_fpu wop2;
655 sim_fpu ans;
656 unsigned64 res;
657 sim_fpu_64to (&wop1, op1);
658 sim_fpu_64to (&wop2, op2);
659 sim_fpu_sub (&ans, &wop1, &wop2);
660 sim_fpu_to64 (&res, &ans);
661 result = res;
662 }
663 break;
664 default:
665 fprintf (stderr, "Bad switch\n");
666 abort ();
667 }
668
669 #ifdef DEBUG
670 printf ("DBG: Sub: returning 0x%s (format = %s)\n",
671 pr_addr (result), fpu_format_name (fmt));
672 #endif /* DEBUG */
673
674 return (result);
675 }
676
677 uword64
678 Multiply (op1, op2, fmt)
679 uword64 op1;
680 uword64 op2;
681 FP_formats fmt;
682 {
683 uword64 result = 0;
684
685 #ifdef DEBUG
686 printf ("DBG: Multiply: %s: op1 = 0x%s : op2 = 0x%s\n",
687 fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
688 #endif /* DEBUG */
689
690 /* The registers must specify FPRs valid for operands of type
691 "fmt". If they are not valid, the result is undefined. */
692
693 /* The format type should already have been checked: */
694 switch (fmt)
695 {
696 case fmt_single:
697 {
698 sim_fpu wop1;
699 sim_fpu wop2;
700 sim_fpu ans;
701 unsigned32 res;
702 sim_fpu_32to (&wop1, op1);
703 sim_fpu_32to (&wop2, op2);
704 sim_fpu_mul (&ans, &wop1, &wop2);
705 sim_fpu_to32 (&res, &ans);
706 result = res;
707 break;
708 }
709 case fmt_double:
710 {
711 sim_fpu wop1;
712 sim_fpu wop2;
713 sim_fpu ans;
714 unsigned64 res;
715 sim_fpu_64to (&wop1, op1);
716 sim_fpu_64to (&wop2, op2);
717 sim_fpu_mul (&ans, &wop1, &wop2);
718 sim_fpu_to64 (&res, &ans);
719 result = res;
720 break;
721 }
722 default:
723 fprintf (stderr, "Bad switch\n");
724 abort ();
725 }
726
727 #ifdef DEBUG
728 printf ("DBG: Multiply: returning 0x%s (format = %s)\n",
729 pr_addr (result), fpu_format_name (fmt));
730 #endif /* DEBUG */
731
732 return (result);
733 }
734
735 uword64
736 Divide (op1, op2, fmt)
737 uword64 op1;
738 uword64 op2;
739 FP_formats fmt;
740 {
741 uword64 result = 0;
742
743 #ifdef DEBUG
744 printf ("DBG: Divide: %s: op1 = 0x%s : op2 = 0x%s\n",
745 fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
746 #endif /* DEBUG */
747
748 /* The registers must specify FPRs valid for operands of type
749 "fmt". If they are not valid, the result is undefined. */
750
751 /* The format type should already have been checked: */
752 switch (fmt)
753 {
754 case fmt_single:
755 {
756 sim_fpu wop1;
757 sim_fpu wop2;
758 sim_fpu ans;
759 unsigned32 res;
760 sim_fpu_32to (&wop1, op1);
761 sim_fpu_32to (&wop2, op2);
762 sim_fpu_div (&ans, &wop1, &wop2);
763 sim_fpu_to32 (&res, &ans);
764 result = res;
765 break;
766 }
767 case fmt_double:
768 {
769 sim_fpu wop1;
770 sim_fpu wop2;
771 sim_fpu ans;
772 unsigned64 res;
773 sim_fpu_64to (&wop1, op1);
774 sim_fpu_64to (&wop2, op2);
775 sim_fpu_div (&ans, &wop1, &wop2);
776 sim_fpu_to64 (&res, &ans);
777 result = res;
778 break;
779 }
780 default:
781 fprintf (stderr, "Bad switch\n");
782 abort ();
783 }
784
785 #ifdef DEBUG
786 printf ("DBG: Divide: returning 0x%s (format = %s)\n",
787 pr_addr (result), fpu_format_name (fmt));
788 #endif /* DEBUG */
789
790 return (result);
791 }
792
793 uword64 UNUSED
794 Recip (op, fmt)
795 uword64 op;
796 FP_formats fmt;
797 {
798 uword64 result = 0;
799
800 #ifdef DEBUG
801 printf ("DBG: Recip: %s: op = 0x%s\n",
802 fpu_format_name (fmt), pr_addr (op));
803 #endif /* DEBUG */
804
805 /* The registers must specify FPRs valid for operands of type
806 "fmt". If they are not valid, the result is undefined. */
807
808 /* The format type should already have been checked: */
809 switch (fmt)
810 {
811 case fmt_single:
812 {
813 sim_fpu wop;
814 sim_fpu ans;
815 unsigned32 res;
816 sim_fpu_32to (&wop, op);
817 sim_fpu_inv (&ans, &wop);
818 sim_fpu_to32 (&res, &ans);
819 result = res;
820 break;
821 }
822 case fmt_double:
823 {
824 sim_fpu wop;
825 sim_fpu ans;
826 unsigned64 res;
827 sim_fpu_64to (&wop, op);
828 sim_fpu_inv (&ans, &wop);
829 sim_fpu_to64 (&res, &ans);
830 result = res;
831 break;
832 }
833 default:
834 fprintf (stderr, "Bad switch\n");
835 abort ();
836 }
837
838 #ifdef DEBUG
839 printf ("DBG: Recip: returning 0x%s (format = %s)\n",
840 pr_addr (result), fpu_format_name (fmt));
841 #endif /* DEBUG */
842
843 return (result);
844 }
845
846 uword64
847 SquareRoot (op, fmt)
848 uword64 op;
849 FP_formats fmt;
850 {
851 uword64 result = 0;
852
853 #ifdef DEBUG
854 printf ("DBG: SquareRoot: %s: op = 0x%s\n",
855 fpu_format_name (fmt), pr_addr (op));
856 #endif /* DEBUG */
857
858 /* The registers must specify FPRs valid for operands of type
859 "fmt". If they are not valid, the result is undefined. */
860
861 /* The format type should already have been checked: */
862 switch (fmt)
863 {
864 case fmt_single:
865 {
866 sim_fpu wop;
867 sim_fpu ans;
868 unsigned32 res;
869 sim_fpu_32to (&wop, op);
870 sim_fpu_sqrt (&ans, &wop);
871 sim_fpu_to32 (&res, &ans);
872 result = res;
873 break;
874 }
875 case fmt_double:
876 {
877 sim_fpu wop;
878 sim_fpu ans;
879 unsigned64 res;
880 sim_fpu_64to (&wop, op);
881 sim_fpu_sqrt (&ans, &wop);
882 sim_fpu_to64 (&res, &ans);
883 result = res;
884 break;
885 }
886 default:
887 fprintf (stderr, "Bad switch\n");
888 abort ();
889 }
890
891 #ifdef DEBUG
892 printf ("DBG: SquareRoot: returning 0x%s (format = %s)\n",
893 pr_addr (result), fpu_format_name (fmt));
894 #endif /* DEBUG */
895
896 return (result);
897 }
898
899 #if 0
900 uword64
901 Max (uword64 op1,
902 uword64 op2,
903 FP_formats fmt)
904 {
905 int cmp;
906 unsigned64 result;
907
908 #ifdef DEBUG
909 printf ("DBG: Max: %s: op1 = 0x%s : op2 = 0x%s\n",
910 fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
911 #endif /* DEBUG */
912
913 /* The registers must specify FPRs valid for operands of type
914 "fmt". If they are not valid, the result is undefined. */
915
916 /* The format type should already have been checked: */
917 switch (fmt)
918 {
919 case fmt_single:
920 {
921 sim_fpu wop1;
922 sim_fpu wop2;
923 sim_fpu_32to (&wop1, op1);
924 sim_fpu_32to (&wop2, op2);
925 cmp = sim_fpu_cmp (&wop1, &wop2);
926 break;
927 }
928 case fmt_double:
929 {
930 sim_fpu wop1;
931 sim_fpu wop2;
932 sim_fpu_64to (&wop1, op1);
933 sim_fpu_64to (&wop2, op2);
934 cmp = sim_fpu_cmp (&wop1, &wop2);
935 break;
936 }
937 default:
938 fprintf (stderr, "Bad switch\n");
939 abort ();
940 }
941
942 switch (cmp)
943 {
944 case SIM_FPU_IS_SNAN:
945 case SIM_FPU_IS_QNAN:
946 result = op1;
947 case SIM_FPU_IS_NINF:
948 case SIM_FPU_IS_NNUMBER:
949 case SIM_FPU_IS_NDENORM:
950 case SIM_FPU_IS_NZERO:
951 result = op2; /* op1 - op2 < 0 */
952 case SIM_FPU_IS_PINF:
953 case SIM_FPU_IS_PNUMBER:
954 case SIM_FPU_IS_PDENORM:
955 case SIM_FPU_IS_PZERO:
956 result = op1; /* op1 - op2 > 0 */
957 default:
958 fprintf (stderr, "Bad switch\n");
959 abort ();
960 }
961
962 #ifdef DEBUG
963 printf ("DBG: Max: returning 0x%s (format = %s)\n",
964 pr_addr (result), fpu_format_name (fmt));
965 #endif /* DEBUG */
966
967 return (result);
968 }
969 #endif
970
971 #if 0
972 uword64
973 Min (uword64 op1,
974 uword64 op2,
975 FP_formats fmt)
976 {
977 int cmp;
978 unsigned64 result;
979
980 #ifdef DEBUG
981 printf ("DBG: Min: %s: op1 = 0x%s : op2 = 0x%s\n",
982 fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
983 #endif /* DEBUG */
984
985 /* The registers must specify FPRs valid for operands of type
986 "fmt". If they are not valid, the result is undefined. */
987
988 /* The format type should already have been checked: */
989 switch (fmt)
990 {
991 case fmt_single:
992 {
993 sim_fpu wop1;
994 sim_fpu wop2;
995 sim_fpu_32to (&wop1, op1);
996 sim_fpu_32to (&wop2, op2);
997 cmp = sim_fpu_cmp (&wop1, &wop2);
998 break;
999 }
1000 case fmt_double:
1001 {
1002 sim_fpu wop1;
1003 sim_fpu wop2;
1004 sim_fpu_64to (&wop1, op1);
1005 sim_fpu_64to (&wop2, op2);
1006 cmp = sim_fpu_cmp (&wop1, &wop2);
1007 break;
1008 }
1009 default:
1010 fprintf (stderr, "Bad switch\n");
1011 abort ();
1012 }
1013
1014 switch (cmp)
1015 {
1016 case SIM_FPU_IS_SNAN:
1017 case SIM_FPU_IS_QNAN:
1018 result = op1;
1019 case SIM_FPU_IS_NINF:
1020 case SIM_FPU_IS_NNUMBER:
1021 case SIM_FPU_IS_NDENORM:
1022 case SIM_FPU_IS_NZERO:
1023 result = op1; /* op1 - op2 < 0 */
1024 case SIM_FPU_IS_PINF:
1025 case SIM_FPU_IS_PNUMBER:
1026 case SIM_FPU_IS_PDENORM:
1027 case SIM_FPU_IS_PZERO:
1028 result = op2; /* op1 - op2 > 0 */
1029 default:
1030 fprintf (stderr, "Bad switch\n");
1031 abort ();
1032 }
1033
1034 #ifdef DEBUG
1035 printf ("DBG: Min: returning 0x%s (format = %s)\n",
1036 pr_addr (result), fpu_format_name (fmt));
1037 #endif /* DEBUG */
1038
1039 return (result);
1040 }
1041 #endif
1042
1043 uword64
1044 convert (SIM_DESC sd,
1045 sim_cpu *cpu,
1046 address_word cia,
1047 int rm,
1048 uword64 op,
1049 FP_formats from,
1050 FP_formats to)
1051 {
1052 sim_fpu wop;
1053 sim_fpu_round round;
1054 unsigned32 result32;
1055 unsigned64 result64;
1056
1057 #ifdef DEBUG
1058 #if 0 /* FIXME: doesn't compile */
1059 printf ("DBG: Convert: mode %s : op 0x%s : from %s : to %s : (PC = 0x%s)\n",
1060 fpu_rounding_mode_name (rm), pr_addr (op), fpu_format_name (from),
1061 fpu_format_name (to), pr_addr (IPC));
1062 #endif
1063 #endif /* DEBUG */
1064
1065 switch (rm)
1066 {
1067 case FP_RM_NEAREST:
1068 /* Round result to nearest representable value. When two
1069 representable values are equally near, round to the value
1070 that has a least significant bit of zero (i.e. is even). */
1071 round = sim_fpu_round_near;
1072 break;
1073 case FP_RM_TOZERO:
1074 /* Round result to the value closest to, and not greater in
1075 magnitude than, the result. */
1076 round = sim_fpu_round_zero;
1077 break;
1078 case FP_RM_TOPINF:
1079 /* Round result to the value closest to, and not less than,
1080 the result. */
1081 round = sim_fpu_round_up;
1082 break;
1083
1084 case FP_RM_TOMINF:
1085 /* Round result to the value closest to, and not greater than,
1086 the result. */
1087 round = sim_fpu_round_down;
1088 break;
1089 default:
1090 round = 0;
1091 fprintf (stderr, "Bad switch\n");
1092 abort ();
1093 }
1094
1095 /* Convert the input to sim_fpu internal format */
1096 switch (from)
1097 {
1098 case fmt_double:
1099 sim_fpu_64to (&wop, op);
1100 break;
1101 case fmt_single:
1102 sim_fpu_32to (&wop, op);
1103 break;
1104 case fmt_word:
1105 sim_fpu_i32to (&wop, op, round);
1106 break;
1107 case fmt_long:
1108 sim_fpu_i64to (&wop, op, round);
1109 break;
1110 default:
1111 fprintf (stderr, "Bad switch\n");
1112 abort ();
1113 }
1114
1115 /* Convert sim_fpu format into the output */
1116 /* The value WOP is converted to the destination format, rounding
1117 using mode RM. When the destination is a fixed-point format, then
1118 a source value of Infinity, NaN or one which would round to an
1119 integer outside the fixed point range then an IEEE Invalid
1120 Operation condition is raised. */
1121 switch (to)
1122 {
1123 case fmt_single:
1124 sim_fpu_round_32 (&wop, round, 0);
1125 sim_fpu_to32 (&result32, &wop);
1126 result64 = result32;
1127 break;
1128 case fmt_double:
1129 sim_fpu_round_64 (&wop, round, 0);
1130 sim_fpu_to64 (&result64, &wop);
1131 break;
1132 case fmt_word:
1133 sim_fpu_to32i (&result32, &wop, round);
1134 result64 = result32;
1135 break;
1136 case fmt_long:
1137 sim_fpu_to64i (&result64, &wop, round);
1138 break;
1139 default:
1140 result64 = 0;
1141 fprintf (stderr, "Bad switch\n");
1142 abort ();
1143 }
1144
1145 #ifdef DEBUG
1146 printf ("DBG: Convert: returning 0x%s (to format = %s)\n",
1147 pr_addr (result64), fpu_format_name (to));
1148 #endif /* DEBUG */
1149
1150 return (result64);
1151 }
1152
1153 static const char *
1154 fpu_format_name (FP_formats fmt)
1155 {
1156 switch (fmt)
1157 {
1158 case fmt_single:
1159 return "single";
1160 case fmt_double:
1161 return "double";
1162 case fmt_word:
1163 return "word";
1164 case fmt_long:
1165 return "long";
1166 case fmt_unknown:
1167 return "<unknown>";
1168 case fmt_uninterpreted:
1169 return "<uninterpreted>";
1170 case fmt_uninterpreted_32:
1171 return "<uninterpreted_32>";
1172 case fmt_uninterpreted_64:
1173 return "<uninterpreted_64>";
1174 default:
1175 return "<format error>";
1176 }
1177 }
1178
1179 #ifdef DEBUG
1180 static const char *
1181 fpu_rounding_mode_name (int rm)
1182 {
1183 switch (rm)
1184 {
1185 case FP_RM_NEAREST:
1186 return "Round";
1187 case FP_RM_TOZERO:
1188 return "Trunc";
1189 case FP_RM_TOPINF:
1190 return "Ceil";
1191 case FP_RM_TOMINF:
1192 return "Floor";
1193 default:
1194 return "<rounding mode error>";
1195 }
1196 }
1197 #endif /* DEBUG */