1d46c0c8e482a024b7b5debac6def2c623350a08
[external/binutils.git] / sim / mips / cp1.c
1 /*> cp1.c <*/
2 /* Floating Point Support for gdb MIPS simulators
3
4    This file is part of the MIPS sim
5
6                 THIS SOFTWARE IS NOT COPYRIGHTED
7
8    Cygnus offers the following for use in the public domain.  Cygnus
9    makes no warranty with regard to the software or it's performance
10    and the user accepts the software "AS IS" with all faults.
11
12    CYGNUS DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO
13    THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15
16    (Originally, this code was in interp.c)
17 */
18
19 #include "sim-main.h"
20 #include "sim-fpu.h"
21
22 /* Within cp1.c we refer to sim_cpu directly.  */
23 #define CPU cpu
24 #define SD CPU_STATE(cpu)
25
26 /*-- FPU support routines ---------------------------------------------------*/
27
28 /* Numbers are held in normalized form. The SINGLE and DOUBLE binary
29    formats conform to ANSI/IEEE Std 754-1985.
30
31    SINGLE precision floating:
32       seeeeeeeefffffffffffffffffffffff
33         s =  1bit  = sign
34         e =  8bits = exponent
35         f = 23bits = fraction
36
37    SINGLE precision fixed:
38       siiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
39         s =  1bit  = sign
40         i = 31bits = integer
41
42    DOUBLE precision floating:
43       seeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffff
44         s =  1bit  = sign
45         e = 11bits = exponent
46         f = 52bits = fraction
47
48    DOUBLE precision fixed:
49       siiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
50         s =  1bit  = sign
51         i = 63bits = integer
52  */
53
54 /* Explicit QNaN values used when value required:  */
55 #define FPQNaN_SINGLE   (0x7FBFFFFF)
56 #define FPQNaN_WORD     (0x7FFFFFFF)
57 #define FPQNaN_DOUBLE   (UNSIGNED64 (0x7FF7FFFFFFFFFFFF))
58 #define FPQNaN_LONG     (UNSIGNED64 (0x7FFFFFFFFFFFFFFF))
59
60 static const char *fpu_format_name (FP_formats fmt);
61 #ifdef DEBUG
62 static const char *fpu_rounding_mode_name (int rm);
63 #endif
64
65 uword64
66 value_fpr (sim_cpu *cpu,
67            address_word cia,
68            int fpr,
69            FP_formats fmt)
70 {
71   uword64 value = 0;
72   int err = 0;
73
74   /* Treat unused register values, as fixed-point 64bit values:  */
75   if ((fmt == fmt_uninterpreted) || (fmt == fmt_unknown))
76     {
77 #if 1
78       /* If request to read data as "uninterpreted", then use the current
79          encoding:  */
80       fmt = FPR_STATE[fpr];
81 #else
82       fmt = fmt_long;
83 #endif
84     }
85
86   /* For values not yet accessed, set to the desired format:  */
87   if (FPR_STATE[fpr] == fmt_uninterpreted)
88     {
89       FPR_STATE[fpr] = fmt;
90 #ifdef DEBUG
91       printf ("DBG: Register %d was fmt_uninterpreted. Now %s\n", fpr,
92               fpu_format_name (fmt));
93 #endif /* DEBUG */
94     }
95   if (fmt != FPR_STATE[fpr])
96     {
97       sim_io_eprintf (SD, "FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",
98                       fpr, fpu_format_name (FPR_STATE[fpr]),
99                       fpu_format_name (fmt), pr_addr (cia));
100       FPR_STATE[fpr] = fmt_unknown;
101     }
102
103   if (FPR_STATE[fpr] == fmt_unknown)
104     {
105       /* Set QNaN value:  */
106       switch (fmt)
107         {
108         case fmt_single:
109           value = FPQNaN_SINGLE;
110           break;
111
112         case fmt_double:
113           value = FPQNaN_DOUBLE;
114           break;
115
116         case fmt_word:
117           value = FPQNaN_WORD;
118           break;
119
120         case fmt_long:
121           value = FPQNaN_LONG;
122           break;
123
124         default:
125           err = -1;
126           break;
127         }
128     }
129   else if (SizeFGR () == 64)
130     {
131       switch (fmt)
132         {
133         case fmt_single:
134         case fmt_word:
135           value = (FGR[fpr] & 0xFFFFFFFF);
136           break;
137
138         case fmt_uninterpreted:
139         case fmt_double:
140         case fmt_long:
141           value = FGR[fpr];
142           break;
143
144         default:
145           err = -1;
146           break;
147         }
148     }
149   else
150     {
151       switch (fmt)
152         {
153         case fmt_single:
154         case fmt_word:
155           value = (FGR[fpr] & 0xFFFFFFFF);
156           break;
157
158         case fmt_uninterpreted:
159         case fmt_double:
160         case fmt_long:
161           if ((fpr & 1) == 0)
162             {
163               /* even registers only */
164 #ifdef DEBUG
165               printf ("DBG: ValueFPR: FGR[%d] = %s, FGR[%d] = %s\n",
166                       fpr + 1, pr_uword64 ((uword64) FGR[fpr+1]),
167                       fpr, pr_uword64 ((uword64) FGR[fpr]));
168 #endif
169               value = ((((uword64) FGR[fpr+1]) << 32)
170                        | (FGR[fpr] & 0xFFFFFFFF));
171             }
172           else
173             {
174               SignalException (ReservedInstruction, 0);
175             }
176           break;
177
178         default:
179           err = -1;
180           break;
181         }
182     }
183
184   if (err)
185     SignalExceptionSimulatorFault ("Unrecognised FP format in ValueFPR ()");
186
187 #ifdef DEBUG
188   printf ("DBG: ValueFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR () = %d\n",
189           fpr, fpu_format_name (fmt), pr_uword64 (value), pr_addr (cia),
190           SizeFGR ());
191 #endif /* DEBUG */
192
193   return (value);
194 }
195
196 void
197 store_fpr (sim_cpu *cpu,
198            address_word cia,
199            int fpr,
200            FP_formats fmt,
201            uword64 value)
202 {
203   int err = 0;
204
205 #ifdef DEBUG
206   printf ("DBG: StoreFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR () = %d, \n",
207           fpr, fpu_format_name (fmt), pr_uword64 (value), pr_addr (cia),
208           SizeFGR ());
209 #endif /* DEBUG */
210
211   if (SizeFGR () == 64)
212     {
213       switch (fmt)
214         {
215         case fmt_uninterpreted_32:
216           fmt = fmt_uninterpreted;
217         case fmt_single:
218         case fmt_word:
219           if (STATE_VERBOSE_P (SD))
220             sim_io_eprintf (SD,
221                             "Warning: PC 0x%s: interp.c store_fpr DEADCODE\n",
222                             pr_addr (cia));
223           FGR[fpr] = (((uword64) 0xDEADC0DE << 32) | (value & 0xFFFFFFFF));
224           FPR_STATE[fpr] = fmt;
225           break;
226
227         case fmt_uninterpreted_64:
228           fmt = fmt_uninterpreted;
229         case fmt_uninterpreted:
230         case fmt_double:
231         case fmt_long:
232           FGR[fpr] = value;
233           FPR_STATE[fpr] = fmt;
234           break;
235
236         default:
237           FPR_STATE[fpr] = fmt_unknown;
238           err = -1;
239           break;
240         }
241     }
242   else
243     {
244       switch (fmt)
245         {
246         case fmt_uninterpreted_32:
247           fmt = fmt_uninterpreted;
248         case fmt_single:
249         case fmt_word:
250           FGR[fpr] = (value & 0xFFFFFFFF);
251           FPR_STATE[fpr] = fmt;
252           break;
253
254         case fmt_uninterpreted_64:
255           fmt = fmt_uninterpreted;
256         case fmt_uninterpreted:
257         case fmt_double:
258         case fmt_long:
259           if ((fpr & 1) == 0)
260             {
261               /* even register number only */
262               FGR[fpr+1] = (value >> 32);
263               FGR[fpr] = (value & 0xFFFFFFFF);
264               FPR_STATE[fpr + 1] = fmt;
265               FPR_STATE[fpr] = fmt;
266             }
267           else
268             {
269               FPR_STATE[fpr] = fmt_unknown;
270               FPR_STATE[fpr + 1] = fmt_unknown;
271               SignalException (ReservedInstruction, 0);
272             }
273           break;
274
275         default:
276           FPR_STATE[fpr] = fmt_unknown;
277           err = -1;
278           break;
279         }
280     }
281
282   if (err)
283     SignalExceptionSimulatorFault ("Unrecognised FP format in StoreFPR ()");
284
285 #ifdef DEBUG
286   printf ("DBG: StoreFPR: fpr[%d] = 0x%s (format %s)\n",
287           fpr, pr_uword64 (FGR[fpr]), fpu_format_name (fmt));
288 #endif /* DEBUG */
289
290   return;
291 }
292
293 int
294 NaN (op, fmt)
295      uword64 op;
296      FP_formats fmt;
297 {
298   int boolean = 0;
299   switch (fmt)
300     {
301     case fmt_single:
302     case fmt_word:
303       {
304         sim_fpu wop;
305         sim_fpu_32to (&wop, op);
306         boolean = sim_fpu_is_nan (&wop);
307         break;
308       }
309     case fmt_double:
310     case fmt_long:
311       {
312         sim_fpu wop;
313         sim_fpu_64to (&wop, op);
314         boolean = sim_fpu_is_nan (&wop);
315         break;
316       }
317     default:
318       fprintf (stderr, "Bad switch\n");
319       abort ();
320     }
321
322 #ifdef DEBUG
323   printf ("DBG: NaN: returning %d for 0x%s (format = %s)\n",
324           boolean, pr_addr (op), fpu_format_name (fmt));
325 #endif /* DEBUG */
326
327   return (boolean);
328 }
329
330 int
331 Less (op1, op2, fmt)
332      uword64 op1;
333      uword64 op2;
334      FP_formats fmt;
335 {
336   int boolean = 0;
337
338   /* Argument checking already performed by the FPCOMPARE code */
339
340 #ifdef DEBUG
341   printf ("DBG: Less: %s: op1 = 0x%s : op2 = 0x%s\n",
342           fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
343 #endif /* DEBUG */
344
345   /* The format type should already have been checked:  */
346   switch (fmt)
347     {
348     case fmt_single:
349       {
350         sim_fpu wop1;
351         sim_fpu wop2;
352         sim_fpu_32to (&wop1, op1);
353         sim_fpu_32to (&wop2, op2);
354         boolean = sim_fpu_is_lt (&wop1, &wop2);
355         break;
356       }
357     case fmt_double:
358       {
359         sim_fpu wop1;
360         sim_fpu wop2;
361         sim_fpu_64to (&wop1, op1);
362         sim_fpu_64to (&wop2, op2);
363         boolean = sim_fpu_is_lt (&wop1, &wop2);
364         break;
365       }
366     default:
367       fprintf (stderr, "Bad switch\n");
368       abort ();
369     }
370
371 #ifdef DEBUG
372   printf ("DBG: Less: returning %d (format = %s)\n",
373           boolean, fpu_format_name (fmt));
374 #endif /* DEBUG */
375
376   return (boolean);
377 }
378
379 int
380 Equal (op1, op2, fmt)
381      uword64 op1;
382      uword64 op2;
383      FP_formats fmt;
384 {
385   int boolean = 0;
386
387   /* Argument checking already performed by the FPCOMPARE code */
388
389 #ifdef DEBUG
390   printf ("DBG: Equal: %s: op1 = 0x%s : op2 = 0x%s\n",
391           fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
392 #endif /* DEBUG */
393
394   /* The format type should already have been checked:  */
395   switch (fmt)
396     {
397     case fmt_single:
398       {
399         sim_fpu wop1;
400         sim_fpu wop2;
401         sim_fpu_32to (&wop1, op1);
402         sim_fpu_32to (&wop2, op2);
403         boolean = sim_fpu_is_eq (&wop1, &wop2);
404         break;
405       }
406     case fmt_double:
407       {
408         sim_fpu wop1;
409         sim_fpu wop2;
410         sim_fpu_64to (&wop1, op1);
411         sim_fpu_64to (&wop2, op2);
412         boolean = sim_fpu_is_eq (&wop1, &wop2);
413         break;
414       }
415     default:
416       fprintf (stderr, "Bad switch\n");
417       abort ();
418     }
419
420 #ifdef DEBUG
421   printf ("DBG: Equal: returning %d (format = %s)\n",
422           boolean, fpu_format_name (fmt));
423 #endif /* DEBUG */
424
425   return (boolean);
426 }
427
428
429 /* Basic arithmetic operations.  */
430
431 static unsigned64
432 fp_unary(sim_cpu *cpu,
433          address_word cia,
434          int (*sim_fpu_op)(sim_fpu *, const sim_fpu *),
435          unsigned64 op,
436          FP_formats fmt)
437 {
438   sim_fpu wop;
439   sim_fpu ans;
440   unsigned64 result = 0;
441
442   /* The format type has already been checked: */
443   switch (fmt)
444     {
445     case fmt_single:
446       {
447         unsigned32 res;
448         sim_fpu_32to (&wop, op);
449         (*sim_fpu_op) (&ans, &wop);
450         sim_fpu_to32 (&res, &ans);
451         result = res;
452         break;
453       }
454     case fmt_double:
455       {
456         unsigned64 res;
457         sim_fpu_64to (&wop, op);
458         (*sim_fpu_op) (&ans, &wop);
459         sim_fpu_to64 (&res, &ans);
460         result = res;
461         break;
462       }
463     default:
464       sim_io_eprintf (SD, "Bad switch\n");
465       abort ();
466     }
467
468   return result;
469 }
470
471 static unsigned64
472 fp_binary(sim_cpu *cpu,
473           address_word cia,
474           int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *),
475           unsigned64 op1,
476           unsigned64 op2,
477           FP_formats fmt)
478 {
479   sim_fpu wop1;
480   sim_fpu wop2;
481   sim_fpu ans;
482   unsigned64 result = 0;
483
484   /* The format type has already been checked: */
485   switch (fmt)
486     {
487     case fmt_single:
488       {
489         unsigned32 res;
490         sim_fpu_32to (&wop1, op1);
491         sim_fpu_32to (&wop2, op2);
492         (*sim_fpu_op) (&ans, &wop1, &wop2);
493         sim_fpu_to32 (&res, &ans);
494         result = res;
495         break;
496       }
497     case fmt_double:
498       {
499         unsigned64 res;
500         sim_fpu_64to (&wop1, op1);
501         sim_fpu_64to (&wop2, op2);
502         (*sim_fpu_op) (&ans, &wop1, &wop2);
503         sim_fpu_to64 (&res, &ans);
504         result = res;
505         break;
506       }
507     default:
508       sim_io_eprintf (SD, "Bad switch\n");
509       abort ();
510     }
511
512   return result;
513 }
514
515
516 unsigned64
517 fp_abs(sim_cpu *cpu,
518        address_word cia,
519        unsigned64 op,
520        FP_formats fmt)
521 {
522   return fp_unary(cpu, cia, &sim_fpu_abs, op, fmt);
523 }
524
525 unsigned64
526 fp_neg(sim_cpu *cpu,
527        address_word cia,
528        unsigned64 op,
529        FP_formats fmt)
530 {
531   return fp_unary(cpu, cia, &sim_fpu_neg, op, fmt);
532 }
533
534 unsigned64
535 fp_add(sim_cpu *cpu,
536        address_word cia,
537        unsigned64 op1,
538        unsigned64 op2,
539        FP_formats fmt)
540 {
541   return fp_binary(cpu, cia, &sim_fpu_add, op1, op2, fmt);
542 }
543
544 unsigned64
545 fp_sub(sim_cpu *cpu,
546        address_word cia,
547        unsigned64 op1,
548        unsigned64 op2,
549        FP_formats fmt)
550 {
551   return fp_binary(cpu, cia, &sim_fpu_sub, op1, op2, fmt);
552 }
553
554 unsigned64
555 fp_mul(sim_cpu *cpu,
556        address_word cia,
557        unsigned64 op1,
558        unsigned64 op2,
559        FP_formats fmt)
560 {
561   return fp_binary(cpu, cia, &sim_fpu_mul, op1, op2, fmt);
562 }
563
564 unsigned64
565 fp_div(sim_cpu *cpu,
566        address_word cia,
567        unsigned64 op1,
568        unsigned64 op2,
569        FP_formats fmt)
570 {
571   return fp_binary(cpu, cia, &sim_fpu_div, op1, op2, fmt);
572 }
573
574 unsigned64
575 fp_recip(sim_cpu *cpu,
576          address_word cia,
577          unsigned64 op,
578          FP_formats fmt)
579 {
580   return fp_unary(cpu, cia, &sim_fpu_inv, op, fmt);
581 }
582
583 unsigned64
584 fp_sqrt(sim_cpu *cpu,
585         address_word cia,
586         unsigned64 op,
587         FP_formats fmt)
588 {
589   return fp_unary(cpu, cia, &sim_fpu_sqrt, op, fmt);
590 }
591
592
593 uword64
594 convert (sim_cpu *cpu,
595          address_word cia,
596          int rm,
597          uword64 op,
598          FP_formats from,
599          FP_formats to)
600 {
601   sim_fpu wop;
602   sim_fpu_round round;
603   unsigned32 result32;
604   unsigned64 result64;
605
606 #ifdef DEBUG
607 #if 0 /* FIXME: doesn't compile */
608   printf ("DBG: Convert: mode %s : op 0x%s : from %s : to %s : (PC = 0x%s)\n",
609           fpu_rounding_mode_name (rm), pr_addr (op), fpu_format_name (from),
610           fpu_format_name (to), pr_addr (IPC));
611 #endif
612 #endif /* DEBUG */
613
614   switch (rm)
615     {
616     case FP_RM_NEAREST:
617       /* Round result to nearest representable value. When two
618          representable values are equally near, round to the value
619          that has a least significant bit of zero (i.e. is even).  */
620       round = sim_fpu_round_near;
621       break;
622     case FP_RM_TOZERO:
623       /* Round result to the value closest to, and not greater in
624          magnitude than, the result.  */
625       round = sim_fpu_round_zero;
626       break;
627     case FP_RM_TOPINF:
628       /* Round result to the value closest to, and not less than,
629          the result.  */
630       round = sim_fpu_round_up;
631       break;
632
633     case FP_RM_TOMINF:
634       /* Round result to the value closest to, and not greater than,
635          the result.  */
636       round = sim_fpu_round_down;
637       break;
638     default:
639       round = 0;
640       fprintf (stderr, "Bad switch\n");
641       abort ();
642     }
643
644   /* Convert the input to sim_fpu internal format */
645   switch (from)
646     {
647     case fmt_double:
648       sim_fpu_64to (&wop, op);
649       break;
650     case fmt_single:
651       sim_fpu_32to (&wop, op);
652       break;
653     case fmt_word:
654       sim_fpu_i32to (&wop, op, round);
655       break;
656     case fmt_long:
657       sim_fpu_i64to (&wop, op, round);
658       break;
659     default:
660       fprintf (stderr, "Bad switch\n");
661       abort ();
662     }
663
664   /* Convert sim_fpu format into the output */
665   /* The value WOP is converted to the destination format, rounding
666      using mode RM. When the destination is a fixed-point format, then
667      a source value of Infinity, NaN or one which would round to an
668      integer outside the fixed point range then an IEEE Invalid
669      Operation condition is raised.  */
670   switch (to)
671     {
672     case fmt_single:
673       sim_fpu_round_32 (&wop, round, 0);
674       sim_fpu_to32 (&result32, &wop);
675       result64 = result32;
676       break;
677     case fmt_double:
678       sim_fpu_round_64 (&wop, round, 0);
679       sim_fpu_to64 (&result64, &wop);
680       break;
681     case fmt_word:
682       sim_fpu_to32i (&result32, &wop, round);
683       result64 = result32;
684       break;
685     case fmt_long:
686       sim_fpu_to64i (&result64, &wop, round);
687       break;
688     default:
689       result64 = 0;
690       fprintf (stderr, "Bad switch\n");
691       abort ();
692     }
693
694 #ifdef DEBUG
695   printf ("DBG: Convert: returning 0x%s (to format = %s)\n",
696           pr_addr (result64), fpu_format_name (to));
697 #endif /* DEBUG */
698
699   return (result64);
700 }
701
702 static const char *
703 fpu_format_name (FP_formats fmt)
704 {
705   switch (fmt)
706     {
707     case fmt_single:
708       return "single";
709     case fmt_double:
710       return "double";
711     case fmt_word:
712       return "word";
713     case fmt_long:
714       return "long";
715     case fmt_unknown:
716       return "<unknown>";
717     case fmt_uninterpreted:
718       return "<uninterpreted>";
719     case fmt_uninterpreted_32:
720       return "<uninterpreted_32>";
721     case fmt_uninterpreted_64:
722       return "<uninterpreted_64>";
723     default:
724       return "<format error>";
725     }
726 }
727
728 #ifdef DEBUG
729 static const char *
730 fpu_rounding_mode_name (int rm)
731 {
732   switch (rm)
733     {
734     case FP_RM_NEAREST:
735       return "Round";
736     case FP_RM_TOZERO:
737       return "Trunc";
738     case FP_RM_TOPINF:
739       return "Ceil";
740     case FP_RM_TOMINF:
741       return "Floor";
742     default:
743       return "<rounding mode error>";
744     }
745 }
746 #endif /* DEBUG */