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