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