]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/mips/cp1.c
2002-06-07 Chris Demetriou <cgd@broadcom.com>
[thirdparty/binutils-gdb.git] / sim / mips / cp1.c
CommitLineData
487f79b7 1/*> cp1.c <*/
d3eb724f
CD
2/* MIPS Simulator FPU (CoProcessor 1) support.
3 Copyright (C) 2002 Free Software Foundation, Inc.
4 Originally created by Cygnus Solutions, modified substially
5 by Broadcom Corporation (SiByte).
6
7This file is part of GDB, the GNU debugger.
8
9This program is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 2, or (at your option)
12any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License along
20with this program; if not, write to the Free Software Foundation, Inc.,
2159 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22
23/* XXX: The following notice should be removed as soon as is practical: */
487f79b7
CD
24/* Floating Point Support for gdb MIPS simulators
25
26 This file is part of the MIPS sim
27
28 THIS SOFTWARE IS NOT COPYRIGHTED
d3eb724f 29 (by Cygnus.)
487f79b7
CD
30
31 Cygnus offers the following for use in the public domain. Cygnus
32 makes no warranty with regard to the software or it's performance
33 and the user accepts the software "AS IS" with all faults.
34
35 CYGNUS DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO
36 THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
37 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
38
39 (Originally, this code was in interp.c)
40*/
41
42#include "sim-main.h"
487f79b7
CD
43
44/* Within cp1.c we refer to sim_cpu directly. */
45#define CPU cpu
18d8a52d 46#define SD CPU_STATE(cpu)
487f79b7
CD
47
48/*-- FPU support routines ---------------------------------------------------*/
49
50/* Numbers are held in normalized form. The SINGLE and DOUBLE binary
bad673a9
CD
51 formats conform to ANSI/IEEE Std 754-1985.
52
53 SINGLE precision floating:
54 seeeeeeeefffffffffffffffffffffff
55 s = 1bit = sign
56 e = 8bits = exponent
57 f = 23bits = fraction
58
59 SINGLE precision fixed:
60 siiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
61 s = 1bit = sign
62 i = 31bits = integer
63
64 DOUBLE precision floating:
65 seeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffff
66 s = 1bit = sign
67 e = 11bits = exponent
68 f = 52bits = fraction
69
70 DOUBLE precision fixed:
71 siiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
72 s = 1bit = sign
73 i = 63bits = integer
487f79b7
CD
74 */
75
37d146fa 76/* Explicit QNaN values used when value required: */
487f79b7
CD
77#define FPQNaN_SINGLE (0x7FBFFFFF)
78#define FPQNaN_WORD (0x7FFFFFFF)
bad673a9
CD
79#define FPQNaN_DOUBLE (UNSIGNED64 (0x7FF7FFFFFFFFFFFF))
80#define FPQNaN_LONG (UNSIGNED64 (0x7FFFFFFFFFFFFFFF))
487f79b7 81
07892c0b
CD
82static const char *fpu_format_name (FP_formats fmt);
83#ifdef DEBUG
84static const char *fpu_rounding_mode_name (int rm);
85#endif
487f79b7
CD
86
87uword64
18d8a52d 88value_fpr (sim_cpu *cpu,
487f79b7
CD
89 address_word cia,
90 int fpr,
91 FP_formats fmt)
92{
93 uword64 value = 0;
94 int err = 0;
95
37d146fa 96 /* Treat unused register values, as fixed-point 64bit values: */
487f79b7 97 if ((fmt == fmt_uninterpreted) || (fmt == fmt_unknown))
37d146fa 98 {
487f79b7 99#if 1
37d146fa
CD
100 /* If request to read data as "uninterpreted", then use the current
101 encoding: */
102 fmt = FPR_STATE[fpr];
487f79b7 103#else
37d146fa 104 fmt = fmt_long;
487f79b7 105#endif
37d146fa 106 }
487f79b7 107
37d146fa
CD
108 /* For values not yet accessed, set to the desired format: */
109 if (FPR_STATE[fpr] == fmt_uninterpreted)
110 {
111 FPR_STATE[fpr] = fmt;
487f79b7 112#ifdef DEBUG
37d146fa
CD
113 printf ("DBG: Register %d was fmt_uninterpreted. Now %s\n", fpr,
114 fpu_format_name (fmt));
487f79b7 115#endif /* DEBUG */
487f79b7 116 }
37d146fa
CD
117 if (fmt != FPR_STATE[fpr])
118 {
18d8a52d 119 sim_io_eprintf (SD, "FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",
37d146fa
CD
120 fpr, fpu_format_name (FPR_STATE[fpr]),
121 fpu_format_name (fmt), pr_addr (cia));
122 FPR_STATE[fpr] = fmt_unknown;
123 }
487f79b7 124
37d146fa
CD
125 if (FPR_STATE[fpr] == fmt_unknown)
126 {
127 /* Set QNaN value: */
128 switch (fmt)
129 {
196496ed
CD
130 case fmt_single: value = FPQNaN_SINGLE; break;
131 case fmt_double: value = FPQNaN_DOUBLE; break;
132 case fmt_word: value = FPQNaN_WORD; break;
133 case fmt_long: value = FPQNaN_LONG; break;
134 default: err = -1; break;
37d146fa
CD
135 }
136 }
137 else if (SizeFGR () == 64)
138 {
139 switch (fmt)
140 {
141 case fmt_single:
142 case fmt_word:
143 value = (FGR[fpr] & 0xFFFFFFFF);
144 break;
145
146 case fmt_uninterpreted:
147 case fmt_double:
148 case fmt_long:
149 value = FGR[fpr];
150 break;
151
152 default:
153 err = -1;
154 break;
155 }
156 }
157 else
158 {
159 switch (fmt)
160 {
161 case fmt_single:
162 case fmt_word:
163 value = (FGR[fpr] & 0xFFFFFFFF);
164 break;
165
166 case fmt_uninterpreted:
167 case fmt_double:
168 case fmt_long:
169 if ((fpr & 1) == 0)
170 {
196496ed 171 /* Even registers numbers only. */
487f79b7 172#ifdef DEBUG
37d146fa
CD
173 printf ("DBG: ValueFPR: FGR[%d] = %s, FGR[%d] = %s\n",
174 fpr + 1, pr_uword64 ((uword64) FGR[fpr+1]),
175 fpr, pr_uword64 ((uword64) FGR[fpr]));
487f79b7 176#endif
37d146fa
CD
177 value = ((((uword64) FGR[fpr+1]) << 32)
178 | (FGR[fpr] & 0xFFFFFFFF));
179 }
180 else
181 {
182 SignalException (ReservedInstruction, 0);
183 }
184 break;
185
e80fc152 186 default:
37d146fa
CD
187 err = -1;
188 break;
189 }
487f79b7 190 }
487f79b7
CD
191
192 if (err)
37d146fa 193 SignalExceptionSimulatorFault ("Unrecognised FP format in ValueFPR ()");
487f79b7
CD
194
195#ifdef DEBUG
37d146fa
CD
196 printf ("DBG: ValueFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR () = %d\n",
197 fpr, fpu_format_name (fmt), pr_uword64 (value), pr_addr (cia),
198 SizeFGR ());
487f79b7
CD
199#endif /* DEBUG */
200
37d146fa 201 return (value);
487f79b7
CD
202}
203
204void
18d8a52d 205store_fpr (sim_cpu *cpu,
487f79b7
CD
206 address_word cia,
207 int fpr,
208 FP_formats fmt,
209 uword64 value)
210{
211 int err = 0;
212
213#ifdef DEBUG
37d146fa
CD
214 printf ("DBG: StoreFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR () = %d, \n",
215 fpr, fpu_format_name (fmt), pr_uword64 (value), pr_addr (cia),
216 SizeFGR ());
487f79b7
CD
217#endif /* DEBUG */
218
37d146fa
CD
219 if (SizeFGR () == 64)
220 {
221 switch (fmt)
222 {
223 case fmt_uninterpreted_32:
224 fmt = fmt_uninterpreted;
e80fc152
CD
225 case fmt_single:
226 case fmt_word:
37d146fa
CD
227 if (STATE_VERBOSE_P (SD))
228 sim_io_eprintf (SD,
229 "Warning: PC 0x%s: interp.c store_fpr DEADCODE\n",
230 pr_addr (cia));
231 FGR[fpr] = (((uword64) 0xDEADC0DE << 32) | (value & 0xFFFFFFFF));
232 FPR_STATE[fpr] = fmt;
233 break;
234
235 case fmt_uninterpreted_64:
236 fmt = fmt_uninterpreted;
237 case fmt_uninterpreted:
e80fc152
CD
238 case fmt_double:
239 case fmt_long:
37d146fa
CD
240 FGR[fpr] = value;
241 FPR_STATE[fpr] = fmt;
242 break;
243
e80fc152 244 default:
37d146fa
CD
245 FPR_STATE[fpr] = fmt_unknown;
246 err = -1;
247 break;
248 }
487f79b7 249 }
37d146fa
CD
250 else
251 {
252 switch (fmt)
253 {
254 case fmt_uninterpreted_32:
255 fmt = fmt_uninterpreted;
e80fc152
CD
256 case fmt_single:
257 case fmt_word:
487f79b7 258 FGR[fpr] = (value & 0xFFFFFFFF);
487f79b7 259 FPR_STATE[fpr] = fmt;
37d146fa
CD
260 break;
261
262 case fmt_uninterpreted_64:
263 fmt = fmt_uninterpreted;
264 case fmt_uninterpreted:
e80fc152
CD
265 case fmt_double:
266 case fmt_long:
37d146fa
CD
267 if ((fpr & 1) == 0)
268 {
196496ed 269 /* Even register numbers only. */
37d146fa
CD
270 FGR[fpr+1] = (value >> 32);
271 FGR[fpr] = (value & 0xFFFFFFFF);
272 FPR_STATE[fpr + 1] = fmt;
273 FPR_STATE[fpr] = fmt;
274 }
275 else
276 {
277 FPR_STATE[fpr] = fmt_unknown;
278 FPR_STATE[fpr + 1] = fmt_unknown;
279 SignalException (ReservedInstruction, 0);
280 }
281 break;
282
e80fc152 283 default:
487f79b7 284 FPR_STATE[fpr] = fmt_unknown;
37d146fa
CD
285 err = -1;
286 break;
487f79b7 287 }
487f79b7 288 }
487f79b7
CD
289
290 if (err)
37d146fa 291 SignalExceptionSimulatorFault ("Unrecognised FP format in StoreFPR ()");
487f79b7
CD
292
293#ifdef DEBUG
37d146fa
CD
294 printf ("DBG: StoreFPR: fpr[%d] = 0x%s (format %s)\n",
295 fpr, pr_uword64 (FGR[fpr]), fpu_format_name (fmt));
487f79b7
CD
296#endif /* DEBUG */
297
298 return;
299}
300
cfe9ea23
CD
301
302/* CP1 control/status registers */
303
304void
305test_fcsr (sim_cpu *cpu,
306 address_word cia)
487f79b7 307{
cfe9ea23
CD
308 unsigned int cause;
309
310 cause = (FCSR & fcsr_CAUSE_mask) >> fcsr_CAUSE_shift;
311 if ((cause & ((FCSR & fcsr_ENABLES_mask) >> fcsr_ENABLES_shift)) != 0
312 || (cause & (1 << UO)))
487f79b7 313 {
cfe9ea23 314 SignalExceptionFPE();
487f79b7 315 }
cfe9ea23 316}
487f79b7 317
cfe9ea23
CD
318unsigned_word
319value_fcr(sim_cpu *cpu,
320 address_word cia,
321 int fcr)
322{
323 unsigned32 value = 0;
324
325 switch (fcr)
326 {
327 case 0: /* FP Implementation and Revision Register */
328 value = FCR0;
329 break;
330 case 25: /* FP Condition Codes Register */
331 value = (FCR31 & fcsr_FCC_mask) >> fcsr_FCC_shift;
332 value = (value & 0x1) | (value >> 1); /* close FCC gap */
333 break;
334 case 26: /* FP Exceptions Register */
335 value = FCR31 & (fcsr_CAUSE_mask | fcsr_FLAGS_mask);
336 break;
337 case 28: /* FP Enables Register */
338 value = FCR31 & (fcsr_ENABLES_mask | fcsr_RM_mask);
339 if (FCR31 & fcsr_FS)
340 value |= 0x4; /* nonstandard FS bit */
341 break;
342 case 31: /* FP Control/Status Register */
343 value = FCR31 & ~fcsr_ZERO_mask;
344 break;
345 }
346
347 return (EXTEND32 (value));
348}
349
350void
351store_fcr(sim_cpu *cpu,
352 address_word cia,
353 int fcr,
354 unsigned_word value)
355{
356 unsigned32 v;
487f79b7 357
cfe9ea23
CD
358 v = VL4_8(value);
359 switch (fcr)
360 {
361 case 25: /* FP Condition Codes Register */
362 v = (v << 1) | (v & 0x1); /* adjust for FCC gap */
363 FCR31 &= ~fcsr_FCC_mask;
364 FCR31 |= ((v << fcsr_FCC_shift) & fcsr_FCC_mask);
365 break;
366 case 26: /* FP Exceptions Register */
367 FCR31 &= ~(fcsr_CAUSE_mask | fcsr_FLAGS_mask);
368 FCR31 |= (v & (fcsr_CAUSE_mask | fcsr_FLAGS_mask));
369 test_fcsr(cpu, cia);
370 break;
371 case 28: /* FP Enables Register */
372 if (v & 0x4) /* nonstandard FS bit */
373 v |= fcsr_FS;
374 else
375 v &= ~fcsr_FS;
376 FCR31 &= (fcsr_FCC_mask | fcsr_CAUSE_mask | fcsr_FLAGS_mask);
377 FCR31 |= (v & (fcsr_FS | fcsr_ENABLES_mask | fcsr_RM_mask));
378 test_fcsr(cpu, cia);
379 break;
380 case 31: /* FP Control/Status Register */
381 FCR31 = v & ~fcsr_ZERO_mask;
382 test_fcsr(cpu, cia);
383 break;
384 }
487f79b7
CD
385}
386
cfe9ea23
CD
387void
388update_fcsr (sim_cpu *cpu,
389 address_word cia,
390 sim_fpu_status status)
487f79b7 391{
cfe9ea23 392 FCSR &= ~fcsr_CAUSE_mask;
487f79b7 393
cfe9ea23
CD
394 if (status != 0)
395 {
396 unsigned int cause = 0;
397
398 /* map between sim_fpu codes and MIPS FCSR */
399 if (status & (sim_fpu_status_invalid_snan
400 | sim_fpu_status_invalid_isi
401 | sim_fpu_status_invalid_idi
402 | sim_fpu_status_invalid_zdz
403 | sim_fpu_status_invalid_imz
404 | sim_fpu_status_invalid_cmp
405 | sim_fpu_status_invalid_sqrt
406 | sim_fpu_status_invalid_cvi))
407 cause |= (1 << IO);
408 if (status & sim_fpu_status_invalid_div0)
409 cause |= (1 << DZ);
410 if (status & sim_fpu_status_overflow)
411 cause |= (1 << OF);
412 if (status & sim_fpu_status_underflow)
413 cause |= (1 << UF);
414 if (status & sim_fpu_status_inexact)
415 cause |= (1 << IR);
416#if 0 /* Not yet. */
417 /* Implicit clearing of other bits by unimplemented done by callers. */
418 if (status & sim_fpu_status_unimplemented)
419 cause |= (1 << UO);
420#endif
487f79b7 421
cfe9ea23
CD
422 FCSR |= (cause << fcsr_CAUSE_shift);
423 test_fcsr (cpu, cia);
424 FCSR |= ((cause & ~(1 << UO)) << fcsr_FLAGS_shift);
425 }
426 return;
427}
428
577d8c4b
CD
429static sim_fpu_round
430rounding_mode(int rm)
431{
432 sim_fpu_round round;
433
434 switch (rm)
435 {
436 case FP_RM_NEAREST:
437 /* Round result to nearest representable value. When two
438 representable values are equally near, round to the value
439 that has a least significant bit of zero (i.e. is even). */
440 round = sim_fpu_round_near;
441 break;
442 case FP_RM_TOZERO:
443 /* Round result to the value closest to, and not greater in
444 magnitude than, the result. */
445 round = sim_fpu_round_zero;
446 break;
447 case FP_RM_TOPINF:
448 /* Round result to the value closest to, and not less than,
449 the result. */
450 round = sim_fpu_round_up;
451 break;
452 case FP_RM_TOMINF:
453 /* Round result to the value closest to, and not greater than,
454 the result. */
455 round = sim_fpu_round_down;
456 break;
457 default:
458 round = 0;
459 fprintf (stderr, "Bad switch\n");
460 abort ();
461 }
462 return round;
463}
464
cfe9ea23
CD
465
466/* Comparison operations. */
467
468static sim_fpu_status
469fp_test(unsigned64 op1,
470 unsigned64 op2,
471 FP_formats fmt,
472 int abs,
473 int cond,
474 int *condition)
475{
476 sim_fpu wop1;
477 sim_fpu wop2;
478 sim_fpu_status status = 0;
479 int less, equal, unordered;
487f79b7 480
cfe9ea23 481 /* The format type has already been checked: */
37d146fa 482 switch (fmt)
487f79b7 483 {
37d146fa
CD
484 case fmt_single:
485 {
37d146fa
CD
486 sim_fpu_32to (&wop1, op1);
487 sim_fpu_32to (&wop2, op2);
37d146fa
CD
488 break;
489 }
490 case fmt_double:
491 {
37d146fa
CD
492 sim_fpu_64to (&wop1, op1);
493 sim_fpu_64to (&wop2, op2);
37d146fa
CD
494 break;
495 }
496 default:
497 fprintf (stderr, "Bad switch\n");
498 abort ();
487f79b7 499 }
487f79b7 500
cfe9ea23
CD
501 if (sim_fpu_is_nan (&wop1) || sim_fpu_is_nan (&wop2))
502 {
503 if ((cond & (1 << 3)) ||
504 sim_fpu_is_snan (&wop1) || sim_fpu_is_snan (&wop2))
505 status = sim_fpu_status_invalid_snan;
506 less = 0;
507 equal = 0;
508 unordered = 1;
509 }
510 else
511 {
512 if (abs)
513 {
514 status |= sim_fpu_abs (&wop1, &wop1);
515 status |= sim_fpu_abs (&wop2, &wop2);
516 }
517 equal = sim_fpu_is_eq (&wop1, &wop2);
518 less = !equal && sim_fpu_is_lt (&wop1, &wop2);
519 unordered = 0;
520 }
521 *condition = (((cond & (1 << 2)) && less)
522 || ((cond & (1 << 1)) && equal)
523 || ((cond & (1 << 0)) && unordered));
524 return status;
487f79b7
CD
525}
526
cfe9ea23
CD
527void
528fp_cmp(sim_cpu *cpu,
529 address_word cia,
530 unsigned64 op1,
531 unsigned64 op2,
532 FP_formats fmt,
533 int abs,
534 int cond,
535 int cc)
487f79b7 536{
cfe9ea23 537 sim_fpu_status status = 0;
487f79b7 538
cfe9ea23 539 /* The format type should already have been checked: */
37d146fa 540 switch (fmt)
487f79b7 541 {
37d146fa 542 case fmt_single:
37d146fa
CD
543 case fmt_double:
544 {
cfe9ea23
CD
545 int result;
546 status = fp_test(op1, op2, fmt, abs, cond, &result);
547 update_fcsr (cpu, cia, status);
548 SETFCC (cc, result);
37d146fa
CD
549 break;
550 }
551 default:
cfe9ea23 552 sim_io_eprintf (SD, "Bad switch\n");
37d146fa 553 abort ();
487f79b7 554 }
487f79b7
CD
555}
556
487f79b7 557
ba46ddd0 558/* Basic arithmetic operations. */
487f79b7 559
ba46ddd0
CD
560static unsigned64
561fp_unary(sim_cpu *cpu,
562 address_word cia,
563 int (*sim_fpu_op)(sim_fpu *, const sim_fpu *),
564 unsigned64 op,
565 FP_formats fmt)
487f79b7 566{
ba46ddd0
CD
567 sim_fpu wop;
568 sim_fpu ans;
569 unsigned64 result = 0;
487f79b7 570
ba46ddd0 571 /* The format type has already been checked: */
37d146fa 572 switch (fmt)
487f79b7 573 {
37d146fa
CD
574 case fmt_single:
575 {
37d146fa 576 unsigned32 res;
ba46ddd0
CD
577 sim_fpu_32to (&wop, op);
578 (*sim_fpu_op) (&ans, &wop);
37d146fa
CD
579 sim_fpu_to32 (&res, &ans);
580 result = res;
581 break;
582 }
583 case fmt_double:
584 {
37d146fa 585 unsigned64 res;
ba46ddd0
CD
586 sim_fpu_64to (&wop, op);
587 (*sim_fpu_op) (&ans, &wop);
37d146fa
CD
588 sim_fpu_to64 (&res, &ans);
589 result = res;
590 break;
591 }
592 default:
ba46ddd0 593 sim_io_eprintf (SD, "Bad switch\n");
37d146fa 594 abort ();
487f79b7 595 }
487f79b7 596
ba46ddd0 597 return result;
487f79b7
CD
598}
599
ba46ddd0
CD
600static unsigned64
601fp_binary(sim_cpu *cpu,
602 address_word cia,
603 int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *),
604 unsigned64 op1,
605 unsigned64 op2,
606 FP_formats fmt)
487f79b7 607{
ba46ddd0
CD
608 sim_fpu wop1;
609 sim_fpu wop2;
610 sim_fpu ans;
611 unsigned64 result = 0;
487f79b7 612
ba46ddd0 613 /* The format type has already been checked: */
37d146fa 614 switch (fmt)
487f79b7 615 {
37d146fa
CD
616 case fmt_single:
617 {
37d146fa
CD
618 unsigned32 res;
619 sim_fpu_32to (&wop1, op1);
620 sim_fpu_32to (&wop2, op2);
ba46ddd0 621 (*sim_fpu_op) (&ans, &wop1, &wop2);
37d146fa
CD
622 sim_fpu_to32 (&res, &ans);
623 result = res;
624 break;
625 }
626 case fmt_double:
627 {
37d146fa
CD
628 unsigned64 res;
629 sim_fpu_64to (&wop1, op1);
630 sim_fpu_64to (&wop2, op2);
ba46ddd0 631 (*sim_fpu_op) (&ans, &wop1, &wop2);
37d146fa
CD
632 sim_fpu_to64 (&res, &ans);
633 result = res;
634 break;
635 }
636 default:
ba46ddd0 637 sim_io_eprintf (SD, "Bad switch\n");
37d146fa 638 abort ();
487f79b7 639 }
487f79b7 640
ba46ddd0 641 return result;
487f79b7
CD
642}
643
487f79b7 644
ba46ddd0
CD
645unsigned64
646fp_abs(sim_cpu *cpu,
647 address_word cia,
648 unsigned64 op,
649 FP_formats fmt)
650{
651 return fp_unary(cpu, cia, &sim_fpu_abs, op, fmt);
487f79b7
CD
652}
653
ba46ddd0
CD
654unsigned64
655fp_neg(sim_cpu *cpu,
656 address_word cia,
657 unsigned64 op,
658 FP_formats fmt)
487f79b7 659{
ba46ddd0 660 return fp_unary(cpu, cia, &sim_fpu_neg, op, fmt);
487f79b7
CD
661}
662
ba46ddd0
CD
663unsigned64
664fp_add(sim_cpu *cpu,
665 address_word cia,
666 unsigned64 op1,
667 unsigned64 op2,
668 FP_formats fmt)
487f79b7 669{
ba46ddd0
CD
670 return fp_binary(cpu, cia, &sim_fpu_add, op1, op2, fmt);
671}
487f79b7 672
ba46ddd0
CD
673unsigned64
674fp_sub(sim_cpu *cpu,
675 address_word cia,
676 unsigned64 op1,
677 unsigned64 op2,
678 FP_formats fmt)
679{
680 return fp_binary(cpu, cia, &sim_fpu_sub, op1, op2, fmt);
681}
487f79b7 682
ba46ddd0
CD
683unsigned64
684fp_mul(sim_cpu *cpu,
685 address_word cia,
686 unsigned64 op1,
687 unsigned64 op2,
688 FP_formats fmt)
689{
690 return fp_binary(cpu, cia, &sim_fpu_mul, op1, op2, fmt);
691}
487f79b7 692
ba46ddd0
CD
693unsigned64
694fp_div(sim_cpu *cpu,
695 address_word cia,
696 unsigned64 op1,
697 unsigned64 op2,
698 FP_formats fmt)
699{
700 return fp_binary(cpu, cia, &sim_fpu_div, op1, op2, fmt);
701}
487f79b7 702
ba46ddd0
CD
703unsigned64
704fp_recip(sim_cpu *cpu,
705 address_word cia,
706 unsigned64 op,
707 FP_formats fmt)
708{
709 return fp_unary(cpu, cia, &sim_fpu_inv, op, fmt);
710}
487f79b7 711
ba46ddd0
CD
712unsigned64
713fp_sqrt(sim_cpu *cpu,
714 address_word cia,
715 unsigned64 op,
716 FP_formats fmt)
717{
718 return fp_unary(cpu, cia, &sim_fpu_sqrt, op, fmt);
487f79b7
CD
719}
720
ba46ddd0 721
cfe9ea23
CD
722/* Conversion operations. */
723
487f79b7 724uword64
18d8a52d 725convert (sim_cpu *cpu,
487f79b7
CD
726 address_word cia,
727 int rm,
728 uword64 op,
729 FP_formats from,
730 FP_formats to)
731{
732 sim_fpu wop;
577d8c4b 733 sim_fpu_round round = rounding_mode (rm);
487f79b7
CD
734 unsigned32 result32;
735 unsigned64 result64;
736
487f79b7
CD
737 /* Convert the input to sim_fpu internal format */
738 switch (from)
739 {
740 case fmt_double:
741 sim_fpu_64to (&wop, op);
742 break;
743 case fmt_single:
744 sim_fpu_32to (&wop, op);
745 break;
746 case fmt_word:
747 sim_fpu_i32to (&wop, op, round);
748 break;
749 case fmt_long:
750 sim_fpu_i64to (&wop, op, round);
751 break;
752 default:
753 fprintf (stderr, "Bad switch\n");
754 abort ();
755 }
756
757 /* Convert sim_fpu format into the output */
758 /* The value WOP is converted to the destination format, rounding
759 using mode RM. When the destination is a fixed-point format, then
760 a source value of Infinity, NaN or one which would round to an
761 integer outside the fixed point range then an IEEE Invalid
37d146fa 762 Operation condition is raised. */
487f79b7
CD
763 switch (to)
764 {
765 case fmt_single:
766 sim_fpu_round_32 (&wop, round, 0);
767 sim_fpu_to32 (&result32, &wop);
768 result64 = result32;
769 break;
770 case fmt_double:
771 sim_fpu_round_64 (&wop, round, 0);
772 sim_fpu_to64 (&result64, &wop);
773 break;
774 case fmt_word:
775 sim_fpu_to32i (&result32, &wop, round);
776 result64 = result32;
777 break;
778 case fmt_long:
779 sim_fpu_to64i (&result64, &wop, round);
780 break;
781 default:
782 result64 = 0;
783 fprintf (stderr, "Bad switch\n");
784 abort ();
785 }
37d146fa 786
487f79b7 787#ifdef DEBUG
37d146fa
CD
788 printf ("DBG: Convert: returning 0x%s (to format = %s)\n",
789 pr_addr (result64), fpu_format_name (to));
487f79b7
CD
790#endif /* DEBUG */
791
37d146fa 792 return (result64);
487f79b7
CD
793}
794
07892c0b
CD
795static const char *
796fpu_format_name (FP_formats fmt)
797{
798 switch (fmt)
799 {
800 case fmt_single:
801 return "single";
802 case fmt_double:
803 return "double";
804 case fmt_word:
805 return "word";
806 case fmt_long:
807 return "long";
808 case fmt_unknown:
809 return "<unknown>";
810 case fmt_uninterpreted:
811 return "<uninterpreted>";
812 case fmt_uninterpreted_32:
813 return "<uninterpreted_32>";
814 case fmt_uninterpreted_64:
815 return "<uninterpreted_64>";
816 default:
817 return "<format error>";
818 }
819}
487f79b7 820
07892c0b
CD
821#ifdef DEBUG
822static const char *
823fpu_rounding_mode_name (int rm)
824{
825 switch (rm)
826 {
827 case FP_RM_NEAREST:
828 return "Round";
829 case FP_RM_TOZERO:
830 return "Trunc";
831 case FP_RM_TOPINF:
832 return "Ceil";
833 case FP_RM_TOMINF:
834 return "Floor";
835 default:
836 return "<rounding mode error>";
837 }
838}
839#endif /* DEBUG */