OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-6.8/] [sim/] [mips/] [cp1.c] - Blame information for rev 862

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.