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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [sim/] [mips/] [cp1.c] - Blame information for rev 1767

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

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

powered by: WebSVN 2.1.0

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