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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [hal/] [mips/] [arch/] [v2_0/] [src/] [mipsfp.c] - Blame information for rev 27

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

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      mipsfp.c
4
//
5
//      HAL miscellaneous functions
6
//
7
//==========================================================================
8
//####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later version.
16
//
17
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
// for more details.
21
//
22
// You should have received a copy of the GNU General Public License along
23
// with eCos; if not, write to the Free Software Foundation, Inc.,
24
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25
//
26
// As a special exception, if other files instantiate templates or use macros
27
// or inline functions from this file, or you compile this file and link it
28
// with other works to produce a work based on this file, this file does not
29
// by itself cause the resulting work to be covered by the GNU General Public
30
// License. However the source code for this file must still be made available
31
// in accordance with section (3) of the GNU General Public License.
32
//
33
// This exception does not invalidate any other reasons why a work based on
34
// this file might be covered by the GNU General Public License.
35
//
36
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37
// at http://sources.redhat.com/ecos/ecos-license/
38
// -------------------------------------------
39
//####ECOSGPLCOPYRIGHTEND####
40
//==========================================================================
41
//#####DESCRIPTIONBEGIN####
42
//
43
// Author(s):    jlarmour
44
// Contributors: jlarmour
45
// Date:         1999-07-13
46
// Purpose:      Emulate unimplemented FP operations on MIPS architectures
47
// Description:  This catches the unimplemented operation excetion only,
48
//               and if possible deals with it so processing can continue
49
//               as if the MIPS had a proper IEEE FPU
50
//               
51
//
52
//####DESCRIPTIONEND####
53
//
54
//========================================================================*/
55
 
56
// CONFIGURATION
57
 
58
#include <pkgconf/hal.h>
59
 
60
#ifdef CYGHWR_HAL_MIPS_FPU
61
 
62
// INCLUDES
63
 
64
#include <cyg/infra/cyg_type.h>    // Standard eCos types
65
#include <cyg/infra/cyg_ass.h>     // Standard eCos assertion support
66
#include <cyg/infra/cyg_trac.h>    // Standard eCos tracing support
67
#include <cyg/hal/hal_intr.h>      // HAL interrupt vectors
68
#include <cyg/hal/hal_arch.h>      // Architecture types such as
69
                                   // HAL_SavedRegisters
70
#define CYGARC_HAL_COMMON_EXPORT_CPU_MACROS
71
#include <cyg/hal/mips-regs.h>     // MIPS register and bitmask definitions
72
 
73
// TYPES
74
 
75
// The following types were taken from <sys/ieeefp.h> from libm.
76
 
77
#if (CYG_BYTEORDER == CYG_MSBFIRST) // Big endian
78
 
79
typedef union
80
{
81
    cyg_int32 asi32[2];
82
 
83
    cyg_int64 asi64;
84
 
85
    double value;
86
 
87
    struct
88
    {
89
#if (CYG_DOUBLE_BYTEORDER == CYG_MSBFIRST)
90
        unsigned int sign : 1;
91
        unsigned int exponent: 11;
92
        unsigned int fraction0:4;
93
        unsigned int fraction1:16;
94
        unsigned int fraction2:16;
95
        unsigned int fraction3:16;
96
#else
97
        unsigned int fraction2:16;
98
        unsigned int fraction3:16;
99
        unsigned int sign : 1;
100
        unsigned int exponent: 11;
101
        unsigned int fraction0:4;
102
        unsigned int fraction1:16;
103
#endif        
104
    } number;
105
 
106
    struct
107
    {
108
#if (CYG_DOUBLE_BYTEORDER == CYG_MSBFIRST)
109
        unsigned int sign : 1;
110
        unsigned int exponent: 11;
111
        unsigned int quiet:1;
112
        unsigned int function0:3;
113
        unsigned int function1:16;
114
        unsigned int function2:16;
115
        unsigned int function3:16;
116
#else
117
        unsigned int function2:16;
118
        unsigned int function3:16;
119
        unsigned int sign : 1;
120
        unsigned int exponent: 11;
121
        unsigned int quiet:1;
122
        unsigned int function0:3;
123
        unsigned int function1:16;
124
#endif
125
    } nan;
126
 
127
    struct
128
    {
129
#if (CYG_DOUBLE_BYTEORDER == CYG_MSBFIRST)
130
        cyg_uint32 msw;
131
        cyg_uint32 lsw;
132
#else
133
        cyg_uint32 lsw;
134
        cyg_uint32 msw;
135
#endif
136
    } parts;
137
 
138
 
139
} Cyg_libm_ieee_double_shape_type;
140
 
141
 
142
typedef union
143
{
144
    cyg_int32 asi32;
145
 
146
    float value;
147
 
148
    struct
149
    {
150
        unsigned int sign : 1;
151
        unsigned int exponent: 8;
152
        unsigned int fraction0: 7;
153
        unsigned int fraction1: 16;
154
    } number;
155
 
156
    struct
157
    {
158
        unsigned int sign:1;
159
        unsigned int exponent:8;
160
        unsigned int quiet:1;
161
        unsigned int function0:6;
162
        unsigned int function1:16;
163
    } nan;
164
 
165
} Cyg_libm_ieee_float_shape_type;
166
 
167
 
168
#else // Little endian
169
 
170
typedef union
171
{
172
    cyg_int32 asi32[2];
173
 
174
    cyg_int64 asi64;
175
 
176
    double value;
177
 
178
    struct
179
    {
180
#if (CYG_DOUBLE_BYTEORDER == CYG_MSBFIRST) // Big endian
181
        unsigned int fraction1:16;
182
        unsigned int fraction0: 4;
183
        unsigned int exponent :11;
184
        unsigned int sign     : 1;
185
        unsigned int fraction3:16;
186
        unsigned int fraction2:16;
187
#else
188
        unsigned int fraction3:16;
189
        unsigned int fraction2:16;
190
        unsigned int fraction1:16;
191
        unsigned int fraction0: 4;
192
        unsigned int exponent :11;
193
        unsigned int sign     : 1;
194
#endif
195
    } number;
196
 
197
    struct
198
    {
199
#if (CYG_DOUBLE_BYTEORDER == CYG_MSBFIRST) // Big endian
200
        unsigned int function1:16;
201
        unsigned int function0:3;
202
        unsigned int quiet:1;
203
        unsigned int exponent: 11;
204
        unsigned int sign : 1;
205
        unsigned int function3:16;
206
        unsigned int function2:16;
207
#else
208
        unsigned int function3:16;
209
        unsigned int function2:16;
210
        unsigned int function1:16;
211
        unsigned int function0:3;
212
        unsigned int quiet:1;
213
        unsigned int exponent: 11;
214
        unsigned int sign : 1;
215
#endif
216
    } nan;
217
 
218
    struct
219
    {
220
#if (CYG_DOUBLE_BYTEORDER == CYG_MSBFIRST) // Big endian
221
        cyg_uint32 msw;
222
        cyg_uint32 lsw;
223
#else
224
        cyg_uint32 lsw;
225
        cyg_uint32 msw;
226
#endif
227
    } parts;
228
 
229
} Cyg_libm_ieee_double_shape_type;
230
 
231
 
232
typedef union
233
{
234
    cyg_int32 asi32;
235
 
236
    float value;
237
 
238
    struct
239
    {
240
        unsigned int fraction0: 7;
241
        unsigned int fraction1: 16;
242
        unsigned int exponent: 8;
243
        unsigned int sign : 1;
244
    } number;
245
 
246
    struct
247
    {
248
        unsigned int function1:16;
249
        unsigned int function0:6;
250
        unsigned int quiet:1;
251
        unsigned int exponent:8;
252
        unsigned int sign:1;
253
    } nan;
254
 
255
} Cyg_libm_ieee_float_shape_type;
256
 
257
#endif // little-endian
258
 
259
typedef enum {
260
    ADD_INSN=0,       // 0
261
    SUB_INSN,
262
    MUL_INSN,
263
    DIV_INSN,
264
    SQRT_INSN,
265
    ABS_INSN,         // 5
266
    MOV_INSN,
267
    NEG_INSN,
268
    ROUNDL_INSN,
269
    TRUNCL_INSN,
270
    CEILL_INSN,       // 10
271
    FLOORL_INSN,
272
    ROUNDW_INSN,
273
    TRUNCW_INSN,
274
    CEILW_INSN,
275
    FLOORW_INSN,      // 15
276
    // ...
277
    CVTS_INSN=32,
278
    CVTD_INSN,
279
    // ...
280
    CVTW_INSN=36,
281
    CVTL_INSN,
282
    // ...
283
    // 
284
    // 48-63 are floating point compare - treated separately
285
 
286
} fp_operation;
287
 
288
typedef enum {
289
    S_FORMAT=16,
290
    D_FORMAT=17,
291
    W_FORMAT=20,
292
    L_FORMAT=21
293
} fp_format;
294
 
295
// FUNCTIONS
296
 
297
#define issubnormal(_x_) ((_x_).number.exponent == 0)
298
 
299
// These functions convert between single precision floating point numbers
300
// represented in register or union form. This is required because endian-ness
301
// matters when a 32-bit float is in a 64-bit register.
302
 
303
static __inline__ void
304
reg2flt( CYG_HAL_FPU_REG *fpu_reg_p, Cyg_libm_ieee_float_shape_type *flt)
305
{
306
#if defined(CYGHWR_HAL_MIPS_FPU_32BIT) || (CYG_BYTEORDER == CYG_LSBFIRST)
307
    flt->asi32 = *(cyg_int32 *)fpu_reg_p;
308
#else
309
    flt->asi32 = *((cyg_int32 *)fpu_reg_p + 1);
310
# endif
311
} // reg2flt()
312
 
313
static __inline__ void
314
flt2reg( Cyg_libm_ieee_float_shape_type *flt, CYG_HAL_FPU_REG *fpu_reg_p )
315
{
316
#if defined(CYGHWR_HAL_MIPS_FPU_32BIT) || (CYG_BYTEORDER == CYG_LSBFIRST)
317
    *(cyg_int32 *)fpu_reg_p = flt->asi32;
318
#else
319
    *((cyg_int32 *)fpu_reg_p + 1) = flt->asi32;
320
# endif
321
} // flt2reg()
322
 
323
static __inline__ void
324
reg2dbl( CYG_HAL_FPU_REG *fpu_reg_p, Cyg_libm_ieee_double_shape_type *flt)
325
{
326
    flt->asi64 = *(cyg_int64 *)fpu_reg_p;
327
} // reg2dbl()
328
 
329
static __inline__ void
330
dbl2reg( Cyg_libm_ieee_double_shape_type *flt, CYG_HAL_FPU_REG *fpu_reg_p )
331
{
332
    *(cyg_uint64*)fpu_reg_p = flt->asi64;
333
} // dbl2reg()
334
 
335
 
336
// This function returns non-zero if the exception has been handled
337
// successfully.
338
 
339
// FIXME: Arguably we should raise underflow exceptions in some of the cases
340
// below e.g. sqrt(subnormal). And perhaps we should round appropriately to
341
// +/- 2^^Emin if round to +/- infinity is enabled, as per the FS bit. Not sure.
342
 
343
externC cyg_uint8
344
cyg_hal_mips_process_fpe( HAL_SavedRegisters *regs )
345
{
346
    CYG_WORD insn;
347
    CYG_HAL_FPU_REG *srcreg1, *srcreg2, *dstreg;
348
    cyg_uint8 handled=0;
349
    fp_format format;
350
    cyg_uint8 fp64bit=0;             // true if format is 64bit, false if 32bit
351
    cyg_uint8 fixedpoint=0;          // true if format is fixed point, false if
352
                                     // floating point
353
    cyg_uint8 computational_insn=1;  // computational FP instruction
354
    cyg_bool delay_slot;             // did it happen in a delay slot
355
 
356
    CYG_REPORT_FUNCNAMETYPE("cyg_hal_mips_process_fpe", "returning %d");
357
 
358
    CYG_CHECK_DATA_PTR( regs,
359
                    "cyg_hal_mips_process_fpe() called with invalid regs ptr");
360
 
361
    CYG_PRECONDITION( (regs->vector>>2) == CYGNUM_HAL_VECTOR_FPE,
362
                      "Asked to process non-FPE exception");
363
 
364
    // First of all, we only handle the unimplemented operation exception
365
    // here, so if we don't have that, we just exit
366
    if ((regs->fcr31 & FCR31_CAUSE_E) == 0) {
367
        CYG_REPORT_RETVAL(0);
368
        return 0;
369
    }
370
 
371
    // Get the contents of the instruction that caused the exception. This
372
    // may have been in a branch delay slot however, so we have to check
373
    // the BD bit in the cause register first.
374
    if (regs->cause & CAUSE_BD) {
375
        insn = *(((CYG_WORD *) regs->pc) + 1);
376
        delay_slot = true;
377
    } else {
378
        insn = *(CYG_WORD *) regs->pc;
379
        delay_slot = false;
380
    }
381
 
382
    CYG_TRACE2(true, "exception at pc %08x containing %08x", regs->pc, insn);
383
 
384
    CYG_ASSERT( (insn>>26) == 0x11,
385
                "Instruction at pc doesn't have expected opcode COP1");
386
 
387
    // Determine the format
388
    format = (insn >> 21) & 0x1f;
389
 
390
    switch (format)
391
    {
392
    case S_FORMAT:
393
        break;
394
    case D_FORMAT:
395
        fp64bit++;
396
        break;
397
    case W_FORMAT:
398
        fixedpoint++;
399
        break;
400
    case L_FORMAT:
401
        fixedpoint++;
402
        fp64bit++;
403
        break;
404
    default:
405
        computational_insn=0;
406
        break;
407
    } // switch
408
 
409
    // This module only emulates computational floating point instructions
410
    if (computational_insn && !fixedpoint) {
411
 
412
        // Decode the registers used
413
        dstreg  = &regs->f[ (insn >>  6) & 0x1f ];
414
        srcreg1 = &regs->f[ (insn >> 11) & 0x1f ];
415
        srcreg2 = &regs->f[ (insn >> 16) & 0x1f ];
416
 
417
        // Determine the operation requested
418
        switch (insn & 0x3f)
419
        {
420
        case ADD_INSN:
421
        case SUB_INSN:
422
        case MUL_INSN:
423
        case DIV_INSN:
424
 
425
            if (fp64bit) {
426
                Cyg_libm_ieee_double_shape_type s1, s2;
427
 
428
                reg2dbl( srcreg1, &s1 );
429
                reg2dbl( srcreg2, &s2 );
430
 
431
                if ( issubnormal( s1 ) ) {  // flush to 0 and restart
432
                    // but preserve sign
433
                    if (s1.number.sign)
434
                        s1.value = -0.0;
435
                    else
436
                        s1.value = 0.0;
437
                    dbl2reg( &s1, srcreg1 );
438
                    handled++;
439
                }
440
 
441
                // We could try flushing both to 0 at the same time, but
442
                // that's inadvisable if both numbers are very small.
443
                // Particularly if this is DIV_INSN, when we could therefore
444
                // get 0/0 even when the program explicitly checked for
445
                // denominator != 0. That's also why we check s1 first.
446
 
447
                else if (  issubnormal( s2 ) ) {  // flush to 0 and restart
448
                    // but preserve sign
449
                    if (s2.number.sign)
450
                        s2.value = -0.0;
451
                    else
452
                        s2.value = 0.0;
453
                    dbl2reg( &s2, srcreg2 );
454
                    handled++;
455
                }
456
 
457
            } else { // 32-bit
458
                Cyg_libm_ieee_float_shape_type s1, s2;
459
 
460
                reg2flt( srcreg1, &s1 );
461
                reg2flt( srcreg2, &s2 );
462
 
463
                if ( issubnormal( s1 )) {  // flush to 0 and restart
464
                    // but preserve sign
465
                    if (s1.number.sign)
466
                        s1.value = -0.0;
467
                    else
468
                        s1.value = 0.0;
469
                    flt2reg( &s1, srcreg1 );
470
                    handled++;
471
                }
472
                else if ( issubnormal( s2 ) ) {  // flush to 0 and restart
473
                    // but preserve sign
474
                    if (s2.number.sign)
475
                        s2.value = -0.0;
476
                    else
477
                        s2.value = 0.0;
478
                    flt2reg( &s2, srcreg2 );
479
                    handled++;
480
                }
481
            }
482
            break;
483
 
484
        case SQRT_INSN:
485
            if ( fp64bit ) {
486
                Cyg_libm_ieee_double_shape_type d, s;
487
 
488
                reg2dbl( dstreg, &d );
489
                reg2dbl( srcreg1, &s );
490
 
491
                if ( issubnormal( s ) ) {  // Sqrt of something tiny is 0
492
                    // if this is a delay slot, we can't restart properly
493
                    // so if it is subnormal, clear the source register instead
494
                    if ( delay_slot ) {
495
                        // but preserve sign
496
                        if (s.number.sign)
497
                            s.value = -0.0;
498
                        else
499
                            s.value = 0.0;
500
                        dbl2reg( &s, srcreg1 );
501
                    } else {
502
                        // but preserve sign
503
                        if (s.number.sign)
504
                            d.value = -0.0;
505
                        else
506
                            d.value = 0.0;
507
                        dbl2reg( &d, dstreg );
508
                        regs->pc += 4; // We've dealt with this so move on
509
                    }
510
                    handled++;
511
                }
512
 
513
            } else { // 32-bit
514
                Cyg_libm_ieee_float_shape_type d, s;
515
 
516
                reg2flt( dstreg, &d );
517
                reg2flt( srcreg1, &s );
518
 
519
                if ( issubnormal( s ) ) {  // Sqrt of something tiny is 0
520
                    // if this is a delay slot, we can't restart properly
521
                    // so if it is subnormal, clear the source register instead
522
                    if ( delay_slot ) {
523
                        // but preserve sign
524
                        if (s.number.sign)
525
                            s.value = -0.0;
526
                        else
527
                            s.value = 0.0;
528
                        flt2reg( &s, srcreg1 );
529
                    } else {
530
                        // but preserve sign
531
                        if (s.number.sign)
532
                            d.value = -0.0;
533
                        else
534
                            d.value = 0.0;
535
                        flt2reg( &d, dstreg );
536
                        regs->pc += 4; // We've dealt with this so move on
537
                    }
538
                    handled++;
539
                }
540
            }
541
            break;
542
 
543
        case ABS_INSN:
544
            // We may as well do this right if we can
545
            if ( fp64bit ) {
546
                Cyg_libm_ieee_double_shape_type d, s;
547
 
548
                reg2dbl( dstreg, &d );
549
                reg2dbl( srcreg1, &s );
550
 
551
                // if this is a delay slot, we can't restart properly
552
                // so if it is subnormal, clear the source register instead
553
                if ( delay_slot ) {
554
                    if ( issubnormal( s ) ) {
555
                        // The sign is still important for abs in case
556
                        // there are any further operations on the same
557
                        // register
558
                        if (s.number.sign)
559
                            s.value = -0.0;
560
                        else
561
                            s.value = 0.0;
562
                        dbl2reg( &s, srcreg1 );
563
                        handled++;
564
                    }
565
                } else {
566
                    d.asi64 = s.asi64;
567
                    d.number.sign = 0;
568
                    dbl2reg( &d, dstreg );
569
                    regs->pc += 4;
570
                    handled++;
571
                }
572
            } else { // 32-bit
573
                Cyg_libm_ieee_float_shape_type d, s;
574
 
575
                reg2flt( dstreg, &d );
576
                reg2flt( srcreg1, &s );
577
 
578
                // if this is a delay slot, we can't restart properly
579
                // so if it is subnormal, clear the source register instead
580
                if ( delay_slot ) {
581
                    if ( issubnormal( s ) ) {
582
                        // The sign is still important for abs in case
583
                        // there are any further operations on the same
584
                        // register
585
                        if (s.number.sign)
586
                            s.value = -0.0;
587
                        else
588
                            s.value = 0.0;
589
                        flt2reg( &s, srcreg1 );
590
                        handled++;
591
                    }
592
                } else {
593
                    d.asi32 = s.asi32;
594
                    d.number.sign = 0;
595
                    flt2reg( &d, dstreg );
596
                    regs->pc += 4;
597
                    handled++;
598
                }
599
            }
600
            break;
601
 
602
        case MOV_INSN:
603
            // We may as well do this right if we can
604
            if ( fp64bit ) {
605
                Cyg_libm_ieee_double_shape_type d, s;
606
 
607
                reg2dbl( dstreg, &d );
608
                reg2dbl( srcreg1, &s );
609
 
610
                // if this is a delay slot, we can't restart properly
611
                // so if it is subnormal, clear the source register instead
612
                if ( delay_slot ) {
613
                    if ( issubnormal( s ) ) {
614
                        // but preserve sign
615
                        if (s.number.sign)
616
                            s.value = -0.0;
617
                        else
618
                            s.value = 0.0;
619
                        dbl2reg( &s, srcreg1 );
620
                        handled++;
621
                    }
622
                } else {
623
                    d.asi64 = s.asi64;
624
                    dbl2reg( &d, dstreg );
625
                    regs->pc += 4;
626
                    handled++;
627
                }
628
            } else { // 32-bit
629
                Cyg_libm_ieee_float_shape_type d, s;
630
 
631
                reg2flt( dstreg, &d );
632
                reg2flt( srcreg1, &s );
633
 
634
                // if this is a delay slot, we can't restart properly
635
                // so if it is subnormal, clear the source register instead
636
                if ( delay_slot ) {
637
                    if ( issubnormal( s ) ) {
638
                        // The sign is still important for abs in case
639
                        // there are any further operations on the same
640
                        // register
641
                        if (s.number.sign)
642
                            s.value = -0.0;
643
                        else
644
                            s.value = 0.0;
645
                        flt2reg( &s, srcreg1 );
646
                        handled++;
647
                    }
648
                } else {
649
                    d.asi32 = s.asi32;
650
                    flt2reg( &d, dstreg );
651
                    regs->pc += 4;
652
                    handled++;
653
                }
654
            }
655
            break;
656
 
657
        case NEG_INSN:
658
            // We may as well do this right if we can
659
            if ( fp64bit ) {
660
                Cyg_libm_ieee_double_shape_type d, s;
661
 
662
                reg2dbl( dstreg, &d );
663
                reg2dbl( srcreg1, &s );
664
 
665
                // if this is a delay slot, we can't restart properly
666
                // so if it is subnormal, clear the source register instead
667
                if ( delay_slot ) {
668
                    if ( issubnormal( s ) ) {
669
                        // but preserve sign
670
                        if (s.number.sign)
671
                            s.value = -0.0;
672
                        else
673
                            s.value = 0.0;
674
                        dbl2reg( &s, srcreg1 );
675
                        handled++;
676
                    }
677
                } else {
678
                    d.asi64 = s.asi64;
679
                    d.number.sign = s.number.sign ? 0 : 1;
680
                    dbl2reg( &d, dstreg );
681
                    regs->pc += 4;
682
                    handled++;
683
                }
684
            } else { // 32-bit
685
                Cyg_libm_ieee_float_shape_type d, s;
686
 
687
                reg2flt( dstreg, &d );
688
                reg2flt( srcreg1, &s );
689
 
690
                // if this is a delay slot, we can't restart properly
691
                // so if it is subnormal, clear the source register instead
692
                if ( delay_slot ) {
693
                    if ( issubnormal( s ) ) {
694
                        // but preserve sign
695
                        if (s.number.sign)
696
                            s.value = -0.0;
697
                        else
698
                            s.value = 0.0;
699
                        flt2reg( &s, srcreg1 );
700
                        handled++;
701
                    }
702
                } else {
703
                    d.asi32 = s.asi32;
704
                    d.number.sign = s.number.sign ? 0 : 1;
705
                    flt2reg( &d, dstreg );
706
                    regs->pc += 4;
707
                    handled++;
708
                }
709
            }
710
            break;
711
 
712
        // We can't do much about floating-point to fixed-point arithmetic
713
        // without emulating the FPU here ourselves!
714
        // So simply zero denormalized numbers
715
        case ROUNDL_INSN:
716
        case TRUNCL_INSN:
717
        case CEILL_INSN:
718
        case FLOORL_INSN:
719
        case ROUNDW_INSN:
720
        case TRUNCW_INSN:
721
        case CEILW_INSN:
722
        case FLOORW_INSN:
723
        case CVTS_INSN:
724
        case CVTD_INSN:
725
        case CVTW_INSN:
726
        case CVTL_INSN:
727
 
728
            if ( fp64bit ) {
729
                Cyg_libm_ieee_double_shape_type s;
730
 
731
                reg2dbl( srcreg1, &s );
732
 
733
                // just try and 0 the source register if it is subnormal
734
                if ( issubnormal( s ) ) {
735
                    // but preserve sign
736
                    if (s.number.sign)
737
                        s.value = -0.0;
738
                    else
739
                        s.value = 0.0;
740
                    dbl2reg( &s, srcreg1 );
741
                    handled++;
742
                }
743
            } else { // 32-bit
744
                Cyg_libm_ieee_float_shape_type s;
745
 
746
                reg2flt( srcreg1, &s );
747
 
748
                // just try and 0 the source register if it is subnormal
749
                if ( issubnormal( s ) ) {
750
                    // but preserve sign
751
                    if (s.number.sign)
752
                        s.value = -0.0;
753
                    else
754
                        s.value = 0.0;
755
                    flt2reg( &s, srcreg1 );
756
                    handled++;
757
                }
758
            }
759
            break;
760
 
761
        default:
762
            // check for floating-point compare (C.cond.fmt)
763
            if ( (insn & 0x30) == 0x30 ) {
764
                if (fp64bit) {
765
                    Cyg_libm_ieee_double_shape_type s1, s2;
766
 
767
                    reg2dbl( srcreg1, &s1 );
768
                    reg2dbl( srcreg2, &s2 );
769
 
770
                    if ( issubnormal( s1 ) ) {  // flush to 0 and restart
771
                        // but preserve sign
772
                        if (s1.number.sign)
773
                            s1.value = -0.0;
774
                        else
775
                            s1.value = 0.0;
776
                        dbl2reg( &s1, srcreg1 );
777
                        handled++;
778
                    }
779
 
780
                    if (  issubnormal( s2 ) ) {  // flush to 0 and restart
781
                        // but preserve sign
782
                        if (s2.number.sign)
783
                            s2.value = -0.0;
784
                        else
785
                            s2.value = 0.0;
786
                        dbl2reg( &s2, srcreg2 );
787
                        handled++;
788
                    }
789
 
790
                } else { // 32-bit
791
                    Cyg_libm_ieee_float_shape_type s1, s2;
792
 
793
                    reg2flt( srcreg1, &s1 );
794
                    reg2flt( srcreg2, &s2 );
795
 
796
                    if ( issubnormal( s1 )) {  // flush to 0 and restart
797
                        // but preserve sign
798
                        if (s1.number.sign)
799
                            s1.value = -0.0;
800
                        else
801
                            s1.value = 0.0;
802
                        flt2reg( &s1, srcreg1 );
803
                        handled++;
804
                    }
805
                    if ( issubnormal( s2 ) ) {  // flush to 0 and restart
806
                        // but preserve sign
807
                        if (s2.number.sign)
808
                            s2.value = -0.0;
809
                        else
810
                            s2.value = 0.0;
811
                        flt2reg( &s2, srcreg2 );
812
                        handled++;
813
                    }
814
                } // else 
815
            } // if
816
            break;
817
        } // switch
818
    } // if (computational_insn && !fixedpoint)
819
 
820
    if ( handled != 0) {
821
        // We must clear the cause and flag bits before restoring FPCR31
822
        regs->fcr31 &= ~(FCR31_CAUSE_E | FCR31_CAUSE_V | FCR31_CAUSE_Z |
823
                         FCR31_CAUSE_O | FCR31_CAUSE_U | FCR31_CAUSE_I |
824
                         FCR31_FLAGS_V | FCR31_FLAGS_Z |
825
                         FCR31_FLAGS_O | FCR31_FLAGS_U | FCR31_FLAGS_I);
826
 
827
    }
828
 
829
    CYG_REPORT_RETVAL( handled );
830
    return handled;
831
} // cyg_hal_mips_process_fpe()
832
 
833
#endif // ifdef CYGHWR_HAL_MIPS_FPU
834
 
835
// EOF mipsfp.c

powered by: WebSVN 2.1.0

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