[igen/ChangeLog]
[deliverable/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. Extensive modifications,
5 including paired-single operation support and MIPS-3D support
6 contributed by Ed Satterthwaite and Chris Demetriou, of Broadcom
7 Corporation (SiByte).
8
9 This file is part of GDB, the GNU debugger.
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License along
22 with this program; if not, write to the Free Software Foundation, Inc.,
23 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24
25 /* XXX: The following notice should be removed as soon as is practical: */
26 /* Floating Point Support for gdb MIPS simulators
27
28 This file is part of the MIPS sim
29
30 THIS SOFTWARE IS NOT COPYRIGHTED
31 (by Cygnus.)
32
33 Cygnus offers the following for use in the public domain. Cygnus
34 makes no warranty with regard to the software or it's performance
35 and the user accepts the software "AS IS" with all faults.
36
37 CYGNUS DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO
38 THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
39 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
40
41 (Originally, this code was in interp.c)
42 */
43
44 #include "sim-main.h"
45
46 /* Within cp1.c we refer to sim_cpu directly. */
47 #define CPU cpu
48 #define SD CPU_STATE(cpu)
49
50 /*-- FPU support routines ---------------------------------------------------*/
51
52 /* Numbers are held in normalized form. The SINGLE and DOUBLE binary
53 formats conform to ANSI/IEEE Std 754-1985.
54
55 SINGLE precision floating:
56 seeeeeeeefffffffffffffffffffffff
57 s = 1bit = sign
58 e = 8bits = exponent
59 f = 23bits = fraction
60
61 SINGLE precision fixed:
62 siiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
63 s = 1bit = sign
64 i = 31bits = integer
65
66 DOUBLE precision floating:
67 seeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffff
68 s = 1bit = sign
69 e = 11bits = exponent
70 f = 52bits = fraction
71
72 DOUBLE precision fixed:
73 siiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
74 s = 1bit = sign
75 i = 63bits = integer
76
77 PAIRED SINGLE precision floating:
78 seeeeeeeefffffffffffffffffffffffseeeeeeeefffffffffffffffffffffff
79 | upper || lower |
80 s = 1bit = sign
81 e = 8bits = exponent
82 f = 23bits = fraction
83 Note: upper = [63..32], lower = [31..0]
84 */
85
86 /* Extract packed single values: */
87 #define FP_PS_upper(v) (((v) >> 32) & (unsigned)0xFFFFFFFF)
88 #define FP_PS_lower(v) ((v) & (unsigned)0xFFFFFFFF)
89 #define FP_PS_cat(u,l) (((unsigned64)((u) & (unsigned)0xFFFFFFFF) << 32) \
90 | (unsigned64)((l) & 0xFFFFFFFF))
91
92 /* Explicit QNaN values. */
93 #define FPQNaN_SINGLE (0x7FBFFFFF)
94 #define FPQNaN_WORD (0x7FFFFFFF)
95 #define FPQNaN_DOUBLE (UNSIGNED64 (0x7FF7FFFFFFFFFFFF))
96 #define FPQNaN_LONG (UNSIGNED64 (0x7FFFFFFFFFFFFFFF))
97 #define FPQNaN_PS (FP_PS_cat (FPQNaN_SINGLE, FPQNaN_SINGLE))
98
99 static const char *fpu_format_name (FP_formats fmt);
100 #ifdef DEBUG
101 static const char *fpu_rounding_mode_name (int rm);
102 #endif
103
104 uword64
105 value_fpr (sim_cpu *cpu,
106 address_word cia,
107 int fpr,
108 FP_formats fmt)
109 {
110 uword64 value = 0;
111 int err = 0;
112
113 /* Treat unused register values, as fixed-point 64bit values. */
114 if ((fmt == fmt_uninterpreted) || (fmt == fmt_unknown))
115 {
116 #if 1
117 /* If request to read data as "uninterpreted", then use the current
118 encoding: */
119 fmt = FPR_STATE[fpr];
120 #else
121 fmt = fmt_long;
122 #endif
123 }
124
125 /* For values not yet accessed, set to the desired format. */
126 if (FPR_STATE[fpr] == fmt_uninterpreted)
127 {
128 FPR_STATE[fpr] = fmt;
129 #ifdef DEBUG
130 printf ("DBG: Register %d was fmt_uninterpreted. Now %s\n", fpr,
131 fpu_format_name (fmt));
132 #endif /* DEBUG */
133 }
134 if (fmt != FPR_STATE[fpr])
135 {
136 sim_io_eprintf (SD, "FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",
137 fpr, fpu_format_name (FPR_STATE[fpr]),
138 fpu_format_name (fmt), pr_addr (cia));
139 FPR_STATE[fpr] = fmt_unknown;
140 }
141
142 if (FPR_STATE[fpr] == fmt_unknown)
143 {
144 /* Set QNaN value: */
145 switch (fmt)
146 {
147 case fmt_single: value = FPQNaN_SINGLE; break;
148 case fmt_double: value = FPQNaN_DOUBLE; break;
149 case fmt_word: value = FPQNaN_WORD; break;
150 case fmt_long: value = FPQNaN_LONG; break;
151 case fmt_ps: value = FPQNaN_PS; break;
152 default: err = -1; break;
153 }
154 }
155 else if (SizeFGR () == 64)
156 {
157 switch (fmt)
158 {
159 case fmt_single:
160 case fmt_word:
161 value = (FGR[fpr] & 0xFFFFFFFF);
162 break;
163
164 case fmt_uninterpreted:
165 case fmt_double:
166 case fmt_long:
167 case fmt_ps:
168 value = FGR[fpr];
169 break;
170
171 default:
172 err = -1;
173 break;
174 }
175 }
176 else
177 {
178 switch (fmt)
179 {
180 case fmt_single:
181 case fmt_word:
182 value = (FGR[fpr] & 0xFFFFFFFF);
183 break;
184
185 case fmt_uninterpreted:
186 case fmt_double:
187 case fmt_long:
188 if ((fpr & 1) == 0)
189 {
190 /* Even register numbers only. */
191 #ifdef DEBUG
192 printf ("DBG: ValueFPR: FGR[%d] = %s, FGR[%d] = %s\n",
193 fpr + 1, pr_uword64 ((uword64) FGR[fpr+1]),
194 fpr, pr_uword64 ((uword64) FGR[fpr]));
195 #endif
196 value = ((((uword64) FGR[fpr+1]) << 32)
197 | (FGR[fpr] & 0xFFFFFFFF));
198 }
199 else
200 {
201 SignalException (ReservedInstruction, 0);
202 }
203 break;
204
205 case fmt_ps:
206 SignalException (ReservedInstruction, 0);
207 break;
208
209 default:
210 err = -1;
211 break;
212 }
213 }
214
215 if (err)
216 SignalExceptionSimulatorFault ("Unrecognised FP format in ValueFPR ()");
217
218 #ifdef DEBUG
219 printf ("DBG: ValueFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR () = %d\n",
220 fpr, fpu_format_name (fmt), pr_uword64 (value), pr_addr (cia),
221 SizeFGR ());
222 #endif /* DEBUG */
223
224 return (value);
225 }
226
227 void
228 store_fpr (sim_cpu *cpu,
229 address_word cia,
230 int fpr,
231 FP_formats fmt,
232 uword64 value)
233 {
234 int err = 0;
235
236 #ifdef DEBUG
237 printf ("DBG: StoreFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR () = %d, \n",
238 fpr, fpu_format_name (fmt), pr_uword64 (value), pr_addr (cia),
239 SizeFGR ());
240 #endif /* DEBUG */
241
242 if (SizeFGR () == 64)
243 {
244 switch (fmt)
245 {
246 case fmt_uninterpreted_32:
247 fmt = fmt_uninterpreted;
248 case fmt_single:
249 case fmt_word:
250 if (STATE_VERBOSE_P (SD))
251 sim_io_eprintf (SD,
252 "Warning: PC 0x%s: interp.c store_fpr DEADCODE\n",
253 pr_addr (cia));
254 FGR[fpr] = (((uword64) 0xDEADC0DE << 32) | (value & 0xFFFFFFFF));
255 FPR_STATE[fpr] = fmt;
256 break;
257
258 case fmt_uninterpreted_64:
259 fmt = fmt_uninterpreted;
260 case fmt_uninterpreted:
261 case fmt_double:
262 case fmt_long:
263 case fmt_ps:
264 FGR[fpr] = value;
265 FPR_STATE[fpr] = fmt;
266 break;
267
268 default:
269 FPR_STATE[fpr] = fmt_unknown;
270 err = -1;
271 break;
272 }
273 }
274 else
275 {
276 switch (fmt)
277 {
278 case fmt_uninterpreted_32:
279 fmt = fmt_uninterpreted;
280 case fmt_single:
281 case fmt_word:
282 FGR[fpr] = (value & 0xFFFFFFFF);
283 FPR_STATE[fpr] = fmt;
284 break;
285
286 case fmt_uninterpreted_64:
287 fmt = fmt_uninterpreted;
288 case fmt_uninterpreted:
289 case fmt_double:
290 case fmt_long:
291 if ((fpr & 1) == 0)
292 {
293 /* Even register numbers only. */
294 FGR[fpr+1] = (value >> 32);
295 FGR[fpr] = (value & 0xFFFFFFFF);
296 FPR_STATE[fpr + 1] = fmt;
297 FPR_STATE[fpr] = fmt;
298 }
299 else
300 {
301 FPR_STATE[fpr] = fmt_unknown;
302 FPR_STATE[fpr + 1] = fmt_unknown;
303 SignalException (ReservedInstruction, 0);
304 }
305 break;
306
307 case fmt_ps:
308 FPR_STATE[fpr] = fmt_unknown;
309 SignalException (ReservedInstruction, 0);
310 break;
311
312 default:
313 FPR_STATE[fpr] = fmt_unknown;
314 err = -1;
315 break;
316 }
317 }
318
319 if (err)
320 SignalExceptionSimulatorFault ("Unrecognised FP format in StoreFPR ()");
321
322 #ifdef DEBUG
323 printf ("DBG: StoreFPR: fpr[%d] = 0x%s (format %s)\n",
324 fpr, pr_uword64 (FGR[fpr]), fpu_format_name (fmt));
325 #endif /* DEBUG */
326
327 return;
328 }
329
330
331 /* CP1 control/status register access functions. */
332
333 void
334 test_fcsr (sim_cpu *cpu,
335 address_word cia)
336 {
337 unsigned int cause;
338
339 cause = (FCSR & fcsr_CAUSE_mask) >> fcsr_CAUSE_shift;
340 if ((cause & ((FCSR & fcsr_ENABLES_mask) >> fcsr_ENABLES_shift)) != 0
341 || (cause & (1 << UO)))
342 {
343 SignalExceptionFPE();
344 }
345 }
346
347 unsigned_word
348 value_fcr(sim_cpu *cpu,
349 address_word cia,
350 int fcr)
351 {
352 unsigned32 value = 0;
353
354 switch (fcr)
355 {
356 case 0: /* FP Implementation and Revision Register. */
357 value = FCR0;
358 break;
359 case 25: /* FP Condition Codes Register (derived from FCSR). */
360 value = (FCR31 & fcsr_FCC_mask) >> fcsr_FCC_shift;
361 value = (value & 0x1) | (value >> 1); /* Close FCC gap. */
362 break;
363 case 26: /* FP Exceptions Register (derived from FCSR). */
364 value = FCR31 & (fcsr_CAUSE_mask | fcsr_FLAGS_mask);
365 break;
366 case 28: /* FP Enables Register (derived from FCSR). */
367 value = FCR31 & (fcsr_ENABLES_mask | fcsr_RM_mask);
368 if ((FCR31 & fcsr_FS) != 0)
369 value |= fenr_FS;
370 break;
371 case 31: /* FP Control/Status Register (FCSR). */
372 value = FCR31 & ~fcsr_ZERO_mask;
373 break;
374 }
375
376 return (EXTEND32 (value));
377 }
378
379 void
380 store_fcr(sim_cpu *cpu,
381 address_word cia,
382 int fcr,
383 unsigned_word value)
384 {
385 unsigned32 v;
386
387 v = VL4_8(value);
388 switch (fcr)
389 {
390 case 25: /* FP Condition Codes Register (stored into FCSR). */
391 v = (v << 1) | (v & 0x1); /* Adjust for FCC gap. */
392 FCR31 &= ~fcsr_FCC_mask;
393 FCR31 |= ((v << fcsr_FCC_shift) & fcsr_FCC_mask);
394 break;
395 case 26: /* FP Exceptions Register (stored into FCSR). */
396 FCR31 &= ~(fcsr_CAUSE_mask | fcsr_FLAGS_mask);
397 FCR31 |= (v & (fcsr_CAUSE_mask | fcsr_FLAGS_mask));
398 test_fcsr(cpu, cia);
399 break;
400 case 28: /* FP Enables Register (stored into FCSR). */
401 if ((v & fenr_FS) != 0)
402 v |= fcsr_FS;
403 else
404 v &= ~fcsr_FS;
405 FCR31 &= (fcsr_FCC_mask | fcsr_CAUSE_mask | fcsr_FLAGS_mask);
406 FCR31 |= (v & (fcsr_FS | fcsr_ENABLES_mask | fcsr_RM_mask));
407 test_fcsr(cpu, cia);
408 break;
409 case 31: /* FP Control/Status Register (FCSR). */
410 FCR31 = v & ~fcsr_ZERO_mask;
411 test_fcsr(cpu, cia);
412 break;
413 }
414 }
415
416 void
417 update_fcsr (sim_cpu *cpu,
418 address_word cia,
419 sim_fpu_status status)
420 {
421 FCSR &= ~fcsr_CAUSE_mask;
422
423 if (status != 0)
424 {
425 unsigned int cause = 0;
426
427 /* map between sim_fpu codes and MIPS FCSR */
428 if (status & (sim_fpu_status_invalid_snan
429 | sim_fpu_status_invalid_isi
430 | sim_fpu_status_invalid_idi
431 | sim_fpu_status_invalid_zdz
432 | sim_fpu_status_invalid_imz
433 | sim_fpu_status_invalid_cmp
434 | sim_fpu_status_invalid_sqrt
435 | sim_fpu_status_invalid_cvi))
436 cause |= (1 << IO);
437 if (status & sim_fpu_status_invalid_div0)
438 cause |= (1 << DZ);
439 if (status & sim_fpu_status_overflow)
440 cause |= (1 << OF);
441 if (status & sim_fpu_status_underflow)
442 cause |= (1 << UF);
443 if (status & sim_fpu_status_inexact)
444 cause |= (1 << IR);
445 #if 0 /* Not yet. */
446 /* Implicit clearing of other bits by unimplemented done by callers. */
447 if (status & sim_fpu_status_unimplemented)
448 cause |= (1 << UO);
449 #endif
450
451 FCSR |= (cause << fcsr_CAUSE_shift);
452 test_fcsr (cpu, cia);
453 FCSR |= ((cause & ~(1 << UO)) << fcsr_FLAGS_shift);
454 }
455 return;
456 }
457
458 static sim_fpu_round
459 rounding_mode(int rm)
460 {
461 sim_fpu_round round;
462
463 switch (rm)
464 {
465 case FP_RM_NEAREST:
466 /* Round result to nearest representable value. When two
467 representable values are equally near, round to the value
468 that has a least significant bit of zero (i.e. is even). */
469 round = sim_fpu_round_near;
470 break;
471 case FP_RM_TOZERO:
472 /* Round result to the value closest to, and not greater in
473 magnitude than, the result. */
474 round = sim_fpu_round_zero;
475 break;
476 case FP_RM_TOPINF:
477 /* Round result to the value closest to, and not less than,
478 the result. */
479 round = sim_fpu_round_up;
480 break;
481 case FP_RM_TOMINF:
482 /* Round result to the value closest to, and not greater than,
483 the result. */
484 round = sim_fpu_round_down;
485 break;
486 default:
487 round = 0;
488 fprintf (stderr, "Bad switch\n");
489 abort ();
490 }
491 return round;
492 }
493
494 /* When the FS bit is set, MIPS processors return zero for
495 denormalized results and optionally replace denormalized inputs
496 with zero. When FS is clear, some implementation trap on input
497 and/or output, while other perform the operation in hardware. */
498 static sim_fpu_denorm
499 denorm_mode(sim_cpu *cpu)
500 {
501 sim_fpu_denorm denorm;
502
503 /* XXX: FIXME: Eventually should be CPU model dependent. */
504 if (GETFS())
505 denorm = sim_fpu_denorm_zero;
506 else
507 denorm = 0;
508 return denorm;
509 }
510
511
512 /* Comparison operations. */
513
514 static sim_fpu_status
515 fp_test(unsigned64 op1,
516 unsigned64 op2,
517 FP_formats fmt,
518 int abs,
519 int cond,
520 int *condition)
521 {
522 sim_fpu wop1;
523 sim_fpu wop2;
524 sim_fpu_status status = 0;
525 int less, equal, unordered;
526
527 /* The format type has already been checked: */
528 switch (fmt)
529 {
530 case fmt_single:
531 {
532 sim_fpu_32to (&wop1, op1);
533 sim_fpu_32to (&wop2, op2);
534 break;
535 }
536 case fmt_double:
537 {
538 sim_fpu_64to (&wop1, op1);
539 sim_fpu_64to (&wop2, op2);
540 break;
541 }
542 default:
543 fprintf (stderr, "Bad switch\n");
544 abort ();
545 }
546
547 if (sim_fpu_is_nan (&wop1) || sim_fpu_is_nan (&wop2))
548 {
549 if ((cond & (1 << 3)) ||
550 sim_fpu_is_snan (&wop1) || sim_fpu_is_snan (&wop2))
551 status = sim_fpu_status_invalid_snan;
552 less = 0;
553 equal = 0;
554 unordered = 1;
555 }
556 else
557 {
558 if (abs)
559 {
560 status |= sim_fpu_abs (&wop1, &wop1);
561 status |= sim_fpu_abs (&wop2, &wop2);
562 }
563 equal = sim_fpu_is_eq (&wop1, &wop2);
564 less = !equal && sim_fpu_is_lt (&wop1, &wop2);
565 unordered = 0;
566 }
567 *condition = (((cond & (1 << 2)) && less)
568 || ((cond & (1 << 1)) && equal)
569 || ((cond & (1 << 0)) && unordered));
570 return status;
571 }
572
573 void
574 fp_cmp(sim_cpu *cpu,
575 address_word cia,
576 unsigned64 op1,
577 unsigned64 op2,
578 FP_formats fmt,
579 int abs,
580 int cond,
581 int cc)
582 {
583 sim_fpu_status status = 0;
584
585 /* The format type should already have been checked. The FCSR is
586 updated before the condition codes so that any exceptions will
587 be signalled before the condition codes are changed. */
588 switch (fmt)
589 {
590 case fmt_single:
591 case fmt_double:
592 {
593 int result;
594 status = fp_test(op1, op2, fmt, abs, cond, &result);
595 update_fcsr (cpu, cia, status);
596 SETFCC (cc, result);
597 break;
598 }
599 case fmt_ps:
600 {
601 int result0, result1;
602 status = fp_test(FP_PS_lower (op1), FP_PS_lower (op2), fmt_single,
603 abs, cond, &result0);
604 status |= fp_test(FP_PS_upper (op1), FP_PS_upper (op2), fmt_single,
605 abs, cond, &result1);
606 update_fcsr (cpu, cia, status);
607 SETFCC (cc, result0);
608 SETFCC (cc+1, result1);
609 break;
610 }
611 default:
612 sim_io_eprintf (SD, "Bad switch\n");
613 abort ();
614 }
615 }
616
617
618 /* Basic arithmetic operations. */
619
620 static unsigned64
621 fp_unary(sim_cpu *cpu,
622 address_word cia,
623 int (*sim_fpu_op)(sim_fpu *, const sim_fpu *),
624 unsigned64 op,
625 FP_formats fmt)
626 {
627 sim_fpu wop;
628 sim_fpu ans;
629 sim_fpu_round round = rounding_mode (GETRM());
630 sim_fpu_denorm denorm = denorm_mode (cpu);
631 sim_fpu_status status = 0;
632 unsigned64 result = 0;
633
634 /* The format type has already been checked: */
635 switch (fmt)
636 {
637 case fmt_single:
638 {
639 unsigned32 res;
640 sim_fpu_32to (&wop, op);
641 status |= (*sim_fpu_op) (&ans, &wop);
642 status |= sim_fpu_round_32 (&ans, round, denorm);
643 sim_fpu_to32 (&res, &ans);
644 result = res;
645 break;
646 }
647 case fmt_double:
648 {
649 unsigned64 res;
650 sim_fpu_64to (&wop, op);
651 status |= (*sim_fpu_op) (&ans, &wop);
652 status |= sim_fpu_round_64 (&ans, round, denorm);
653 sim_fpu_to64 (&res, &ans);
654 result = res;
655 break;
656 }
657 case fmt_ps:
658 {
659 int status_u = 0, status_l = 0;
660 unsigned32 res_u, res_l;
661 sim_fpu_32to (&wop, FP_PS_upper(op));
662 status_u |= (*sim_fpu_op) (&ans, &wop);
663 sim_fpu_to32 (&res_u, &ans);
664 sim_fpu_32to (&wop, FP_PS_lower(op));
665 status_l |= (*sim_fpu_op) (&ans, &wop);
666 sim_fpu_to32 (&res_l, &ans);
667 result = FP_PS_cat(res_u, res_l);
668 status = status_u | status_l;
669 break;
670 }
671 default:
672 sim_io_eprintf (SD, "Bad switch\n");
673 abort ();
674 }
675
676 update_fcsr (cpu, cia, status);
677 return result;
678 }
679
680 static unsigned64
681 fp_binary(sim_cpu *cpu,
682 address_word cia,
683 int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *),
684 unsigned64 op1,
685 unsigned64 op2,
686 FP_formats fmt)
687 {
688 sim_fpu wop1;
689 sim_fpu wop2;
690 sim_fpu ans;
691 sim_fpu_round round = rounding_mode (GETRM());
692 sim_fpu_denorm denorm = denorm_mode (cpu);
693 sim_fpu_status status = 0;
694 unsigned64 result = 0;
695
696 /* The format type has already been checked: */
697 switch (fmt)
698 {
699 case fmt_single:
700 {
701 unsigned32 res;
702 sim_fpu_32to (&wop1, op1);
703 sim_fpu_32to (&wop2, op2);
704 status |= (*sim_fpu_op) (&ans, &wop1, &wop2);
705 status |= sim_fpu_round_32 (&ans, round, denorm);
706 sim_fpu_to32 (&res, &ans);
707 result = res;
708 break;
709 }
710 case fmt_double:
711 {
712 unsigned64 res;
713 sim_fpu_64to (&wop1, op1);
714 sim_fpu_64to (&wop2, op2);
715 status |= (*sim_fpu_op) (&ans, &wop1, &wop2);
716 status |= sim_fpu_round_64 (&ans, round, denorm);
717 sim_fpu_to64 (&res, &ans);
718 result = res;
719 break;
720 }
721 case fmt_ps:
722 {
723 int status_u = 0, status_l = 0;
724 unsigned32 res_u, res_l;
725 sim_fpu_32to (&wop1, FP_PS_upper(op1));
726 sim_fpu_32to (&wop2, FP_PS_upper(op2));
727 status_u |= (*sim_fpu_op) (&ans, &wop1, &wop2);
728 sim_fpu_to32 (&res_u, &ans);
729 sim_fpu_32to (&wop1, FP_PS_lower(op1));
730 sim_fpu_32to (&wop2, FP_PS_lower(op2));
731 status_l |= (*sim_fpu_op) (&ans, &wop1, &wop2);
732 sim_fpu_to32 (&res_l, &ans);
733 result = FP_PS_cat(res_u, res_l);
734 status = status_u | status_l;
735 break;
736 }
737 default:
738 sim_io_eprintf (SD, "Bad switch\n");
739 abort ();
740 }
741
742 update_fcsr (cpu, cia, status);
743 return result;
744 }
745
746 /* Common MAC code for single operands (.s or .d), defers setting FCSR. */
747 static sim_fpu_status
748 inner_mac(int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *),
749 unsigned64 op1,
750 unsigned64 op2,
751 unsigned64 op3,
752 int scale,
753 int negate,
754 FP_formats fmt,
755 sim_fpu_round round,
756 sim_fpu_denorm denorm,
757 unsigned64 *result)
758 {
759 sim_fpu wop1;
760 sim_fpu wop2;
761 sim_fpu ans;
762 sim_fpu_status status = 0;
763 sim_fpu_status op_status;
764 unsigned64 temp = 0;
765
766 switch (fmt)
767 {
768 case fmt_single:
769 {
770 unsigned32 res;
771 sim_fpu_32to (&wop1, op1);
772 sim_fpu_32to (&wop2, op2);
773 status |= sim_fpu_mul (&ans, &wop1, &wop2);
774 if (scale != 0 && sim_fpu_is_number (&ans)) /* number or denorm */
775 ans.normal_exp += scale;
776 status |= sim_fpu_round_32 (&ans, round, denorm);
777 wop1 = ans;
778 op_status = 0;
779 sim_fpu_32to (&wop2, op3);
780 op_status |= (*sim_fpu_op) (&ans, &wop1, &wop2);
781 op_status |= sim_fpu_round_32 (&ans, round, denorm);
782 status |= op_status;
783 if (negate)
784 {
785 wop1 = ans;
786 op_status = sim_fpu_neg (&ans, &wop1);
787 op_status |= sim_fpu_round_32 (&ans, round, denorm);
788 status |= op_status;
789 }
790 sim_fpu_to32 (&res, &ans);
791 temp = res;
792 break;
793 }
794 case fmt_double:
795 {
796 unsigned64 res;
797 sim_fpu_64to (&wop1, op1);
798 sim_fpu_64to (&wop2, op2);
799 status |= sim_fpu_mul (&ans, &wop1, &wop2);
800 if (scale != 0 && sim_fpu_is_number (&ans)) /* number or denorm */
801 ans.normal_exp += scale;
802 status |= sim_fpu_round_64 (&ans, round, denorm);
803 wop1 = ans;
804 op_status = 0;
805 sim_fpu_64to (&wop2, op3);
806 op_status |= (*sim_fpu_op) (&ans, &wop1, &wop2);
807 op_status |= sim_fpu_round_64 (&ans, round, denorm);
808 status |= op_status;
809 if (negate)
810 {
811 wop1 = ans;
812 op_status = sim_fpu_neg (&ans, &wop1);
813 op_status |= sim_fpu_round_64 (&ans, round, denorm);
814 status |= op_status;
815 }
816 sim_fpu_to64 (&res, &ans);
817 temp = res;
818 break;
819 }
820 default:
821 fprintf (stderr, "Bad switch\n");
822 abort ();
823 }
824 *result = temp;
825 return status;
826 }
827
828 /* Common implementation of madd, nmadd, msub, nmsub that does
829 intermediate rounding per spec. Also used for recip2 and rsqrt2,
830 which are transformed into equivalent nmsub operations. The scale
831 argument is an adjustment to the exponent of the intermediate
832 product op1*op2. It is currently non-zero for rsqrt2 (-1), which
833 requires an effective division by 2. */
834 static unsigned64
835 fp_mac(sim_cpu *cpu,
836 address_word cia,
837 int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *),
838 unsigned64 op1,
839 unsigned64 op2,
840 unsigned64 op3,
841 int scale,
842 int negate,
843 FP_formats fmt)
844 {
845 sim_fpu_round round = rounding_mode (GETRM());
846 sim_fpu_denorm denorm = denorm_mode (cpu);
847 sim_fpu_status status = 0;
848 unsigned64 result = 0;
849
850 /* The format type has already been checked: */
851 switch (fmt)
852 {
853 case fmt_single:
854 case fmt_double:
855 status = inner_mac(sim_fpu_op, op1, op2, op3, scale,
856 negate, fmt, round, denorm, &result);
857 break;
858 case fmt_ps:
859 {
860 int status_u, status_l;
861 unsigned64 result_u, result_l;
862 status_u = inner_mac(sim_fpu_op, FP_PS_upper(op1), FP_PS_upper(op2),
863 FP_PS_upper(op3), scale, negate, fmt_single,
864 round, denorm, &result_u);
865 status_l = inner_mac(sim_fpu_op, FP_PS_lower(op1), FP_PS_lower(op2),
866 FP_PS_lower(op3), scale, negate, fmt_single,
867 round, denorm, &result_l);
868 result = FP_PS_cat(result_u, result_l);
869 status = status_u | status_l;
870 break;
871 }
872 default:
873 sim_io_eprintf (SD, "Bad switch\n");
874 abort ();
875 }
876
877 update_fcsr (cpu, cia, status);
878 return result;
879 }
880
881 /* Common rsqrt code for single operands (.s or .d), intermediate rounding. */
882 static sim_fpu_status
883 inner_rsqrt(unsigned64 op1,
884 FP_formats fmt,
885 sim_fpu_round round,
886 sim_fpu_denorm denorm,
887 unsigned64 *result)
888 {
889 sim_fpu wop1;
890 sim_fpu ans;
891 sim_fpu_status status = 0;
892 sim_fpu_status op_status;
893 unsigned64 temp = 0;
894
895 switch (fmt)
896 {
897 case fmt_single:
898 {
899 unsigned32 res;
900 sim_fpu_32to (&wop1, op1);
901 status |= sim_fpu_sqrt (&ans, &wop1);
902 status |= sim_fpu_round_32 (&ans, status, round);
903 wop1 = ans;
904 op_status = sim_fpu_inv (&ans, &wop1);
905 op_status |= sim_fpu_round_32 (&ans, round, denorm);
906 sim_fpu_to32 (&res, &ans);
907 temp = res;
908 status |= op_status;
909 break;
910 }
911 case fmt_double:
912 {
913 unsigned64 res;
914 sim_fpu_64to (&wop1, op1);
915 status |= sim_fpu_sqrt (&ans, &wop1);
916 status |= sim_fpu_round_64 (&ans, round, denorm);
917 wop1 = ans;
918 op_status = sim_fpu_inv (&ans, &wop1);
919 op_status |= sim_fpu_round_64 (&ans, round, denorm);
920 sim_fpu_to64 (&res, &ans);
921 temp = res;
922 status |= op_status;
923 break;
924 }
925 default:
926 fprintf (stderr, "Bad switch\n");
927 abort ();
928 }
929 *result = temp;
930 return status;
931 }
932
933 static unsigned64
934 fp_inv_sqrt(sim_cpu *cpu,
935 address_word cia,
936 unsigned64 op1,
937 FP_formats fmt)
938 {
939 sim_fpu_round round = rounding_mode (GETRM());
940 sim_fpu_round denorm = denorm_mode (cpu);
941 sim_fpu_status status = 0;
942 unsigned64 result = 0;
943
944 /* The format type has already been checked: */
945 switch (fmt)
946 {
947 case fmt_single:
948 case fmt_double:
949 status = inner_rsqrt (op1, fmt, round, denorm, &result);
950 break;
951 case fmt_ps:
952 {
953 int status_u, status_l;
954 unsigned64 result_u, result_l;
955 status_u = inner_rsqrt (FP_PS_upper(op1), fmt_single, round, denorm,
956 &result_u);
957 status_l = inner_rsqrt (FP_PS_lower(op1), fmt_single, round, denorm,
958 &result_l);
959 result = FP_PS_cat(result_u, result_l);
960 status = status_u | status_l;
961 break;
962 }
963 default:
964 sim_io_eprintf (SD, "Bad switch\n");
965 abort ();
966 }
967
968 update_fcsr (cpu, cia, status);
969 return result;
970 }
971
972
973 unsigned64
974 fp_abs(sim_cpu *cpu,
975 address_word cia,
976 unsigned64 op,
977 FP_formats fmt)
978 {
979 return fp_unary(cpu, cia, &sim_fpu_abs, op, fmt);
980 }
981
982 unsigned64
983 fp_neg(sim_cpu *cpu,
984 address_word cia,
985 unsigned64 op,
986 FP_formats fmt)
987 {
988 return fp_unary(cpu, cia, &sim_fpu_neg, op, fmt);
989 }
990
991 unsigned64
992 fp_add(sim_cpu *cpu,
993 address_word cia,
994 unsigned64 op1,
995 unsigned64 op2,
996 FP_formats fmt)
997 {
998 return fp_binary(cpu, cia, &sim_fpu_add, op1, op2, fmt);
999 }
1000
1001 unsigned64
1002 fp_sub(sim_cpu *cpu,
1003 address_word cia,
1004 unsigned64 op1,
1005 unsigned64 op2,
1006 FP_formats fmt)
1007 {
1008 return fp_binary(cpu, cia, &sim_fpu_sub, op1, op2, fmt);
1009 }
1010
1011 unsigned64
1012 fp_mul(sim_cpu *cpu,
1013 address_word cia,
1014 unsigned64 op1,
1015 unsigned64 op2,
1016 FP_formats fmt)
1017 {
1018 return fp_binary(cpu, cia, &sim_fpu_mul, op1, op2, fmt);
1019 }
1020
1021 unsigned64
1022 fp_div(sim_cpu *cpu,
1023 address_word cia,
1024 unsigned64 op1,
1025 unsigned64 op2,
1026 FP_formats fmt)
1027 {
1028 return fp_binary(cpu, cia, &sim_fpu_div, op1, op2, fmt);
1029 }
1030
1031 unsigned64
1032 fp_recip(sim_cpu *cpu,
1033 address_word cia,
1034 unsigned64 op,
1035 FP_formats fmt)
1036 {
1037 return fp_unary(cpu, cia, &sim_fpu_inv, op, fmt);
1038 }
1039
1040 unsigned64
1041 fp_sqrt(sim_cpu *cpu,
1042 address_word cia,
1043 unsigned64 op,
1044 FP_formats fmt)
1045 {
1046 return fp_unary(cpu, cia, &sim_fpu_sqrt, op, fmt);
1047 }
1048
1049 unsigned64
1050 fp_rsqrt(sim_cpu *cpu,
1051 address_word cia,
1052 unsigned64 op,
1053 FP_formats fmt)
1054 {
1055 return fp_inv_sqrt(cpu, cia, op, fmt);
1056 }
1057
1058 unsigned64
1059 fp_madd(sim_cpu *cpu,
1060 address_word cia,
1061 unsigned64 op1,
1062 unsigned64 op2,
1063 unsigned64 op3,
1064 FP_formats fmt)
1065 {
1066 return fp_mac(cpu, cia, &sim_fpu_add, op1, op2, op3, 0, 0, fmt);
1067 }
1068
1069 unsigned64
1070 fp_msub(sim_cpu *cpu,
1071 address_word cia,
1072 unsigned64 op1,
1073 unsigned64 op2,
1074 unsigned64 op3,
1075 FP_formats fmt)
1076 {
1077 return fp_mac(cpu, cia, &sim_fpu_sub, op1, op2, op3, 0, 0, fmt);
1078 }
1079
1080 unsigned64
1081 fp_nmadd(sim_cpu *cpu,
1082 address_word cia,
1083 unsigned64 op1,
1084 unsigned64 op2,
1085 unsigned64 op3,
1086 FP_formats fmt)
1087 {
1088 return fp_mac(cpu, cia, &sim_fpu_add, op1, op2, op3, 0, 1, fmt);
1089 }
1090
1091 unsigned64
1092 fp_nmsub(sim_cpu *cpu,
1093 address_word cia,
1094 unsigned64 op1,
1095 unsigned64 op2,
1096 unsigned64 op3,
1097 FP_formats fmt)
1098 {
1099 return fp_mac(cpu, cia, &sim_fpu_sub, op1, op2, op3, 0, 1, fmt);
1100 }
1101
1102
1103 /* MIPS-3D ASE operations. */
1104
1105 /* Variant of fp_binary for *r.ps MIPS-3D operations. */
1106 static unsigned64
1107 fp_binary_r(sim_cpu *cpu,
1108 address_word cia,
1109 int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *),
1110 unsigned64 op1,
1111 unsigned64 op2)
1112 {
1113 sim_fpu wop1;
1114 sim_fpu wop2;
1115 sim_fpu ans;
1116 sim_fpu_round round = rounding_mode (GETRM ());
1117 sim_fpu_denorm denorm = denorm_mode (cpu);
1118 sim_fpu_status status_u, status_l;
1119 unsigned64 result;
1120 unsigned32 res_u, res_l;
1121
1122 /* The format must be fmt_ps. */
1123 status_u = 0;
1124 sim_fpu_32to (&wop1, FP_PS_upper (op1));
1125 sim_fpu_32to (&wop2, FP_PS_lower (op1));
1126 status_u |= (*sim_fpu_op) (&ans, &wop1, &wop2);
1127 status_u |= sim_fpu_round_32 (&ans, round, denorm);
1128 sim_fpu_to32 (&res_u, &ans);
1129 status_l = 0;
1130 sim_fpu_32to (&wop1, FP_PS_upper (op2));
1131 sim_fpu_32to (&wop2, FP_PS_lower (op2));
1132 status_l |= (*sim_fpu_op) (&ans, &wop1, &wop2);
1133 status_l |= sim_fpu_round_32 (&ans, round, denorm);
1134 sim_fpu_to32 (&res_l, &ans);
1135 result = FP_PS_cat (res_u, res_l);
1136
1137 update_fcsr (cpu, cia, status_u | status_l);
1138 return result;
1139 }
1140
1141 unsigned64
1142 fp_add_r(sim_cpu *cpu,
1143 address_word cia,
1144 unsigned64 op1,
1145 unsigned64 op2,
1146 FP_formats fmt)
1147 {
1148 return fp_binary_r (cpu, cia, &sim_fpu_add, op1, op2);
1149 }
1150
1151 unsigned64
1152 fp_mul_r(sim_cpu *cpu,
1153 address_word cia,
1154 unsigned64 op1,
1155 unsigned64 op2,
1156 FP_formats fmt)
1157 {
1158 return fp_binary_r (cpu, cia, &sim_fpu_mul, op1, op2);
1159 }
1160
1161 #define NR_FRAC_GUARD (60)
1162 #define IMPLICIT_1 LSBIT64 (NR_FRAC_GUARD)
1163
1164 static int
1165 fpu_inv1(sim_fpu *f, const sim_fpu *l)
1166 {
1167 static const sim_fpu sim_fpu_one = {
1168 sim_fpu_class_number, 0, IMPLICIT_1, 0
1169 };
1170 int status = 0;
1171 sim_fpu t;
1172
1173 if (sim_fpu_is_zero (l))
1174 {
1175 *f = sim_fpu_maxfp;
1176 f->sign = l->sign;
1177 return sim_fpu_status_invalid_div0;
1178 }
1179 if (sim_fpu_is_infinity (l))
1180 {
1181 *f = sim_fpu_zero;
1182 f->sign = l->sign;
1183 return status;
1184 }
1185 status |= sim_fpu_div (f, &sim_fpu_one, l);
1186 return status;
1187 }
1188
1189 static int
1190 fpu_inv1_32(sim_fpu *f, const sim_fpu *l)
1191 {
1192 if (sim_fpu_is_zero (l))
1193 {
1194 *f = sim_fpu_max32;
1195 f->sign = l->sign;
1196 return sim_fpu_status_invalid_div0;
1197 }
1198 return fpu_inv1 (f, l);
1199 }
1200
1201 static int
1202 fpu_inv1_64(sim_fpu *f, const sim_fpu *l)
1203 {
1204 if (sim_fpu_is_zero (l))
1205 {
1206 *f = sim_fpu_max64;
1207 f->sign = l->sign;
1208 return sim_fpu_status_invalid_div0;
1209 }
1210 return fpu_inv1 (f, l);
1211 }
1212
1213 unsigned64
1214 fp_recip1(sim_cpu *cpu,
1215 address_word cia,
1216 unsigned64 op,
1217 FP_formats fmt)
1218 {
1219 switch (fmt)
1220 {
1221 case fmt_single:
1222 case fmt_ps:
1223 return fp_unary (cpu, cia, &fpu_inv1_32, op, fmt);
1224 case fmt_double:
1225 return fp_unary (cpu, cia, &fpu_inv1_64, op, fmt);
1226 }
1227 return 0;
1228 }
1229
1230 unsigned64
1231 fp_recip2(sim_cpu *cpu,
1232 address_word cia,
1233 unsigned64 op1,
1234 unsigned64 op2,
1235 FP_formats fmt)
1236 {
1237 static const unsigned64 one_single = UNSIGNED64 (0x3F800000);
1238 static const unsigned64 one_double = UNSIGNED64 (0x3FF0000000000000);
1239 static const unsigned64 one_ps = (UNSIGNED64 (0x3F800000) << 32 | UNSIGNED64 (0x3F800000));
1240 unsigned64 one;
1241
1242 /* Implemented as nmsub fd, 1, fs, ft. */
1243 switch (fmt)
1244 {
1245 case fmt_single: one = one_single; break;
1246 case fmt_double: one = one_double; break;
1247 case fmt_ps: one = one_ps; break;
1248 default: one = 0; abort ();
1249 }
1250 return fp_mac (cpu, cia, &sim_fpu_sub, op1, op2, one, 0, 1, fmt);
1251 }
1252
1253 static int
1254 fpu_inv_sqrt1(sim_fpu *f, const sim_fpu *l)
1255 {
1256 static const sim_fpu sim_fpu_one = {
1257 sim_fpu_class_number, 0, IMPLICIT_1, 0
1258 };
1259 int status = 0;
1260 sim_fpu t;
1261
1262 if (sim_fpu_is_zero (l))
1263 {
1264 *f = sim_fpu_maxfp;
1265 f->sign = l->sign;
1266 return sim_fpu_status_invalid_div0;
1267 }
1268 if (sim_fpu_is_infinity (l))
1269 {
1270 if (!l->sign)
1271 {
1272 f->class = sim_fpu_class_zero;
1273 f->sign = 0;
1274 }
1275 else
1276 {
1277 *f = sim_fpu_qnan;
1278 status = sim_fpu_status_invalid_sqrt;
1279 }
1280 return status;
1281 }
1282 status |= sim_fpu_sqrt (&t, l);
1283 status |= sim_fpu_div (f, &sim_fpu_one, &t);
1284 return status;
1285 }
1286
1287 static int
1288 fpu_inv_sqrt1_32(sim_fpu *f, const sim_fpu *l)
1289 {
1290 if (sim_fpu_is_zero (l))
1291 {
1292 *f = sim_fpu_max32;
1293 f->sign = l->sign;
1294 return sim_fpu_status_invalid_div0;
1295 }
1296 return fpu_inv_sqrt1 (f, l);
1297 }
1298
1299 static int
1300 fpu_inv_sqrt1_64(sim_fpu *f, const sim_fpu *l)
1301 {
1302 if (sim_fpu_is_zero (l))
1303 {
1304 *f = sim_fpu_max64;
1305 f->sign = l->sign;
1306 return sim_fpu_status_invalid_div0;
1307 }
1308 return fpu_inv_sqrt1 (f, l);
1309 }
1310
1311 unsigned64
1312 fp_rsqrt1(sim_cpu *cpu,
1313 address_word cia,
1314 unsigned64 op,
1315 FP_formats fmt)
1316 {
1317 switch (fmt)
1318 {
1319 case fmt_single:
1320 case fmt_ps:
1321 return fp_unary (cpu, cia, &fpu_inv_sqrt1_32, op, fmt);
1322 case fmt_double:
1323 return fp_unary (cpu, cia, &fpu_inv_sqrt1_64, op, fmt);
1324 }
1325 return 0;
1326 }
1327
1328 unsigned64
1329 fp_rsqrt2(sim_cpu *cpu,
1330 address_word cia,
1331 unsigned64 op1,
1332 unsigned64 op2,
1333 FP_formats fmt)
1334 {
1335 static const unsigned64 half_single = UNSIGNED64 (0x3F000000);
1336 static const unsigned64 half_double = UNSIGNED64 (0x3FE0000000000000);
1337 static const unsigned64 half_ps = (UNSIGNED64 (0x3F000000) << 32 | UNSIGNED64 (0x3F000000));
1338 unsigned64 half;
1339
1340 /* Implemented as (nmsub fd, 0.5, fs, ft)/2, where the divide is
1341 done by scaling the exponent during multiply. */
1342 switch (fmt)
1343 {
1344 case fmt_single: half = half_single; break;
1345 case fmt_double: half = half_double; break;
1346 case fmt_ps: half = half_ps; break;
1347 default: half = 0; abort ();
1348 }
1349 return fp_mac (cpu, cia, &sim_fpu_sub, op1, op2, half, -1, 1, fmt);
1350 }
1351
1352
1353 /* Conversion operations. */
1354
1355 uword64
1356 convert (sim_cpu *cpu,
1357 address_word cia,
1358 int rm,
1359 uword64 op,
1360 FP_formats from,
1361 FP_formats to)
1362 {
1363 sim_fpu wop;
1364 sim_fpu_round round = rounding_mode (rm);
1365 sim_fpu_denorm denorm = denorm_mode (cpu);
1366 unsigned32 result32;
1367 unsigned64 result64;
1368 sim_fpu_status status = 0;
1369
1370 /* Convert the input to sim_fpu internal format */
1371 switch (from)
1372 {
1373 case fmt_double:
1374 sim_fpu_64to (&wop, op);
1375 break;
1376 case fmt_single:
1377 sim_fpu_32to (&wop, op);
1378 break;
1379 case fmt_word:
1380 status = sim_fpu_i32to (&wop, op, round);
1381 break;
1382 case fmt_long:
1383 status = sim_fpu_i64to (&wop, op, round);
1384 break;
1385 default:
1386 sim_io_eprintf (SD, "Bad switch\n");
1387 abort ();
1388 }
1389
1390 /* Convert sim_fpu format into the output */
1391 /* The value WOP is converted to the destination format, rounding
1392 using mode RM. When the destination is a fixed-point format, then
1393 a source value of Infinity, NaN or one which would round to an
1394 integer outside the fixed point range then an IEEE Invalid Operation
1395 condition is raised. Not used if destination format is PS. */
1396 switch (to)
1397 {
1398 case fmt_single:
1399 status |= sim_fpu_round_32 (&wop, round, denorm);
1400 /* For a NaN, normalize mantissa bits (cvt.s.d can't preserve them) */
1401 if (sim_fpu_is_qnan (&wop))
1402 wop = sim_fpu_qnan;
1403 sim_fpu_to32 (&result32, &wop);
1404 result64 = result32;
1405 break;
1406 case fmt_double:
1407 status |= sim_fpu_round_64 (&wop, round, denorm);
1408 /* For a NaN, normalize mantissa bits (make cvt.d.s consistent) */
1409 if (sim_fpu_is_qnan (&wop))
1410 wop = sim_fpu_qnan;
1411 sim_fpu_to64 (&result64, &wop);
1412 break;
1413 case fmt_word:
1414 status |= sim_fpu_to32i (&result32, &wop, round);
1415 result64 = result32;
1416 break;
1417 case fmt_long:
1418 status |= sim_fpu_to64i (&result64, &wop, round);
1419 break;
1420 default:
1421 result64 = 0;
1422 sim_io_eprintf (SD, "Bad switch\n");
1423 abort ();
1424 }
1425
1426 update_fcsr (cpu, cia, status);
1427 return result64;
1428 }
1429
1430 unsigned64
1431 ps_lower(sim_cpu *cpu,
1432 address_word cia,
1433 unsigned64 op)
1434 {
1435 return FP_PS_lower (op);
1436 }
1437
1438 unsigned64
1439 ps_upper(sim_cpu *cpu,
1440 address_word cia,
1441 unsigned64 op)
1442 {
1443 return FP_PS_upper(op);
1444 }
1445
1446 unsigned64
1447 pack_ps(sim_cpu *cpu,
1448 address_word cia,
1449 unsigned64 op1,
1450 unsigned64 op2,
1451 FP_formats fmt)
1452 {
1453 unsigned64 result = 0;
1454
1455 /* The registers must specify FPRs valid for operands of type
1456 "fmt". If they are not valid, the result is undefined. */
1457
1458 /* The format type should already have been checked: */
1459 switch (fmt)
1460 {
1461 case fmt_single:
1462 {
1463 sim_fpu wop;
1464 unsigned32 res_u, res_l;
1465 sim_fpu_32to (&wop, op1);
1466 sim_fpu_to32 (&res_u, &wop);
1467 sim_fpu_32to (&wop, op2);
1468 sim_fpu_to32 (&res_l, &wop);
1469 result = FP_PS_cat(res_u, res_l);
1470 break;
1471 }
1472 default:
1473 sim_io_eprintf (SD, "Bad switch\n");
1474 abort ();
1475 }
1476
1477 return result;
1478 }
1479
1480 unsigned64
1481 convert_ps (sim_cpu *cpu,
1482 address_word cia,
1483 int rm,
1484 unsigned64 op,
1485 FP_formats from,
1486 FP_formats to)
1487 {
1488 sim_fpu wop_u, wop_l;
1489 sim_fpu_round round = rounding_mode (rm);
1490 sim_fpu_denorm denorm = denorm_mode (cpu);
1491 unsigned32 res_u, res_l;
1492 unsigned64 result;
1493 sim_fpu_status status_u = 0, status_l = 0;
1494
1495 /* As convert, but used only for paired values (formats PS, PW) */
1496
1497 /* Convert the input to sim_fpu internal format */
1498 switch (from)
1499 {
1500 case fmt_word: /* fmt_pw */
1501 sim_fpu_i32to (&wop_u, (op >> 32) & (unsigned)0xFFFFFFFF, round);
1502 sim_fpu_i32to (&wop_l, op & (unsigned)0xFFFFFFFF, round);
1503 break;
1504 case fmt_ps:
1505 sim_fpu_32to (&wop_u, FP_PS_upper(op));
1506 sim_fpu_32to (&wop_l, FP_PS_lower(op));
1507 break;
1508 default:
1509 sim_io_eprintf (SD, "Bad switch\n");
1510 abort ();
1511 }
1512
1513 /* Convert sim_fpu format into the output */
1514 switch (to)
1515 {
1516 case fmt_word: /* fmt_pw */
1517 status_u |= sim_fpu_to32i (&res_u, &wop_u, round);
1518 status_l |= sim_fpu_to32i (&res_l, &wop_l, round);
1519 result = (((unsigned64)res_u) << 32) | (unsigned64)res_l;
1520 break;
1521 case fmt_ps:
1522 status_u |= sim_fpu_round_32 (&wop_u, 0, round);
1523 status_l |= sim_fpu_round_32 (&wop_l, 0, round);
1524 sim_fpu_to32 (&res_u, &wop_u);
1525 sim_fpu_to32 (&res_l, &wop_l);
1526 result = FP_PS_cat(res_u, res_l);
1527 break;
1528 default:
1529 result = 0;
1530 sim_io_eprintf (SD, "Bad switch\n");
1531 abort ();
1532 }
1533
1534 update_fcsr (cpu, cia, status_u | status_l);
1535 return result;
1536 }
1537
1538 static const char *
1539 fpu_format_name (FP_formats fmt)
1540 {
1541 switch (fmt)
1542 {
1543 case fmt_single:
1544 return "single";
1545 case fmt_double:
1546 return "double";
1547 case fmt_word:
1548 return "word";
1549 case fmt_long:
1550 return "long";
1551 case fmt_ps:
1552 return "ps";
1553 case fmt_unknown:
1554 return "<unknown>";
1555 case fmt_uninterpreted:
1556 return "<uninterpreted>";
1557 case fmt_uninterpreted_32:
1558 return "<uninterpreted_32>";
1559 case fmt_uninterpreted_64:
1560 return "<uninterpreted_64>";
1561 default:
1562 return "<format error>";
1563 }
1564 }
1565
1566 #ifdef DEBUG
1567 static const char *
1568 fpu_rounding_mode_name (int rm)
1569 {
1570 switch (rm)
1571 {
1572 case FP_RM_NEAREST:
1573 return "Round";
1574 case FP_RM_TOZERO:
1575 return "Trunc";
1576 case FP_RM_TOPINF:
1577 return "Ceil";
1578 case FP_RM_TOMINF:
1579 return "Floor";
1580 default:
1581 return "<rounding mode error>";
1582 }
1583 }
1584 #endif /* DEBUG */
This page took 0.06126 seconds and 4 git commands to generate.