24c0a21fefac5366e46f993089bdfa3ad356b6bf
[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).
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 PAIRED SINGLE precision floating:
76 seeeeeeeefffffffffffffffffffffffseeeeeeeefffffffffffffffffffffff
77 | upper || lower |
78 s = 1bit = sign
79 e = 8bits = exponent
80 f = 23bits = fraction
81 Note: upper = [63..32], lower = [31..0]
82 */
83
84 /* Extract packed single values: */
85 #define FP_PS_upper(v) (((v) >> 32) & (unsigned)0xFFFFFFFF)
86 #define FP_PS_lower(v) ((v) & (unsigned)0xFFFFFFFF)
87 #define FP_PS_cat(u,l) (((unsigned64)((u) & (unsigned)0xFFFFFFFF) << 32) \
88 | (unsigned64)((l) & 0xFFFFFFFF))
89
90 /* Explicit QNaN values. */
91 #define FPQNaN_SINGLE (0x7FBFFFFF)
92 #define FPQNaN_WORD (0x7FFFFFFF)
93 #define FPQNaN_DOUBLE (UNSIGNED64 (0x7FF7FFFFFFFFFFFF))
94 #define FPQNaN_LONG (UNSIGNED64 (0x7FFFFFFFFFFFFFFF))
95 #define FPQNaN_PS (FP_PS_cat (FPQNaN_SINGLE, FPQNaN_SINGLE))
96
97 static const char *fpu_format_name (FP_formats fmt);
98 #ifdef DEBUG
99 static const char *fpu_rounding_mode_name (int rm);
100 #endif
101
102 uword64
103 value_fpr (sim_cpu *cpu,
104 address_word cia,
105 int fpr,
106 FP_formats fmt)
107 {
108 uword64 value = 0;
109 int err = 0;
110
111 /* Treat unused register values, as fixed-point 64bit values. */
112 if ((fmt == fmt_uninterpreted) || (fmt == fmt_unknown))
113 {
114 #if 1
115 /* If request to read data as "uninterpreted", then use the current
116 encoding: */
117 fmt = FPR_STATE[fpr];
118 #else
119 fmt = fmt_long;
120 #endif
121 }
122
123 /* For values not yet accessed, set to the desired format. */
124 if (FPR_STATE[fpr] == fmt_uninterpreted)
125 {
126 FPR_STATE[fpr] = fmt;
127 #ifdef DEBUG
128 printf ("DBG: Register %d was fmt_uninterpreted. Now %s\n", fpr,
129 fpu_format_name (fmt));
130 #endif /* DEBUG */
131 }
132 if (fmt != FPR_STATE[fpr])
133 {
134 sim_io_eprintf (SD, "FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",
135 fpr, fpu_format_name (FPR_STATE[fpr]),
136 fpu_format_name (fmt), pr_addr (cia));
137 FPR_STATE[fpr] = fmt_unknown;
138 }
139
140 if (FPR_STATE[fpr] == fmt_unknown)
141 {
142 /* Set QNaN value: */
143 switch (fmt)
144 {
145 case fmt_single: value = FPQNaN_SINGLE; break;
146 case fmt_double: value = FPQNaN_DOUBLE; break;
147 case fmt_word: value = FPQNaN_WORD; break;
148 case fmt_long: value = FPQNaN_LONG; break;
149 case fmt_ps: value = FPQNaN_PS; break;
150 default: err = -1; break;
151 }
152 }
153 else if (SizeFGR () == 64)
154 {
155 switch (fmt)
156 {
157 case fmt_single:
158 case fmt_word:
159 value = (FGR[fpr] & 0xFFFFFFFF);
160 break;
161
162 case fmt_uninterpreted:
163 case fmt_double:
164 case fmt_long:
165 case fmt_ps:
166 value = FGR[fpr];
167 break;
168
169 default:
170 err = -1;
171 break;
172 }
173 }
174 else
175 {
176 switch (fmt)
177 {
178 case fmt_single:
179 case fmt_word:
180 value = (FGR[fpr] & 0xFFFFFFFF);
181 break;
182
183 case fmt_uninterpreted:
184 case fmt_double:
185 case fmt_long:
186 if ((fpr & 1) == 0)
187 {
188 /* Even register numbers only. */
189 #ifdef DEBUG
190 printf ("DBG: ValueFPR: FGR[%d] = %s, FGR[%d] = %s\n",
191 fpr + 1, pr_uword64 ((uword64) FGR[fpr+1]),
192 fpr, pr_uword64 ((uword64) FGR[fpr]));
193 #endif
194 value = ((((uword64) FGR[fpr+1]) << 32)
195 | (FGR[fpr] & 0xFFFFFFFF));
196 }
197 else
198 {
199 SignalException (ReservedInstruction, 0);
200 }
201 break;
202
203 case fmt_ps:
204 SignalException (ReservedInstruction, 0);
205 break;
206
207 default:
208 err = -1;
209 break;
210 }
211 }
212
213 if (err)
214 SignalExceptionSimulatorFault ("Unrecognised FP format in ValueFPR ()");
215
216 #ifdef DEBUG
217 printf ("DBG: ValueFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR () = %d\n",
218 fpr, fpu_format_name (fmt), pr_uword64 (value), pr_addr (cia),
219 SizeFGR ());
220 #endif /* DEBUG */
221
222 return (value);
223 }
224
225 void
226 store_fpr (sim_cpu *cpu,
227 address_word cia,
228 int fpr,
229 FP_formats fmt,
230 uword64 value)
231 {
232 int err = 0;
233
234 #ifdef DEBUG
235 printf ("DBG: StoreFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR () = %d, \n",
236 fpr, fpu_format_name (fmt), pr_uword64 (value), pr_addr (cia),
237 SizeFGR ());
238 #endif /* DEBUG */
239
240 if (SizeFGR () == 64)
241 {
242 switch (fmt)
243 {
244 case fmt_uninterpreted_32:
245 fmt = fmt_uninterpreted;
246 case fmt_single:
247 case fmt_word:
248 if (STATE_VERBOSE_P (SD))
249 sim_io_eprintf (SD,
250 "Warning: PC 0x%s: interp.c store_fpr DEADCODE\n",
251 pr_addr (cia));
252 FGR[fpr] = (((uword64) 0xDEADC0DE << 32) | (value & 0xFFFFFFFF));
253 FPR_STATE[fpr] = fmt;
254 break;
255
256 case fmt_uninterpreted_64:
257 fmt = fmt_uninterpreted;
258 case fmt_uninterpreted:
259 case fmt_double:
260 case fmt_long:
261 case fmt_ps:
262 FGR[fpr] = value;
263 FPR_STATE[fpr] = fmt;
264 break;
265
266 default:
267 FPR_STATE[fpr] = fmt_unknown;
268 err = -1;
269 break;
270 }
271 }
272 else
273 {
274 switch (fmt)
275 {
276 case fmt_uninterpreted_32:
277 fmt = fmt_uninterpreted;
278 case fmt_single:
279 case fmt_word:
280 FGR[fpr] = (value & 0xFFFFFFFF);
281 FPR_STATE[fpr] = fmt;
282 break;
283
284 case fmt_uninterpreted_64:
285 fmt = fmt_uninterpreted;
286 case fmt_uninterpreted:
287 case fmt_double:
288 case fmt_long:
289 if ((fpr & 1) == 0)
290 {
291 /* Even register numbers only. */
292 FGR[fpr+1] = (value >> 32);
293 FGR[fpr] = (value & 0xFFFFFFFF);
294 FPR_STATE[fpr + 1] = fmt;
295 FPR_STATE[fpr] = fmt;
296 }
297 else
298 {
299 FPR_STATE[fpr] = fmt_unknown;
300 FPR_STATE[fpr + 1] = fmt_unknown;
301 SignalException (ReservedInstruction, 0);
302 }
303 break;
304
305 case fmt_ps:
306 FPR_STATE[fpr] = fmt_unknown;
307 SignalException (ReservedInstruction, 0);
308 break;
309
310 default:
311 FPR_STATE[fpr] = fmt_unknown;
312 err = -1;
313 break;
314 }
315 }
316
317 if (err)
318 SignalExceptionSimulatorFault ("Unrecognised FP format in StoreFPR ()");
319
320 #ifdef DEBUG
321 printf ("DBG: StoreFPR: fpr[%d] = 0x%s (format %s)\n",
322 fpr, pr_uword64 (FGR[fpr]), fpu_format_name (fmt));
323 #endif /* DEBUG */
324
325 return;
326 }
327
328
329 /* CP1 control/status register access functions. */
330
331 void
332 test_fcsr (sim_cpu *cpu,
333 address_word cia)
334 {
335 unsigned int cause;
336
337 cause = (FCSR & fcsr_CAUSE_mask) >> fcsr_CAUSE_shift;
338 if ((cause & ((FCSR & fcsr_ENABLES_mask) >> fcsr_ENABLES_shift)) != 0
339 || (cause & (1 << UO)))
340 {
341 SignalExceptionFPE();
342 }
343 }
344
345 unsigned_word
346 value_fcr(sim_cpu *cpu,
347 address_word cia,
348 int fcr)
349 {
350 unsigned32 value = 0;
351
352 switch (fcr)
353 {
354 case 0: /* FP Implementation and Revision Register. */
355 value = FCR0;
356 break;
357 case 25: /* FP Condition Codes Register (derived from FCSR). */
358 value = (FCR31 & fcsr_FCC_mask) >> fcsr_FCC_shift;
359 value = (value & 0x1) | (value >> 1); /* Close FCC gap. */
360 break;
361 case 26: /* FP Exceptions Register (derived from FCSR). */
362 value = FCR31 & (fcsr_CAUSE_mask | fcsr_FLAGS_mask);
363 break;
364 case 28: /* FP Enables Register (derived from FCSR). */
365 value = FCR31 & (fcsr_ENABLES_mask | fcsr_RM_mask);
366 if ((FCR31 & fcsr_FS) != 0)
367 value |= fenr_FS;
368 break;
369 case 31: /* FP Control/Status Register (FCSR). */
370 value = FCR31 & ~fcsr_ZERO_mask;
371 break;
372 }
373
374 return (EXTEND32 (value));
375 }
376
377 void
378 store_fcr(sim_cpu *cpu,
379 address_word cia,
380 int fcr,
381 unsigned_word value)
382 {
383 unsigned32 v;
384
385 v = VL4_8(value);
386 switch (fcr)
387 {
388 case 25: /* FP Condition Codes Register (stored into FCSR). */
389 v = (v << 1) | (v & 0x1); /* Adjust for FCC gap. */
390 FCR31 &= ~fcsr_FCC_mask;
391 FCR31 |= ((v << fcsr_FCC_shift) & fcsr_FCC_mask);
392 break;
393 case 26: /* FP Exceptions Register (stored into FCSR). */
394 FCR31 &= ~(fcsr_CAUSE_mask | fcsr_FLAGS_mask);
395 FCR31 |= (v & (fcsr_CAUSE_mask | fcsr_FLAGS_mask));
396 test_fcsr(cpu, cia);
397 break;
398 case 28: /* FP Enables Register (stored into FCSR). */
399 if ((v & fenr_FS) != 0)
400 v |= fcsr_FS;
401 else
402 v &= ~fcsr_FS;
403 FCR31 &= (fcsr_FCC_mask | fcsr_CAUSE_mask | fcsr_FLAGS_mask);
404 FCR31 |= (v & (fcsr_FS | fcsr_ENABLES_mask | fcsr_RM_mask));
405 test_fcsr(cpu, cia);
406 break;
407 case 31: /* FP Control/Status Register (FCSR). */
408 FCR31 = v & ~fcsr_ZERO_mask;
409 test_fcsr(cpu, cia);
410 break;
411 }
412 }
413
414 void
415 update_fcsr (sim_cpu *cpu,
416 address_word cia,
417 sim_fpu_status status)
418 {
419 FCSR &= ~fcsr_CAUSE_mask;
420
421 if (status != 0)
422 {
423 unsigned int cause = 0;
424
425 /* map between sim_fpu codes and MIPS FCSR */
426 if (status & (sim_fpu_status_invalid_snan
427 | sim_fpu_status_invalid_isi
428 | sim_fpu_status_invalid_idi
429 | sim_fpu_status_invalid_zdz
430 | sim_fpu_status_invalid_imz
431 | sim_fpu_status_invalid_cmp
432 | sim_fpu_status_invalid_sqrt
433 | sim_fpu_status_invalid_cvi))
434 cause |= (1 << IO);
435 if (status & sim_fpu_status_invalid_div0)
436 cause |= (1 << DZ);
437 if (status & sim_fpu_status_overflow)
438 cause |= (1 << OF);
439 if (status & sim_fpu_status_underflow)
440 cause |= (1 << UF);
441 if (status & sim_fpu_status_inexact)
442 cause |= (1 << IR);
443 #if 0 /* Not yet. */
444 /* Implicit clearing of other bits by unimplemented done by callers. */
445 if (status & sim_fpu_status_unimplemented)
446 cause |= (1 << UO);
447 #endif
448
449 FCSR |= (cause << fcsr_CAUSE_shift);
450 test_fcsr (cpu, cia);
451 FCSR |= ((cause & ~(1 << UO)) << fcsr_FLAGS_shift);
452 }
453 return;
454 }
455
456 static sim_fpu_round
457 rounding_mode(int rm)
458 {
459 sim_fpu_round round;
460
461 switch (rm)
462 {
463 case FP_RM_NEAREST:
464 /* Round result to nearest representable value. When two
465 representable values are equally near, round to the value
466 that has a least significant bit of zero (i.e. is even). */
467 round = sim_fpu_round_near;
468 break;
469 case FP_RM_TOZERO:
470 /* Round result to the value closest to, and not greater in
471 magnitude than, the result. */
472 round = sim_fpu_round_zero;
473 break;
474 case FP_RM_TOPINF:
475 /* Round result to the value closest to, and not less than,
476 the result. */
477 round = sim_fpu_round_up;
478 break;
479 case FP_RM_TOMINF:
480 /* Round result to the value closest to, and not greater than,
481 the result. */
482 round = sim_fpu_round_down;
483 break;
484 default:
485 round = 0;
486 fprintf (stderr, "Bad switch\n");
487 abort ();
488 }
489 return round;
490 }
491
492 /* When the FS bit is set, MIPS processors return zero for
493 denormalized results and optionally replace denormalized inputs
494 with zero. When FS is clear, some implementation trap on input
495 and/or output, while other perform the operation in hardware. */
496 static sim_fpu_denorm
497 denorm_mode(sim_cpu *cpu)
498 {
499 sim_fpu_denorm denorm;
500
501 /* XXX: FIXME: Eventually should be CPU model dependent. */
502 if (GETFS())
503 denorm = sim_fpu_denorm_zero;
504 else
505 denorm = 0;
506 return denorm;
507 }
508
509
510 /* Comparison operations. */
511
512 static sim_fpu_status
513 fp_test(unsigned64 op1,
514 unsigned64 op2,
515 FP_formats fmt,
516 int abs,
517 int cond,
518 int *condition)
519 {
520 sim_fpu wop1;
521 sim_fpu wop2;
522 sim_fpu_status status = 0;
523 int less, equal, unordered;
524
525 /* The format type has already been checked: */
526 switch (fmt)
527 {
528 case fmt_single:
529 {
530 sim_fpu_32to (&wop1, op1);
531 sim_fpu_32to (&wop2, op2);
532 break;
533 }
534 case fmt_double:
535 {
536 sim_fpu_64to (&wop1, op1);
537 sim_fpu_64to (&wop2, op2);
538 break;
539 }
540 default:
541 fprintf (stderr, "Bad switch\n");
542 abort ();
543 }
544
545 if (sim_fpu_is_nan (&wop1) || sim_fpu_is_nan (&wop2))
546 {
547 if ((cond & (1 << 3)) ||
548 sim_fpu_is_snan (&wop1) || sim_fpu_is_snan (&wop2))
549 status = sim_fpu_status_invalid_snan;
550 less = 0;
551 equal = 0;
552 unordered = 1;
553 }
554 else
555 {
556 if (abs)
557 {
558 status |= sim_fpu_abs (&wop1, &wop1);
559 status |= sim_fpu_abs (&wop2, &wop2);
560 }
561 equal = sim_fpu_is_eq (&wop1, &wop2);
562 less = !equal && sim_fpu_is_lt (&wop1, &wop2);
563 unordered = 0;
564 }
565 *condition = (((cond & (1 << 2)) && less)
566 || ((cond & (1 << 1)) && equal)
567 || ((cond & (1 << 0)) && unordered));
568 return status;
569 }
570
571 void
572 fp_cmp(sim_cpu *cpu,
573 address_word cia,
574 unsigned64 op1,
575 unsigned64 op2,
576 FP_formats fmt,
577 int abs,
578 int cond,
579 int cc)
580 {
581 sim_fpu_status status = 0;
582
583 /* The format type should already have been checked. The FCSR is
584 updated before the condition codes so that any exceptions will
585 be signalled before the condition codes are changed. */
586 switch (fmt)
587 {
588 case fmt_single:
589 case fmt_double:
590 {
591 int result;
592 status = fp_test(op1, op2, fmt, abs, cond, &result);
593 update_fcsr (cpu, cia, status);
594 SETFCC (cc, result);
595 break;
596 }
597 case fmt_ps:
598 {
599 int result0, result1;
600 status = fp_test(FP_PS_lower (op1), FP_PS_lower (op2), fmt_single,
601 abs, cond, &result0);
602 status |= fp_test(FP_PS_upper (op1), FP_PS_upper (op2), fmt_single,
603 abs, cond, &result1);
604 update_fcsr (cpu, cia, status);
605 SETFCC (cc, result0);
606 SETFCC (cc+1, result1);
607 break;
608 }
609 default:
610 sim_io_eprintf (SD, "Bad switch\n");
611 abort ();
612 }
613 }
614
615
616 /* Basic arithmetic operations. */
617
618 static unsigned64
619 fp_unary(sim_cpu *cpu,
620 address_word cia,
621 int (*sim_fpu_op)(sim_fpu *, const sim_fpu *),
622 unsigned64 op,
623 FP_formats fmt)
624 {
625 sim_fpu wop;
626 sim_fpu ans;
627 sim_fpu_round round = rounding_mode (GETRM());
628 sim_fpu_denorm denorm = denorm_mode (cpu);
629 sim_fpu_status status = 0;
630 unsigned64 result = 0;
631
632 /* The format type has already been checked: */
633 switch (fmt)
634 {
635 case fmt_single:
636 {
637 unsigned32 res;
638 sim_fpu_32to (&wop, op);
639 status |= (*sim_fpu_op) (&ans, &wop);
640 status |= sim_fpu_round_32 (&ans, round, denorm);
641 sim_fpu_to32 (&res, &ans);
642 result = res;
643 break;
644 }
645 case fmt_double:
646 {
647 unsigned64 res;
648 sim_fpu_64to (&wop, op);
649 status |= (*sim_fpu_op) (&ans, &wop);
650 status |= sim_fpu_round_64 (&ans, round, denorm);
651 sim_fpu_to64 (&res, &ans);
652 result = res;
653 break;
654 }
655 case fmt_ps:
656 {
657 int status_u = 0, status_l = 0;
658 unsigned32 res_u, res_l;
659 sim_fpu_32to (&wop, FP_PS_upper(op));
660 status_u |= (*sim_fpu_op) (&ans, &wop);
661 sim_fpu_to32 (&res_u, &ans);
662 sim_fpu_32to (&wop, FP_PS_lower(op));
663 status_l |= (*sim_fpu_op) (&ans, &wop);
664 sim_fpu_to32 (&res_l, &ans);
665 result = FP_PS_cat(res_u, res_l);
666 status = status_u | status_l;
667 break;
668 }
669 default:
670 sim_io_eprintf (SD, "Bad switch\n");
671 abort ();
672 }
673
674 update_fcsr (cpu, cia, status);
675 return result;
676 }
677
678 static unsigned64
679 fp_binary(sim_cpu *cpu,
680 address_word cia,
681 int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *),
682 unsigned64 op1,
683 unsigned64 op2,
684 FP_formats fmt)
685 {
686 sim_fpu wop1;
687 sim_fpu wop2;
688 sim_fpu ans;
689 sim_fpu_round round = rounding_mode (GETRM());
690 sim_fpu_denorm denorm = denorm_mode (cpu);
691 sim_fpu_status status = 0;
692 unsigned64 result = 0;
693
694 /* The format type has already been checked: */
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_op) (&ans, &wop1, &wop2);
703 status |= sim_fpu_round_32 (&ans, round, denorm);
704 sim_fpu_to32 (&res, &ans);
705 result = res;
706 break;
707 }
708 case fmt_double:
709 {
710 unsigned64 res;
711 sim_fpu_64to (&wop1, op1);
712 sim_fpu_64to (&wop2, op2);
713 status |= (*sim_fpu_op) (&ans, &wop1, &wop2);
714 status |= sim_fpu_round_64 (&ans, round, denorm);
715 sim_fpu_to64 (&res, &ans);
716 result = res;
717 break;
718 }
719 case fmt_ps:
720 {
721 int status_u = 0, status_l = 0;
722 unsigned32 res_u, res_l;
723 sim_fpu_32to (&wop1, FP_PS_upper(op1));
724 sim_fpu_32to (&wop2, FP_PS_upper(op2));
725 status_u |= (*sim_fpu_op) (&ans, &wop1, &wop2);
726 sim_fpu_to32 (&res_u, &ans);
727 sim_fpu_32to (&wop1, FP_PS_lower(op1));
728 sim_fpu_32to (&wop2, FP_PS_lower(op2));
729 status_l |= (*sim_fpu_op) (&ans, &wop1, &wop2);
730 sim_fpu_to32 (&res_l, &ans);
731 result = FP_PS_cat(res_u, res_l);
732 status = status_u | status_l;
733 break;
734 }
735 default:
736 sim_io_eprintf (SD, "Bad switch\n");
737 abort ();
738 }
739
740 update_fcsr (cpu, cia, status);
741 return result;
742 }
743
744 /* Common MAC code for single operands (.s or .d), defers setting FCSR. */
745 static sim_fpu_status
746 inner_mac(int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *),
747 unsigned64 op1,
748 unsigned64 op2,
749 unsigned64 op3,
750 int scale,
751 int negate,
752 FP_formats fmt,
753 sim_fpu_round round,
754 sim_fpu_denorm denorm,
755 unsigned64 *result)
756 {
757 sim_fpu wop1;
758 sim_fpu wop2;
759 sim_fpu ans;
760 sim_fpu_status status = 0;
761 sim_fpu_status op_status;
762 unsigned64 temp = 0;
763
764 switch (fmt)
765 {
766 case fmt_single:
767 {
768 unsigned32 res;
769 sim_fpu_32to (&wop1, op1);
770 sim_fpu_32to (&wop2, op2);
771 status |= sim_fpu_mul (&ans, &wop1, &wop2);
772 if (scale != 0 && sim_fpu_is_number (&ans)) /* number or denorm */
773 ans.normal_exp += scale;
774 status |= sim_fpu_round_32 (&ans, round, denorm);
775 wop1 = ans;
776 op_status = 0;
777 sim_fpu_32to (&wop2, op3);
778 op_status |= (*sim_fpu_op) (&ans, &wop1, &wop2);
779 op_status |= sim_fpu_round_32 (&ans, round, denorm);
780 status |= op_status;
781 if (negate)
782 {
783 wop1 = ans;
784 op_status = sim_fpu_neg (&ans, &wop1);
785 op_status |= sim_fpu_round_32 (&ans, round, denorm);
786 status |= op_status;
787 }
788 sim_fpu_to32 (&res, &ans);
789 temp = res;
790 break;
791 }
792 case fmt_double:
793 {
794 unsigned64 res;
795 sim_fpu_64to (&wop1, op1);
796 sim_fpu_64to (&wop2, op2);
797 status |= sim_fpu_mul (&ans, &wop1, &wop2);
798 if (scale != 0 && sim_fpu_is_number (&ans)) /* number or denorm */
799 ans.normal_exp += scale;
800 status |= sim_fpu_round_64 (&ans, round, denorm);
801 wop1 = ans;
802 op_status = 0;
803 sim_fpu_64to (&wop2, op3);
804 op_status |= (*sim_fpu_op) (&ans, &wop1, &wop2);
805 op_status |= sim_fpu_round_64 (&ans, round, denorm);
806 status |= op_status;
807 if (negate)
808 {
809 wop1 = ans;
810 op_status = sim_fpu_neg (&ans, &wop1);
811 op_status |= sim_fpu_round_64 (&ans, round, denorm);
812 status |= op_status;
813 }
814 sim_fpu_to64 (&res, &ans);
815 temp = res;
816 break;
817 }
818 default:
819 fprintf (stderr, "Bad switch\n");
820 abort ();
821 }
822 *result = temp;
823 return status;
824 }
825
826 /* Common implementation of madd, nmadd, msub, nmsub that does
827 intermediate rounding per spec. Also used for recip2 and rsqrt2,
828 which are transformed into equivalent nmsub operations. The scale
829 argument is an adjustment to the exponent of the intermediate
830 product op1*op2. It is currently non-zero for rsqrt2 (-1), which
831 requires an effective division by 2. */
832 static unsigned64
833 fp_mac(sim_cpu *cpu,
834 address_word cia,
835 int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *),
836 unsigned64 op1,
837 unsigned64 op2,
838 unsigned64 op3,
839 int scale,
840 int negate,
841 FP_formats fmt)
842 {
843 sim_fpu_round round = rounding_mode (GETRM());
844 sim_fpu_denorm denorm = denorm_mode (cpu);
845 sim_fpu_status status = 0;
846 unsigned64 result = 0;
847
848 /* The format type has already been checked: */
849 switch (fmt)
850 {
851 case fmt_single:
852 case fmt_double:
853 status = inner_mac(sim_fpu_op, op1, op2, op3, scale,
854 negate, fmt, round, denorm, &result);
855 break;
856 case fmt_ps:
857 {
858 int status_u, status_l;
859 unsigned64 result_u, result_l;
860 status_u = inner_mac(sim_fpu_op, FP_PS_upper(op1), FP_PS_upper(op2),
861 FP_PS_upper(op3), scale, negate, fmt_single,
862 round, denorm, &result_u);
863 status_l = inner_mac(sim_fpu_op, FP_PS_lower(op1), FP_PS_lower(op2),
864 FP_PS_lower(op3), scale, negate, fmt_single,
865 round, denorm, &result_l);
866 result = FP_PS_cat(result_u, result_l);
867 status = status_u | status_l;
868 break;
869 }
870 default:
871 sim_io_eprintf (SD, "Bad switch\n");
872 abort ();
873 }
874
875 update_fcsr (cpu, cia, status);
876 return result;
877 }
878
879 /* Common rsqrt code for single operands (.s or .d), intermediate rounding. */
880 static sim_fpu_status
881 inner_rsqrt(unsigned64 op1,
882 FP_formats fmt,
883 sim_fpu_round round,
884 sim_fpu_denorm denorm,
885 unsigned64 *result)
886 {
887 sim_fpu wop1;
888 sim_fpu ans;
889 sim_fpu_status status = 0;
890 sim_fpu_status op_status;
891 unsigned64 temp = 0;
892
893 switch (fmt)
894 {
895 case fmt_single:
896 {
897 unsigned32 res;
898 sim_fpu_32to (&wop1, op1);
899 status |= sim_fpu_sqrt (&ans, &wop1);
900 status |= sim_fpu_round_32 (&ans, status, round);
901 wop1 = ans;
902 op_status = sim_fpu_inv (&ans, &wop1);
903 op_status |= sim_fpu_round_32 (&ans, round, denorm);
904 sim_fpu_to32 (&res, &ans);
905 temp = res;
906 status |= op_status;
907 break;
908 }
909 case fmt_double:
910 {
911 unsigned64 res;
912 sim_fpu_64to (&wop1, op1);
913 status |= sim_fpu_sqrt (&ans, &wop1);
914 status |= sim_fpu_round_64 (&ans, round, denorm);
915 wop1 = ans;
916 op_status = sim_fpu_inv (&ans, &wop1);
917 op_status |= sim_fpu_round_64 (&ans, round, denorm);
918 sim_fpu_to64 (&res, &ans);
919 temp = res;
920 status |= op_status;
921 break;
922 }
923 default:
924 fprintf (stderr, "Bad switch\n");
925 abort ();
926 }
927 *result = temp;
928 return status;
929 }
930
931 static unsigned64
932 fp_inv_sqrt(sim_cpu *cpu,
933 address_word cia,
934 unsigned64 op1,
935 FP_formats fmt)
936 {
937 sim_fpu_round round = rounding_mode (GETRM());
938 sim_fpu_round denorm = denorm_mode (cpu);
939 sim_fpu_status status = 0;
940 unsigned64 result = 0;
941
942 /* The format type has already been checked: */
943 switch (fmt)
944 {
945 case fmt_single:
946 case fmt_double:
947 status = inner_rsqrt (op1, fmt, round, denorm, &result);
948 break;
949 case fmt_ps:
950 {
951 int status_u, status_l;
952 unsigned64 result_u, result_l;
953 status_u = inner_rsqrt (FP_PS_upper(op1), fmt_single, round, denorm,
954 &result_u);
955 status_l = inner_rsqrt (FP_PS_lower(op1), fmt_single, round, denorm,
956 &result_l);
957 result = FP_PS_cat(result_u, result_l);
958 status = status_u | status_l;
959 break;
960 }
961 default:
962 sim_io_eprintf (SD, "Bad switch\n");
963 abort ();
964 }
965
966 update_fcsr (cpu, cia, status);
967 return result;
968 }
969
970
971 unsigned64
972 fp_abs(sim_cpu *cpu,
973 address_word cia,
974 unsigned64 op,
975 FP_formats fmt)
976 {
977 return fp_unary(cpu, cia, &sim_fpu_abs, op, fmt);
978 }
979
980 unsigned64
981 fp_neg(sim_cpu *cpu,
982 address_word cia,
983 unsigned64 op,
984 FP_formats fmt)
985 {
986 return fp_unary(cpu, cia, &sim_fpu_neg, op, fmt);
987 }
988
989 unsigned64
990 fp_add(sim_cpu *cpu,
991 address_word cia,
992 unsigned64 op1,
993 unsigned64 op2,
994 FP_formats fmt)
995 {
996 return fp_binary(cpu, cia, &sim_fpu_add, op1, op2, fmt);
997 }
998
999 unsigned64
1000 fp_sub(sim_cpu *cpu,
1001 address_word cia,
1002 unsigned64 op1,
1003 unsigned64 op2,
1004 FP_formats fmt)
1005 {
1006 return fp_binary(cpu, cia, &sim_fpu_sub, op1, op2, fmt);
1007 }
1008
1009 unsigned64
1010 fp_mul(sim_cpu *cpu,
1011 address_word cia,
1012 unsigned64 op1,
1013 unsigned64 op2,
1014 FP_formats fmt)
1015 {
1016 return fp_binary(cpu, cia, &sim_fpu_mul, op1, op2, fmt);
1017 }
1018
1019 unsigned64
1020 fp_div(sim_cpu *cpu,
1021 address_word cia,
1022 unsigned64 op1,
1023 unsigned64 op2,
1024 FP_formats fmt)
1025 {
1026 return fp_binary(cpu, cia, &sim_fpu_div, op1, op2, fmt);
1027 }
1028
1029 unsigned64
1030 fp_recip(sim_cpu *cpu,
1031 address_word cia,
1032 unsigned64 op,
1033 FP_formats fmt)
1034 {
1035 return fp_unary(cpu, cia, &sim_fpu_inv, op, fmt);
1036 }
1037
1038 unsigned64
1039 fp_sqrt(sim_cpu *cpu,
1040 address_word cia,
1041 unsigned64 op,
1042 FP_formats fmt)
1043 {
1044 return fp_unary(cpu, cia, &sim_fpu_sqrt, op, fmt);
1045 }
1046
1047 unsigned64
1048 fp_rsqrt(sim_cpu *cpu,
1049 address_word cia,
1050 unsigned64 op,
1051 FP_formats fmt)
1052 {
1053 return fp_inv_sqrt(cpu, cia, op, fmt);
1054 }
1055
1056 unsigned64
1057 fp_madd(sim_cpu *cpu,
1058 address_word cia,
1059 unsigned64 op1,
1060 unsigned64 op2,
1061 unsigned64 op3,
1062 FP_formats fmt)
1063 {
1064 return fp_mac(cpu, cia, &sim_fpu_add, op1, op2, op3, 0, 0, fmt);
1065 }
1066
1067 unsigned64
1068 fp_msub(sim_cpu *cpu,
1069 address_word cia,
1070 unsigned64 op1,
1071 unsigned64 op2,
1072 unsigned64 op3,
1073 FP_formats fmt)
1074 {
1075 return fp_mac(cpu, cia, &sim_fpu_sub, op1, op2, op3, 0, 0, fmt);
1076 }
1077
1078 unsigned64
1079 fp_nmadd(sim_cpu *cpu,
1080 address_word cia,
1081 unsigned64 op1,
1082 unsigned64 op2,
1083 unsigned64 op3,
1084 FP_formats fmt)
1085 {
1086 return fp_mac(cpu, cia, &sim_fpu_add, op1, op2, op3, 0, 1, fmt);
1087 }
1088
1089 unsigned64
1090 fp_nmsub(sim_cpu *cpu,
1091 address_word cia,
1092 unsigned64 op1,
1093 unsigned64 op2,
1094 unsigned64 op3,
1095 FP_formats fmt)
1096 {
1097 return fp_mac(cpu, cia, &sim_fpu_sub, op1, op2, op3, 0, 1, fmt);
1098 }
1099
1100
1101 /* Conversion operations. */
1102
1103 uword64
1104 convert (sim_cpu *cpu,
1105 address_word cia,
1106 int rm,
1107 uword64 op,
1108 FP_formats from,
1109 FP_formats to)
1110 {
1111 sim_fpu wop;
1112 sim_fpu_round round = rounding_mode (rm);
1113 sim_fpu_denorm denorm = denorm_mode (cpu);
1114 unsigned32 result32;
1115 unsigned64 result64;
1116 sim_fpu_status status = 0;
1117
1118 /* Convert the input to sim_fpu internal format */
1119 switch (from)
1120 {
1121 case fmt_double:
1122 sim_fpu_64to (&wop, op);
1123 break;
1124 case fmt_single:
1125 sim_fpu_32to (&wop, op);
1126 break;
1127 case fmt_word:
1128 status = sim_fpu_i32to (&wop, op, round);
1129 break;
1130 case fmt_long:
1131 status = sim_fpu_i64to (&wop, op, round);
1132 break;
1133 default:
1134 sim_io_eprintf (SD, "Bad switch\n");
1135 abort ();
1136 }
1137
1138 /* Convert sim_fpu format into the output */
1139 /* The value WOP is converted to the destination format, rounding
1140 using mode RM. When the destination is a fixed-point format, then
1141 a source value of Infinity, NaN or one which would round to an
1142 integer outside the fixed point range then an IEEE Invalid Operation
1143 condition is raised. Not used if destination format is PS. */
1144 switch (to)
1145 {
1146 case fmt_single:
1147 status |= sim_fpu_round_32 (&wop, round, denorm);
1148 /* For a NaN, normalize mantissa bits (cvt.s.d can't preserve them) */
1149 if (sim_fpu_is_qnan (&wop))
1150 wop = sim_fpu_qnan;
1151 sim_fpu_to32 (&result32, &wop);
1152 result64 = result32;
1153 break;
1154 case fmt_double:
1155 status |= sim_fpu_round_64 (&wop, round, denorm);
1156 /* For a NaN, normalize mantissa bits (make cvt.d.s consistent) */
1157 if (sim_fpu_is_qnan (&wop))
1158 wop = sim_fpu_qnan;
1159 sim_fpu_to64 (&result64, &wop);
1160 break;
1161 case fmt_word:
1162 status |= sim_fpu_to32i (&result32, &wop, round);
1163 result64 = result32;
1164 break;
1165 case fmt_long:
1166 status |= sim_fpu_to64i (&result64, &wop, round);
1167 break;
1168 default:
1169 result64 = 0;
1170 sim_io_eprintf (SD, "Bad switch\n");
1171 abort ();
1172 }
1173
1174 update_fcsr (cpu, cia, status);
1175 return result64;
1176 }
1177
1178 unsigned64
1179 ps_lower(sim_cpu *cpu,
1180 address_word cia,
1181 unsigned64 op)
1182 {
1183 return FP_PS_lower (op);
1184 }
1185
1186 unsigned64
1187 ps_upper(sim_cpu *cpu,
1188 address_word cia,
1189 unsigned64 op)
1190 {
1191 return FP_PS_upper(op);
1192 }
1193
1194 unsigned64
1195 pack_ps(sim_cpu *cpu,
1196 address_word cia,
1197 unsigned64 op1,
1198 unsigned64 op2,
1199 FP_formats fmt)
1200 {
1201 unsigned64 result = 0;
1202
1203 /* The registers must specify FPRs valid for operands of type
1204 "fmt". If they are not valid, the result is undefined. */
1205
1206 /* The format type should already have been checked: */
1207 switch (fmt)
1208 {
1209 case fmt_single:
1210 {
1211 sim_fpu wop;
1212 unsigned32 res_u, res_l;
1213 sim_fpu_32to (&wop, op1);
1214 sim_fpu_to32 (&res_u, &wop);
1215 sim_fpu_32to (&wop, op2);
1216 sim_fpu_to32 (&res_l, &wop);
1217 result = FP_PS_cat(res_u, res_l);
1218 break;
1219 }
1220 default:
1221 sim_io_eprintf (SD, "Bad switch\n");
1222 abort ();
1223 }
1224
1225 return result;
1226 }
1227
1228 unsigned64
1229 convert_ps (sim_cpu *cpu,
1230 address_word cia,
1231 int rm,
1232 unsigned64 op,
1233 FP_formats from,
1234 FP_formats to)
1235 {
1236 sim_fpu wop_u, wop_l;
1237 sim_fpu_round round = rounding_mode (rm);
1238 sim_fpu_denorm denorm = denorm_mode (cpu);
1239 unsigned32 res_u, res_l;
1240 unsigned64 result;
1241 sim_fpu_status status_u = 0, status_l = 0;
1242
1243 /* As convert, but used only for paired values (formats PS, PW) */
1244
1245 /* Convert the input to sim_fpu internal format */
1246 switch (from)
1247 {
1248 case fmt_word: /* fmt_pw */
1249 sim_fpu_i32to (&wop_u, (op >> 32) & (unsigned)0xFFFFFFFF, round);
1250 sim_fpu_i32to (&wop_l, op & (unsigned)0xFFFFFFFF, round);
1251 break;
1252 case fmt_ps:
1253 sim_fpu_32to (&wop_u, FP_PS_upper(op));
1254 sim_fpu_32to (&wop_l, FP_PS_lower(op));
1255 break;
1256 default:
1257 sim_io_eprintf (SD, "Bad switch\n");
1258 abort ();
1259 }
1260
1261 /* Convert sim_fpu format into the output */
1262 switch (to)
1263 {
1264 case fmt_word: /* fmt_pw */
1265 status_u |= sim_fpu_to32i (&res_u, &wop_u, round);
1266 status_l |= sim_fpu_to32i (&res_l, &wop_l, round);
1267 result = (((unsigned64)res_u) << 32) | (unsigned64)res_l;
1268 break;
1269 case fmt_ps:
1270 status_u |= sim_fpu_round_32 (&wop_u, 0, round);
1271 status_l |= sim_fpu_round_32 (&wop_l, 0, round);
1272 sim_fpu_to32 (&res_u, &wop_u);
1273 sim_fpu_to32 (&res_l, &wop_l);
1274 result = FP_PS_cat(res_u, res_l);
1275 break;
1276 default:
1277 result = 0;
1278 sim_io_eprintf (SD, "Bad switch\n");
1279 abort ();
1280 }
1281
1282 update_fcsr (cpu, cia, status_u | status_l);
1283 return result;
1284 }
1285
1286 static const char *
1287 fpu_format_name (FP_formats fmt)
1288 {
1289 switch (fmt)
1290 {
1291 case fmt_single:
1292 return "single";
1293 case fmt_double:
1294 return "double";
1295 case fmt_word:
1296 return "word";
1297 case fmt_long:
1298 return "long";
1299 case fmt_ps:
1300 return "ps";
1301 case fmt_unknown:
1302 return "<unknown>";
1303 case fmt_uninterpreted:
1304 return "<uninterpreted>";
1305 case fmt_uninterpreted_32:
1306 return "<uninterpreted_32>";
1307 case fmt_uninterpreted_64:
1308 return "<uninterpreted_64>";
1309 default:
1310 return "<format error>";
1311 }
1312 }
1313
1314 #ifdef DEBUG
1315 static const char *
1316 fpu_rounding_mode_name (int rm)
1317 {
1318 switch (rm)
1319 {
1320 case FP_RM_NEAREST:
1321 return "Round";
1322 case FP_RM_TOZERO:
1323 return "Trunc";
1324 case FP_RM_TOPINF:
1325 return "Ceil";
1326 case FP_RM_TOMINF:
1327 return "Floor";
1328 default:
1329 return "<rounding mode error>";
1330 }
1331 }
1332 #endif /* DEBUG */
This page took 0.065328 seconds and 4 git commands to generate.