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