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