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).
7 This file is part of GDB, the GNU debugger.
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)
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.
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. */
23 /* XXX: The following notice should be removed as soon as is practical: */
24 /* Floating Point Support for gdb MIPS simulators
26 This file is part of the MIPS sim
28 THIS SOFTWARE IS NOT COPYRIGHTED
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.
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.
39 (Originally, this code was in interp.c)
44 /* Within cp1.c we refer to sim_cpu directly. */
46 #define SD CPU_STATE(cpu)
48 /*-- FPU support routines ---------------------------------------------------*/
50 /* Numbers are held in normalized form. The SINGLE and DOUBLE binary
51 formats conform to ANSI/IEEE Std 754-1985.
53 SINGLE precision floating:
54 seeeeeeeefffffffffffffffffffffff
59 SINGLE precision fixed:
60 siiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
64 DOUBLE precision floating:
65 seeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffff
70 DOUBLE precision fixed:
71 siiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
76 /* Explicit QNaN values used when value required: */
77 #define FPQNaN_SINGLE (0x7FBFFFFF)
78 #define FPQNaN_WORD (0x7FFFFFFF)
79 #define FPQNaN_DOUBLE (UNSIGNED64 (0x7FF7FFFFFFFFFFFF))
80 #define FPQNaN_LONG (UNSIGNED64 (0x7FFFFFFFFFFFFFFF))
82 static const char *fpu_format_name (FP_formats fmt
);
84 static const char *fpu_rounding_mode_name (int rm
);
88 value_fpr (sim_cpu
*cpu
,
96 /* Treat unused register values, as fixed-point 64bit values: */
97 if ((fmt
== fmt_uninterpreted
) || (fmt
== fmt_unknown
))
100 /* If request to read data as "uninterpreted", then use the current
102 fmt
= FPR_STATE
[fpr
];
108 /* For values not yet accessed, set to the desired format: */
109 if (FPR_STATE
[fpr
] == fmt_uninterpreted
)
111 FPR_STATE
[fpr
] = fmt
;
113 printf ("DBG: Register %d was fmt_uninterpreted. Now %s\n", fpr
,
114 fpu_format_name (fmt
));
117 if (fmt
!= FPR_STATE
[fpr
])
119 sim_io_eprintf (SD
, "FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",
120 fpr
, fpu_format_name (FPR_STATE
[fpr
]),
121 fpu_format_name (fmt
), pr_addr (cia
));
122 FPR_STATE
[fpr
] = fmt_unknown
;
125 if (FPR_STATE
[fpr
] == fmt_unknown
)
127 /* Set QNaN value: */
130 case fmt_single
: value
= FPQNaN_SINGLE
; break;
131 case fmt_double
: value
= FPQNaN_DOUBLE
; break;
132 case fmt_word
: value
= FPQNaN_WORD
; break;
133 case fmt_long
: value
= FPQNaN_LONG
; break;
134 default: err
= -1; break;
137 else if (SizeFGR () == 64)
143 value
= (FGR
[fpr
] & 0xFFFFFFFF);
146 case fmt_uninterpreted
:
163 value
= (FGR
[fpr
] & 0xFFFFFFFF);
166 case fmt_uninterpreted
:
171 /* Even registers numbers only. */
173 printf ("DBG: ValueFPR: FGR[%d] = %s, FGR[%d] = %s\n",
174 fpr
+ 1, pr_uword64 ((uword64
) FGR
[fpr
+1]),
175 fpr
, pr_uword64 ((uword64
) FGR
[fpr
]));
177 value
= ((((uword64
) FGR
[fpr
+1]) << 32)
178 | (FGR
[fpr
] & 0xFFFFFFFF));
182 SignalException (ReservedInstruction
, 0);
193 SignalExceptionSimulatorFault ("Unrecognised FP format in ValueFPR ()");
196 printf ("DBG: ValueFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR () = %d\n",
197 fpr
, fpu_format_name (fmt
), pr_uword64 (value
), pr_addr (cia
),
205 store_fpr (sim_cpu
*cpu
,
214 printf ("DBG: StoreFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR () = %d, \n",
215 fpr
, fpu_format_name (fmt
), pr_uword64 (value
), pr_addr (cia
),
219 if (SizeFGR () == 64)
223 case fmt_uninterpreted_32
:
224 fmt
= fmt_uninterpreted
;
227 if (STATE_VERBOSE_P (SD
))
229 "Warning: PC 0x%s: interp.c store_fpr DEADCODE\n",
231 FGR
[fpr
] = (((uword64
) 0xDEADC0DE << 32) | (value
& 0xFFFFFFFF));
232 FPR_STATE
[fpr
] = fmt
;
235 case fmt_uninterpreted_64
:
236 fmt
= fmt_uninterpreted
;
237 case fmt_uninterpreted
:
241 FPR_STATE
[fpr
] = fmt
;
245 FPR_STATE
[fpr
] = fmt_unknown
;
254 case fmt_uninterpreted_32
:
255 fmt
= fmt_uninterpreted
;
258 FGR
[fpr
] = (value
& 0xFFFFFFFF);
259 FPR_STATE
[fpr
] = fmt
;
262 case fmt_uninterpreted_64
:
263 fmt
= fmt_uninterpreted
;
264 case fmt_uninterpreted
:
269 /* Even register numbers only. */
270 FGR
[fpr
+1] = (value
>> 32);
271 FGR
[fpr
] = (value
& 0xFFFFFFFF);
272 FPR_STATE
[fpr
+ 1] = fmt
;
273 FPR_STATE
[fpr
] = fmt
;
277 FPR_STATE
[fpr
] = fmt_unknown
;
278 FPR_STATE
[fpr
+ 1] = fmt_unknown
;
279 SignalException (ReservedInstruction
, 0);
284 FPR_STATE
[fpr
] = fmt_unknown
;
291 SignalExceptionSimulatorFault ("Unrecognised FP format in StoreFPR ()");
294 printf ("DBG: StoreFPR: fpr[%d] = 0x%s (format %s)\n",
295 fpr
, pr_uword64 (FGR
[fpr
]), fpu_format_name (fmt
));
302 /* CP1 control/status registers */
305 test_fcsr (sim_cpu
*cpu
,
310 cause
= (FCSR
& fcsr_CAUSE_mask
) >> fcsr_CAUSE_shift
;
311 if ((cause
& ((FCSR
& fcsr_ENABLES_mask
) >> fcsr_ENABLES_shift
)) != 0
312 || (cause
& (1 << UO
)))
314 SignalExceptionFPE();
319 value_fcr(sim_cpu
*cpu
,
323 unsigned32 value
= 0;
327 case 0: /* FP Implementation and Revision Register */
330 case 25: /* FP Condition Codes Register */
331 value
= (FCR31
& fcsr_FCC_mask
) >> fcsr_FCC_shift
;
332 value
= (value
& 0x1) | (value
>> 1); /* close FCC gap */
334 case 26: /* FP Exceptions Register */
335 value
= FCR31
& (fcsr_CAUSE_mask
| fcsr_FLAGS_mask
);
337 case 28: /* FP Enables Register */
338 value
= FCR31
& (fcsr_ENABLES_mask
| fcsr_RM_mask
);
340 value
|= 0x4; /* nonstandard FS bit */
342 case 31: /* FP Control/Status Register */
343 value
= FCR31
& ~fcsr_ZERO_mask
;
347 return (EXTEND32 (value
));
351 store_fcr(sim_cpu
*cpu
,
361 case 25: /* FP Condition Codes Register */
362 v
= (v
<< 1) | (v
& 0x1); /* adjust for FCC gap */
363 FCR31
&= ~fcsr_FCC_mask
;
364 FCR31
|= ((v
<< fcsr_FCC_shift
) & fcsr_FCC_mask
);
366 case 26: /* FP Exceptions Register */
367 FCR31
&= ~(fcsr_CAUSE_mask
| fcsr_FLAGS_mask
);
368 FCR31
|= (v
& (fcsr_CAUSE_mask
| fcsr_FLAGS_mask
));
371 case 28: /* FP Enables Register */
372 if (v
& 0x4) /* nonstandard FS bit */
376 FCR31
&= (fcsr_FCC_mask
| fcsr_CAUSE_mask
| fcsr_FLAGS_mask
);
377 FCR31
|= (v
& (fcsr_FS
| fcsr_ENABLES_mask
| fcsr_RM_mask
));
380 case 31: /* FP Control/Status Register */
381 FCR31
= v
& ~fcsr_ZERO_mask
;
388 update_fcsr (sim_cpu
*cpu
,
390 sim_fpu_status status
)
392 FCSR
&= ~fcsr_CAUSE_mask
;
396 unsigned int cause
= 0;
398 /* map between sim_fpu codes and MIPS FCSR */
399 if (status
& (sim_fpu_status_invalid_snan
400 | sim_fpu_status_invalid_isi
401 | sim_fpu_status_invalid_idi
402 | sim_fpu_status_invalid_zdz
403 | sim_fpu_status_invalid_imz
404 | sim_fpu_status_invalid_cmp
405 | sim_fpu_status_invalid_sqrt
406 | sim_fpu_status_invalid_cvi
))
408 if (status
& sim_fpu_status_invalid_div0
)
410 if (status
& sim_fpu_status_overflow
)
412 if (status
& sim_fpu_status_underflow
)
414 if (status
& sim_fpu_status_inexact
)
417 /* Implicit clearing of other bits by unimplemented done by callers. */
418 if (status
& sim_fpu_status_unimplemented
)
422 FCSR
|= (cause
<< fcsr_CAUSE_shift
);
423 test_fcsr (cpu
, cia
);
424 FCSR
|= ((cause
& ~(1 << UO
)) << fcsr_FLAGS_shift
);
430 rounding_mode(int rm
)
437 /* Round result to nearest representable value. When two
438 representable values are equally near, round to the value
439 that has a least significant bit of zero (i.e. is even). */
440 round
= sim_fpu_round_near
;
443 /* Round result to the value closest to, and not greater in
444 magnitude than, the result. */
445 round
= sim_fpu_round_zero
;
448 /* Round result to the value closest to, and not less than,
450 round
= sim_fpu_round_up
;
453 /* Round result to the value closest to, and not greater than,
455 round
= sim_fpu_round_down
;
459 fprintf (stderr
, "Bad switch\n");
466 /* Comparison operations. */
468 static sim_fpu_status
469 fp_test(unsigned64 op1
,
478 sim_fpu_status status
= 0;
479 int less
, equal
, unordered
;
481 /* The format type has already been checked: */
486 sim_fpu_32to (&wop1
, op1
);
487 sim_fpu_32to (&wop2
, op2
);
492 sim_fpu_64to (&wop1
, op1
);
493 sim_fpu_64to (&wop2
, op2
);
497 fprintf (stderr
, "Bad switch\n");
501 if (sim_fpu_is_nan (&wop1
) || sim_fpu_is_nan (&wop2
))
503 if ((cond
& (1 << 3)) ||
504 sim_fpu_is_snan (&wop1
) || sim_fpu_is_snan (&wop2
))
505 status
= sim_fpu_status_invalid_snan
;
514 status
|= sim_fpu_abs (&wop1
, &wop1
);
515 status
|= sim_fpu_abs (&wop2
, &wop2
);
517 equal
= sim_fpu_is_eq (&wop1
, &wop2
);
518 less
= !equal
&& sim_fpu_is_lt (&wop1
, &wop2
);
521 *condition
= (((cond
& (1 << 2)) && less
)
522 || ((cond
& (1 << 1)) && equal
)
523 || ((cond
& (1 << 0)) && unordered
));
537 sim_fpu_status status
= 0;
539 /* The format type should already have been checked: */
546 status
= fp_test(op1
, op2
, fmt
, abs
, cond
, &result
);
547 update_fcsr (cpu
, cia
, status
);
552 sim_io_eprintf (SD
, "Bad switch\n");
558 /* Basic arithmetic operations. */
561 fp_unary(sim_cpu
*cpu
,
563 int (*sim_fpu_op
)(sim_fpu
*, const sim_fpu
*),
569 unsigned64 result
= 0;
571 /* The format type has already been checked: */
577 sim_fpu_32to (&wop
, op
);
578 (*sim_fpu_op
) (&ans
, &wop
);
579 sim_fpu_to32 (&res
, &ans
);
586 sim_fpu_64to (&wop
, op
);
587 (*sim_fpu_op
) (&ans
, &wop
);
588 sim_fpu_to64 (&res
, &ans
);
593 sim_io_eprintf (SD
, "Bad switch\n");
601 fp_binary(sim_cpu
*cpu
,
603 int (*sim_fpu_op
)(sim_fpu
*, const sim_fpu
*, const sim_fpu
*),
611 unsigned64 result
= 0;
613 /* The format type has already been checked: */
619 sim_fpu_32to (&wop1
, op1
);
620 sim_fpu_32to (&wop2
, op2
);
621 (*sim_fpu_op
) (&ans
, &wop1
, &wop2
);
622 sim_fpu_to32 (&res
, &ans
);
629 sim_fpu_64to (&wop1
, op1
);
630 sim_fpu_64to (&wop2
, op2
);
631 (*sim_fpu_op
) (&ans
, &wop1
, &wop2
);
632 sim_fpu_to64 (&res
, &ans
);
637 sim_io_eprintf (SD
, "Bad switch\n");
651 return fp_unary(cpu
, cia
, &sim_fpu_abs
, op
, fmt
);
660 return fp_unary(cpu
, cia
, &sim_fpu_neg
, op
, fmt
);
670 return fp_binary(cpu
, cia
, &sim_fpu_add
, op1
, op2
, fmt
);
680 return fp_binary(cpu
, cia
, &sim_fpu_sub
, op1
, op2
, fmt
);
690 return fp_binary(cpu
, cia
, &sim_fpu_mul
, op1
, op2
, fmt
);
700 return fp_binary(cpu
, cia
, &sim_fpu_div
, op1
, op2
, fmt
);
704 fp_recip(sim_cpu
*cpu
,
709 return fp_unary(cpu
, cia
, &sim_fpu_inv
, op
, fmt
);
713 fp_sqrt(sim_cpu
*cpu
,
718 return fp_unary(cpu
, cia
, &sim_fpu_sqrt
, op
, fmt
);
722 /* Conversion operations. */
725 convert (sim_cpu
*cpu
,
733 sim_fpu_round round
= rounding_mode (rm
);
737 /* Convert the input to sim_fpu internal format */
741 sim_fpu_64to (&wop
, op
);
744 sim_fpu_32to (&wop
, op
);
747 sim_fpu_i32to (&wop
, op
, round
);
750 sim_fpu_i64to (&wop
, op
, round
);
753 fprintf (stderr
, "Bad switch\n");
757 /* Convert sim_fpu format into the output */
758 /* The value WOP is converted to the destination format, rounding
759 using mode RM. When the destination is a fixed-point format, then
760 a source value of Infinity, NaN or one which would round to an
761 integer outside the fixed point range then an IEEE Invalid
762 Operation condition is raised. */
766 sim_fpu_round_32 (&wop
, round
, 0);
767 sim_fpu_to32 (&result32
, &wop
);
771 sim_fpu_round_64 (&wop
, round
, 0);
772 sim_fpu_to64 (&result64
, &wop
);
775 sim_fpu_to32i (&result32
, &wop
, round
);
779 sim_fpu_to64i (&result64
, &wop
, round
);
783 fprintf (stderr
, "Bad switch\n");
788 printf ("DBG: Convert: returning 0x%s (to format = %s)\n",
789 pr_addr (result64
), fpu_format_name (to
));
796 fpu_format_name (FP_formats fmt
)
810 case fmt_uninterpreted
:
811 return "<uninterpreted>";
812 case fmt_uninterpreted_32
:
813 return "<uninterpreted_32>";
814 case fmt_uninterpreted_64
:
815 return "<uninterpreted_64>";
817 return "<format error>";
823 fpu_rounding_mode_name (int rm
)
836 return "<rounding mode error>";