Revision 7c58044c

b/darwin-user/main.c
224 224
            case POWERPC_EXCP_FP:
225 225
                EXCP_DUMP(env, "Floating point program exception\n");
226 226
                /* Set FX */
227
                env->fpscr[7] |= 0x8;
228
                /* Finally, update FEX */
229
                if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
230
                    ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
231
                    env->fpscr[7] |= 0x4;
232 227
                info.si_signo = SIGFPE;
233 228
                info.si_errno = 0;
234 229
                switch (env->error_code & 0xF) {
......
248 243
                case POWERPC_EXCP_FP_VXSOFT:
249 244
                    info.si_code = FPE_FLTINV;
250 245
                    break;
251
                case POWERPC_EXCP_FP_VXNAN:
246
                case POWERPC_EXCP_FP_VXSNAN:
252 247
                case POWERPC_EXCP_FP_VXISI:
253 248
                case POWERPC_EXCP_FP_VXIDI:
254 249
                case POWERPC_EXCP_FP_VXIMZ:
b/linux-user/main.c
829 829
            switch (env->error_code & ~0xF) {
830 830
            case POWERPC_EXCP_FP:
831 831
                EXCP_DUMP(env, "Floating point program exception\n");
832
                /* Set FX */
833
                env->fpscr[7] |= 0x8;
834
                /* Finally, update FEX */
835
                if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
836
                    ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
837
                    env->fpscr[7] |= 0x4;
838 832
                info.si_signo = TARGET_SIGFPE;
839 833
                info.si_errno = 0;
840 834
                switch (env->error_code & 0xF) {
......
854 848
                case POWERPC_EXCP_FP_VXSOFT:
855 849
                    info.si_code = TARGET_FPE_FLTINV;
856 850
                    break;
857
                case POWERPC_EXCP_FP_VXNAN:
851
                case POWERPC_EXCP_FP_VXSNAN:
858 852
                case POWERPC_EXCP_FP_VXISI:
859 853
                case POWERPC_EXCP_FP_VXIDI:
860 854
                case POWERPC_EXCP_FP_VXIMZ:
b/target-ppc/cpu.h
239 239
    POWERPC_EXCP_FP_UX         = 0x02,  /* FP underflow                      */
240 240
    POWERPC_EXCP_FP_ZX         = 0x03,  /* FP divide by zero                 */
241 241
    POWERPC_EXCP_FP_XX         = 0x04,  /* FP inexact                        */
242
    POWERPC_EXCP_FP_VXNAN      = 0x05,  /* FP invalid SNaN op                */
242
    POWERPC_EXCP_FP_VXSNAN     = 0x05,  /* FP invalid SNaN op                */
243 243
    POWERPC_EXCP_FP_VXISI      = 0x06,  /* FP invalid infinite subtraction   */
244 244
    POWERPC_EXCP_FP_VXIDI      = 0x07,  /* FP invalid infinite divide        */
245 245
    POWERPC_EXCP_FP_VXZDZ      = 0x08,  /* FP invalid zero divide            */
......
433 433
    POWERPC_FLAG_PMM  = 0x00000400,
434 434
};
435 435

  
436
/*****************************************************************************/
437
/* Floating point status and control register                                */
438
#define FPSCR_FX     31 /* Floating-point exception summary                  */
439
#define FPSCR_FEX    30 /* Floating-point enabled exception summary          */
440
#define FPSCR_VX     29 /* Floating-point invalid operation exception summ.  */
441
#define FPSCR_OX     28 /* Floating-point overflow exception                 */
442
#define FPSCR_UX     27 /* Floating-point underflow exception                */
443
#define FPSCR_ZX     26 /* Floating-point zero divide exception              */
444
#define FPSCR_XX     25 /* Floating-point inexact exception                  */
445
#define FPSCR_VXSNAN 24 /* Floating-point invalid operation exception (sNan) */
446
#define FPSCR_VXISI  23 /* Floating-point invalid operation exception (inf)  */
447
#define FPSCR_VXIDI  22 /* Floating-point invalid operation exception (inf)  */
448
#define FPSCR_VXZDZ  21 /* Floating-point invalid operation exception (zero) */
449
#define FPSCR_VXIMZ  20 /* Floating-point invalid operation exception (inf)  */
450
#define FPSCR_VXVC   19 /* Floating-point invalid operation exception (comp) */
451
#define FPSCR_FR     18 /* Floating-point fraction rounded                   */
452
#define FPSCR_FI     17 /* Floating-point fraction inexact                   */
453
#define FPSCR_C      16 /* Floating-point result class descriptor            */
454
#define FPSCR_FL     15 /* Floating-point less than or negative              */
455
#define FPSCR_FG     14 /* Floating-point greater than or negative           */
456
#define FPSCR_FE     13 /* Floating-point equal or zero                      */
457
#define FPSCR_FU     12 /* Floating-point unordered or NaN                   */
458
#define FPSCR_FPCC   12 /* Floating-point condition code                     */
459
#define FPSCR_FPRF   12 /* Floating-point result flags                       */
460
#define FPSCR_VXSOFT 10 /* Floating-point invalid operation exception (soft) */
461
#define FPSCR_VXSQRT 9  /* Floating-point invalid operation exception (sqrt) */
462
#define FPSCR_VXCVI  8  /* Floating-point invalid operation exception (int)  */
463
#define FPSCR_VE     7  /* Floating-point invalid operation exception enable */
464
#define FPSCR_OE     6  /* Floating-point overflow exception enable          */
465
#define FPSCR_UE     5  /* Floating-point undeflow exception enable          */
466
#define FPSCR_ZE     4  /* Floating-point zero divide exception enable       */
467
#define FPSCR_XE     3  /* Floating-point inexact exception enable           */
468
#define FPSCR_NI     2  /* Floating-point non-IEEE mode                      */
469
#define FPSCR_RN1    1
470
#define FPSCR_RN     0  /* Floating-point rounding control                   */
471
#define fpscr_fex    (((env->fpscr) >> FPSCR_FEX)    & 0x1)
472
#define fpscr_vx     (((env->fpscr) >> FPSCR_VX)     & 0x1)
473
#define fpscr_ox     (((env->fpscr) >> FPSCR_OX)     & 0x1)
474
#define fpscr_ux     (((env->fpscr) >> FPSCR_UX)     & 0x1)
475
#define fpscr_zx     (((env->fpscr) >> FPSCR_ZX)     & 0x1)
476
#define fpscr_xx     (((env->fpscr) >> FPSCR_XX)     & 0x1)
477
#define fpscr_vxsnan (((env->fpscr) >> FPSCR_VXSNAN) & 0x1)
478
#define fpscr_vxisi  (((env->fpscr) >> FPSCR_VXISI)  & 0x1)
479
#define fpscr_vxidi  (((env->fpscr) >> FPSCR_VXIDI)  & 0x1)
480
#define fpscr_vxzdz  (((env->fpscr) >> FPSCR_VXZDZ)  & 0x1)
481
#define fpscr_vximz  (((env->fpscr) >> FPSCR_VXIMZ)  & 0x1)
482
#define fpscr_vxvc   (((env->fpscr) >> FPSCR_VXVC)   & 0x1)
483
#define fpscr_fpcc   (((env->fpscr) >> FPSCR_FPCC)   & 0xF)
484
#define fpscr_vxsoft (((env->fpscr) >> FPSCR_VXSOFT) & 0x1)
485
#define fpscr_vxsqrt (((env->fpscr) >> FPSCR_VXSQRT) & 0x1)
486
#define fpscr_vxcvi  (((env->fpscr) >> FPSCR_VXCVI)  & 0x1)
487
#define fpscr_ve     (((env->fpscr) >> FPSCR_VE)     & 0x1)
488
#define fpscr_oe     (((env->fpscr) >> FPSCR_OE)     & 0x1)
489
#define fpscr_ue     (((env->fpscr) >> FPSCR_UE)     & 0x1)
490
#define fpscr_ze     (((env->fpscr) >> FPSCR_ZE)     & 0x1)
491
#define fpscr_xe     (((env->fpscr) >> FPSCR_XE)     & 0x1)
492
#define fpscr_ni     (((env->fpscr) >> FPSCR_NI)     & 0x1)
493
#define fpscr_rn     (((env->fpscr) >> FPSCR_RN)     & 0x3)
494
/* Invalid operation exception summary */
495
#define fpscr_ix ((env->fpscr) & ((1 << FPSCR_VXSNAN) | (1 << FPSCR_VXISI)  | \
496
                                  (1 << FPSCR_VXIDI)  | (1 << FPSCR_VXZDZ)  | \
497
                                  (1 << FPSCR_VXIMZ)  | (1 << FPSCR_VXVC)   | \
498
                                  (1 << FPSCR_VXSOFT) | (1 << FPSCR_VXSQRT) | \
499
                                  (1 << FPSCR_VXCVI)))
500
/* exception summary */
501
#define fpscr_ex  (((env->fpscr) >> FPSCR_XX) & 0x1F)
502
/* enabled exception summary */
503
#define fpscr_eex (((env->fpscr) >> FPSCR_XX) & ((env->fpscr) >> FPSCR_XE) &  \
504
                   0x1F)
505

  
506
/*****************************************************************************/
507
/* The whole PowerPC CPU context */
436 508
#if defined(TARGET_PPC64H)
437 509
#define NB_MMU_MODES 3
438 510
#else
439 511
#define NB_MMU_MODES 2
440 512
#endif
441 513

  
442
/*****************************************************************************/
443
/* The whole PowerPC CPU context */
444 514
struct CPUPPCState {
445 515
    /* First are the most commonly used resources
446 516
     * during translated code execution
......
482 552
    /* floating point registers */
483 553
    float64 fpr[32];
484 554
    /* floating point status and control register */
485
    uint8_t fpscr[8];
555
    uint32_t fpscr;
486 556

  
487 557
    CPU_COMMON
488 558

  
b/target-ppc/helper.c
2130 2130
                    fprintf(logfile, "Ignore floating point exception\n");
2131 2131
                }
2132 2132
#endif
2133
                env->exception_index = POWERPC_EXCP_NONE;
2134
                env->error_code = 0;
2133 2135
                return;
2134 2136
            }
2135 2137
            new_msr &= ~((target_ulong)1 << MSR_RI);
......
2138 2140
                new_msr |= (target_ulong)1 << MSR_HV;
2139 2141
#endif
2140 2142
            msr |= 0x00100000;
2141
            /* Set FX */
2142
            env->fpscr[7] |= 0x8;
2143
            /* Finally, update FEX */
2144
            if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
2145
                ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
2146
                env->fpscr[7] |= 0x4;
2147 2143
            if (msr_fe0 != msr_fe1) {
2148 2144
                msr |= 0x00010000;
2149 2145
                goto store_current;
......
2199 2195
        /* XXX: To be removed */
2200 2196
        if (env->gpr[3] == 0x113724fa && env->gpr[4] == 0x77810f9b &&
2201 2197
            env->osi_call) {
2202
            if (env->osi_call(env) != 0)
2198
            if (env->osi_call(env) != 0) {
2199
                env->exception_index = POWERPC_EXCP_NONE;
2200
                env->error_code = 0;
2203 2201
                return;
2202
            }
2204 2203
        }
2205 2204
        if (loglevel & CPU_LOG_INT) {
2206 2205
            dump_syscall(env);
b/target-ppc/op.c
135 135
    RETURN();
136 136
}
137 137

  
138
/* Set Rc1 (for floating point arithmetic) */
139
void OPPROTO op_set_Rc1 (void)
140
{
141
    env->crf[1] = env->fpscr[7];
142
    RETURN();
143
}
144

  
145 138
/* Constants load */
146 139
void OPPROTO op_reset_T0 (void)
147 140
{
......
552 545
#endif /* !defined(CONFIG_USER_ONLY) */
553 546

  
554 547
/* FPSCR */
555
void OPPROTO op_load_fpscr (void)
548
#ifdef CONFIG_SOFTFLOAT
549
void OPPROTO op_reset_fpstatus (void)
556 550
{
557
    do_load_fpscr();
551
    env->fp_status.float_exception_flags = 0;
558 552
    RETURN();
559 553
}
554
#endif
560 555

  
561
void OPPROTO op_store_fpscr (void)
556
void OPPROTO op_compute_fprf (void)
562 557
{
563
    do_store_fpscr(PARAM1);
558
    do_compute_fprf(PARAM1);
564 559
    RETURN();
565 560
}
566 561

  
567
void OPPROTO op_reset_scrfx (void)
562
#ifdef CONFIG_SOFTFLOAT
563
void OPPROTO op_float_check_status (void)
568 564
{
569
    env->fpscr[7] &= ~0x8;
565
    do_float_check_status();
566
    RETURN();
567
}
568
#else
569
void OPPROTO op_float_check_status (void)
570
{
571
    if (env->exception_index == POWERPC_EXCP_PROGRAM &&
572
        (env->error_code & POWERPC_EXCP_FP)) {
573
        /* Differred floating-point exception after target FPR update */
574
        if (msr_fe0 != 0 || msr_fe1 != 0)
575
            do_raise_exception_err(env->exception_index, env->error_code);
576
    }
577
    RETURN();
578
}
579
#endif
580

  
581
#if defined(WORDS_BIGENDIAN)
582
#define WORD0 0
583
#define WORD1 1
584
#else
585
#define WORD0 1
586
#define WORD1 0
587
#endif
588
void OPPROTO op_load_fpscr_FT0 (void)
589
{
590
    /* The 32 MSB of the target fpr are undefined.
591
     * They'll be zero...
592
     */
593
    union {
594
        float64 d;
595
        struct {
596
            uint32_t u[2];
597
        } s;
598
    } u;
599

  
600
    u.s.u[WORD0] = 0;
601
    u.s.u[WORD1] = env->fpscr;
602
    FT0 = u.d;
603
    RETURN();
604
}
605

  
606
void OPPROTO op_set_FT0 (void)
607
{
608
    union {
609
        float64 d;
610
        struct {
611
            uint32_t u[2];
612
        } s;
613
    } u;
614

  
615
    u.s.u[WORD0] = 0;
616
    u.s.u[WORD1] = PARAM1;
617
    FT0 = u.d;
618
    RETURN();
619
}
620
#undef WORD0
621
#undef WORD1
622

  
623
void OPPROTO op_load_fpscr_T0 (void)
624
{
625
    T0 = (env->fpscr >> PARAM1) & 0xF;
626
    RETURN();
627
}
628

  
629
void OPPROTO op_load_fpcc (void)
630
{
631
    T0 = fpscr_fpcc;
632
    RETURN();
633
}
634

  
635
void OPPROTO op_fpscr_resetbit (void)
636
{
637
    env->fpscr &= PARAM1;
638
    RETURN();
639
}
640

  
641
void OPPROTO op_fpscr_setbit (void)
642
{
643
    do_fpscr_setbit(PARAM1);
644
    RETURN();
645
}
646

  
647
void OPPROTO op_store_fpscr (void)
648
{
649
    do_store_fpscr(PARAM1);
570 650
    RETURN();
571 651
}
572 652

  
......
1702 1782
/* fadd - fadd. */
1703 1783
void OPPROTO op_fadd (void)
1704 1784
{
1785
#if USE_PRECISE_EMULATION
1786
    do_fadd();
1787
#else
1705 1788
    FT0 = float64_add(FT0, FT1, &env->fp_status);
1789
#endif
1706 1790
    RETURN();
1707 1791
}
1708 1792

  
1709 1793
/* fsub - fsub. */
1710 1794
void OPPROTO op_fsub (void)
1711 1795
{
1796
#if USE_PRECISE_EMULATION
1797
    do_fsub();
1798
#else
1712 1799
    FT0 = float64_sub(FT0, FT1, &env->fp_status);
1800
#endif
1713 1801
    RETURN();
1714 1802
}
1715 1803

  
1716 1804
/* fmul - fmul. */
1717 1805
void OPPROTO op_fmul (void)
1718 1806
{
1807
#if USE_PRECISE_EMULATION
1808
    do_fmul();
1809
#else
1719 1810
    FT0 = float64_mul(FT0, FT1, &env->fp_status);
1811
#endif
1720 1812
    RETURN();
1721 1813
}
1722 1814

  
1723 1815
/* fdiv - fdiv. */
1724 1816
void OPPROTO op_fdiv (void)
1725 1817
{
1818
#if USE_PRECISE_EMULATION
1819
    do_fdiv();
1820
#else
1726 1821
    FT0 = float64_div(FT0, FT1, &env->fp_status);
1822
#endif
1727 1823
    RETURN();
1728 1824
}
1729 1825

  
......
1805 1901
/* frsp - frsp. */
1806 1902
void OPPROTO op_frsp (void)
1807 1903
{
1904
#if USE_PRECISE_EMULATION
1905
    do_frsp();
1906
#else
1808 1907
    FT0 = float64_to_float32(FT0, &env->fp_status);
1908
#endif
1809 1909
    RETURN();
1810 1910
}
1811 1911

  
b/target-ppc/op_helper.c
51 51
#if 0
52 52
    printf("Raise exception %3x code : %d\n", exception, error_code);
53 53
#endif
54
    switch (exception) {
55
    case POWERPC_EXCP_PROGRAM:
56
        if (error_code == POWERPC_EXCP_FP && msr_fe0 == 0 && msr_fe1 == 0)
57
            return;
58
        break;
59
    default:
60
        break;
61
    }
62 54
    env->exception_index = exception;
63 55
    env->error_code = error_code;
64 56
    cpu_loop_exit();
......
107 99
}
108 100
#endif
109 101

  
110
void do_load_fpscr (void)
111
{
112
    /* The 32 MSB of the target fpr are undefined.
113
     * They'll be zero...
114
     */
115
    union {
116
        float64 d;
117
        struct {
118
            uint32_t u[2];
119
        } s;
120
    } u;
121
    int i;
122

  
123
#if defined(WORDS_BIGENDIAN)
124
#define WORD0 0
125
#define WORD1 1
126
#else
127
#define WORD0 1
128
#define WORD1 0
129
#endif
130
    u.s.u[WORD0] = 0;
131
    u.s.u[WORD1] = 0;
132
    for (i = 0; i < 8; i++)
133
        u.s.u[WORD1] |= env->fpscr[i] << (4 * i);
134
    FT0 = u.d;
135
}
136

  
137
void do_store_fpscr (uint32_t mask)
138
{
139
    /*
140
     * We use only the 32 LSB of the incoming fpr
141
     */
142
    union {
143
        double d;
144
        struct {
145
            uint32_t u[2];
146
        } s;
147
    } u;
148
    int i, rnd_type;
149

  
150
    u.d = FT0;
151
    if (mask & 0x80)
152
        env->fpscr[0] = (env->fpscr[0] & 0x9) | ((u.s.u[WORD1] >> 28) & ~0x9);
153
    for (i = 1; i < 7; i++) {
154
        if (mask & (1 << (7 - i)))
155
            env->fpscr[i] = (u.s.u[WORD1] >> (4 * (7 - i))) & 0xF;
156
    }
157
    /* TODO: update FEX & VX */
158
    /* Set rounding mode */
159
    switch (env->fpscr[0] & 0x3) {
160
    case 0:
161
        /* Best approximation (round to nearest) */
162
        rnd_type = float_round_nearest_even;
163
        break;
164
    case 1:
165
        /* Smaller magnitude (round toward zero) */
166
        rnd_type = float_round_to_zero;
167
        break;
168
    case 2:
169
        /* Round toward +infinite */
170
        rnd_type = float_round_up;
171
        break;
172
    default:
173
    case 3:
174
        /* Round toward -infinite */
175
        rnd_type = float_round_down;
176
        break;
177
    }
178
    set_float_rounding_mode(rnd_type, &env->fp_status);
179
}
180

  
181 102
target_ulong ppc_load_dump_spr (int sprn)
182 103
{
183 104
    if (loglevel != 0) {
......
553 474

  
554 475
/*****************************************************************************/
555 476
/* Floating point operations helpers */
477
static inline int fpisneg (float64 f)
478
{
479
    union {
480
        float64 f;
481
        uint64_t u;
482
    } u;
483

  
484
    u.f = f;
485

  
486
    return u.u >> 63 != 0;
487
}
488

  
489
static inline int isden (float f)
490
{
491
    union {
492
        float64 f;
493
        uint64_t u;
494
    } u;
495

  
496
    u.f = f;
497

  
498
    return ((u.u >> 52) & 0x7FF) == 0;
499
}
500

  
501
static inline int iszero (float64 f)
502
{
503
    union {
504
        float64 f;
505
        uint64_t u;
506
    } u;
507

  
508
    u.f = f;
509

  
510
    return (u.u & ~0x8000000000000000ULL) == 0;
511
}
512

  
513
static inline int isinfinity (float64 f)
514
{
515
    union {
516
        float64 f;
517
        uint64_t u;
518
    } u;
519

  
520
    u.f = f;
521

  
522
    return ((u.u >> 51) & 0x3FF) == 0x3FF &&
523
        (u.u & 0x000FFFFFFFFFFFFFULL) == 0;
524
}
525

  
526
void do_compute_fprf (int set_fprf)
527
{
528
    int isneg;
529

  
530
    isneg = fpisneg(FT0);
531
    if (unlikely(float64_is_nan(FT0))) {
532
        if (float64_is_signaling_nan(FT0)) {
533
            /* Signaling NaN: flags are undefined */
534
            T0 = 0x00;
535
        } else {
536
            /* Quiet NaN */
537
            T0 = 0x11;
538
        }
539
    } else if (unlikely(isinfinity(FT0))) {
540
        /* +/- infinity */
541
        if (isneg)
542
            T0 = 0x09;
543
        else
544
            T0 = 0x05;
545
    } else {
546
        if (iszero(FT0)) {
547
            /* +/- zero */
548
            if (isneg)
549
                T0 = 0x12;
550
            else
551
                T0 = 0x02;
552
        } else {
553
            if (isden(FT0)) {
554
                /* Denormalized numbers */
555
                T0 = 0x10;
556
            } else {
557
                /* Normalized numbers */
558
                T0 = 0x00;
559
            }
560
            if (isneg) {
561
                T0 |= 0x08;
562
            } else {
563
                T0 |= 0x04;
564
            }
565
        }
566
    }
567
    if (set_fprf) {
568
        /* We update FPSCR_FPRF */
569
        env->fpscr &= ~(0x1F << FPSCR_FPRF);
570
        env->fpscr |= T0 << FPSCR_FPRF;
571
    }
572
    /* We just need fpcc to update Rc1 */
573
    T0 &= 0xF;
574
}
575

  
576
/* Floating-point invalid operations exception */
577
static always_inline void fload_invalid_op_excp (int op)
578
{
579
    int ve;
580

  
581
    ve = fpscr_ve;
582
    if (op & POWERPC_EXCP_FP_VXSNAN) {
583
        /* Operation on signaling NaN */
584
        env->fpscr |= 1 << FPSCR_VXSNAN;
585
    }
586
    if (op & POWERPC_EXCP_FP_VXSOFT) {
587
        /* Software-defined condition */
588
        env->fpscr |= 1 << FPSCR_VXSOFT;
589
    }
590
    switch (op & ~(POWERPC_EXCP_FP_VXSOFT | POWERPC_EXCP_FP_VXSNAN)) {
591
    case POWERPC_EXCP_FP_VXISI:
592
        /* Magnitude subtraction of infinities */
593
        env->fpscr |= 1 << FPSCR_VXISI;
594
        goto update_arith;
595
    case POWERPC_EXCP_FP_VXIDI:
596
        /* Division of infinity by infinity */
597
        env->fpscr |= 1 << FPSCR_VXIDI;
598
        goto update_arith;
599
    case POWERPC_EXCP_FP_VXZDZ:
600
        /* Division of zero by zero */
601
        env->fpscr |= 1 << FPSCR_VXZDZ;
602
        goto update_arith;
603
    case POWERPC_EXCP_FP_VXIMZ:
604
        /* Multiplication of zero by infinity */
605
        env->fpscr |= 1 << FPSCR_VXIMZ;
606
        goto update_arith;
607
    case POWERPC_EXCP_FP_VXVC:
608
        /* Ordered comparison of NaN */
609
        env->fpscr |= 1 << FPSCR_VXVC;
610
        env->fpscr &= ~(0xF << FPSCR_FPCC);
611
        env->fpscr |= 0x11 << FPSCR_FPCC;
612
        /* We must update the target FPR before raising the exception */
613
        if (ve != 0) {
614
            env->exception_index = POWERPC_EXCP_PROGRAM;
615
            env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_VXVC;
616
            /* Update the floating-point enabled exception summary */
617
            env->fpscr |= 1 << FPSCR_FEX;
618
            /* Exception is differed */
619
            ve = 0;
620
        }
621
        break;
622
    case POWERPC_EXCP_FP_VXSQRT:
623
        /* Square root of a negative number */
624
        env->fpscr |= 1 << FPSCR_VXSQRT;
625
    update_arith:
626
        env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
627
        if (ve == 0) {
628
            /* Set the result to quiet NaN */
629
            FT0 = (uint64_t)-1;
630
            env->fpscr &= ~(0xF << FPSCR_FPCC);
631
            env->fpscr |= 0x11 << FPSCR_FPCC;
632
        }
633
        break;
634
    case POWERPC_EXCP_FP_VXCVI:
635
        /* Invalid conversion */
636
        env->fpscr |= 1 << FPSCR_VXCVI;
637
        env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
638
        if (ve == 0) {
639
            /* Set the result to quiet NaN */
640
            FT0 = (uint64_t)-1;
641
            env->fpscr &= ~(0xF << FPSCR_FPCC);
642
            env->fpscr |= 0x11 << FPSCR_FPCC;
643
        }
644
        break;
645
    }
646
    /* Update the floating-point invalid operation summary */
647
    env->fpscr |= 1 << FPSCR_VX;
648
    /* Update the floating-point exception summary */
649
    env->fpscr |= 1 << FPSCR_FX;
650
    if (ve != 0) {
651
        /* Update the floating-point enabled exception summary */
652
        env->fpscr |= 1 << FPSCR_FEX;
653
        if (msr_fe0 != 0 || msr_fe1 != 0)
654
            do_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_FP | op);
655
    }
656
}
657

  
658
static always_inline void float_zero_divide_excp (void)
659
{
660
    union {
661
        float64 f;
662
        uint64_t u;
663
    } u0, u1;
664
    
665

  
666
    env->fpscr |= 1 << FPSCR_ZX;
667
    env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
668
    /* Update the floating-point exception summary */
669
    env->fpscr |= 1 << FPSCR_FX;
670
    if (fpscr_ze != 0) {
671
        /* Update the floating-point enabled exception summary */
672
        env->fpscr |= 1 << FPSCR_FEX;
673
        if (msr_fe0 != 0 || msr_fe1 != 0) {
674
            do_raise_exception_err(POWERPC_EXCP_PROGRAM,
675
                                   POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX);
676
        }
677
    } else {
678
        /* Set the result to infinity */
679
        u0.f = FT0;
680
        u1.f = FT1;
681
        u0.u = ((u0.u ^ u1.u) & 0x8000000000000000ULL);
682
        u0.u |= 0x3FFULL << 51;
683
        FT0 = u0.f;
684
    }
685
}
686

  
687
static always_inline void float_overflow_excp (void)
688
{
689
    env->fpscr |= 1 << FPSCR_OX;
690
    /* Update the floating-point exception summary */
691
    env->fpscr |= 1 << FPSCR_FX;
692
    if (fpscr_oe != 0) {
693
        /* XXX: should adjust the result */
694
        /* Update the floating-point enabled exception summary */
695
        env->fpscr |= 1 << FPSCR_FEX;
696
        /* We must update the target FPR before raising the exception */
697
        env->exception_index = POWERPC_EXCP_PROGRAM;
698
        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX;
699
    } else {
700
        env->fpscr |= 1 << FPSCR_XX;
701
        env->fpscr |= 1 << FPSCR_FI;
702
    }
703
}
704

  
705
static always_inline void float_underflow_excp (void)
706
{
707
    env->fpscr |= 1 << FPSCR_UX;
708
    /* Update the floating-point exception summary */
709
    env->fpscr |= 1 << FPSCR_FX;
710
    if (fpscr_ue != 0) {
711
        /* XXX: should adjust the result */
712
        /* Update the floating-point enabled exception summary */
713
        env->fpscr |= 1 << FPSCR_FEX;
714
        /* We must update the target FPR before raising the exception */
715
        env->exception_index = POWERPC_EXCP_PROGRAM;
716
        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX;
717
    }
718
}
719

  
720
static always_inline void float_inexact_excp (void)
721
{
722
    env->fpscr |= 1 << FPSCR_XX;
723
    /* Update the floating-point exception summary */
724
    env->fpscr |= 1 << FPSCR_FX;
725
    if (fpscr_xe != 0) {
726
        /* Update the floating-point enabled exception summary */
727
        env->fpscr |= 1 << FPSCR_FEX;
728
        /* We must update the target FPR before raising the exception */
729
        env->exception_index = POWERPC_EXCP_PROGRAM;
730
        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX;
731
    }
732
}
733

  
734
static always_inline void fpscr_set_rounding_mode (void)
735
{
736
    int rnd_type;
737

  
738
    /* Set rounding mode */
739
    switch (fpscr_rn) {
740
    case 0:
741
        /* Best approximation (round to nearest) */
742
        rnd_type = float_round_nearest_even;
743
        break;
744
    case 1:
745
        /* Smaller magnitude (round toward zero) */
746
        rnd_type = float_round_to_zero;
747
        break;
748
    case 2:
749
        /* Round toward +infinite */
750
        rnd_type = float_round_up;
751
        break;
752
    default:
753
    case 3:
754
        /* Round toward -infinite */
755
        rnd_type = float_round_down;
756
        break;
757
    }
758
    set_float_rounding_mode(rnd_type, &env->fp_status);
759
}
760

  
761
void do_fpscr_setbit (int bit)
762
{
763
    int prev;
764

  
765
    prev = (env->fpscr >> bit) & 1;
766
    env->fpscr |= 1 << bit;
767
    if (prev == 0) {
768
        switch (bit) {
769
        case FPSCR_VX:
770
            env->fpscr |= 1 << FPSCR_FX;
771
            if (fpscr_ve)
772
                goto raise_ve;
773
        case FPSCR_OX:
774
            env->fpscr |= 1 << FPSCR_FX;
775
            if (fpscr_oe)
776
                goto raise_oe;
777
            break;
778
        case FPSCR_UX:
779
            env->fpscr |= 1 << FPSCR_FX;
780
            if (fpscr_ue)
781
                goto raise_ue;
782
            break;
783
        case FPSCR_ZX:
784
            env->fpscr |= 1 << FPSCR_FX;
785
            if (fpscr_ze)
786
                goto raise_ze;
787
            break;
788
        case FPSCR_XX:
789
            env->fpscr |= 1 << FPSCR_FX;
790
            if (fpscr_xe)
791
                goto raise_xe;
792
            break;
793
        case FPSCR_VXSNAN:
794
        case FPSCR_VXISI:
795
        case FPSCR_VXIDI:
796
        case FPSCR_VXZDZ:
797
        case FPSCR_VXIMZ:
798
        case FPSCR_VXVC:
799
        case FPSCR_VXSOFT:
800
        case FPSCR_VXSQRT:
801
        case FPSCR_VXCVI:
802
            env->fpscr |= 1 << FPSCR_VX;
803
            env->fpscr |= 1 << FPSCR_FX;
804
            if (fpscr_ve != 0)
805
                goto raise_ve;
806
            break;
807
        case FPSCR_VE:
808
            if (fpscr_vx != 0) {
809
            raise_ve:
810
                env->error_code = POWERPC_EXCP_FP;
811
                if (fpscr_vxsnan)
812
                    env->error_code |= POWERPC_EXCP_FP_VXSNAN;
813
                if (fpscr_vxisi)
814
                    env->error_code |= POWERPC_EXCP_FP_VXISI;
815
                if (fpscr_vxidi)
816
                    env->error_code |= POWERPC_EXCP_FP_VXIDI;
817
                if (fpscr_vxzdz)
818
                    env->error_code |= POWERPC_EXCP_FP_VXZDZ;
819
                if (fpscr_vximz)
820
                    env->error_code |= POWERPC_EXCP_FP_VXIMZ;
821
                if (fpscr_vxvc)
822
                    env->error_code |= POWERPC_EXCP_FP_VXVC;
823
                if (fpscr_vxsoft)
824
                    env->error_code |= POWERPC_EXCP_FP_VXSOFT;
825
                if (fpscr_vxsqrt)
826
                    env->error_code |= POWERPC_EXCP_FP_VXSQRT;
827
                if (fpscr_vxcvi)
828
                    env->error_code |= POWERPC_EXCP_FP_VXCVI;
829
                goto raise_excp;
830
            }
831
            break;
832
        case FPSCR_OE:
833
            if (fpscr_ox != 0) {
834
            raise_oe:
835
                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX;
836
                goto raise_excp;
837
            }
838
            break;
839
        case FPSCR_UE:
840
            if (fpscr_ux != 0) {
841
            raise_ue:
842
                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX;
843
                goto raise_excp;
844
            }
845
            break;
846
        case FPSCR_ZE:
847
            if (fpscr_zx != 0) {
848
            raise_ze:
849
                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX;
850
                goto raise_excp;
851
            }
852
            break;
853
        case FPSCR_XE:
854
            if (fpscr_xx != 0) {
855
            raise_xe:
856
                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX;
857
                goto raise_excp;
858
            }
859
            break;
860
        case FPSCR_RN1:
861
        case FPSCR_RN:
862
            fpscr_set_rounding_mode();
863
            break;
864
        default:
865
            break;
866
        raise_excp:
867
            /* Update the floating-point enabled exception summary */
868
            env->fpscr |= 1 << FPSCR_FEX;
869
                /* We have to update Rc1 before raising the exception */
870
            env->exception_index = POWERPC_EXCP_PROGRAM;
871
            break;
872
        }
873
    }
874
}
875

  
876
#if defined(WORDS_BIGENDIAN)
877
#define WORD0 0
878
#define WORD1 1
879
#else
880
#define WORD0 1
881
#define WORD1 0
882
#endif
883
void do_store_fpscr (uint32_t mask)
884
{
885
    /*
886
     * We use only the 32 LSB of the incoming fpr
887
     */
888
    union {
889
        double d;
890
        struct {
891
            uint32_t u[2];
892
        } s;
893
    } u;
894
    uint32_t prev, new;
895
    int i;
896

  
897
    u.d = FT0;
898
    prev = env->fpscr;
899
    new = u.s.u[WORD1];
900
    new &= ~0x90000000;
901
    new |= prev & 0x90000000;
902
    for (i = 0; i < 7; i++) {
903
        if (mask & (1 << i)) {
904
            env->fpscr &= ~(0xF << (4 * i));
905
            env->fpscr |= new & (0xF << (4 * i));
906
        }
907
    }
908
    /* Update VX and FEX */
909
    if (fpscr_ix != 0)
910
        env->fpscr |= 1 << FPSCR_VX;
911
    if ((fpscr_ex & fpscr_eex) != 0) {
912
        env->fpscr |= 1 << FPSCR_FEX;
913
        env->exception_index = POWERPC_EXCP_PROGRAM;
914
        /* XXX: we should compute it properly */
915
        env->error_code = POWERPC_EXCP_FP;
916
    }
917
    fpscr_set_rounding_mode();
918
}
919
#undef WORD0
920
#undef WORD1
921

  
922
#ifdef CONFIG_SOFTFLOAT
923
void do_float_check_status (void)
924
{
925
    if (env->exception_index == POWERPC_EXCP_PROGRAM &&
926
        (env->error_code & POWERPC_EXCP_FP)) {
927
        /* Differred floating-point exception after target FPR update */
928
        if (msr_fe0 != 0 || msr_fe1 != 0)
929
            do_raise_exception_err(env->exception_index, env->error_code);
930
    } else if (env->fp_status.float_exception_flags & float_flag_overflow) {
931
        float_overflow_excp();
932
    } else if (env->fp_status.float_exception_flags & float_flag_underflow) {
933
        float_underflow_excp();
934
    } else if (env->fp_status.float_exception_flags & float_flag_inexact) {
935
        float_inexact_excp();
936
    }
937
}
938
#endif
939

  
940
#if USE_PRECISE_EMULATION
941
void do_fadd (void)
942
{
943
    if (unlikely(float64_is_signaling_nan(FT0) ||
944
                 float64_is_signaling_nan(FT1))) {
945
        /* sNaN addition */
946
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
947
    } else if (likely(isfinite(FT0) || isfinite(FT1) ||
948
                      fpisneg(FT0) == fpisneg(FT1))) {
949
        FT0 = float64_add(FT0, FT1, &env->fp_status);
950
    } else {
951
        /* Magnitude subtraction of infinities */
952
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
953
    }
954
}
955

  
956
void do_fsub (void)
957
{
958
    if (unlikely(float64_is_signaling_nan(FT0) ||
959
                 float64_is_signaling_nan(FT1))) {
960
        /* sNaN subtraction */
961
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
962
    } else if (likely(isfinite(FT0) || isfinite(FT1) ||
963
                      fpisneg(FT0) != fpisneg(FT1))) {
964
        FT0 = float64_sub(FT0, FT1, &env->fp_status);
965
    } else {
966
        /* Magnitude subtraction of infinities */
967
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
968
    }
969
}
970

  
971
void do_fmul (void)
972
{
973
    if (unlikely(float64_is_signaling_nan(FT0) ||
974
                 float64_is_signaling_nan(FT1))) {
975
        /* sNaN multiplication */
976
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
977
    } else if (unlikely((ifinf(FT0) && iszero(FT1)) ||
978
                        (inzero(FT0) && isinfinity(FT1)))) {
979
        /* Multiplication of zero by infinity */
980
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
981
    } else {
982
        FT0 = float64_mul(FT0, FT1, &env->fp_status);
983
    }
984
}
985

  
986
void do_fdiv (void)
987
{
988
    if (unlikely(float64_is_signaling_nan(FT0) ||
989
                 float64_is_signaling_nan(FT1))) {
990
        /* sNaN division */
991
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
992
    } else if (unlikely(isinfinity(FT0) && isinfinity(FT1))) {
993
        /* Division of infinity by infinity */
994
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXIDI);
995
    } else if (unlikely(iszero(FT1))) {
996
        if (iszero(FT0)) {
997
            /* Division of zero by zero */
998
            fload_invalid_op_excp(POWERPC_EXCP_FP_VXZDZ);
999
        } else {
1000
            /* Division by zero */
1001
            float_zero_divide_excp();
1002
        }
1003
    } else {
1004
        FT0 = float64_div(FT0, FT1, &env->fp_status);
1005
    }
1006
}
1007
#endif /* USE_PRECISE_EMULATION */
1008

  
556 1009
void do_fctiw (void)
557 1010
{
558 1011
    union {
......
560 1013
        uint64_t i;
561 1014
    } p;
562 1015

  
563
    p.i = float64_to_int32(FT0, &env->fp_status);
1016
    if (unlikely(float64_is_signaling_nan(FT0))) {
1017
        /* sNaN conversion */
1018
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1019
    } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
1020
        /* qNan / infinity conversion */
1021
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1022
    } else {
1023
        p.i = float64_to_int32(FT0, &env->fp_status);
564 1024
#if USE_PRECISE_EMULATION
565
    /* XXX: higher bits are not supposed to be significant.
566
     *     to make tests easier, return the same as a real PowerPC 750 (aka G3)
567
     */
568
    p.i |= 0xFFF80000ULL << 32;
1025
        /* XXX: higher bits are not supposed to be significant.
1026
         *     to make tests easier, return the same as a real PowerPC 750
1027
         */
1028
        p.i |= 0xFFF80000ULL << 32;
569 1029
#endif
570
    FT0 = p.d;
1030
        FT0 = p.d;
1031
    }
571 1032
}
572 1033

  
573 1034
void do_fctiwz (void)
......
577 1038
        uint64_t i;
578 1039
    } p;
579 1040

  
580
    p.i = float64_to_int32_round_to_zero(FT0, &env->fp_status);
1041
    if (unlikely(float64_is_signaling_nan(FT0))) {
1042
        /* sNaN conversion */
1043
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1044
    } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
1045
        /* qNan / infinity conversion */
1046
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1047
    } else {
1048
        p.i = float64_to_int32_round_to_zero(FT0, &env->fp_status);
581 1049
#if USE_PRECISE_EMULATION
582
    /* XXX: higher bits are not supposed to be significant.
583
     *     to make tests easier, return the same as a real PowerPC 750 (aka G3)
584
     */
585
    p.i |= 0xFFF80000ULL << 32;
1050
        /* XXX: higher bits are not supposed to be significant.
1051
         *     to make tests easier, return the same as a real PowerPC 750
1052
         */
1053
        p.i |= 0xFFF80000ULL << 32;
586 1054
#endif
587
    FT0 = p.d;
1055
        FT0 = p.d;
1056
    }
588 1057
}
589 1058

  
590 1059
#if defined(TARGET_PPC64)
......
606 1075
        uint64_t i;
607 1076
    } p;
608 1077

  
609
    p.i = float64_to_int64(FT0, &env->fp_status);
610
    FT0 = p.d;
1078
    if (unlikely(float64_is_signaling_nan(FT0))) {
1079
        /* sNaN conversion */
1080
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1081
    } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
1082
        /* qNan / infinity conversion */
1083
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1084
    } else {
1085
        p.i = float64_to_int64(FT0, &env->fp_status);
1086
        FT0 = p.d;
1087
    }
611 1088
}
612 1089

  
613 1090
void do_fctidz (void)
......
617 1094
        uint64_t i;
618 1095
    } p;
619 1096

  
620
    p.i = float64_to_int64_round_to_zero(FT0, &env->fp_status);
621
    FT0 = p.d;
1097
    if (unlikely(float64_is_signaling_nan(FT0))) {
1098
        /* sNaN conversion */
1099
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1100
    } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
1101
        /* qNan / infinity conversion */
1102
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1103
    } else {
1104
        p.i = float64_to_int64_round_to_zero(FT0, &env->fp_status);
1105
        FT0 = p.d;
1106
    }
622 1107
}
623 1108

  
624 1109
#endif
625 1110

  
626 1111
static always_inline void do_fri (int rounding_mode)
627 1112
{
628
    int curmode;
629

  
630
    curmode = env->fp_status.float_rounding_mode;
631
    set_float_rounding_mode(rounding_mode, &env->fp_status);
632
    FT0 = float64_round_to_int(FT0, &env->fp_status);
633
    set_float_rounding_mode(curmode, &env->fp_status);
1113
    if (unlikely(float64_is_signaling_nan(FT0))) {
1114
        /* sNaN round */
1115
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1116
    } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
1117
        /* qNan / infinity round */
1118
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1119
    } else {
1120
        set_float_rounding_mode(rounding_mode, &env->fp_status);
1121
        FT0 = float64_round_to_int(FT0, &env->fp_status);
1122
        /* Restore rounding mode from FPSCR */
1123
        fpscr_set_rounding_mode();
1124
    }
634 1125
}
635 1126

  
636 1127
void do_frin (void)
......
656 1147
#if USE_PRECISE_EMULATION
657 1148
void do_fmadd (void)
658 1149
{
1150
    if (unlikely(float64_is_signaling_nan(FT0) ||
1151
                 float64_is_signaling_nan(FT1) ||
1152
                 float64_is_signaling_nan(FT2))) {
1153
        /* sNaN operation */
1154
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1155
    } else {
659 1156
#ifdef FLOAT128
660
    float128 ft0_128, ft1_128;
661

  
662
    ft0_128 = float64_to_float128(FT0, &env->fp_status);
663
    ft1_128 = float64_to_float128(FT1, &env->fp_status);
664
    ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
665
    ft1_128 = float64_to_float128(FT2, &env->fp_status);
666
    ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
667
    FT0 = float128_to_float64(ft0_128, &env->fp_status);
1157
        /* This is the way the PowerPC specification defines it */
1158
        float128 ft0_128, ft1_128;
1159

  
1160
        ft0_128 = float64_to_float128(FT0, &env->fp_status);
1161
        ft1_128 = float64_to_float128(FT1, &env->fp_status);
1162
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1163
        ft1_128 = float64_to_float128(FT2, &env->fp_status);
1164
        ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
1165
        FT0 = float128_to_float64(ft0_128, &env->fp_status);
668 1166
#else
669
    /* This is OK on x86 hosts */
670
    FT0 = (FT0 * FT1) + FT2;
1167
        /* This is OK on x86 hosts */
1168
        FT0 = (FT0 * FT1) + FT2;
671 1169
#endif
1170
    }
672 1171
}
673 1172

  
674 1173
void do_fmsub (void)
675 1174
{
1175
    if (unlikely(float64_is_signaling_nan(FT0) ||
1176
                 float64_is_signaling_nan(FT1) ||
1177
                 float64_is_signaling_nan(FT2))) {
1178
        /* sNaN operation */
1179
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1180
    } else {
676 1181
#ifdef FLOAT128
677
    float128 ft0_128, ft1_128;
678

  
679
    ft0_128 = float64_to_float128(FT0, &env->fp_status);
680
    ft1_128 = float64_to_float128(FT1, &env->fp_status);
681
    ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
682
    ft1_128 = float64_to_float128(FT2, &env->fp_status);
683
    ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
684
    FT0 = float128_to_float64(ft0_128, &env->fp_status);
1182
        /* This is the way the PowerPC specification defines it */
1183
        float128 ft0_128, ft1_128;
1184

  
1185
        ft0_128 = float64_to_float128(FT0, &env->fp_status);
1186
        ft1_128 = float64_to_float128(FT1, &env->fp_status);
1187
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1188
        ft1_128 = float64_to_float128(FT2, &env->fp_status);
1189
        ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
1190
        FT0 = float128_to_float64(ft0_128, &env->fp_status);
685 1191
#else
686
    /* This is OK on x86 hosts */
687
    FT0 = (FT0 * FT1) - FT2;
1192
        /* This is OK on x86 hosts */
1193
        FT0 = (FT0 * FT1) - FT2;
688 1194
#endif
1195
    }
689 1196
}
690 1197
#endif /* USE_PRECISE_EMULATION */
691 1198

  
692 1199
void do_fnmadd (void)
693 1200
{
1201
    if (unlikely(float64_is_signaling_nan(FT0) ||
1202
                 float64_is_signaling_nan(FT1) ||
1203
                 float64_is_signaling_nan(FT2))) {
1204
        /* sNaN operation */
1205
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1206
    } else {
694 1207
#if USE_PRECISE_EMULATION
695 1208
#ifdef FLOAT128
696
    float128 ft0_128, ft1_128;
697

  
698
    ft0_128 = float64_to_float128(FT0, &env->fp_status);
699
    ft1_128 = float64_to_float128(FT1, &env->fp_status);
700
    ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
701
    ft1_128 = float64_to_float128(FT2, &env->fp_status);
702
    ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
703
    FT0 = float128_to_float64(ft0_128, &env->fp_status);
1209
        /* This is the way the PowerPC specification defines it */
1210
        float128 ft0_128, ft1_128;
1211

  
1212
        ft0_128 = float64_to_float128(FT0, &env->fp_status);
1213
        ft1_128 = float64_to_float128(FT1, &env->fp_status);
1214
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1215
        ft1_128 = float64_to_float128(FT2, &env->fp_status);
1216
        ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
1217
        FT0 = float128_to_float64(ft0_128, &env->fp_status);
704 1218
#else
705
    /* This is OK on x86 hosts */
706
    FT0 = (FT0 * FT1) + FT2;
1219
        /* This is OK on x86 hosts */
1220
        FT0 = (FT0 * FT1) + FT2;
707 1221
#endif
708 1222
#else
709
    FT0 = float64_mul(FT0, FT1, &env->fp_status);
710
    FT0 = float64_add(FT0, FT2, &env->fp_status);
1223
        FT0 = float64_mul(FT0, FT1, &env->fp_status);
1224
        FT0 = float64_add(FT0, FT2, &env->fp_status);
711 1225
#endif
712
    if (likely(!isnan(FT0)))
713
        FT0 = float64_chs(FT0);
1226
        if (likely(!isnan(FT0)))
1227
            FT0 = float64_chs(FT0);
1228
    }
714 1229
}
715 1230

  
716 1231
void do_fnmsub (void)
717 1232
{
1233
    if (unlikely(float64_is_signaling_nan(FT0) ||
1234
                 float64_is_signaling_nan(FT1) ||
1235
                 float64_is_signaling_nan(FT2))) {
1236
        /* sNaN operation */
1237
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1238
    } else {
718 1239
#if USE_PRECISE_EMULATION
719 1240
#ifdef FLOAT128
720
    float128 ft0_128, ft1_128;
721

  
722
    ft0_128 = float64_to_float128(FT0, &env->fp_status);
723
    ft1_128 = float64_to_float128(FT1, &env->fp_status);
724
    ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
725
    ft1_128 = float64_to_float128(FT2, &env->fp_status);
726
    ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
727
    FT0 = float128_to_float64(ft0_128, &env->fp_status);
1241
        /* This is the way the PowerPC specification defines it */
1242
        float128 ft0_128, ft1_128;
1243

  
1244
        ft0_128 = float64_to_float128(FT0, &env->fp_status);
1245
        ft1_128 = float64_to_float128(FT1, &env->fp_status);
1246
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1247
        ft1_128 = float64_to_float128(FT2, &env->fp_status);
1248
        ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
1249
        FT0 = float128_to_float64(ft0_128, &env->fp_status);
728 1250
#else
729
    /* This is OK on x86 hosts */
730
    FT0 = (FT0 * FT1) - FT2;
1251
        /* This is OK on x86 hosts */
1252
        FT0 = (FT0 * FT1) - FT2;
731 1253
#endif
732 1254
#else
733
    FT0 = float64_mul(FT0, FT1, &env->fp_status);
734
    FT0 = float64_sub(FT0, FT2, &env->fp_status);
1255
        FT0 = float64_mul(FT0, FT1, &env->fp_status);
1256
        FT0 = float64_sub(FT0, FT2, &env->fp_status);
735 1257
#endif
736
    if (likely(!isnan(FT0)))
737
        FT0 = float64_chs(FT0);
1258
        if (likely(!isnan(FT0)))
1259
            FT0 = float64_chs(FT0);
1260
    }
738 1261
}
739 1262

  
1263
#if USE_PRECISE_EMULATION
1264
void do_frsp (void)
1265
{
1266
    if (unlikely(float64_is_signaling_nan(FT0))) {
1267
        /* sNaN square root */
1268
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1269
    } else {
1270
        FT0 = float64_to_float32(FT0, &env->fp_status);
1271
    }
1272
}
1273
#endif /* USE_PRECISE_EMULATION */
1274

  
740 1275
void do_fsqrt (void)
741 1276
{
742
    FT0 = float64_sqrt(FT0, &env->fp_status);
1277
    if (unlikely(float64_is_signaling_nan(FT0))) {
1278
        /* sNaN square root */
1279
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1280
    } else if (unlikely(fpisneg(FT0) && !iszero(FT0))) {
1281
        /* Square root of a negative nonzero number */
1282
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
1283
    } else {
1284
        FT0 = float64_sqrt(FT0, &env->fp_status);
1285
    }
743 1286
}
744 1287

  
745 1288
void do_fre (void)
......
749 1292
        uint64_t i;
750 1293
    } p;
751 1294

  
752
    if (likely(isnormal(FT0))) {
1295
    if (unlikely(float64_is_signaling_nan(FT0))) {
1296
        /* sNaN reciprocal */
1297
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1298
    } else if (unlikely(iszero(FT0))) {
1299
        /* Zero reciprocal */
1300
        float_zero_divide_excp();
1301
    } else if (likely(isnormal(FT0))) {
753 1302
        FT0 = float64_div(1.0, FT0, &env->fp_status);
754 1303
    } else {
755 1304
        p.d = FT0;
......
759 1308
            p.i = 0x7FF0000000000000ULL;
760 1309
        } else if (isnan(FT0)) {
761 1310
            p.i = 0x7FF8000000000000ULL;
762
        } else if (FT0 < 0.0) {
1311
        } else if (fpisneg(FT0)) {
763 1312
            p.i = 0x8000000000000000ULL;
764 1313
        } else {
765 1314
            p.i = 0x0000000000000000ULL;
......
775 1324
        uint64_t i;
776 1325
    } p;
777 1326

  
778
    if (likely(isnormal(FT0))) {
1327
    if (unlikely(float64_is_signaling_nan(FT0))) {
1328
        /* sNaN reciprocal */
1329
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1330
    } else if (unlikely(iszero(FT0))) {
1331
        /* Zero reciprocal */
1332
        float_zero_divide_excp();
1333
    } else if (likely(isnormal(FT0))) {
779 1334
#if USE_PRECISE_EMULATION
780 1335
        FT0 = float64_div(1.0, FT0, &env->fp_status);
781 1336
        FT0 = float64_to_float32(FT0, &env->fp_status);
......
790 1345
            p.i = 0x7FF0000000000000ULL;
791 1346
        } else if (isnan(FT0)) {
792 1347
            p.i = 0x7FF8000000000000ULL;
793
        } else if (FT0 < 0.0) {
1348
        } else if (fpisneg(FT0)) {
794 1349
            p.i = 0x8000000000000000ULL;
795 1350
        } else {
796 1351
            p.i = 0x0000000000000000ULL;
......
806 1361
        uint64_t i;
807 1362
    } p;
808 1363

  
809
    if (likely(isnormal(FT0) && FT0 > 0.0)) {
1364
    if (unlikely(float64_is_signaling_nan(FT0))) {
1365
        /* sNaN reciprocal square root */
1366
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1367
    } else if (unlikely(fpisneg(FT0) && !iszero(FT0))) {
1368
        /* Reciprocal square root of a negative nonzero number */
1369
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
1370
    } else if (likely(isnormal(FT0))) {
810 1371
        FT0 = float64_sqrt(FT0, &env->fp_status);
811 1372
        FT0 = float32_div(1.0, FT0, &env->fp_status);
812 1373
    } else {
......
816 1377
        } else if (p.i == 0x0000000000000000ULL) {
817 1378
            p.i = 0x7FF0000000000000ULL;
818 1379
        } else if (isnan(FT0)) {
819
            if (!(p.i & 0x0008000000000000ULL))
820
                p.i |= 0x000FFFFFFFFFFFFFULL;
821
        } else if (FT0 < 0) {
1380
            p.i |= 0x000FFFFFFFFFFFFFULL;
1381
        } else if (fpisneg(FT0)) {
822 1382
            p.i = 0x7FF8000000000000ULL;
823 1383
        } else {
824 1384
            p.i = 0x0000000000000000ULL;
......
829 1389

  
830 1390
void do_fsel (void)
831 1391
{
832
    if (FT0 >= 0)
1392
    if (!fpisneg(FT0) || iszero(FT0))
833 1393
        FT0 = FT1;
834 1394
    else
835 1395
        FT0 = FT2;
......
837 1397

  
838 1398
void do_fcmpu (void)
839 1399
{
840
    if (likely(!isnan(FT0) && !isnan(FT1))) {
1400
    if (unlikely(float64_is_signaling_nan(FT0) ||
1401
                 float64_is_signaling_nan(FT1))) {
1402
        /* sNaN comparison */
1403
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1404
    } else {
841 1405
        if (float64_lt(FT0, FT1, &env->fp_status)) {
842 1406
            T0 = 0x08UL;
843 1407
        } else if (!float64_le(FT0, FT1, &env->fp_status)) {
......
845 1409
        } else {
846 1410
            T0 = 0x02UL;
847 1411
        }
848
    } else {
849
        T0 = 0x01UL;
850
        env->fpscr[4] |= 0x1;
851
        env->fpscr[6] |= 0x1;
852 1412
    }
853
    env->fpscr[3] = T0;
1413
    env->fpscr &= ~(0x0F << FPSCR_FPRF);
1414
    env->fpscr |= T0 << FPSCR_FPRF;
854 1415
}
855 1416

  
856 1417
void do_fcmpo (void)
857 1418
{
858
    env->fpscr[4] &= ~0x1;
859
    if (likely(!isnan(FT0) && !isnan(FT1))) {
1419
    if (unlikely(float64_is_nan(FT0) ||
1420
                 float64_is_nan(FT1))) {
1421
        if (float64_is_signaling_nan(FT0) ||
1422
            float64_is_signaling_nan(FT1)) {
1423
            /* sNaN comparison */
1424
            fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN |
1425
                                  POWERPC_EXCP_FP_VXVC);
1426
        } else {
1427
            /* qNaN comparison */
1428
            fload_invalid_op_excp(POWERPC_EXCP_FP_VXVC);
1429
        }
1430
    } else {
860 1431
        if (float64_lt(FT0, FT1, &env->fp_status)) {
861 1432
            T0 = 0x08UL;
862 1433
        } else if (!float64_le(FT0, FT1, &env->fp_status)) {
......
864 1435
        } else {
865 1436
            T0 = 0x02UL;
866 1437
        }
867
    } else {
868
        T0 = 0x01UL;
869
        env->fpscr[4] |= 0x1;
870
        if (!float64_is_signaling_nan(FT0) || !float64_is_signaling_nan(FT1)) {
871
            /* Quiet NaN case */
872
            env->fpscr[6] |= 0x1;
873
            if (!(env->fpscr[1] & 0x8))
874
                env->fpscr[4] |= 0x8;
875
        } else {
876
            env->fpscr[4] |= 0x8;
877
        }
878 1438
    }
879
    env->fpscr[3] = T0;
1439
    env->fpscr &= ~(0x0F << FPSCR_FPRF);
1440
    env->fpscr |= T0 << FPSCR_FPRF;
880 1441
}
881 1442

  
882 1443
#if !defined (CONFIG_USER_ONLY)
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff