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