2002-06-07 Chris Demetriou <cgd@broadcom.com>
[external/binutils.git] / sim / mips / cp1.c
1 /*> cp1.c <*/
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
7 This file is part of GDB, the GNU debugger.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License along
20 with this program; if not, write to the Free Software Foundation, Inc.,
21 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
22
23 /* XXX: The following notice should be removed as soon as is practical:  */
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
29    (by Cygnus.)
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"
43
44 /* Within cp1.c we refer to sim_cpu directly.  */
45 #define CPU cpu
46 #define SD CPU_STATE(cpu)
47
48 /*-- FPU support routines ---------------------------------------------------*/
49
50 /* Numbers are held in normalized form. The SINGLE and DOUBLE binary
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
74  */
75
76 /* Explicit QNaN values.  */
77 #define FPQNaN_SINGLE   (0x7FBFFFFF)
78 #define FPQNaN_WORD     (0x7FFFFFFF)
79 #define FPQNaN_DOUBLE   (UNSIGNED64 (0x7FF7FFFFFFFFFFFF))
80 #define FPQNaN_LONG     (UNSIGNED64 (0x7FFFFFFFFFFFFFFF))
81
82 static const char *fpu_format_name (FP_formats fmt);
83 #ifdef DEBUG
84 static const char *fpu_rounding_mode_name (int rm);
85 #endif
86
87 uword64
88 value_fpr (sim_cpu *cpu,
89            address_word cia,
90            int fpr,
91            FP_formats fmt)
92 {
93   uword64 value = 0;
94   int err = 0;
95
96   /* Treat unused register values, as fixed-point 64bit values.  */
97   if ((fmt == fmt_uninterpreted) || (fmt == fmt_unknown))
98     {
99 #if 1
100       /* If request to read data as "uninterpreted", then use the current
101          encoding:  */
102       fmt = FPR_STATE[fpr];
103 #else
104       fmt = fmt_long;
105 #endif
106     }
107
108   /* For values not yet accessed, set to the desired format.  */
109   if (FPR_STATE[fpr] == fmt_uninterpreted)
110     {
111       FPR_STATE[fpr] = fmt;
112 #ifdef DEBUG
113       printf ("DBG: Register %d was fmt_uninterpreted. Now %s\n", fpr,
114               fpu_format_name (fmt));
115 #endif /* DEBUG */
116     }
117   if (fmt != FPR_STATE[fpr])
118     {
119       sim_io_eprintf (SD, "FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",
120                       fpr, fpu_format_name (FPR_STATE[fpr]),
121                       fpu_format_name (fmt), pr_addr (cia));
122       FPR_STATE[fpr] = fmt_unknown;
123     }
124
125   if (FPR_STATE[fpr] == fmt_unknown)
126     {
127       /* Set QNaN value:  */
128       switch (fmt)
129         {
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;
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             {
171               /* Even register numbers only.  */
172 #ifdef DEBUG
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]));
176 #endif
177               value = ((((uword64) FGR[fpr+1]) << 32)
178                        | (FGR[fpr] & 0xFFFFFFFF));
179             }
180           else
181             {
182               SignalException (ReservedInstruction, 0);
183             }
184           break;
185
186         default:
187           err = -1;
188           break;
189         }
190     }
191
192   if (err)
193     SignalExceptionSimulatorFault ("Unrecognised FP format in ValueFPR ()");
194
195 #ifdef DEBUG
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 ());
199 #endif /* DEBUG */
200
201   return (value);
202 }
203
204 void
205 store_fpr (sim_cpu *cpu,
206            address_word cia,
207            int fpr,
208            FP_formats fmt,
209            uword64 value)
210 {
211   int err = 0;
212
213 #ifdef DEBUG
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 ());
217 #endif /* DEBUG */
218
219   if (SizeFGR () == 64)
220     {
221       switch (fmt)
222         {
223         case fmt_uninterpreted_32:
224           fmt = fmt_uninterpreted;
225         case fmt_single:
226         case fmt_word:
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:
238         case fmt_double:
239         case fmt_long:
240           FGR[fpr] = value;
241           FPR_STATE[fpr] = fmt;
242           break;
243
244         default:
245           FPR_STATE[fpr] = fmt_unknown;
246           err = -1;
247           break;
248         }
249     }
250   else
251     {
252       switch (fmt)
253         {
254         case fmt_uninterpreted_32:
255           fmt = fmt_uninterpreted;
256         case fmt_single:
257         case fmt_word:
258           FGR[fpr] = (value & 0xFFFFFFFF);
259           FPR_STATE[fpr] = fmt;
260           break;
261
262         case fmt_uninterpreted_64:
263           fmt = fmt_uninterpreted;
264         case fmt_uninterpreted:
265         case fmt_double:
266         case fmt_long:
267           if ((fpr & 1) == 0)
268             {
269               /* Even register numbers only.  */
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
283         default:
284           FPR_STATE[fpr] = fmt_unknown;
285           err = -1;
286           break;
287         }
288     }
289
290   if (err)
291     SignalExceptionSimulatorFault ("Unrecognised FP format in StoreFPR ()");
292
293 #ifdef DEBUG
294   printf ("DBG: StoreFPR: fpr[%d] = 0x%s (format %s)\n",
295           fpr, pr_uword64 (FGR[fpr]), fpu_format_name (fmt));
296 #endif /* DEBUG */
297
298   return;
299 }
300
301
302 /* CP1 control/status register access functions.  */
303
304 void
305 test_fcsr (sim_cpu *cpu,
306            address_word cia)
307 {
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)))
313     {
314       SignalExceptionFPE();
315     }
316 }
317
318 unsigned_word
319 value_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 (derived from FCSR).  */
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 (derived from FCSR).  */
335       value = FCR31 & (fcsr_CAUSE_mask | fcsr_FLAGS_mask);
336       break;
337     case 28:  /* FP Enables Register (derived from FCSR).  */
338       value = FCR31 & (fcsr_ENABLES_mask | fcsr_RM_mask);
339       if ((FCR31 & fcsr_FS) != 0)
340         value |= fenr_FS;
341       break;
342     case 31:  /* FP Control/Status Register (FCSR).  */
343       value = FCR31 & ~fcsr_ZERO_mask;
344       break;
345     }
346
347   return (EXTEND32 (value));
348 }
349
350 void
351 store_fcr(sim_cpu *cpu,
352           address_word cia,
353           int fcr,
354           unsigned_word value)
355 {
356   unsigned32 v;
357
358   v = VL4_8(value);
359   switch (fcr)
360     {
361     case 25:  /* FP Condition Codes Register (stored into FCSR).  */
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 (stored into FCSR).  */
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 (stored into FCSR).  */
372       if ((v & fenr_FS) != 0)
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 (FCSR).  */
381       FCR31 = v & ~fcsr_ZERO_mask;
382       test_fcsr(cpu, cia);
383       break;
384     }
385 }
386
387 void
388 update_fcsr (sim_cpu *cpu,
389              address_word cia,
390              sim_fpu_status status)
391 {
392   FCSR &= ~fcsr_CAUSE_mask;
393
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
421
422       FCSR |= (cause << fcsr_CAUSE_shift);
423       test_fcsr (cpu, cia);
424       FCSR |= ((cause & ~(1 << UO)) << fcsr_FLAGS_shift);
425     }
426   return;
427 }
428
429 static sim_fpu_round
430 rounding_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
465 /* When the FS bit is set, MIPS processors return zero for
466    denormalized results and optionally replace denormalized inputs
467    with zero.  When FS is clear, some implementation trap on input
468    and/or output, while other perform the operation in hardware.  */
469 static sim_fpu_denorm
470 denorm_mode(sim_cpu *cpu)
471 {
472   sim_fpu_denorm denorm;
473
474   /* XXX: FIXME: Eventually should be CPU model dependent.  */
475   if (GETFS())
476     denorm = sim_fpu_denorm_zero;
477   else
478     denorm = 0;
479   return denorm;
480 }
481
482
483 /* Comparison operations.  */
484
485 static sim_fpu_status
486 fp_test(unsigned64 op1,
487         unsigned64 op2,
488         FP_formats fmt,
489         int abs,
490         int cond,
491         int *condition)
492 {
493   sim_fpu wop1;
494   sim_fpu wop2;
495   sim_fpu_status status = 0;
496   int  less, equal, unordered;
497
498   /* The format type has already been checked:  */
499   switch (fmt)
500     {
501     case fmt_single:
502       {
503         sim_fpu_32to (&wop1, op1);
504         sim_fpu_32to (&wop2, op2);
505         break;
506       }
507     case fmt_double:
508       {
509         sim_fpu_64to (&wop1, op1);
510         sim_fpu_64to (&wop2, op2);
511         break;
512       }
513     default:
514       fprintf (stderr, "Bad switch\n");
515       abort ();
516     }
517
518   if (sim_fpu_is_nan (&wop1) || sim_fpu_is_nan (&wop2))
519     {
520       if ((cond & (1 << 3)) ||
521           sim_fpu_is_snan (&wop1) || sim_fpu_is_snan (&wop2))
522         status = sim_fpu_status_invalid_snan;
523       less = 0;
524       equal = 0;
525       unordered = 1;
526     }
527   else
528     {
529       if (abs)
530         {
531           status |= sim_fpu_abs (&wop1, &wop1);
532           status |= sim_fpu_abs (&wop2, &wop2);
533         }
534       equal = sim_fpu_is_eq (&wop1, &wop2);
535       less = !equal && sim_fpu_is_lt (&wop1, &wop2);
536       unordered = 0;
537     }
538   *condition = (((cond & (1 << 2)) && less)
539                 || ((cond & (1 << 1)) && equal)
540                 || ((cond & (1 << 0)) && unordered));
541   return status;
542 }
543
544 void
545 fp_cmp(sim_cpu *cpu,
546        address_word cia,
547        unsigned64 op1,
548        unsigned64 op2,
549        FP_formats fmt,
550        int abs,
551        int cond,
552        int cc)
553 {
554   sim_fpu_status status = 0;
555
556   /* The format type should already have been checked.  The FCSR is
557      updated before the condition codes so that any exceptions will
558      be signalled before the condition codes are changed.  */
559   switch (fmt)
560     {
561     case fmt_single:
562     case fmt_double:
563       {
564         int result;
565         status = fp_test(op1, op2, fmt, abs, cond, &result);
566         update_fcsr (cpu, cia, status);
567         SETFCC (cc, result);
568         break;
569       }
570     default:
571       sim_io_eprintf (SD, "Bad switch\n");
572       abort ();
573     }
574 }
575
576
577 /* Basic arithmetic operations.  */
578
579 static unsigned64
580 fp_unary(sim_cpu *cpu,
581          address_word cia,
582          int (*sim_fpu_op)(sim_fpu *, const sim_fpu *),
583          unsigned64 op,
584          FP_formats fmt)
585 {
586   sim_fpu wop;
587   sim_fpu ans;
588   sim_fpu_round round = rounding_mode (GETRM());
589   sim_fpu_denorm denorm = denorm_mode (cpu);
590   sim_fpu_status status = 0;
591   unsigned64 result = 0;
592
593   /* The format type has already been checked: */
594   switch (fmt)
595     {
596     case fmt_single:
597       {
598         unsigned32 res;
599         sim_fpu_32to (&wop, op);
600         status |= (*sim_fpu_op) (&ans, &wop);
601         status |= sim_fpu_round_32 (&ans, round, denorm);
602         sim_fpu_to32 (&res, &ans);
603         result = res;
604         break;
605       }
606     case fmt_double:
607       {
608         unsigned64 res;
609         sim_fpu_64to (&wop, op);
610         status |= (*sim_fpu_op) (&ans, &wop);
611         status |= sim_fpu_round_64 (&ans, round, denorm);
612         sim_fpu_to64 (&res, &ans);
613         result = res;
614         break;
615       }
616     default:
617       sim_io_eprintf (SD, "Bad switch\n");
618       abort ();
619     }
620
621   update_fcsr (cpu, cia, status);
622   return result;
623 }
624
625 static unsigned64
626 fp_binary(sim_cpu *cpu,
627           address_word cia,
628           int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *),
629           unsigned64 op1,
630           unsigned64 op2,
631           FP_formats fmt)
632 {
633   sim_fpu wop1;
634   sim_fpu wop2;
635   sim_fpu ans;
636   sim_fpu_round round = rounding_mode (GETRM());
637   sim_fpu_denorm denorm = denorm_mode (cpu);
638   sim_fpu_status status = 0;
639   unsigned64 result = 0;
640
641   /* The format type has already been checked: */
642   switch (fmt)
643     {
644     case fmt_single:
645       {
646         unsigned32 res;
647         sim_fpu_32to (&wop1, op1);
648         sim_fpu_32to (&wop2, op2);
649         status |= (*sim_fpu_op) (&ans, &wop1, &wop2);
650         status |= sim_fpu_round_32 (&ans, round, denorm);
651         sim_fpu_to32 (&res, &ans);
652         result = res;
653         break;
654       }
655     case fmt_double:
656       {
657         unsigned64 res;
658         sim_fpu_64to (&wop1, op1);
659         sim_fpu_64to (&wop2, op2);
660         status |= (*sim_fpu_op) (&ans, &wop1, &wop2);
661         status |= sim_fpu_round_64 (&ans, round, denorm);
662         sim_fpu_to64 (&res, &ans);
663         result = res;
664         break;
665       }
666     default:
667       sim_io_eprintf (SD, "Bad switch\n");
668       abort ();
669     }
670
671   update_fcsr (cpu, cia, status);
672   return result;
673 }
674
675 /* Common MAC code for single operands (.s or .d), defers setting FCSR.  */
676 static sim_fpu_status
677 inner_mac(int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *),
678           unsigned64 op1,
679           unsigned64 op2,
680           unsigned64 op3,
681           int scale,
682           int negate,
683           FP_formats fmt,
684           sim_fpu_round round,
685           sim_fpu_denorm denorm,
686           unsigned64 *result)
687 {
688   sim_fpu wop1;
689   sim_fpu wop2;
690   sim_fpu ans;
691   sim_fpu_status status = 0;
692   sim_fpu_status op_status;
693   unsigned64 temp = 0;
694
695   switch (fmt)
696     {
697     case fmt_single:
698       {
699         unsigned32 res;
700         sim_fpu_32to (&wop1, op1);
701         sim_fpu_32to (&wop2, op2);
702         status |= sim_fpu_mul (&ans, &wop1, &wop2);
703         if (scale != 0 && sim_fpu_is_number (&ans))  /* number or denorm */
704           ans.normal_exp += scale;
705         status |= sim_fpu_round_32 (&ans, round, denorm);
706         wop1 = ans;
707         op_status = 0;
708         sim_fpu_32to (&wop2, op3);
709         op_status |= (*sim_fpu_op) (&ans, &wop1, &wop2);
710         op_status |= sim_fpu_round_32 (&ans, round, denorm);
711         status |= op_status;
712         if (negate)
713           {
714             wop1 = ans;
715             op_status = sim_fpu_neg (&ans, &wop1);
716             op_status |= sim_fpu_round_32 (&ans, round, denorm);
717             status |= op_status;
718           }
719         sim_fpu_to32 (&res, &ans);
720         temp = res;
721         break;
722       }
723     case fmt_double:
724       {
725         unsigned64 res;
726         sim_fpu_64to (&wop1, op1);
727         sim_fpu_64to (&wop2, op2);
728         status |= sim_fpu_mul (&ans, &wop1, &wop2);
729         if (scale != 0 && sim_fpu_is_number (&ans))  /* number or denorm */
730           ans.normal_exp += scale;
731         status |= sim_fpu_round_64 (&ans, round, denorm);
732         wop1 = ans;
733         op_status = 0;
734         sim_fpu_64to (&wop2, op3);
735         op_status |= (*sim_fpu_op) (&ans, &wop1, &wop2);
736         op_status |= sim_fpu_round_64 (&ans, round, denorm);
737         status |= op_status;
738         if (negate)
739           {
740             wop1 = ans;
741             op_status = sim_fpu_neg (&ans, &wop1);
742             op_status |= sim_fpu_round_64 (&ans, round, denorm);
743             status |= op_status;
744           }
745         sim_fpu_to64 (&res, &ans);
746         temp = res;
747         break;
748       }
749     default:
750       fprintf (stderr, "Bad switch\n");
751       abort ();
752     }
753   *result = temp;
754   return status;
755 }
756
757 /* Common implementation of madd, nmadd, msub, nmsub that does
758    intermediate rounding per spec.  Also used for recip2 and rsqrt2,
759    which are transformed into equivalent nmsub operations.  The scale
760    argument is an adjustment to the exponent of the intermediate
761    product op1*op2.  It is currently non-zero for rsqrt2 (-1), which
762    requires an effective division by 2. */
763 static unsigned64
764 fp_mac(sim_cpu *cpu,
765        address_word cia,
766        int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *),
767        unsigned64 op1,
768        unsigned64 op2,
769        unsigned64 op3,
770        int scale,
771        int negate,
772        FP_formats fmt)
773 {
774   sim_fpu_round round = rounding_mode (GETRM());
775   sim_fpu_denorm denorm = denorm_mode (cpu);
776   sim_fpu_status status = 0;
777   unsigned64 result = 0;
778
779   /* The format type has already been checked: */
780   switch (fmt)
781     {
782     case fmt_single:
783     case fmt_double:
784       status = inner_mac(sim_fpu_op, op1, op2, op3, scale,
785                          negate, fmt, round, denorm, &result);
786       break;
787     default:
788       sim_io_eprintf (SD, "Bad switch\n");
789       abort ();
790     }
791
792   update_fcsr (cpu, cia, status);
793   return result;
794 }
795
796 /* Common rsqrt code for single operands (.s or .d), intermediate rounding.  */
797 static sim_fpu_status
798 inner_rsqrt(unsigned64 op1,
799             FP_formats fmt,
800             sim_fpu_round round,
801             sim_fpu_denorm denorm,
802             unsigned64 *result)
803 {
804   sim_fpu wop1;
805   sim_fpu ans;
806   sim_fpu_status status = 0;
807   sim_fpu_status op_status;
808   unsigned64 temp = 0;
809
810   switch (fmt)
811     {
812     case fmt_single:
813       {
814         unsigned32 res;
815         sim_fpu_32to (&wop1, op1);
816         status |= sim_fpu_sqrt (&ans, &wop1);
817         status |= sim_fpu_round_32 (&ans, status, round);
818         wop1 = ans;
819         op_status = sim_fpu_inv (&ans, &wop1);
820         op_status |= sim_fpu_round_32 (&ans, round, denorm);
821         sim_fpu_to32 (&res, &ans);
822         temp = res;
823         status |= op_status;
824         break;
825       }
826     case fmt_double:
827       {
828         unsigned64 res;
829         sim_fpu_64to (&wop1, op1);
830         status |= sim_fpu_sqrt (&ans, &wop1);
831         status |= sim_fpu_round_64 (&ans, round, denorm);
832         wop1 = ans;
833         op_status = sim_fpu_inv (&ans, &wop1);
834         op_status |= sim_fpu_round_64 (&ans, round, denorm);
835         sim_fpu_to64 (&res, &ans);
836         temp = res;
837         status |= op_status;
838         break;
839       }
840     default:
841       fprintf (stderr, "Bad switch\n");
842       abort ();
843     }
844   *result = temp;
845   return status;
846 }
847
848 static unsigned64
849 fp_inv_sqrt(sim_cpu *cpu,
850             address_word cia,
851             unsigned64 op1,
852             FP_formats fmt)
853 {
854   sim_fpu_round round = rounding_mode (GETRM());
855   sim_fpu_round denorm = denorm_mode (cpu);
856   sim_fpu_status status = 0;
857   unsigned64 result = 0;
858
859   /* The format type has already been checked: */
860   switch (fmt)
861     {
862     case fmt_single:
863     case fmt_double:
864       status = inner_rsqrt (op1, fmt, round, denorm, &result);
865       break;
866     default:
867       sim_io_eprintf (SD, "Bad switch\n");
868       abort ();
869     }
870
871   update_fcsr (cpu, cia, status);
872   return result;
873 }
874
875
876 unsigned64
877 fp_abs(sim_cpu *cpu,
878        address_word cia,
879        unsigned64 op,
880        FP_formats fmt)
881 {
882   return fp_unary(cpu, cia, &sim_fpu_abs, op, fmt);
883 }
884
885 unsigned64
886 fp_neg(sim_cpu *cpu,
887        address_word cia,
888        unsigned64 op,
889        FP_formats fmt)
890 {
891   return fp_unary(cpu, cia, &sim_fpu_neg, op, fmt);
892 }
893
894 unsigned64
895 fp_add(sim_cpu *cpu,
896        address_word cia,
897        unsigned64 op1,
898        unsigned64 op2,
899        FP_formats fmt)
900 {
901   return fp_binary(cpu, cia, &sim_fpu_add, op1, op2, fmt);
902 }
903
904 unsigned64
905 fp_sub(sim_cpu *cpu,
906        address_word cia,
907        unsigned64 op1,
908        unsigned64 op2,
909        FP_formats fmt)
910 {
911   return fp_binary(cpu, cia, &sim_fpu_sub, op1, op2, fmt);
912 }
913
914 unsigned64
915 fp_mul(sim_cpu *cpu,
916        address_word cia,
917        unsigned64 op1,
918        unsigned64 op2,
919        FP_formats fmt)
920 {
921   return fp_binary(cpu, cia, &sim_fpu_mul, op1, op2, fmt);
922 }
923
924 unsigned64
925 fp_div(sim_cpu *cpu,
926        address_word cia,
927        unsigned64 op1,
928        unsigned64 op2,
929        FP_formats fmt)
930 {
931   return fp_binary(cpu, cia, &sim_fpu_div, op1, op2, fmt);
932 }
933
934 unsigned64
935 fp_recip(sim_cpu *cpu,
936          address_word cia,
937          unsigned64 op,
938          FP_formats fmt)
939 {
940   return fp_unary(cpu, cia, &sim_fpu_inv, op, fmt);
941 }
942
943 unsigned64
944 fp_sqrt(sim_cpu *cpu,
945         address_word cia,
946         unsigned64 op,
947         FP_formats fmt)
948 {
949   return fp_unary(cpu, cia, &sim_fpu_sqrt, op, fmt);
950 }
951
952 unsigned64
953 fp_rsqrt(sim_cpu *cpu,
954          address_word cia,
955          unsigned64 op,
956          FP_formats fmt)
957 {
958   return fp_inv_sqrt(cpu, cia, op, fmt);
959 }
960
961 unsigned64
962 fp_madd(sim_cpu *cpu,
963         address_word cia,
964         unsigned64 op1,
965         unsigned64 op2,
966         unsigned64 op3,
967         FP_formats fmt)
968 {
969   return fp_mac(cpu, cia, &sim_fpu_add, op1, op2, op3, 0, 0, fmt);
970 }
971
972 unsigned64
973 fp_msub(sim_cpu *cpu,
974         address_word cia,
975         unsigned64 op1,
976         unsigned64 op2,
977         unsigned64 op3,
978         FP_formats fmt)
979 {
980   return fp_mac(cpu, cia, &sim_fpu_sub, op1, op2, op3, 0, 0, fmt);
981 }
982
983 unsigned64
984 fp_nmadd(sim_cpu *cpu,
985          address_word cia,
986          unsigned64 op1,
987          unsigned64 op2,
988          unsigned64 op3,
989          FP_formats fmt)
990 {
991   return fp_mac(cpu, cia, &sim_fpu_add, op1, op2, op3, 0, 1, fmt);
992 }
993
994 unsigned64
995 fp_nmsub(sim_cpu *cpu,
996          address_word cia,
997          unsigned64 op1,
998          unsigned64 op2,
999          unsigned64 op3,
1000          FP_formats fmt)
1001 {
1002   return fp_mac(cpu, cia, &sim_fpu_sub, op1, op2, op3, 0, 1, fmt);
1003 }
1004
1005
1006 /* Conversion operations.  */
1007
1008 uword64
1009 convert (sim_cpu *cpu,
1010          address_word cia,
1011          int rm,
1012          uword64 op,
1013          FP_formats from,
1014          FP_formats to)
1015 {
1016   sim_fpu wop;
1017   sim_fpu_round round = rounding_mode (rm);
1018   sim_fpu_denorm denorm = denorm_mode (cpu);
1019   unsigned32 result32;
1020   unsigned64 result64;
1021   sim_fpu_status status = 0;
1022
1023   /* Convert the input to sim_fpu internal format */
1024   switch (from)
1025     {
1026     case fmt_double:
1027       sim_fpu_64to (&wop, op);
1028       break;
1029     case fmt_single:
1030       sim_fpu_32to (&wop, op);
1031       break;
1032     case fmt_word:
1033       status = sim_fpu_i32to (&wop, op, round);
1034       break;
1035     case fmt_long:
1036       status = sim_fpu_i64to (&wop, op, round);
1037       break;
1038     default:
1039       sim_io_eprintf (SD, "Bad switch\n");
1040       abort ();
1041     }
1042
1043   /* Convert sim_fpu format into the output */
1044   /* The value WOP is converted to the destination format, rounding
1045      using mode RM. When the destination is a fixed-point format, then
1046      a source value of Infinity, NaN or one which would round to an
1047      integer outside the fixed point range then an IEEE Invalid
1048      Operation condition is raised.  */
1049   switch (to)
1050     {
1051     case fmt_single:
1052       status |= sim_fpu_round_32 (&wop, round, denorm);
1053       /* For a NaN, normalize mantissa bits (cvt.s.d can't preserve them) */
1054       if (sim_fpu_is_qnan (&wop))
1055         wop = sim_fpu_qnan;
1056       sim_fpu_to32 (&result32, &wop);
1057       result64 = result32;
1058       break;
1059     case fmt_double:
1060       status |= sim_fpu_round_64 (&wop, round, denorm);
1061       /* For a NaN, normalize mantissa bits (make cvt.d.s consistent) */
1062       if (sim_fpu_is_qnan (&wop))
1063         wop = sim_fpu_qnan;
1064       sim_fpu_to64 (&result64, &wop);
1065       break;
1066     case fmt_word:
1067       status |= sim_fpu_to32i (&result32, &wop, round);
1068       result64 = result32;
1069       break;
1070     case fmt_long:
1071       status |= sim_fpu_to64i (&result64, &wop, round);
1072       break;
1073     default:
1074       result64 = 0;
1075       sim_io_eprintf (SD, "Bad switch\n");
1076       abort ();
1077     }
1078
1079   update_fcsr (cpu, cia, status);
1080   return result64;
1081 }
1082
1083 static const char *
1084 fpu_format_name (FP_formats fmt)
1085 {
1086   switch (fmt)
1087     {
1088     case fmt_single:
1089       return "single";
1090     case fmt_double:
1091       return "double";
1092     case fmt_word:
1093       return "word";
1094     case fmt_long:
1095       return "long";
1096     case fmt_unknown:
1097       return "<unknown>";
1098     case fmt_uninterpreted:
1099       return "<uninterpreted>";
1100     case fmt_uninterpreted_32:
1101       return "<uninterpreted_32>";
1102     case fmt_uninterpreted_64:
1103       return "<uninterpreted_64>";
1104     default:
1105       return "<format error>";
1106     }
1107 }
1108
1109 #ifdef DEBUG
1110 static const char *
1111 fpu_rounding_mode_name (int rm)
1112 {
1113   switch (rm)
1114     {
1115     case FP_RM_NEAREST:
1116       return "Round";
1117     case FP_RM_TOZERO:
1118       return "Trunc";
1119     case FP_RM_TOPINF:
1120       return "Ceil";
1121     case FP_RM_TOMINF:
1122       return "Floor";
1123     default:
1124       return "<rounding mode error>";
1125     }
1126 }
1127 #endif /* DEBUG */