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