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