]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/mips/cp1.c
Copyright updates for 2007.
[thirdparty/binutils-gdb.git] / sim / mips / cp1.c
CommitLineData
487f79b7 1/*> cp1.c <*/
d3eb724f 2/* MIPS Simulator FPU (CoProcessor 1) support.
6aba47ca 3 Copyright (C) 2002, 2007 Free Software Foundation, Inc.
dd69d292
CD
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).
d3eb724f
CD
8
9This file is part of GDB, the GNU debugger.
10
11This program is free software; you can redistribute it and/or modify
12it under the terms of the GNU General Public License as published by
13the Free Software Foundation; either version 2, or (at your option)
14any later version.
15
16This program is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19GNU General Public License for more details.
20
21You should have received a copy of the GNU General Public License along
22with this program; if not, write to the Free Software Foundation, Inc.,
2359 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24
25/* XXX: The following notice should be removed as soon as is practical: */
487f79b7
CD
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
d3eb724f 31 (by Cygnus.)
487f79b7
CD
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"
487f79b7
CD
45
46/* Within cp1.c we refer to sim_cpu directly. */
47#define CPU cpu
18d8a52d 48#define SD CPU_STATE(cpu)
487f79b7
CD
49
50/*-- FPU support routines ---------------------------------------------------*/
51
52/* Numbers are held in normalized form. The SINGLE and DOUBLE binary
bad673a9
CD
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
3a2b820e
CD
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]
487f79b7
CD
84 */
85
3a2b820e
CD
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
52714ff9 92/* Explicit QNaN values. */
487f79b7
CD
93#define FPQNaN_SINGLE (0x7FBFFFFF)
94#define FPQNaN_WORD (0x7FFFFFFF)
bad673a9
CD
95#define FPQNaN_DOUBLE (UNSIGNED64 (0x7FF7FFFFFFFFFFFF))
96#define FPQNaN_LONG (UNSIGNED64 (0x7FFFFFFFFFFFFFFF))
3a2b820e 97#define FPQNaN_PS (FP_PS_cat (FPQNaN_SINGLE, FPQNaN_SINGLE))
487f79b7 98
07892c0b
CD
99static const char *fpu_format_name (FP_formats fmt);
100#ifdef DEBUG
101static const char *fpu_rounding_mode_name (int rm);
102#endif
487f79b7
CD
103
104uword64
18d8a52d 105value_fpr (sim_cpu *cpu,
487f79b7
CD
106 address_word cia,
107 int fpr,
108 FP_formats fmt)
109{
110 uword64 value = 0;
111 int err = 0;
112
52714ff9 113 /* Treat unused register values, as fixed-point 64bit values. */
487f79b7 114 if ((fmt == fmt_uninterpreted) || (fmt == fmt_unknown))
37d146fa 115 {
487f79b7 116#if 1
37d146fa
CD
117 /* If request to read data as "uninterpreted", then use the current
118 encoding: */
119 fmt = FPR_STATE[fpr];
487f79b7 120#else
37d146fa 121 fmt = fmt_long;
487f79b7 122#endif
37d146fa 123 }
487f79b7 124
52714ff9 125 /* For values not yet accessed, set to the desired format. */
37d146fa
CD
126 if (FPR_STATE[fpr] == fmt_uninterpreted)
127 {
128 FPR_STATE[fpr] = fmt;
487f79b7 129#ifdef DEBUG
37d146fa
CD
130 printf ("DBG: Register %d was fmt_uninterpreted. Now %s\n", fpr,
131 fpu_format_name (fmt));
487f79b7 132#endif /* DEBUG */
487f79b7 133 }
37d146fa
CD
134 if (fmt != FPR_STATE[fpr])
135 {
18d8a52d 136 sim_io_eprintf (SD, "FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",
37d146fa
CD
137 fpr, fpu_format_name (FPR_STATE[fpr]),
138 fpu_format_name (fmt), pr_addr (cia));
139 FPR_STATE[fpr] = fmt_unknown;
140 }
487f79b7 141
37d146fa
CD
142 if (FPR_STATE[fpr] == fmt_unknown)
143 {
144 /* Set QNaN value: */
145 switch (fmt)
146 {
196496ed
CD
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;
3a2b820e 151 case fmt_ps: value = FPQNaN_PS; break;
196496ed 152 default: err = -1; break;
37d146fa
CD
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:
3a2b820e 167 case fmt_ps:
37d146fa
CD
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 {
52714ff9 190 /* Even register numbers only. */
487f79b7 191#ifdef DEBUG
37d146fa
CD
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]));
487f79b7 195#endif
37d146fa
CD
196 value = ((((uword64) FGR[fpr+1]) << 32)
197 | (FGR[fpr] & 0xFFFFFFFF));
198 }
199 else
200 {
201 SignalException (ReservedInstruction, 0);
202 }
203 break;
204
3a2b820e
CD
205 case fmt_ps:
206 SignalException (ReservedInstruction, 0);
207 break;
208
e80fc152 209 default:
37d146fa
CD
210 err = -1;
211 break;
212 }
487f79b7 213 }
487f79b7
CD
214
215 if (err)
37d146fa 216 SignalExceptionSimulatorFault ("Unrecognised FP format in ValueFPR ()");
487f79b7
CD
217
218#ifdef DEBUG
37d146fa
CD
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 ());
487f79b7
CD
222#endif /* DEBUG */
223
37d146fa 224 return (value);
487f79b7
CD
225}
226
227void
18d8a52d 228store_fpr (sim_cpu *cpu,
487f79b7
CD
229 address_word cia,
230 int fpr,
231 FP_formats fmt,
232 uword64 value)
233{
234 int err = 0;
235
236#ifdef DEBUG
37d146fa
CD
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 ());
487f79b7
CD
240#endif /* DEBUG */
241
37d146fa
CD
242 if (SizeFGR () == 64)
243 {
244 switch (fmt)
245 {
246 case fmt_uninterpreted_32:
247 fmt = fmt_uninterpreted;
e80fc152
CD
248 case fmt_single:
249 case fmt_word:
37d146fa
CD
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:
e80fc152
CD
261 case fmt_double:
262 case fmt_long:
3a2b820e 263 case fmt_ps:
37d146fa
CD
264 FGR[fpr] = value;
265 FPR_STATE[fpr] = fmt;
266 break;
267
e80fc152 268 default:
37d146fa
CD
269 FPR_STATE[fpr] = fmt_unknown;
270 err = -1;
271 break;
272 }
487f79b7 273 }
37d146fa
CD
274 else
275 {
276 switch (fmt)
277 {
278 case fmt_uninterpreted_32:
279 fmt = fmt_uninterpreted;
e80fc152
CD
280 case fmt_single:
281 case fmt_word:
487f79b7 282 FGR[fpr] = (value & 0xFFFFFFFF);
487f79b7 283 FPR_STATE[fpr] = fmt;
37d146fa
CD
284 break;
285
286 case fmt_uninterpreted_64:
287 fmt = fmt_uninterpreted;
288 case fmt_uninterpreted:
e80fc152
CD
289 case fmt_double:
290 case fmt_long:
37d146fa
CD
291 if ((fpr & 1) == 0)
292 {
196496ed 293 /* Even register numbers only. */
37d146fa
CD
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
3a2b820e
CD
307 case fmt_ps:
308 FPR_STATE[fpr] = fmt_unknown;
309 SignalException (ReservedInstruction, 0);
310 break;
311
e80fc152 312 default:
487f79b7 313 FPR_STATE[fpr] = fmt_unknown;
37d146fa
CD
314 err = -1;
315 break;
487f79b7 316 }
487f79b7 317 }
487f79b7
CD
318
319 if (err)
37d146fa 320 SignalExceptionSimulatorFault ("Unrecognised FP format in StoreFPR ()");
487f79b7
CD
321
322#ifdef DEBUG
37d146fa
CD
323 printf ("DBG: StoreFPR: fpr[%d] = 0x%s (format %s)\n",
324 fpr, pr_uword64 (FGR[fpr]), fpu_format_name (fmt));
487f79b7
CD
325#endif /* DEBUG */
326
327 return;
328}
329
cfe9ea23 330
52714ff9 331/* CP1 control/status register access functions. */
cfe9ea23
CD
332
333void
334test_fcsr (sim_cpu *cpu,
335 address_word cia)
487f79b7 336{
cfe9ea23
CD
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)))
487f79b7 342 {
cfe9ea23 343 SignalExceptionFPE();
487f79b7 344 }
cfe9ea23 345}
487f79b7 346
cfe9ea23
CD
347unsigned_word
348value_fcr(sim_cpu *cpu,
349 address_word cia,
350 int fcr)
351{
352 unsigned32 value = 0;
353
354 switch (fcr)
355 {
52714ff9 356 case 0: /* FP Implementation and Revision Register. */
cfe9ea23
CD
357 value = FCR0;
358 break;
52714ff9 359 case 25: /* FP Condition Codes Register (derived from FCSR). */
cfe9ea23 360 value = (FCR31 & fcsr_FCC_mask) >> fcsr_FCC_shift;
52714ff9 361 value = (value & 0x1) | (value >> 1); /* Close FCC gap. */
cfe9ea23 362 break;
52714ff9 363 case 26: /* FP Exceptions Register (derived from FCSR). */
cfe9ea23
CD
364 value = FCR31 & (fcsr_CAUSE_mask | fcsr_FLAGS_mask);
365 break;
52714ff9 366 case 28: /* FP Enables Register (derived from FCSR). */
cfe9ea23 367 value = FCR31 & (fcsr_ENABLES_mask | fcsr_RM_mask);
52714ff9
CD
368 if ((FCR31 & fcsr_FS) != 0)
369 value |= fenr_FS;
cfe9ea23 370 break;
52714ff9 371 case 31: /* FP Control/Status Register (FCSR). */
cfe9ea23
CD
372 value = FCR31 & ~fcsr_ZERO_mask;
373 break;
374 }
375
376 return (EXTEND32 (value));
377}
378
379void
380store_fcr(sim_cpu *cpu,
381 address_word cia,
382 int fcr,
383 unsigned_word value)
384{
385 unsigned32 v;
487f79b7 386
cfe9ea23
CD
387 v = VL4_8(value);
388 switch (fcr)
389 {
52714ff9
CD
390 case 25: /* FP Condition Codes Register (stored into FCSR). */
391 v = (v << 1) | (v & 0x1); /* Adjust for FCC gap. */
cfe9ea23
CD
392 FCR31 &= ~fcsr_FCC_mask;
393 FCR31 |= ((v << fcsr_FCC_shift) & fcsr_FCC_mask);
394 break;
52714ff9 395 case 26: /* FP Exceptions Register (stored into FCSR). */
cfe9ea23
CD
396 FCR31 &= ~(fcsr_CAUSE_mask | fcsr_FLAGS_mask);
397 FCR31 |= (v & (fcsr_CAUSE_mask | fcsr_FLAGS_mask));
398 test_fcsr(cpu, cia);
399 break;
52714ff9
CD
400 case 28: /* FP Enables Register (stored into FCSR). */
401 if ((v & fenr_FS) != 0)
cfe9ea23
CD
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;
52714ff9 409 case 31: /* FP Control/Status Register (FCSR). */
cfe9ea23
CD
410 FCR31 = v & ~fcsr_ZERO_mask;
411 test_fcsr(cpu, cia);
412 break;
413 }
487f79b7
CD
414}
415
cfe9ea23
CD
416void
417update_fcsr (sim_cpu *cpu,
418 address_word cia,
419 sim_fpu_status status)
487f79b7 420{
cfe9ea23 421 FCSR &= ~fcsr_CAUSE_mask;
487f79b7 422
cfe9ea23
CD
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. */
52714ff9 446 /* Implicit clearing of other bits by unimplemented done by callers. */
cfe9ea23
CD
447 if (status & sim_fpu_status_unimplemented)
448 cause |= (1 << UO);
449#endif
487f79b7 450
cfe9ea23
CD
451 FCSR |= (cause << fcsr_CAUSE_shift);
452 test_fcsr (cpu, cia);
453 FCSR |= ((cause & ~(1 << UO)) << fcsr_FLAGS_shift);
454 }
455 return;
456}
457
577d8c4b
CD
458static sim_fpu_round
459rounding_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
52714ff9 468 that has a least significant bit of zero (i.e. is even). */
577d8c4b
CD
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
52714ff9 473 magnitude than, the result. */
577d8c4b
CD
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,
52714ff9 478 the result. */
577d8c4b
CD
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,
52714ff9 483 the result. */
577d8c4b
CD
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
52714ff9
CD
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. */
498static sim_fpu_denorm
499denorm_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
cfe9ea23
CD
511
512/* Comparison operations. */
513
514static sim_fpu_status
515fp_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;
487f79b7 526
cfe9ea23 527 /* The format type has already been checked: */
37d146fa 528 switch (fmt)
487f79b7 529 {
37d146fa
CD
530 case fmt_single:
531 {
37d146fa
CD
532 sim_fpu_32to (&wop1, op1);
533 sim_fpu_32to (&wop2, op2);
37d146fa
CD
534 break;
535 }
536 case fmt_double:
537 {
37d146fa
CD
538 sim_fpu_64to (&wop1, op1);
539 sim_fpu_64to (&wop2, op2);
37d146fa
CD
540 break;
541 }
542 default:
543 fprintf (stderr, "Bad switch\n");
544 abort ();
487f79b7 545 }
487f79b7 546
cfe9ea23
CD
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;
487f79b7
CD
571}
572
cfe9ea23
CD
573void
574fp_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)
487f79b7 582{
cfe9ea23 583 sim_fpu_status status = 0;
487f79b7 584
52714ff9
CD
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. */
37d146fa 588 switch (fmt)
487f79b7 589 {
37d146fa 590 case fmt_single:
37d146fa
CD
591 case fmt_double:
592 {
cfe9ea23
CD
593 int result;
594 status = fp_test(op1, op2, fmt, abs, cond, &result);
595 update_fcsr (cpu, cia, status);
596 SETFCC (cc, result);
37d146fa
CD
597 break;
598 }
3a2b820e
CD
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 }
37d146fa 611 default:
cfe9ea23 612 sim_io_eprintf (SD, "Bad switch\n");
37d146fa 613 abort ();
487f79b7 614 }
487f79b7
CD
615}
616
487f79b7 617
ba46ddd0 618/* Basic arithmetic operations. */
487f79b7 619
ba46ddd0
CD
620static unsigned64
621fp_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)
487f79b7 626{
ba46ddd0
CD
627 sim_fpu wop;
628 sim_fpu ans;
52714ff9
CD
629 sim_fpu_round round = rounding_mode (GETRM());
630 sim_fpu_denorm denorm = denorm_mode (cpu);
631 sim_fpu_status status = 0;
ba46ddd0 632 unsigned64 result = 0;
487f79b7 633
ba46ddd0 634 /* The format type has already been checked: */
37d146fa 635 switch (fmt)
487f79b7 636 {
37d146fa
CD
637 case fmt_single:
638 {
37d146fa 639 unsigned32 res;
ba46ddd0 640 sim_fpu_32to (&wop, op);
52714ff9
CD
641 status |= (*sim_fpu_op) (&ans, &wop);
642 status |= sim_fpu_round_32 (&ans, round, denorm);
37d146fa
CD
643 sim_fpu_to32 (&res, &ans);
644 result = res;
645 break;
646 }
647 case fmt_double:
648 {
37d146fa 649 unsigned64 res;
ba46ddd0 650 sim_fpu_64to (&wop, op);
52714ff9
CD
651 status |= (*sim_fpu_op) (&ans, &wop);
652 status |= sim_fpu_round_64 (&ans, round, denorm);
37d146fa
CD
653 sim_fpu_to64 (&res, &ans);
654 result = res;
655 break;
656 }
3a2b820e
CD
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 }
37d146fa 671 default:
ba46ddd0 672 sim_io_eprintf (SD, "Bad switch\n");
37d146fa 673 abort ();
487f79b7 674 }
487f79b7 675
52714ff9 676 update_fcsr (cpu, cia, status);
ba46ddd0 677 return result;
487f79b7
CD
678}
679
ba46ddd0
CD
680static unsigned64
681fp_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)
487f79b7 687{
ba46ddd0
CD
688 sim_fpu wop1;
689 sim_fpu wop2;
690 sim_fpu ans;
52714ff9
CD
691 sim_fpu_round round = rounding_mode (GETRM());
692 sim_fpu_denorm denorm = denorm_mode (cpu);
693 sim_fpu_status status = 0;
ba46ddd0 694 unsigned64 result = 0;
487f79b7 695
ba46ddd0 696 /* The format type has already been checked: */
37d146fa 697 switch (fmt)
487f79b7 698 {
37d146fa
CD
699 case fmt_single:
700 {
37d146fa
CD
701 unsigned32 res;
702 sim_fpu_32to (&wop1, op1);
703 sim_fpu_32to (&wop2, op2);
52714ff9
CD
704 status |= (*sim_fpu_op) (&ans, &wop1, &wop2);
705 status |= sim_fpu_round_32 (&ans, round, denorm);
37d146fa
CD
706 sim_fpu_to32 (&res, &ans);
707 result = res;
708 break;
709 }
710 case fmt_double:
711 {
37d146fa
CD
712 unsigned64 res;
713 sim_fpu_64to (&wop1, op1);
714 sim_fpu_64to (&wop2, op2);
52714ff9
CD
715 status |= (*sim_fpu_op) (&ans, &wop1, &wop2);
716 status |= sim_fpu_round_64 (&ans, round, denorm);
37d146fa
CD
717 sim_fpu_to64 (&res, &ans);
718 result = res;
719 break;
720 }
3a2b820e
CD
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 }
37d146fa 737 default:
ba46ddd0 738 sim_io_eprintf (SD, "Bad switch\n");
37d146fa 739 abort ();
487f79b7 740 }
487f79b7 741
52714ff9 742 update_fcsr (cpu, cia, status);
ba46ddd0 743 return result;
487f79b7
CD
744}
745
f3c08b7e
CD
746/* Common MAC code for single operands (.s or .d), defers setting FCSR. */
747static sim_fpu_status
748inner_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. */
834static unsigned64
835fp_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;
3a2b820e
CD
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 }
f3c08b7e
CD
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. */
882static sim_fpu_status
883inner_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
933static unsigned64
934fp_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;
3a2b820e
CD
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 }
f3c08b7e
CD
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
487f79b7 972
ba46ddd0
CD
973unsigned64
974fp_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);
487f79b7
CD
980}
981
ba46ddd0
CD
982unsigned64
983fp_neg(sim_cpu *cpu,
984 address_word cia,
985 unsigned64 op,
986 FP_formats fmt)
487f79b7 987{
ba46ddd0 988 return fp_unary(cpu, cia, &sim_fpu_neg, op, fmt);
487f79b7
CD
989}
990
ba46ddd0
CD
991unsigned64
992fp_add(sim_cpu *cpu,
993 address_word cia,
994 unsigned64 op1,
995 unsigned64 op2,
996 FP_formats fmt)
487f79b7 997{
ba46ddd0
CD
998 return fp_binary(cpu, cia, &sim_fpu_add, op1, op2, fmt);
999}
487f79b7 1000
ba46ddd0
CD
1001unsigned64
1002fp_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}
487f79b7 1010
ba46ddd0
CD
1011unsigned64
1012fp_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}
487f79b7 1020
ba46ddd0
CD
1021unsigned64
1022fp_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}
487f79b7 1030
ba46ddd0
CD
1031unsigned64
1032fp_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}
487f79b7 1039
ba46ddd0
CD
1040unsigned64
1041fp_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);
487f79b7
CD
1047}
1048
f3c08b7e
CD
1049unsigned64
1050fp_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
1058unsigned64
1059fp_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
1069unsigned64
1070fp_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
1080unsigned64
1081fp_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
1091unsigned64
1092fp_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
ba46ddd0 1102
e7e81181
CD
1103/* MIPS-3D ASE operations. */
1104
1105/* Variant of fp_binary for *r.ps MIPS-3D operations. */
1106static unsigned64
1107fp_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
1141unsigned64
1142fp_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
1151unsigned64
1152fp_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
1164static int
1165fpu_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
1189static int
1190fpu_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
1201static int
1202fpu_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
1213unsigned64
1214fp_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
1230unsigned64
1231fp_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);
2265c243 1239 static const unsigned64 one_ps = (UNSIGNED64 (0x3F800000) << 32 | UNSIGNED64 (0x3F800000));
e7e81181
CD
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
1253static int
1254fpu_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
1287static int
1288fpu_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
1299static int
1300fpu_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
1311unsigned64
1312fp_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
1328unsigned64
1329fp_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);
2265c243 1337 static const unsigned64 half_ps = (UNSIGNED64 (0x3F000000) << 32 | UNSIGNED64 (0x3F000000));
e7e81181
CD
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
cfe9ea23
CD
1353/* Conversion operations. */
1354
487f79b7 1355uword64
18d8a52d 1356convert (sim_cpu *cpu,
487f79b7
CD
1357 address_word cia,
1358 int rm,
1359 uword64 op,
1360 FP_formats from,
1361 FP_formats to)
1362{
1363 sim_fpu wop;
577d8c4b 1364 sim_fpu_round round = rounding_mode (rm);
52714ff9 1365 sim_fpu_denorm denorm = denorm_mode (cpu);
487f79b7
CD
1366 unsigned32 result32;
1367 unsigned64 result64;
52714ff9 1368 sim_fpu_status status = 0;
487f79b7 1369
487f79b7
CD
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:
52714ff9 1380 status = sim_fpu_i32to (&wop, op, round);
487f79b7
CD
1381 break;
1382 case fmt_long:
52714ff9 1383 status = sim_fpu_i64to (&wop, op, round);
487f79b7
CD
1384 break;
1385 default:
52714ff9 1386 sim_io_eprintf (SD, "Bad switch\n");
487f79b7
CD
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
3a2b820e
CD
1394 integer outside the fixed point range then an IEEE Invalid Operation
1395 condition is raised. Not used if destination format is PS. */
487f79b7
CD
1396 switch (to)
1397 {
1398 case fmt_single:
52714ff9
CD
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;
487f79b7
CD
1403 sim_fpu_to32 (&result32, &wop);
1404 result64 = result32;
1405 break;
1406 case fmt_double:
52714ff9
CD
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;
487f79b7
CD
1411 sim_fpu_to64 (&result64, &wop);
1412 break;
1413 case fmt_word:
52714ff9 1414 status |= sim_fpu_to32i (&result32, &wop, round);
487f79b7
CD
1415 result64 = result32;
1416 break;
1417 case fmt_long:
52714ff9 1418 status |= sim_fpu_to64i (&result64, &wop, round);
487f79b7
CD
1419 break;
1420 default:
1421 result64 = 0;
52714ff9 1422 sim_io_eprintf (SD, "Bad switch\n");
487f79b7
CD
1423 abort ();
1424 }
37d146fa 1425
52714ff9
CD
1426 update_fcsr (cpu, cia, status);
1427 return result64;
487f79b7
CD
1428}
1429
3a2b820e
CD
1430unsigned64
1431ps_lower(sim_cpu *cpu,
1432 address_word cia,
1433 unsigned64 op)
1434{
1435 return FP_PS_lower (op);
1436}
1437
1438unsigned64
1439ps_upper(sim_cpu *cpu,
1440 address_word cia,
1441 unsigned64 op)
1442{
1443 return FP_PS_upper(op);
1444}
1445
1446unsigned64
1447pack_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
1480unsigned64
1481convert_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
07892c0b
CD
1538static const char *
1539fpu_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";
3a2b820e
CD
1551 case fmt_ps:
1552 return "ps";
07892c0b
CD
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}
487f79b7 1565
07892c0b
CD
1566#ifdef DEBUG
1567static const char *
1568fpu_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 */