66e7c586b75fd72acd7319b7537af199e187e173
[binutils-gdb.git] / sim / mips / cp1.c
1 /*> cp1.c <*/
2 /* MIPS Simulator FPU (CoProcessor 1) support.
3 Copyright (C) 2002 Free Software Foundation, Inc.
4 Originally created by Cygnus Solutions, modified substially
5 by Broadcom Corporation (SiByte).
6
7 This file is part of GDB, the GNU debugger.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License along
20 with this program; if not, write to the Free Software Foundation, Inc.,
21 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22
23 /* XXX: The following notice should be removed as soon as is practical: */
24 /* Floating Point Support for gdb MIPS simulators
25
26 This file is part of the MIPS sim
27
28 THIS SOFTWARE IS NOT COPYRIGHTED
29 (by Cygnus.)
30
31 Cygnus offers the following for use in the public domain. Cygnus
32 makes no warranty with regard to the software or it's performance
33 and the user accepts the software "AS IS" with all faults.
34
35 CYGNUS DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO
36 THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
37 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
38
39 (Originally, this code was in interp.c)
40 */
41
42 #include "sim-main.h"
43
44 /* Within cp1.c we refer to sim_cpu directly. */
45 #define CPU cpu
46 #define SD CPU_STATE(cpu)
47
48 /*-- FPU support routines ---------------------------------------------------*/
49
50 /* Numbers are held in normalized form. The SINGLE and DOUBLE binary
51 formats conform to ANSI/IEEE Std 754-1985.
52
53 SINGLE precision floating:
54 seeeeeeeefffffffffffffffffffffff
55 s = 1bit = sign
56 e = 8bits = exponent
57 f = 23bits = fraction
58
59 SINGLE precision fixed:
60 siiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
61 s = 1bit = sign
62 i = 31bits = integer
63
64 DOUBLE precision floating:
65 seeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffff
66 s = 1bit = sign
67 e = 11bits = exponent
68 f = 52bits = fraction
69
70 DOUBLE precision fixed:
71 siiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
72 s = 1bit = sign
73 i = 63bits = integer
74 */
75
76 /* Explicit QNaN values. */
77 #define FPQNaN_SINGLE (0x7FBFFFFF)
78 #define FPQNaN_WORD (0x7FFFFFFF)
79 #define FPQNaN_DOUBLE (UNSIGNED64 (0x7FF7FFFFFFFFFFFF))
80 #define FPQNaN_LONG (UNSIGNED64 (0x7FFFFFFFFFFFFFFF))
81
82 static const char *fpu_format_name (FP_formats fmt);
83 #ifdef DEBUG
84 static const char *fpu_rounding_mode_name (int rm);
85 #endif
86
87 uword64
88 value_fpr (sim_cpu *cpu,
89 address_word cia,
90 int fpr,
91 FP_formats fmt)
92 {
93 uword64 value = 0;
94 int err = 0;
95
96 /* Treat unused register values, as fixed-point 64bit values. */
97 if ((fmt == fmt_uninterpreted) || (fmt == fmt_unknown))
98 {
99 #if 1
100 /* If request to read data as "uninterpreted", then use the current
101 encoding: */
102 fmt = FPR_STATE[fpr];
103 #else
104 fmt = fmt_long;
105 #endif
106 }
107
108 /* For values not yet accessed, set to the desired format. */
109 if (FPR_STATE[fpr] == fmt_uninterpreted)
110 {
111 FPR_STATE[fpr] = fmt;
112 #ifdef DEBUG
113 printf ("DBG: Register %d was fmt_uninterpreted. Now %s\n", fpr,
114 fpu_format_name (fmt));
115 #endif /* DEBUG */
116 }
117 if (fmt != FPR_STATE[fpr])
118 {
119 sim_io_eprintf (SD, "FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",
120 fpr, fpu_format_name (FPR_STATE[fpr]),
121 fpu_format_name (fmt), pr_addr (cia));
122 FPR_STATE[fpr] = fmt_unknown;
123 }
124
125 if (FPR_STATE[fpr] == fmt_unknown)
126 {
127 /* Set QNaN value: */
128 switch (fmt)
129 {
130 case fmt_single: value = FPQNaN_SINGLE; break;
131 case fmt_double: value = FPQNaN_DOUBLE; break;
132 case fmt_word: value = FPQNaN_WORD; break;
133 case fmt_long: value = FPQNaN_LONG; break;
134 default: err = -1; break;
135 }
136 }
137 else if (SizeFGR () == 64)
138 {
139 switch (fmt)
140 {
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 }
157 else
158 {
159 switch (fmt)
160 {
161 case fmt_single:
162 case fmt_word:
163 value = (FGR[fpr] & 0xFFFFFFFF);
164 break;
165
166 case fmt_uninterpreted:
167 case fmt_double:
168 case fmt_long:
169 if ((fpr & 1) == 0)
170 {
171 /* Even register numbers only. */
172 #ifdef DEBUG
173 printf ("DBG: ValueFPR: FGR[%d] = %s, FGR[%d] = %s\n",
174 fpr + 1, pr_uword64 ((uword64) FGR[fpr+1]),
175 fpr, pr_uword64 ((uword64) FGR[fpr]));
176 #endif
177 value = ((((uword64) FGR[fpr+1]) << 32)
178 | (FGR[fpr] & 0xFFFFFFFF));
179 }
180 else
181 {
182 SignalException (ReservedInstruction, 0);
183 }
184 break;
185
186 default:
187 err = -1;
188 break;
189 }
190 }
191
192 if (err)
193 SignalExceptionSimulatorFault ("Unrecognised FP format in ValueFPR ()");
194
195 #ifdef DEBUG
196 printf ("DBG: ValueFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR () = %d\n",
197 fpr, fpu_format_name (fmt), pr_uword64 (value), pr_addr (cia),
198 SizeFGR ());
199 #endif /* DEBUG */
200
201 return (value);
202 }
203
204 void
205 store_fpr (sim_cpu *cpu,
206 address_word cia,
207 int fpr,
208 FP_formats fmt,
209 uword64 value)
210 {
211 int err = 0;
212
213 #ifdef DEBUG
214 printf ("DBG: StoreFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR () = %d, \n",
215 fpr, fpu_format_name (fmt), pr_uword64 (value), pr_addr (cia),
216 SizeFGR ());
217 #endif /* DEBUG */
218
219 if (SizeFGR () == 64)
220 {
221 switch (fmt)
222 {
223 case fmt_uninterpreted_32:
224 fmt = fmt_uninterpreted;
225 case fmt_single:
226 case fmt_word:
227 if (STATE_VERBOSE_P (SD))
228 sim_io_eprintf (SD,
229 "Warning: PC 0x%s: interp.c store_fpr DEADCODE\n",
230 pr_addr (cia));
231 FGR[fpr] = (((uword64) 0xDEADC0DE << 32) | (value & 0xFFFFFFFF));
232 FPR_STATE[fpr] = fmt;
233 break;
234
235 case fmt_uninterpreted_64:
236 fmt = fmt_uninterpreted;
237 case fmt_uninterpreted:
238 case fmt_double:
239 case fmt_long:
240 FGR[fpr] = value;
241 FPR_STATE[fpr] = fmt;
242 break;
243
244 default:
245 FPR_STATE[fpr] = fmt_unknown;
246 err = -1;
247 break;
248 }
249 }
250 else
251 {
252 switch (fmt)
253 {
254 case fmt_uninterpreted_32:
255 fmt = fmt_uninterpreted;
256 case fmt_single:
257 case fmt_word:
258 FGR[fpr] = (value & 0xFFFFFFFF);
259 FPR_STATE[fpr] = fmt;
260 break;
261
262 case fmt_uninterpreted_64:
263 fmt = fmt_uninterpreted;
264 case fmt_uninterpreted:
265 case fmt_double:
266 case fmt_long:
267 if ((fpr & 1) == 0)
268 {
269 /* Even register numbers only. */
270 FGR[fpr+1] = (value >> 32);
271 FGR[fpr] = (value & 0xFFFFFFFF);
272 FPR_STATE[fpr + 1] = fmt;
273 FPR_STATE[fpr] = fmt;
274 }
275 else
276 {
277 FPR_STATE[fpr] = fmt_unknown;
278 FPR_STATE[fpr + 1] = fmt_unknown;
279 SignalException (ReservedInstruction, 0);
280 }
281 break;
282
283 default:
284 FPR_STATE[fpr] = fmt_unknown;
285 err = -1;
286 break;
287 }
288 }
289
290 if (err)
291 SignalExceptionSimulatorFault ("Unrecognised FP format in StoreFPR ()");
292
293 #ifdef DEBUG
294 printf ("DBG: StoreFPR: fpr[%d] = 0x%s (format %s)\n",
295 fpr, pr_uword64 (FGR[fpr]), fpu_format_name (fmt));
296 #endif /* DEBUG */
297
298 return;
299 }
300
301
302 /* CP1 control/status register access functions. */
303
304 void
305 test_fcsr (sim_cpu *cpu,
306 address_word cia)
307 {
308 unsigned int cause;
309
310 cause = (FCSR & fcsr_CAUSE_mask) >> fcsr_CAUSE_shift;
311 if ((cause & ((FCSR & fcsr_ENABLES_mask) >> fcsr_ENABLES_shift)) != 0
312 || (cause & (1 << UO)))
313 {
314 SignalExceptionFPE();
315 }
316 }
317
318 unsigned_word
319 value_fcr(sim_cpu *cpu,
320 address_word cia,
321 int fcr)
322 {
323 unsigned32 value = 0;
324
325 switch (fcr)
326 {
327 case 0: /* FP Implementation and Revision Register. */
328 value = FCR0;
329 break;
330 case 25: /* FP Condition Codes Register (derived from FCSR). */
331 value = (FCR31 & fcsr_FCC_mask) >> fcsr_FCC_shift;
332 value = (value & 0x1) | (value >> 1); /* Close FCC gap. */
333 break;
334 case 26: /* FP Exceptions Register (derived from FCSR). */
335 value = FCR31 & (fcsr_CAUSE_mask | fcsr_FLAGS_mask);
336 break;
337 case 28: /* FP Enables Register (derived from FCSR). */
338 value = FCR31 & (fcsr_ENABLES_mask | fcsr_RM_mask);
339 if ((FCR31 & fcsr_FS) != 0)
340 value |= fenr_FS;
341 break;
342 case 31: /* FP Control/Status Register (FCSR). */
343 value = FCR31 & ~fcsr_ZERO_mask;
344 break;
345 }
346
347 return (EXTEND32 (value));
348 }
349
350 void
351 store_fcr(sim_cpu *cpu,
352 address_word cia,
353 int fcr,
354 unsigned_word value)
355 {
356 unsigned32 v;
357
358 v = VL4_8(value);
359 switch (fcr)
360 {
361 case 25: /* FP Condition Codes Register (stored into FCSR). */
362 v = (v << 1) | (v & 0x1); /* Adjust for FCC gap. */
363 FCR31 &= ~fcsr_FCC_mask;
364 FCR31 |= ((v << fcsr_FCC_shift) & fcsr_FCC_mask);
365 break;
366 case 26: /* FP Exceptions Register (stored into FCSR). */
367 FCR31 &= ~(fcsr_CAUSE_mask | fcsr_FLAGS_mask);
368 FCR31 |= (v & (fcsr_CAUSE_mask | fcsr_FLAGS_mask));
369 test_fcsr(cpu, cia);
370 break;
371 case 28: /* FP Enables Register (stored into FCSR). */
372 if ((v & fenr_FS) != 0)
373 v |= fcsr_FS;
374 else
375 v &= ~fcsr_FS;
376 FCR31 &= (fcsr_FCC_mask | fcsr_CAUSE_mask | fcsr_FLAGS_mask);
377 FCR31 |= (v & (fcsr_FS | fcsr_ENABLES_mask | fcsr_RM_mask));
378 test_fcsr(cpu, cia);
379 break;
380 case 31: /* FP Control/Status Register (FCSR). */
381 FCR31 = v & ~fcsr_ZERO_mask;
382 test_fcsr(cpu, cia);
383 break;
384 }
385 }
386
387 void
388 update_fcsr (sim_cpu *cpu,
389 address_word cia,
390 sim_fpu_status status)
391 {
392 FCSR &= ~fcsr_CAUSE_mask;
393
394 if (status != 0)
395 {
396 unsigned int cause = 0;
397
398 /* map between sim_fpu codes and MIPS FCSR */
399 if (status & (sim_fpu_status_invalid_snan
400 | sim_fpu_status_invalid_isi
401 | sim_fpu_status_invalid_idi
402 | sim_fpu_status_invalid_zdz
403 | sim_fpu_status_invalid_imz
404 | sim_fpu_status_invalid_cmp
405 | sim_fpu_status_invalid_sqrt
406 | sim_fpu_status_invalid_cvi))
407 cause |= (1 << IO);
408 if (status & sim_fpu_status_invalid_div0)
409 cause |= (1 << DZ);
410 if (status & sim_fpu_status_overflow)
411 cause |= (1 << OF);
412 if (status & sim_fpu_status_underflow)
413 cause |= (1 << UF);
414 if (status & sim_fpu_status_inexact)
415 cause |= (1 << IR);
416 #if 0 /* Not yet. */
417 /* Implicit clearing of other bits by unimplemented done by callers. */
418 if (status & sim_fpu_status_unimplemented)
419 cause |= (1 << UO);
420 #endif
421
422 FCSR |= (cause << fcsr_CAUSE_shift);
423 test_fcsr (cpu, cia);
424 FCSR |= ((cause & ~(1 << UO)) << fcsr_FLAGS_shift);
425 }
426 return;
427 }
428
429 static sim_fpu_round
430 rounding_mode(int rm)
431 {
432 sim_fpu_round round;
433
434 switch (rm)
435 {
436 case FP_RM_NEAREST:
437 /* Round result to nearest representable value. When two
438 representable values are equally near, round to the value
439 that has a least significant bit of zero (i.e. is even). */
440 round = sim_fpu_round_near;
441 break;
442 case FP_RM_TOZERO:
443 /* Round result to the value closest to, and not greater in
444 magnitude than, the result. */
445 round = sim_fpu_round_zero;
446 break;
447 case FP_RM_TOPINF:
448 /* Round result to the value closest to, and not less than,
449 the result. */
450 round = sim_fpu_round_up;
451 break;
452 case FP_RM_TOMINF:
453 /* Round result to the value closest to, and not greater than,
454 the result. */
455 round = sim_fpu_round_down;
456 break;
457 default:
458 round = 0;
459 fprintf (stderr, "Bad switch\n");
460 abort ();
461 }
462 return round;
463 }
464
465 /* When the FS bit is set, MIPS processors return zero for
466 denormalized results and optionally replace denormalized inputs
467 with zero. When FS is clear, some implementation trap on input
468 and/or output, while other perform the operation in hardware. */
469 static sim_fpu_denorm
470 denorm_mode(sim_cpu *cpu)
471 {
472 sim_fpu_denorm denorm;
473
474 /* XXX: FIXME: Eventually should be CPU model dependent. */
475 if (GETFS())
476 denorm = sim_fpu_denorm_zero;
477 else
478 denorm = 0;
479 return denorm;
480 }
481
482
483 /* Comparison operations. */
484
485 static sim_fpu_status
486 fp_test(unsigned64 op1,
487 unsigned64 op2,
488 FP_formats fmt,
489 int abs,
490 int cond,
491 int *condition)
492 {
493 sim_fpu wop1;
494 sim_fpu wop2;
495 sim_fpu_status status = 0;
496 int less, equal, unordered;
497
498 /* The format type has already been checked: */
499 switch (fmt)
500 {
501 case fmt_single:
502 {
503 sim_fpu_32to (&wop1, op1);
504 sim_fpu_32to (&wop2, op2);
505 break;
506 }
507 case fmt_double:
508 {
509 sim_fpu_64to (&wop1, op1);
510 sim_fpu_64to (&wop2, op2);
511 break;
512 }
513 default:
514 fprintf (stderr, "Bad switch\n");
515 abort ();
516 }
517
518 if (sim_fpu_is_nan (&wop1) || sim_fpu_is_nan (&wop2))
519 {
520 if ((cond & (1 << 3)) ||
521 sim_fpu_is_snan (&wop1) || sim_fpu_is_snan (&wop2))
522 status = sim_fpu_status_invalid_snan;
523 less = 0;
524 equal = 0;
525 unordered = 1;
526 }
527 else
528 {
529 if (abs)
530 {
531 status |= sim_fpu_abs (&wop1, &wop1);
532 status |= sim_fpu_abs (&wop2, &wop2);
533 }
534 equal = sim_fpu_is_eq (&wop1, &wop2);
535 less = !equal && sim_fpu_is_lt (&wop1, &wop2);
536 unordered = 0;
537 }
538 *condition = (((cond & (1 << 2)) && less)
539 || ((cond & (1 << 1)) && equal)
540 || ((cond & (1 << 0)) && unordered));
541 return status;
542 }
543
544 void
545 fp_cmp(sim_cpu *cpu,
546 address_word cia,
547 unsigned64 op1,
548 unsigned64 op2,
549 FP_formats fmt,
550 int abs,
551 int cond,
552 int cc)
553 {
554 sim_fpu_status status = 0;
555
556 /* The format type should already have been checked. The FCSR is
557 updated before the condition codes so that any exceptions will
558 be signalled before the condition codes are changed. */
559 switch (fmt)
560 {
561 case fmt_single:
562 case fmt_double:
563 {
564 int result;
565 status = fp_test(op1, op2, fmt, abs, cond, &result);
566 update_fcsr (cpu, cia, status);
567 SETFCC (cc, result);
568 break;
569 }
570 default:
571 sim_io_eprintf (SD, "Bad switch\n");
572 abort ();
573 }
574 }
575
576
577 /* Basic arithmetic operations. */
578
579 static unsigned64
580 fp_unary(sim_cpu *cpu,
581 address_word cia,
582 int (*sim_fpu_op)(sim_fpu *, const sim_fpu *),
583 unsigned64 op,
584 FP_formats fmt)
585 {
586 sim_fpu wop;
587 sim_fpu ans;
588 sim_fpu_round round = rounding_mode (GETRM());
589 sim_fpu_denorm denorm = denorm_mode (cpu);
590 sim_fpu_status status = 0;
591 unsigned64 result = 0;
592
593 /* The format type has already been checked: */
594 switch (fmt)
595 {
596 case fmt_single:
597 {
598 unsigned32 res;
599 sim_fpu_32to (&wop, op);
600 status |= (*sim_fpu_op) (&ans, &wop);
601 status |= sim_fpu_round_32 (&ans, round, denorm);
602 sim_fpu_to32 (&res, &ans);
603 result = res;
604 break;
605 }
606 case fmt_double:
607 {
608 unsigned64 res;
609 sim_fpu_64to (&wop, op);
610 status |= (*sim_fpu_op) (&ans, &wop);
611 status |= sim_fpu_round_64 (&ans, round, denorm);
612 sim_fpu_to64 (&res, &ans);
613 result = res;
614 break;
615 }
616 default:
617 sim_io_eprintf (SD, "Bad switch\n");
618 abort ();
619 }
620
621 update_fcsr (cpu, cia, status);
622 return result;
623 }
624
625 static unsigned64
626 fp_binary(sim_cpu *cpu,
627 address_word cia,
628 int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *),
629 unsigned64 op1,
630 unsigned64 op2,
631 FP_formats fmt)
632 {
633 sim_fpu wop1;
634 sim_fpu wop2;
635 sim_fpu ans;
636 sim_fpu_round round = rounding_mode (GETRM());
637 sim_fpu_denorm denorm = denorm_mode (cpu);
638 sim_fpu_status status = 0;
639 unsigned64 result = 0;
640
641 /* The format type has already been checked: */
642 switch (fmt)
643 {
644 case fmt_single:
645 {
646 unsigned32 res;
647 sim_fpu_32to (&wop1, op1);
648 sim_fpu_32to (&wop2, op2);
649 status |= (*sim_fpu_op) (&ans, &wop1, &wop2);
650 status |= sim_fpu_round_32 (&ans, round, denorm);
651 sim_fpu_to32 (&res, &ans);
652 result = res;
653 break;
654 }
655 case fmt_double:
656 {
657 unsigned64 res;
658 sim_fpu_64to (&wop1, op1);
659 sim_fpu_64to (&wop2, op2);
660 status |= (*sim_fpu_op) (&ans, &wop1, &wop2);
661 status |= sim_fpu_round_64 (&ans, round, denorm);
662 sim_fpu_to64 (&res, &ans);
663 result = res;
664 break;
665 }
666 default:
667 sim_io_eprintf (SD, "Bad switch\n");
668 abort ();
669 }
670
671 update_fcsr (cpu, cia, status);
672 return result;
673 }
674
675 /* Common MAC code for single operands (.s or .d), defers setting FCSR. */
676 static sim_fpu_status
677 inner_mac(int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *),
678 unsigned64 op1,
679 unsigned64 op2,
680 unsigned64 op3,
681 int scale,
682 int negate,
683 FP_formats fmt,
684 sim_fpu_round round,
685 sim_fpu_denorm denorm,
686 unsigned64 *result)
687 {
688 sim_fpu wop1;
689 sim_fpu wop2;
690 sim_fpu ans;
691 sim_fpu_status status = 0;
692 sim_fpu_status op_status;
693 unsigned64 temp = 0;
694
695 switch (fmt)
696 {
697 case fmt_single:
698 {
699 unsigned32 res;
700 sim_fpu_32to (&wop1, op1);
701 sim_fpu_32to (&wop2, op2);
702 status |= sim_fpu_mul (&ans, &wop1, &wop2);
703 if (scale != 0 && sim_fpu_is_number (&ans)) /* number or denorm */
704 ans.normal_exp += scale;
705 status |= sim_fpu_round_32 (&ans, round, denorm);
706 wop1 = ans;
707 op_status = 0;
708 sim_fpu_32to (&wop2, op3);
709 op_status |= (*sim_fpu_op) (&ans, &wop1, &wop2);
710 op_status |= sim_fpu_round_32 (&ans, round, denorm);
711 status |= op_status;
712 if (negate)
713 {
714 wop1 = ans;
715 op_status = sim_fpu_neg (&ans, &wop1);
716 op_status |= sim_fpu_round_32 (&ans, round, denorm);
717 status |= op_status;
718 }
719 sim_fpu_to32 (&res, &ans);
720 temp = res;
721 break;
722 }
723 case fmt_double:
724 {
725 unsigned64 res;
726 sim_fpu_64to (&wop1, op1);
727 sim_fpu_64to (&wop2, op2);
728 status |= sim_fpu_mul (&ans, &wop1, &wop2);
729 if (scale != 0 && sim_fpu_is_number (&ans)) /* number or denorm */
730 ans.normal_exp += scale;
731 status |= sim_fpu_round_64 (&ans, round, denorm);
732 wop1 = ans;
733 op_status = 0;
734 sim_fpu_64to (&wop2, op3);
735 op_status |= (*sim_fpu_op) (&ans, &wop1, &wop2);
736 op_status |= sim_fpu_round_64 (&ans, round, denorm);
737 status |= op_status;
738 if (negate)
739 {
740 wop1 = ans;
741 op_status = sim_fpu_neg (&ans, &wop1);
742 op_status |= sim_fpu_round_64 (&ans, round, denorm);
743 status |= op_status;
744 }
745 sim_fpu_to64 (&res, &ans);
746 temp = res;
747 break;
748 }
749 default:
750 fprintf (stderr, "Bad switch\n");
751 abort ();
752 }
753 *result = temp;
754 return status;
755 }
756
757 /* Common implementation of madd, nmadd, msub, nmsub that does
758 intermediate rounding per spec. Also used for recip2 and rsqrt2,
759 which are transformed into equivalent nmsub operations. The scale
760 argument is an adjustment to the exponent of the intermediate
761 product op1*op2. It is currently non-zero for rsqrt2 (-1), which
762 requires an effective division by 2. */
763 static unsigned64
764 fp_mac(sim_cpu *cpu,
765 address_word cia,
766 int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *),
767 unsigned64 op1,
768 unsigned64 op2,
769 unsigned64 op3,
770 int scale,
771 int negate,
772 FP_formats fmt)
773 {
774 sim_fpu_round round = rounding_mode (GETRM());
775 sim_fpu_denorm denorm = denorm_mode (cpu);
776 sim_fpu_status status = 0;
777 unsigned64 result = 0;
778
779 /* The format type has already been checked: */
780 switch (fmt)
781 {
782 case fmt_single:
783 case fmt_double:
784 status = inner_mac(sim_fpu_op, op1, op2, op3, scale,
785 negate, fmt, round, denorm, &result);
786 break;
787 default:
788 sim_io_eprintf (SD, "Bad switch\n");
789 abort ();
790 }
791
792 update_fcsr (cpu, cia, status);
793 return result;
794 }
795
796 /* Common rsqrt code for single operands (.s or .d), intermediate rounding. */
797 static sim_fpu_status
798 inner_rsqrt(unsigned64 op1,
799 FP_formats fmt,
800 sim_fpu_round round,
801 sim_fpu_denorm denorm,
802 unsigned64 *result)
803 {
804 sim_fpu wop1;
805 sim_fpu ans;
806 sim_fpu_status status = 0;
807 sim_fpu_status op_status;
808 unsigned64 temp = 0;
809
810 switch (fmt)
811 {
812 case fmt_single:
813 {
814 unsigned32 res;
815 sim_fpu_32to (&wop1, op1);
816 status |= sim_fpu_sqrt (&ans, &wop1);
817 status |= sim_fpu_round_32 (&ans, status, round);
818 wop1 = ans;
819 op_status = sim_fpu_inv (&ans, &wop1);
820 op_status |= sim_fpu_round_32 (&ans, round, denorm);
821 sim_fpu_to32 (&res, &ans);
822 temp = res;
823 status |= op_status;
824 break;
825 }
826 case fmt_double:
827 {
828 unsigned64 res;
829 sim_fpu_64to (&wop1, op1);
830 status |= sim_fpu_sqrt (&ans, &wop1);
831 status |= sim_fpu_round_64 (&ans, round, denorm);
832 wop1 = ans;
833 op_status = sim_fpu_inv (&ans, &wop1);
834 op_status |= sim_fpu_round_64 (&ans, round, denorm);
835 sim_fpu_to64 (&res, &ans);
836 temp = res;
837 status |= op_status;
838 break;
839 }
840 default:
841 fprintf (stderr, "Bad switch\n");
842 abort ();
843 }
844 *result = temp;
845 return status;
846 }
847
848 static unsigned64
849 fp_inv_sqrt(sim_cpu *cpu,
850 address_word cia,
851 unsigned64 op1,
852 FP_formats fmt)
853 {
854 sim_fpu_round round = rounding_mode (GETRM());
855 sim_fpu_round denorm = denorm_mode (cpu);
856 sim_fpu_status status = 0;
857 unsigned64 result = 0;
858
859 /* The format type has already been checked: */
860 switch (fmt)
861 {
862 case fmt_single:
863 case fmt_double:
864 status = inner_rsqrt (op1, fmt, round, denorm, &result);
865 break;
866 default:
867 sim_io_eprintf (SD, "Bad switch\n");
868 abort ();
869 }
870
871 update_fcsr (cpu, cia, status);
872 return result;
873 }
874
875
876 unsigned64
877 fp_abs(sim_cpu *cpu,
878 address_word cia,
879 unsigned64 op,
880 FP_formats fmt)
881 {
882 return fp_unary(cpu, cia, &sim_fpu_abs, op, fmt);
883 }
884
885 unsigned64
886 fp_neg(sim_cpu *cpu,
887 address_word cia,
888 unsigned64 op,
889 FP_formats fmt)
890 {
891 return fp_unary(cpu, cia, &sim_fpu_neg, op, fmt);
892 }
893
894 unsigned64
895 fp_add(sim_cpu *cpu,
896 address_word cia,
897 unsigned64 op1,
898 unsigned64 op2,
899 FP_formats fmt)
900 {
901 return fp_binary(cpu, cia, &sim_fpu_add, op1, op2, fmt);
902 }
903
904 unsigned64
905 fp_sub(sim_cpu *cpu,
906 address_word cia,
907 unsigned64 op1,
908 unsigned64 op2,
909 FP_formats fmt)
910 {
911 return fp_binary(cpu, cia, &sim_fpu_sub, op1, op2, fmt);
912 }
913
914 unsigned64
915 fp_mul(sim_cpu *cpu,
916 address_word cia,
917 unsigned64 op1,
918 unsigned64 op2,
919 FP_formats fmt)
920 {
921 return fp_binary(cpu, cia, &sim_fpu_mul, op1, op2, fmt);
922 }
923
924 unsigned64
925 fp_div(sim_cpu *cpu,
926 address_word cia,
927 unsigned64 op1,
928 unsigned64 op2,
929 FP_formats fmt)
930 {
931 return fp_binary(cpu, cia, &sim_fpu_div, op1, op2, fmt);
932 }
933
934 unsigned64
935 fp_recip(sim_cpu *cpu,
936 address_word cia,
937 unsigned64 op,
938 FP_formats fmt)
939 {
940 return fp_unary(cpu, cia, &sim_fpu_inv, op, fmt);
941 }
942
943 unsigned64
944 fp_sqrt(sim_cpu *cpu,
945 address_word cia,
946 unsigned64 op,
947 FP_formats fmt)
948 {
949 return fp_unary(cpu, cia, &sim_fpu_sqrt, op, fmt);
950 }
951
952 unsigned64
953 fp_rsqrt(sim_cpu *cpu,
954 address_word cia,
955 unsigned64 op,
956 FP_formats fmt)
957 {
958 return fp_inv_sqrt(cpu, cia, op, fmt);
959 }
960
961 unsigned64
962 fp_madd(sim_cpu *cpu,
963 address_word cia,
964 unsigned64 op1,
965 unsigned64 op2,
966 unsigned64 op3,
967 FP_formats fmt)
968 {
969 return fp_mac(cpu, cia, &sim_fpu_add, op1, op2, op3, 0, 0, fmt);
970 }
971
972 unsigned64
973 fp_msub(sim_cpu *cpu,
974 address_word cia,
975 unsigned64 op1,
976 unsigned64 op2,
977 unsigned64 op3,
978 FP_formats fmt)
979 {
980 return fp_mac(cpu, cia, &sim_fpu_sub, op1, op2, op3, 0, 0, fmt);
981 }
982
983 unsigned64
984 fp_nmadd(sim_cpu *cpu,
985 address_word cia,
986 unsigned64 op1,
987 unsigned64 op2,
988 unsigned64 op3,
989 FP_formats fmt)
990 {
991 return fp_mac(cpu, cia, &sim_fpu_add, op1, op2, op3, 0, 1, fmt);
992 }
993
994 unsigned64
995 fp_nmsub(sim_cpu *cpu,
996 address_word cia,
997 unsigned64 op1,
998 unsigned64 op2,
999 unsigned64 op3,
1000 FP_formats fmt)
1001 {
1002 return fp_mac(cpu, cia, &sim_fpu_sub, op1, op2, op3, 0, 1, fmt);
1003 }
1004
1005
1006 /* Conversion operations. */
1007
1008 uword64
1009 convert (sim_cpu *cpu,
1010 address_word cia,
1011 int rm,
1012 uword64 op,
1013 FP_formats from,
1014 FP_formats to)
1015 {
1016 sim_fpu wop;
1017 sim_fpu_round round = rounding_mode (rm);
1018 sim_fpu_denorm denorm = denorm_mode (cpu);
1019 unsigned32 result32;
1020 unsigned64 result64;
1021 sim_fpu_status status = 0;
1022
1023 /* Convert the input to sim_fpu internal format */
1024 switch (from)
1025 {
1026 case fmt_double:
1027 sim_fpu_64to (&wop, op);
1028 break;
1029 case fmt_single:
1030 sim_fpu_32to (&wop, op);
1031 break;
1032 case fmt_word:
1033 status = sim_fpu_i32to (&wop, op, round);
1034 break;
1035 case fmt_long:
1036 status = sim_fpu_i64to (&wop, op, round);
1037 break;
1038 default:
1039 sim_io_eprintf (SD, "Bad switch\n");
1040 abort ();
1041 }
1042
1043 /* Convert sim_fpu format into the output */
1044 /* The value WOP is converted to the destination format, rounding
1045 using mode RM. When the destination is a fixed-point format, then
1046 a source value of Infinity, NaN or one which would round to an
1047 integer outside the fixed point range then an IEEE Invalid
1048 Operation condition is raised. */
1049 switch (to)
1050 {
1051 case fmt_single:
1052 status |= sim_fpu_round_32 (&wop, round, denorm);
1053 /* For a NaN, normalize mantissa bits (cvt.s.d can't preserve them) */
1054 if (sim_fpu_is_qnan (&wop))
1055 wop = sim_fpu_qnan;
1056 sim_fpu_to32 (&result32, &wop);
1057 result64 = result32;
1058 break;
1059 case fmt_double:
1060 status |= sim_fpu_round_64 (&wop, round, denorm);
1061 /* For a NaN, normalize mantissa bits (make cvt.d.s consistent) */
1062 if (sim_fpu_is_qnan (&wop))
1063 wop = sim_fpu_qnan;
1064 sim_fpu_to64 (&result64, &wop);
1065 break;
1066 case fmt_word:
1067 status |= sim_fpu_to32i (&result32, &wop, round);
1068 result64 = result32;
1069 break;
1070 case fmt_long:
1071 status |= sim_fpu_to64i (&result64, &wop, round);
1072 break;
1073 default:
1074 result64 = 0;
1075 sim_io_eprintf (SD, "Bad switch\n");
1076 abort ();
1077 }
1078
1079 update_fcsr (cpu, cia, status);
1080 return result64;
1081 }
1082
1083 static const char *
1084 fpu_format_name (FP_formats fmt)
1085 {
1086 switch (fmt)
1087 {
1088 case fmt_single:
1089 return "single";
1090 case fmt_double:
1091 return "double";
1092 case fmt_word:
1093 return "word";
1094 case fmt_long:
1095 return "long";
1096 case fmt_unknown:
1097 return "<unknown>";
1098 case fmt_uninterpreted:
1099 return "<uninterpreted>";
1100 case fmt_uninterpreted_32:
1101 return "<uninterpreted_32>";
1102 case fmt_uninterpreted_64:
1103 return "<uninterpreted_64>";
1104 default:
1105 return "<format error>";
1106 }
1107 }
1108
1109 #ifdef DEBUG
1110 static const char *
1111 fpu_rounding_mode_name (int rm)
1112 {
1113 switch (rm)
1114 {
1115 case FP_RM_NEAREST:
1116 return "Round";
1117 case FP_RM_TOZERO:
1118 return "Trunc";
1119 case FP_RM_TOPINF:
1120 return "Ceil";
1121 case FP_RM_TOMINF:
1122 return "Floor";
1123 default:
1124 return "<rounding mode error>";
1125 }
1126 }
1127 #endif /* DEBUG */