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 used when value required:  */
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 registers 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 registers */
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 */
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
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 */
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     }
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
430 /* Comparison operations.  */
431
432 static sim_fpu_status
433 fp_test(unsigned64 op1,
434         unsigned64 op2,
435         FP_formats fmt,
436         int abs,
437         int cond,
438         int *condition)
439 {
440   sim_fpu wop1;
441   sim_fpu wop2;
442   sim_fpu_status status = 0;
443   int  less, equal, unordered;
444
445   /* The format type has already been checked:  */
446   switch (fmt)
447     {
448     case fmt_single:
449       {
450         sim_fpu_32to (&wop1, op1);
451         sim_fpu_32to (&wop2, op2);
452         break;
453       }
454     case fmt_double:
455       {
456         sim_fpu_64to (&wop1, op1);
457         sim_fpu_64to (&wop2, op2);
458         break;
459       }
460     default:
461       fprintf (stderr, "Bad switch\n");
462       abort ();
463     }
464
465   if (sim_fpu_is_nan (&wop1) || sim_fpu_is_nan (&wop2))
466     {
467       if ((cond & (1 << 3)) ||
468           sim_fpu_is_snan (&wop1) || sim_fpu_is_snan (&wop2))
469         status = sim_fpu_status_invalid_snan;
470       less = 0;
471       equal = 0;
472       unordered = 1;
473     }
474   else
475     {
476       if (abs)
477         {
478           status |= sim_fpu_abs (&wop1, &wop1);
479           status |= sim_fpu_abs (&wop2, &wop2);
480         }
481       equal = sim_fpu_is_eq (&wop1, &wop2);
482       less = !equal && sim_fpu_is_lt (&wop1, &wop2);
483       unordered = 0;
484     }
485   *condition = (((cond & (1 << 2)) && less)
486                 || ((cond & (1 << 1)) && equal)
487                 || ((cond & (1 << 0)) && unordered));
488   return status;
489 }
490
491 void
492 fp_cmp(sim_cpu *cpu,
493        address_word cia,
494        unsigned64 op1,
495        unsigned64 op2,
496        FP_formats fmt,
497        int abs,
498        int cond,
499        int cc)
500 {
501   sim_fpu_status status = 0;
502
503   /* The format type should already have been checked: */
504   switch (fmt)
505     {
506     case fmt_single:
507     case fmt_double:
508       {
509         int result;
510         status = fp_test(op1, op2, fmt, abs, cond, &result);
511         update_fcsr (cpu, cia, status);
512         SETFCC (cc, result);
513         break;
514       }
515     default:
516       sim_io_eprintf (SD, "Bad switch\n");
517       abort ();
518     }
519 }
520
521
522 /* Basic arithmetic operations.  */
523
524 static unsigned64
525 fp_unary(sim_cpu *cpu,
526          address_word cia,
527          int (*sim_fpu_op)(sim_fpu *, const sim_fpu *),
528          unsigned64 op,
529          FP_formats fmt)
530 {
531   sim_fpu wop;
532   sim_fpu ans;
533   unsigned64 result = 0;
534
535   /* The format type has already been checked: */
536   switch (fmt)
537     {
538     case fmt_single:
539       {
540         unsigned32 res;
541         sim_fpu_32to (&wop, op);
542         (*sim_fpu_op) (&ans, &wop);
543         sim_fpu_to32 (&res, &ans);
544         result = res;
545         break;
546       }
547     case fmt_double:
548       {
549         unsigned64 res;
550         sim_fpu_64to (&wop, op);
551         (*sim_fpu_op) (&ans, &wop);
552         sim_fpu_to64 (&res, &ans);
553         result = res;
554         break;
555       }
556     default:
557       sim_io_eprintf (SD, "Bad switch\n");
558       abort ();
559     }
560
561   return result;
562 }
563
564 static unsigned64
565 fp_binary(sim_cpu *cpu,
566           address_word cia,
567           int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *),
568           unsigned64 op1,
569           unsigned64 op2,
570           FP_formats fmt)
571 {
572   sim_fpu wop1;
573   sim_fpu wop2;
574   sim_fpu ans;
575   unsigned64 result = 0;
576
577   /* The format type has already been checked: */
578   switch (fmt)
579     {
580     case fmt_single:
581       {
582         unsigned32 res;
583         sim_fpu_32to (&wop1, op1);
584         sim_fpu_32to (&wop2, op2);
585         (*sim_fpu_op) (&ans, &wop1, &wop2);
586         sim_fpu_to32 (&res, &ans);
587         result = res;
588         break;
589       }
590     case fmt_double:
591       {
592         unsigned64 res;
593         sim_fpu_64to (&wop1, op1);
594         sim_fpu_64to (&wop2, op2);
595         (*sim_fpu_op) (&ans, &wop1, &wop2);
596         sim_fpu_to64 (&res, &ans);
597         result = res;
598         break;
599       }
600     default:
601       sim_io_eprintf (SD, "Bad switch\n");
602       abort ();
603     }
604
605   return result;
606 }
607
608
609 unsigned64
610 fp_abs(sim_cpu *cpu,
611        address_word cia,
612        unsigned64 op,
613        FP_formats fmt)
614 {
615   return fp_unary(cpu, cia, &sim_fpu_abs, op, fmt);
616 }
617
618 unsigned64
619 fp_neg(sim_cpu *cpu,
620        address_word cia,
621        unsigned64 op,
622        FP_formats fmt)
623 {
624   return fp_unary(cpu, cia, &sim_fpu_neg, op, fmt);
625 }
626
627 unsigned64
628 fp_add(sim_cpu *cpu,
629        address_word cia,
630        unsigned64 op1,
631        unsigned64 op2,
632        FP_formats fmt)
633 {
634   return fp_binary(cpu, cia, &sim_fpu_add, op1, op2, fmt);
635 }
636
637 unsigned64
638 fp_sub(sim_cpu *cpu,
639        address_word cia,
640        unsigned64 op1,
641        unsigned64 op2,
642        FP_formats fmt)
643 {
644   return fp_binary(cpu, cia, &sim_fpu_sub, op1, op2, fmt);
645 }
646
647 unsigned64
648 fp_mul(sim_cpu *cpu,
649        address_word cia,
650        unsigned64 op1,
651        unsigned64 op2,
652        FP_formats fmt)
653 {
654   return fp_binary(cpu, cia, &sim_fpu_mul, op1, op2, fmt);
655 }
656
657 unsigned64
658 fp_div(sim_cpu *cpu,
659        address_word cia,
660        unsigned64 op1,
661        unsigned64 op2,
662        FP_formats fmt)
663 {
664   return fp_binary(cpu, cia, &sim_fpu_div, op1, op2, fmt);
665 }
666
667 unsigned64
668 fp_recip(sim_cpu *cpu,
669          address_word cia,
670          unsigned64 op,
671          FP_formats fmt)
672 {
673   return fp_unary(cpu, cia, &sim_fpu_inv, op, fmt);
674 }
675
676 unsigned64
677 fp_sqrt(sim_cpu *cpu,
678         address_word cia,
679         unsigned64 op,
680         FP_formats fmt)
681 {
682   return fp_unary(cpu, cia, &sim_fpu_sqrt, op, fmt);
683 }
684
685
686 /* Conversion operations.  */
687
688 uword64
689 convert (sim_cpu *cpu,
690          address_word cia,
691          int rm,
692          uword64 op,
693          FP_formats from,
694          FP_formats to)
695 {
696   sim_fpu wop;
697   sim_fpu_round round;
698   unsigned32 result32;
699   unsigned64 result64;
700
701 #ifdef DEBUG
702 #if 0 /* FIXME: doesn't compile */
703   printf ("DBG: Convert: mode %s : op 0x%s : from %s : to %s : (PC = 0x%s)\n",
704           fpu_rounding_mode_name (rm), pr_addr (op), fpu_format_name (from),
705           fpu_format_name (to), pr_addr (IPC));
706 #endif
707 #endif /* DEBUG */
708
709   switch (rm)
710     {
711     case FP_RM_NEAREST:
712       /* Round result to nearest representable value. When two
713          representable values are equally near, round to the value
714          that has a least significant bit of zero (i.e. is even).  */
715       round = sim_fpu_round_near;
716       break;
717     case FP_RM_TOZERO:
718       /* Round result to the value closest to, and not greater in
719          magnitude than, the result.  */
720       round = sim_fpu_round_zero;
721       break;
722     case FP_RM_TOPINF:
723       /* Round result to the value closest to, and not less than,
724          the result.  */
725       round = sim_fpu_round_up;
726       break;
727
728     case FP_RM_TOMINF:
729       /* Round result to the value closest to, and not greater than,
730          the result.  */
731       round = sim_fpu_round_down;
732       break;
733     default:
734       round = 0;
735       fprintf (stderr, "Bad switch\n");
736       abort ();
737     }
738
739   /* Convert the input to sim_fpu internal format */
740   switch (from)
741     {
742     case fmt_double:
743       sim_fpu_64to (&wop, op);
744       break;
745     case fmt_single:
746       sim_fpu_32to (&wop, op);
747       break;
748     case fmt_word:
749       sim_fpu_i32to (&wop, op, round);
750       break;
751     case fmt_long:
752       sim_fpu_i64to (&wop, op, round);
753       break;
754     default:
755       fprintf (stderr, "Bad switch\n");
756       abort ();
757     }
758
759   /* Convert sim_fpu format into the output */
760   /* The value WOP is converted to the destination format, rounding
761      using mode RM. When the destination is a fixed-point format, then
762      a source value of Infinity, NaN or one which would round to an
763      integer outside the fixed point range then an IEEE Invalid
764      Operation condition is raised.  */
765   switch (to)
766     {
767     case fmt_single:
768       sim_fpu_round_32 (&wop, round, 0);
769       sim_fpu_to32 (&result32, &wop);
770       result64 = result32;
771       break;
772     case fmt_double:
773       sim_fpu_round_64 (&wop, round, 0);
774       sim_fpu_to64 (&result64, &wop);
775       break;
776     case fmt_word:
777       sim_fpu_to32i (&result32, &wop, round);
778       result64 = result32;
779       break;
780     case fmt_long:
781       sim_fpu_to64i (&result64, &wop, round);
782       break;
783     default:
784       result64 = 0;
785       fprintf (stderr, "Bad switch\n");
786       abort ();
787     }
788
789 #ifdef DEBUG
790   printf ("DBG: Convert: returning 0x%s (to format = %s)\n",
791           pr_addr (result64), fpu_format_name (to));
792 #endif /* DEBUG */
793
794   return (result64);
795 }
796
797 static const char *
798 fpu_format_name (FP_formats fmt)
799 {
800   switch (fmt)
801     {
802     case fmt_single:
803       return "single";
804     case fmt_double:
805       return "double";
806     case fmt_word:
807       return "word";
808     case fmt_long:
809       return "long";
810     case fmt_unknown:
811       return "<unknown>";
812     case fmt_uninterpreted:
813       return "<uninterpreted>";
814     case fmt_uninterpreted_32:
815       return "<uninterpreted_32>";
816     case fmt_uninterpreted_64:
817       return "<uninterpreted_64>";
818     default:
819       return "<format error>";
820     }
821 }
822
823 #ifdef DEBUG
824 static const char *
825 fpu_rounding_mode_name (int rm)
826 {
827   switch (rm)
828     {
829     case FP_RM_NEAREST:
830       return "Round";
831     case FP_RM_TOZERO:
832       return "Trunc";
833     case FP_RM_TOPINF:
834       return "Ceil";
835     case FP_RM_TOMINF:
836       return "Floor";
837     default:
838       return "<rounding mode error>";
839     }
840 }
841 #endif /* DEBUG */