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