Revision af12906f

b/target-ppc/cpu.h
571 571
    /* temporary float registers */
572 572
    float64 ft0;
573 573
    float64 ft1;
574
    float64 ft2;
575 574
    float_status fp_status;
576 575
    /* floating point registers */
577 576
    float64 fpr[32];
b/target-ppc/exec.h
61 61

  
62 62
#define FT0 (env->ft0)
63 63
#define FT1 (env->ft1)
64
#define FT2 (env->ft2)
65 64

  
66 65
#if defined (DEBUG_OP)
67 66
# define RETURN() __asm__ __volatile__("nop" : : : "memory");
b/target-ppc/helper.h
1 1
#include "def-helper.h"
2 2

  
3
DEF_HELPER_0(fcmpo, i32)
4
DEF_HELPER_0(fcmpu, i32)
3
DEF_HELPER_2(fcmpo, i32, i64, i64)
4
DEF_HELPER_2(fcmpu, i32, i64, i64)
5 5

  
6 6
DEF_HELPER_0(load_cr, tl)
7 7
DEF_HELPER_2(store_cr, void, tl, i32)
......
25 25
DEF_HELPER_1(cntlzw32, i32, i32)
26 26
DEF_HELPER_2(brinc, tl, tl, tl)
27 27

  
28
DEF_HELPER_0(float_check_status, void)
29
#ifdef CONFIG_SOFTFLOAT
30
DEF_HELPER_0(reset_fpstatus, void)
31
#endif
32
DEF_HELPER_2(compute_fprf, i32, i64, i32)
33
DEF_HELPER_2(store_fpscr, void, i64, i32)
34
DEF_HELPER_1(fpscr_setbit, void, i32)
35

  
36
DEF_HELPER_1(fctiw, i64, i64)
37
DEF_HELPER_1(fctiwz, i64, i64)
38
#if defined(TARGET_PPC64)
39
DEF_HELPER_1(fcfid, i64, i64)
40
DEF_HELPER_1(fctid, i64, i64)
41
DEF_HELPER_1(fctidz, i64, i64)
42
#endif
43
DEF_HELPER_1(frsp, i64, i64)
44
DEF_HELPER_1(frin, i64, i64)
45
DEF_HELPER_1(friz, i64, i64)
46
DEF_HELPER_1(frip, i64, i64)
47
DEF_HELPER_1(frim, i64, i64)
48

  
49
DEF_HELPER_2(fadd, i64, i64, i64)
50
DEF_HELPER_2(fsub, i64, i64, i64)
51
DEF_HELPER_2(fmul, i64, i64, i64)
52
DEF_HELPER_2(fdiv, i64, i64, i64)
53
DEF_HELPER_3(fmadd, i64, i64, i64, i64)
54
DEF_HELPER_3(fmsub, i64, i64, i64, i64)
55
DEF_HELPER_3(fnmadd, i64, i64, i64, i64)
56
DEF_HELPER_3(fnmsub, i64, i64, i64, i64)
57
DEF_HELPER_1(fabs, i64, i64)
58
DEF_HELPER_1(fnabs, i64, i64)
59
DEF_HELPER_1(fneg, i64, i64)
60
DEF_HELPER_1(fsqrt, i64, i64);
61
DEF_HELPER_1(fre, i64, i64);
62
DEF_HELPER_1(fres, i64, i64);
63
DEF_HELPER_1(frsqrte, i64, i64);
64
DEF_HELPER_3(fsel, i64, i64, i64, i64)
65

  
28 66
#include "def-helper.h"
b/target-ppc/op.c
261 261
}
262 262
#endif /* !defined(CONFIG_USER_ONLY) */
263 263

  
264
/* FPSCR */
265
#ifdef CONFIG_SOFTFLOAT
266
void OPPROTO op_reset_fpstatus (void)
267
{
268
    env->fp_status.float_exception_flags = 0;
269
    RETURN();
270
}
271
#endif
272

  
273
void OPPROTO op_compute_fprf (void)
274
{
275
    do_compute_fprf(PARAM1);
276
    RETURN();
277
}
278

  
279
#ifdef CONFIG_SOFTFLOAT
280
void OPPROTO op_float_check_status (void)
281
{
282
    do_float_check_status();
283
    RETURN();
284
}
285
#else
286
void OPPROTO op_float_check_status (void)
287
{
288
    if (env->exception_index == POWERPC_EXCP_PROGRAM &&
289
        (env->error_code & POWERPC_EXCP_FP)) {
290
        /* Differred floating-point exception after target FPR update */
291
        if (msr_fe0 != 0 || msr_fe1 != 0)
292
            do_raise_exception_err(env->exception_index, env->error_code);
293
    }
294
    RETURN();
295
}
296
#endif
297

  
298
void OPPROTO op_load_fpscr_FT0 (void)
299
{
300
    /* The 32 MSB of the target fpr are undefined.
301
     * They'll be zero...
302
     */
303
    CPU_DoubleU u;
304

  
305
    u.l.upper = 0;
306
    u.l.lower = env->fpscr;
307
    FT0 = u.d;
308
    RETURN();
309
}
310

  
311
void OPPROTO op_fpscr_resetbit (void)
312
{
313
    env->fpscr &= PARAM1;
314
    RETURN();
315
}
316

  
317
void OPPROTO op_fpscr_setbit (void)
318
{
319
    do_fpscr_setbit(PARAM1);
320
    RETURN();
321
}
322

  
323
void OPPROTO op_store_fpscr (void)
324
{
325
    do_store_fpscr(PARAM1);
326
    RETURN();
327
}
328

  
329 264
/***                             Integer shift                             ***/
330 265
void OPPROTO op_srli_T1 (void)
331 266
{
......
333 268
    RETURN();
334 269
}
335 270

  
336
/***                       Floating-Point arithmetic                       ***/
337
/* fadd - fadd. */
338
void OPPROTO op_fadd (void)
339
{
340
#if USE_PRECISE_EMULATION
341
    do_fadd();
342
#else
343
    FT0 = float64_add(FT0, FT1, &env->fp_status);
344
#endif
345
    RETURN();
346
}
347

  
348
/* fsub - fsub. */
349
void OPPROTO op_fsub (void)
350
{
351
#if USE_PRECISE_EMULATION
352
    do_fsub();
353
#else
354
    FT0 = float64_sub(FT0, FT1, &env->fp_status);
355
#endif
356
    RETURN();
357
}
358

  
359
/* fmul - fmul. */
360
void OPPROTO op_fmul (void)
361
{
362
#if USE_PRECISE_EMULATION
363
    do_fmul();
364
#else
365
    FT0 = float64_mul(FT0, FT1, &env->fp_status);
366
#endif
367
    RETURN();
368
}
369

  
370
/* fdiv - fdiv. */
371
void OPPROTO op_fdiv (void)
372
{
373
#if USE_PRECISE_EMULATION
374
    do_fdiv();
375
#else
376
    FT0 = float64_div(FT0, FT1, &env->fp_status);
377
#endif
378
    RETURN();
379
}
380

  
381
/* fsqrt - fsqrt. */
382
void OPPROTO op_fsqrt (void)
383
{
384
    do_fsqrt();
385
    RETURN();
386
}
387

  
388
/* fre - fre. */
389
void OPPROTO op_fre (void)
390
{
391
    do_fre();
392
    RETURN();
393
}
394

  
395
/* fres - fres. */
396
void OPPROTO op_fres (void)
397
{
398
    do_fres();
399
    RETURN();
400
}
401

  
402
/* frsqrte  - frsqrte. */
403
void OPPROTO op_frsqrte (void)
404
{
405
    do_frsqrte();
406
    RETURN();
407
}
408

  
409
/* fsel - fsel. */
410
void OPPROTO op_fsel (void)
411
{
412
    do_fsel();
413
    RETURN();
414
}
415

  
416
/***                     Floating-Point multiply-and-add                   ***/
417
/* fmadd - fmadd. */
418
void OPPROTO op_fmadd (void)
419
{
420
#if USE_PRECISE_EMULATION
421
    do_fmadd();
422
#else
423
    FT0 = float64_mul(FT0, FT1, &env->fp_status);
424
    FT0 = float64_add(FT0, FT2, &env->fp_status);
425
#endif
426
    RETURN();
427
}
428

  
429
/* fmsub - fmsub. */
430
void OPPROTO op_fmsub (void)
431
{
432
#if USE_PRECISE_EMULATION
433
    do_fmsub();
434
#else
435
    FT0 = float64_mul(FT0, FT1, &env->fp_status);
436
    FT0 = float64_sub(FT0, FT2, &env->fp_status);
437
#endif
438
    RETURN();
439
}
440

  
441
/* fnmadd - fnmadd. - fnmadds - fnmadds. */
442
void OPPROTO op_fnmadd (void)
443
{
444
    do_fnmadd();
445
    RETURN();
446
}
447

  
448
/* fnmsub - fnmsub. */
449
void OPPROTO op_fnmsub (void)
450
{
451
    do_fnmsub();
452
    RETURN();
453
}
454

  
455
/***                     Floating-Point round & convert                    ***/
456
/* frsp - frsp. */
457
void OPPROTO op_frsp (void)
458
{
459
#if USE_PRECISE_EMULATION
460
    do_frsp();
461
#else
462
    FT0 = float64_to_float32(FT0, &env->fp_status);
463
#endif
464
    RETURN();
465
}
466

  
467
/* fctiw - fctiw. */
468
void OPPROTO op_fctiw (void)
469
{
470
    do_fctiw();
471
    RETURN();
472
}
473

  
474
/* fctiwz - fctiwz. */
475
void OPPROTO op_fctiwz (void)
476
{
477
    do_fctiwz();
478
    RETURN();
479
}
480

  
481
#if defined(TARGET_PPC64)
482
/* fcfid - fcfid. */
483
void OPPROTO op_fcfid (void)
484
{
485
    do_fcfid();
486
    RETURN();
487
}
488

  
489
/* fctid - fctid. */
490
void OPPROTO op_fctid (void)
491
{
492
    do_fctid();
493
    RETURN();
494
}
495

  
496
/* fctidz - fctidz. */
497
void OPPROTO op_fctidz (void)
498
{
499
    do_fctidz();
500
    RETURN();
501
}
502
#endif
503

  
504
void OPPROTO op_frin (void)
505
{
506
    do_frin();
507
    RETURN();
508
}
509

  
510
void OPPROTO op_friz (void)
511
{
512
    do_friz();
513
    RETURN();
514
}
515

  
516
void OPPROTO op_frip (void)
517
{
518
    do_frip();
519
    RETURN();
520
}
521

  
522
void OPPROTO op_frim (void)
523
{
524
    do_frim();
525
    RETURN();
526
}
527

  
528
/***                         Floating-point move                           ***/
529
/* fabs */
530
void OPPROTO op_fabs (void)
531
{
532
    FT0 = float64_abs(FT0);
533
    RETURN();
534
}
535

  
536
/* fnabs */
537
void OPPROTO op_fnabs (void)
538
{
539
    FT0 = float64_abs(FT0);
540
    FT0 = float64_chs(FT0);
541
    RETURN();
542
}
543

  
544
/* fneg */
545
void OPPROTO op_fneg (void)
546
{
547
    FT0 = float64_chs(FT0);
548
    RETURN();
549
}
550

  
551 271
/* Load and store */
552 272
#define MEMSUFFIX _raw
553 273
#include "op_helper.h"
b/target-ppc/op_helper.c
299 299
}
300 300
#endif
301 301

  
302
void do_compute_fprf (int set_fprf)
302
uint32_t helper_compute_fprf (uint64_t arg, uint32_t set_fprf)
303 303
{
304
    CPU_DoubleU farg;
304 305
    int isneg;
305

  
306
    isneg = fpisneg(FT0);
307
    if (unlikely(float64_is_nan(FT0))) {
308
        if (float64_is_signaling_nan(FT0)) {
306
    int ret;
307
    farg.ll = arg;
308
    isneg = fpisneg(farg.d);
309
    if (unlikely(float64_is_nan(farg.d))) {
310
        if (float64_is_signaling_nan(farg.d)) {
309 311
            /* Signaling NaN: flags are undefined */
310
            T0 = 0x00;
312
            ret = 0x00;
311 313
        } else {
312 314
            /* Quiet NaN */
313
            T0 = 0x11;
315
            ret = 0x11;
314 316
        }
315
    } else if (unlikely(isinfinity(FT0))) {
317
    } else if (unlikely(isinfinity(farg.d))) {
316 318
        /* +/- infinity */
317 319
        if (isneg)
318
            T0 = 0x09;
320
            ret = 0x09;
319 321
        else
320
            T0 = 0x05;
322
            ret = 0x05;
321 323
    } else {
322
        if (iszero(FT0)) {
324
        if (iszero(farg.d)) {
323 325
            /* +/- zero */
324 326
            if (isneg)
325
                T0 = 0x12;
327
                ret = 0x12;
326 328
            else
327
                T0 = 0x02;
329
                ret = 0x02;
328 330
        } else {
329
            if (isden(FT0)) {
331
            if (isden(farg.d)) {
330 332
                /* Denormalized numbers */
331
                T0 = 0x10;
333
                ret = 0x10;
332 334
            } else {
333 335
                /* Normalized numbers */
334
                T0 = 0x00;
336
                ret = 0x00;
335 337
            }
336 338
            if (isneg) {
337
                T0 |= 0x08;
339
                ret |= 0x08;
338 340
            } else {
339
                T0 |= 0x04;
341
                ret |= 0x04;
340 342
            }
341 343
        }
342 344
    }
343 345
    if (set_fprf) {
344 346
        /* We update FPSCR_FPRF */
345 347
        env->fpscr &= ~(0x1F << FPSCR_FPRF);
346
        env->fpscr |= T0 << FPSCR_FPRF;
348
        env->fpscr |= ret << FPSCR_FPRF;
347 349
    }
348 350
    /* We just need fpcc to update Rc1 */
349
    T0 &= 0xF;
351
    return ret & 0xF;
350 352
}
351 353

  
352 354
/* Floating-point invalid operations exception */
353
static always_inline void fload_invalid_op_excp (int op)
355
static always_inline uint64_t fload_invalid_op_excp (int op)
354 356
{
357
    uint64_t ret = 0;
355 358
    int ve;
356 359

  
357 360
    ve = fpscr_ve;
......
402 405
        env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
403 406
        if (ve == 0) {
404 407
            /* Set the result to quiet NaN */
405
            FT0 = UINT64_MAX;
408
            ret = UINT64_MAX;
406 409
            env->fpscr &= ~(0xF << FPSCR_FPCC);
407 410
            env->fpscr |= 0x11 << FPSCR_FPCC;
408 411
        }
......
413 416
        env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
414 417
        if (ve == 0) {
415 418
            /* Set the result to quiet NaN */
416
            FT0 = UINT64_MAX;
419
            ret = UINT64_MAX;
417 420
            env->fpscr &= ~(0xF << FPSCR_FPCC);
418 421
            env->fpscr |= 0x11 << FPSCR_FPCC;
419 422
        }
......
429 432
        if (msr_fe0 != 0 || msr_fe1 != 0)
430 433
            do_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_FP | op);
431 434
    }
435
    return ret;
432 436
}
433 437

  
434
static always_inline void float_zero_divide_excp (void)
438
static always_inline uint64_t float_zero_divide_excp (uint64_t arg1, uint64_t arg2)
435 439
{
436
    CPU_DoubleU u0, u1;
437

  
438 440
    env->fpscr |= 1 << FPSCR_ZX;
439 441
    env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
440 442
    /* Update the floating-point exception summary */
......
448 450
        }
449 451
    } else {
450 452
        /* Set the result to infinity */
451
        u0.d = FT0;
452
        u1.d = FT1;
453
        u0.ll = ((u0.ll ^ u1.ll) & 0x8000000000000000ULL);
454
        u0.ll |= 0x7FFULL << 52;
455
        FT0 = u0.d;
453
        arg1 = ((arg1 ^ arg2) & 0x8000000000000000ULL);
454
        arg1 |= 0x7FFULL << 52;
456 455
    }
456
    return arg1;
457 457
}
458 458

  
459 459
static always_inline void float_overflow_excp (void)
......
530 530
    set_float_rounding_mode(rnd_type, &env->fp_status);
531 531
}
532 532

  
533
void do_fpscr_setbit (int bit)
533
void helper_fpscr_setbit (uint32_t bit)
534 534
{
535 535
    int prev;
536 536

  
......
645 645
    }
646 646
}
647 647

  
648
#if defined(WORDS_BIGENDIAN)
649
#define WORD0 0
650
#define WORD1 1
651
#else
652
#define WORD0 1
653
#define WORD1 0
654
#endif
655
void do_store_fpscr (uint32_t mask)
648
void helper_store_fpscr (uint64_t arg, uint32_t mask)
656 649
{
657 650
    /*
658 651
     * We use only the 32 LSB of the incoming fpr
659 652
     */
660
    CPU_DoubleU u;
661 653
    uint32_t prev, new;
662 654
    int i;
663 655

  
664
    u.d = FT0;
665 656
    prev = env->fpscr;
666
    new = u.l.lower;
657
    new = (uint32_t)arg;
667 658
    new &= ~0x90000000;
668 659
    new |= prev & 0x90000000;
669 660
    for (i = 0; i < 7; i++) {
......
687 678
        env->fpscr &= ~(1 << FPSCR_FEX);
688 679
    fpscr_set_rounding_mode();
689 680
}
690
#undef WORD0
691
#undef WORD1
692 681

  
693
#ifdef CONFIG_SOFTFLOAT
694
void do_float_check_status (void)
682
void helper_float_check_status (void)
695 683
{
684
#ifdef CONFIG_SOFTFLOAT
696 685
    if (env->exception_index == POWERPC_EXCP_PROGRAM &&
697 686
        (env->error_code & POWERPC_EXCP_FP)) {
698 687
        /* Differred floating-point exception after target FPR update */
......
705 694
    } else if (env->fp_status.float_exception_flags & float_flag_inexact) {
706 695
        float_inexact_excp();
707 696
    }
697
#else
698
    if (env->exception_index == POWERPC_EXCP_PROGRAM &&
699
        (env->error_code & POWERPC_EXCP_FP)) {
700
        /* Differred floating-point exception after target FPR update */
701
        if (msr_fe0 != 0 || msr_fe1 != 0)
702
            do_raise_exception_err(env->exception_index, env->error_code);
703
    }
704
    RETURN();
705
#endif
706
}
707

  
708
#ifdef CONFIG_SOFTFLOAT
709
void helper_reset_fpstatus (void)
710
{
711
    env->fp_status.float_exception_flags = 0;
708 712
}
709 713
#endif
710 714

  
711
#if USE_PRECISE_EMULATION
712
void do_fadd (void)
715
/* fadd - fadd. */
716
uint64_t helper_fadd (uint64_t arg1, uint64_t arg2)
713 717
{
714
    if (unlikely(float64_is_signaling_nan(FT0) ||
715
                 float64_is_signaling_nan(FT1))) {
718
    CPU_DoubleU farg1, farg2;
719

  
720
    farg1.ll = arg1;
721
    farg2.ll = arg2;
722
#if USE_PRECISE_EMULATION
723
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
724
                 float64_is_signaling_nan(farg2.d))) {
716 725
        /* sNaN addition */
717
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
718
    } else if (likely(isfinite(FT0) || isfinite(FT1) ||
719
                      fpisneg(FT0) == fpisneg(FT1))) {
720
        FT0 = float64_add(FT0, FT1, &env->fp_status);
726
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
727
    } else if (likely(isfinite(farg1.d) || isfinite(farg2.d) ||
728
                      fpisneg(farg1.d) == fpisneg(farg2.d))) {
729
        farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
721 730
    } else {
722 731
        /* Magnitude subtraction of infinities */
723
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
732
        farg1.ll == fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
724 733
    }
734
#else
735
    farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
736
#endif
737
    return farg1.ll;
725 738
}
726 739

  
727
void do_fsub (void)
740
/* fsub - fsub. */
741
uint64_t helper_fsub (uint64_t arg1, uint64_t arg2)
728 742
{
729
    if (unlikely(float64_is_signaling_nan(FT0) ||
730
                 float64_is_signaling_nan(FT1))) {
743
    CPU_DoubleU farg1, farg2;
744

  
745
    farg1.ll = arg1;
746
    farg2.ll = arg2;
747
#if USE_PRECISE_EMULATION
748
{
749
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
750
                 float64_is_signaling_nan(farg2.d))) {
731 751
        /* sNaN subtraction */
732
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
733
    } else if (likely(isfinite(FT0) || isfinite(FT1) ||
734
                      fpisneg(FT0) != fpisneg(FT1))) {
735
        FT0 = float64_sub(FT0, FT1, &env->fp_status);
752
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
753
    } else if (likely(isfinite(farg1.d) || isfinite(farg2.d) ||
754
                      fpisneg(farg1.d) != fpisneg(farg2.d))) {
755
        farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
736 756
    } else {
737 757
        /* Magnitude subtraction of infinities */
738
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
758
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
739 759
    }
740 760
}
761
#else
762
    farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
763
#endif
764
    return farg1.ll;
765
}
741 766

  
742
void do_fmul (void)
767
/* fmul - fmul. */
768
uint64_t helper_fmul (uint64_t arg1, uint64_t arg2)
743 769
{
744
    if (unlikely(float64_is_signaling_nan(FT0) ||
745
                 float64_is_signaling_nan(FT1))) {
770
    CPU_DoubleU farg1, farg2;
771

  
772
    farg1.ll = arg1;
773
    farg2.ll = arg2;
774
#if USE_PRECISE_EMULATION
775
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
776
                 float64_is_signaling_nan(farg2.d))) {
746 777
        /* sNaN multiplication */
747
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
748
    } else if (unlikely((isinfinity(FT0) && iszero(FT1)) ||
749
                        (iszero(FT0) && isinfinity(FT1)))) {
778
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
779
    } else if (unlikely((isinfinity(farg1.d) && iszero(farg2.d)) ||
780
                        (iszero(farg1.d) && isinfinity(farg2.d)))) {
750 781
        /* Multiplication of zero by infinity */
751
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
782
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
752 783
    } else {
753
        FT0 = float64_mul(FT0, FT1, &env->fp_status);
784
        farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
754 785
    }
755 786
}
787
#else
788
    farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
789
#endif
790
    return farg1.ll;
791
}
756 792

  
757
void do_fdiv (void)
793
/* fdiv - fdiv. */
794
uint64_t helper_fdiv (uint64_t arg1, uint64_t arg2)
758 795
{
759
    if (unlikely(float64_is_signaling_nan(FT0) ||
760
                 float64_is_signaling_nan(FT1))) {
796
    CPU_DoubleU farg1, farg2;
797

  
798
    farg1.ll = arg1;
799
    farg2.ll = arg2;
800
#if USE_PRECISE_EMULATION
801
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
802
                 float64_is_signaling_nan(farg2.d))) {
761 803
        /* sNaN division */
762
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
763
    } else if (unlikely(isinfinity(FT0) && isinfinity(FT1))) {
804
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
805
    } else if (unlikely(isinfinity(farg1.d) && isinfinity(farg2.d))) {
764 806
        /* Division of infinity by infinity */
765
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXIDI);
766
    } else if (unlikely(iszero(FT1))) {
767
        if (iszero(FT0)) {
807
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIDI);
808
    } else if (unlikely(iszero(farg2.d))) {
809
        if (iszero(farg1.d)) {
768 810
            /* Division of zero by zero */
769
            fload_invalid_op_excp(POWERPC_EXCP_FP_VXZDZ);
811
            farg1.ll fload_invalid_op_excp(POWERPC_EXCP_FP_VXZDZ);
770 812
        } else {
771 813
            /* Division by zero */
772
            float_zero_divide_excp();
814
            farg1.ll = float_zero_divide_excp(farg1.d, farg2.d);
773 815
        }
774 816
    } else {
775
        FT0 = float64_div(FT0, FT1, &env->fp_status);
817
        farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
776 818
    }
819
#else
820
    farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
821
#endif
822
    return farg1.ll;
777 823
}
778
#endif /* USE_PRECISE_EMULATION */
779 824

  
780
void do_fctiw (void)
825
/* fabs */
826
uint64_t helper_fabs (uint64_t arg)
781 827
{
782
    CPU_DoubleU p;
828
    CPU_DoubleU farg;
783 829

  
784
    if (unlikely(float64_is_signaling_nan(FT0))) {
830
    farg.ll = arg;
831
    farg.d = float64_abs(farg.d);
832
    return farg.ll;
833
}
834

  
835
/* fnabs */
836
uint64_t helper_fnabs (uint64_t arg)
837
{
838
    CPU_DoubleU farg;
839

  
840
    farg.ll = arg;
841
    farg.d = float64_abs(farg.d);
842
    farg.d = float64_chs(farg.d);
843
    return farg.ll;
844
}
845

  
846
/* fneg */
847
uint64_t helper_fneg (uint64_t arg)
848
{
849
    CPU_DoubleU farg;
850

  
851
    farg.ll = arg;
852
    farg.d = float64_chs(farg.d);
853
    return farg.ll;
854
}
855

  
856
/* fctiw - fctiw. */
857
uint64_t helper_fctiw (uint64_t arg)
858
{
859
    CPU_DoubleU farg;
860
    farg.ll = arg;
861

  
862
    if (unlikely(float64_is_signaling_nan(farg.d))) {
785 863
        /* sNaN conversion */
786
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
787
    } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
864
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
865
    } else if (unlikely(float64_is_nan(farg.d) || isinfinity(farg.d))) {
788 866
        /* qNan / infinity conversion */
789
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
867
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
790 868
    } else {
791
        p.ll = float64_to_int32(FT0, &env->fp_status);
869
        farg.ll = float64_to_int32(farg.d, &env->fp_status);
792 870
#if USE_PRECISE_EMULATION
793 871
        /* XXX: higher bits are not supposed to be significant.
794 872
         *     to make tests easier, return the same as a real PowerPC 750
795 873
         */
796
        p.ll |= 0xFFF80000ULL << 32;
874
        farg.ll |= 0xFFF80000ULL << 32;
797 875
#endif
798
        FT0 = p.d;
799 876
    }
877
    return farg.ll;
800 878
}
801 879

  
802
void do_fctiwz (void)
880
/* fctiwz - fctiwz. */
881
uint64_t helper_fctiwz (uint64_t arg)
803 882
{
804
    CPU_DoubleU p;
883
    CPU_DoubleU farg;
884
    farg.ll = arg;
805 885

  
806
    if (unlikely(float64_is_signaling_nan(FT0))) {
886
    if (unlikely(float64_is_signaling_nan(farg.d))) {
807 887
        /* sNaN conversion */
808
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
809
    } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
888
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
889
    } else if (unlikely(float64_is_nan(farg.d) || isinfinity(farg.d))) {
810 890
        /* qNan / infinity conversion */
811
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
891
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
812 892
    } else {
813
        p.ll = float64_to_int32_round_to_zero(FT0, &env->fp_status);
893
        farg.ll = float64_to_int32_round_to_zero(farg.d, &env->fp_status);
814 894
#if USE_PRECISE_EMULATION
815 895
        /* XXX: higher bits are not supposed to be significant.
816 896
         *     to make tests easier, return the same as a real PowerPC 750
817 897
         */
818
        p.ll |= 0xFFF80000ULL << 32;
898
        farg.ll |= 0xFFF80000ULL << 32;
819 899
#endif
820
        FT0 = p.d;
821 900
    }
901
    return farg.ll;
822 902
}
823 903

  
824 904
#if defined(TARGET_PPC64)
825
void do_fcfid (void)
905
/* fcfid - fcfid. */
906
uint64_t helper_fcfid (uint64_t arg)
826 907
{
827
    CPU_DoubleU p;
828

  
829
    p.d = FT0;
830
    FT0 = int64_to_float64(p.ll, &env->fp_status);
908
    CPU_DoubleU farg;
909
    farg.d = int64_to_float64(arg, &env->fp_status);
910
    return farg.ll;
831 911
}
832 912

  
833
void do_fctid (void)
913
/* fctid - fctid. */
914
uint64_t helper_fctid (uint64_t arg)
834 915
{
835
    CPU_DoubleU p;
916
    CPU_DoubleU farg;
917
    farg.ll = arg;
836 918

  
837
    if (unlikely(float64_is_signaling_nan(FT0))) {
919
    if (unlikely(float64_is_signaling_nan(farg.d))) {
838 920
        /* sNaN conversion */
839
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
840
    } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
921
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
922
    } else if (unlikely(float64_is_nan(farg.d) || isinfinity(farg.d))) {
841 923
        /* qNan / infinity conversion */
842
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
924
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
843 925
    } else {
844
        p.ll = float64_to_int64(FT0, &env->fp_status);
845
        FT0 = p.d;
926
        farg.ll = float64_to_int64(farg.d, &env->fp_status);
846 927
    }
928
    return farg.ll;
847 929
}
848 930

  
849
void do_fctidz (void)
931
/* fctidz - fctidz. */
932
uint64_t helper_fctidz (uint64_t arg)
850 933
{
851
    CPU_DoubleU p;
934
    CPU_DoubleU farg;
935
    farg.ll = arg;
852 936

  
853
    if (unlikely(float64_is_signaling_nan(FT0))) {
937
    if (unlikely(float64_is_signaling_nan(farg.d))) {
854 938
        /* sNaN conversion */
855
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
856
    } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
939
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
940
    } else if (unlikely(float64_is_nan(farg.d) || isinfinity(farg.d))) {
857 941
        /* qNan / infinity conversion */
858
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
942
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
859 943
    } else {
860
        p.ll = float64_to_int64_round_to_zero(FT0, &env->fp_status);
861
        FT0 = p.d;
944
        farg.ll = float64_to_int64_round_to_zero(farg.d, &env->fp_status);
862 945
    }
946
    return farg.ll;
863 947
}
864 948

  
865 949
#endif
866 950

  
867
static always_inline void do_fri (int rounding_mode)
951
static always_inline uint64_t do_fri (uint64_t arg, int rounding_mode)
868 952
{
869
    if (unlikely(float64_is_signaling_nan(FT0))) {
953
    CPU_DoubleU farg;
954
    farg.ll = arg;
955

  
956
    if (unlikely(float64_is_signaling_nan(farg.d))) {
870 957
        /* sNaN round */
871
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
872
    } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
958
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
959
    } else if (unlikely(float64_is_nan(farg.d) || isinfinity(farg.d))) {
873 960
        /* qNan / infinity round */
874
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
961
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
875 962
    } else {
876 963
        set_float_rounding_mode(rounding_mode, &env->fp_status);
877
        FT0 = float64_round_to_int(FT0, &env->fp_status);
964
        farg.ll = float64_round_to_int(farg.d, &env->fp_status);
878 965
        /* Restore rounding mode from FPSCR */
879 966
        fpscr_set_rounding_mode();
880 967
    }
968
    return farg.ll;
881 969
}
882 970

  
883
void do_frin (void)
971
uint64_t helper_frin (uint64_t arg)
884 972
{
885
    do_fri(float_round_nearest_even);
973
    return do_fri(arg, float_round_nearest_even);
886 974
}
887 975

  
888
void do_friz (void)
976
uint64_t helper_friz (uint64_t arg)
889 977
{
890
    do_fri(float_round_to_zero);
978
    return do_fri(arg, float_round_to_zero);
891 979
}
892 980

  
893
void do_frip (void)
981
uint64_t helper_frip (uint64_t arg)
894 982
{
895
    do_fri(float_round_up);
983
    return do_fri(arg, float_round_up);
896 984
}
897 985

  
898
void do_frim (void)
986
uint64_t helper_frim (uint64_t arg)
899 987
{
900
    do_fri(float_round_down);
988
    return do_fri(arg, float_round_down);
901 989
}
902 990

  
903
#if USE_PRECISE_EMULATION
904
void do_fmadd (void)
991
/* fmadd - fmadd. */
992
uint64_t helper_fmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
905 993
{
906
    if (unlikely(float64_is_signaling_nan(FT0) ||
907
                 float64_is_signaling_nan(FT1) ||
908
                 float64_is_signaling_nan(FT2))) {
994
    CPU_DoubleU farg1, farg2, farg3;
995

  
996
    farg1.ll = arg1;
997
    farg2.ll = arg2;
998
    farg3.ll = arg3;
999
#if USE_PRECISE_EMULATION
1000
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1001
                 float64_is_signaling_nan(farg2.d) ||
1002
                 float64_is_signaling_nan(farg3.d))) {
909 1003
        /* sNaN operation */
910
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1004
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
911 1005
    } else {
912 1006
#ifdef FLOAT128
913 1007
        /* This is the way the PowerPC specification defines it */
914 1008
        float128 ft0_128, ft1_128;
915 1009

  
916
        ft0_128 = float64_to_float128(FT0, &env->fp_status);
917
        ft1_128 = float64_to_float128(FT1, &env->fp_status);
1010
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1011
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
918 1012
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
919
        ft1_128 = float64_to_float128(FT2, &env->fp_status);
1013
        ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
920 1014
        ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
921
        FT0 = float128_to_float64(ft0_128, &env->fp_status);
1015
        farg1.d = float128_to_float64(ft0_128, &env->fp_status);
922 1016
#else
923 1017
        /* This is OK on x86 hosts */
924
        FT0 = (FT0 * FT1) + FT2;
1018
        farg1.d = (farg1.d * farg2.d) + farg3.d;
925 1019
#endif
926 1020
    }
1021
#else
1022
    farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1023
    farg1.d = float64_add(farg1.d, farg3.d, &env->fp_status);
1024
#endif
1025
    return farg1.ll;
927 1026
}
928 1027

  
929
void do_fmsub (void)
1028
/* fmsub - fmsub. */
1029
uint64_t helper_fmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
930 1030
{
931
    if (unlikely(float64_is_signaling_nan(FT0) ||
932
                 float64_is_signaling_nan(FT1) ||
933
                 float64_is_signaling_nan(FT2))) {
1031
    CPU_DoubleU farg1, farg2, farg3;
1032

  
1033
    farg1.ll = arg1;
1034
    farg2.ll = arg2;
1035
    farg3.ll = arg3;
1036
#if USE_PRECISE_EMULATION
1037
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1038
                 float64_is_signaling_nan(farg2.d) ||
1039
                 float64_is_signaling_nan(farg3.d))) {
934 1040
        /* sNaN operation */
935
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1041
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
936 1042
    } else {
937 1043
#ifdef FLOAT128
938 1044
        /* This is the way the PowerPC specification defines it */
939 1045
        float128 ft0_128, ft1_128;
940 1046

  
941
        ft0_128 = float64_to_float128(FT0, &env->fp_status);
942
        ft1_128 = float64_to_float128(FT1, &env->fp_status);
1047
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1048
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
943 1049
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
944
        ft1_128 = float64_to_float128(FT2, &env->fp_status);
1050
        ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
945 1051
        ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
946
        FT0 = float128_to_float64(ft0_128, &env->fp_status);
1052
        farg1.d = float128_to_float64(ft0_128, &env->fp_status);
947 1053
#else
948 1054
        /* This is OK on x86 hosts */
949
        FT0 = (FT0 * FT1) - FT2;
1055
        farg1.d = (farg1.d * farg2.d) - farg3.d;
950 1056
#endif
951 1057
    }
1058
#else
1059
    farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1060
    farg1.d = float64_sub(farg1.d, farg3.d, &env->fp_status);
1061
#endif
1062
    return farg1.ll;
952 1063
}
953
#endif /* USE_PRECISE_EMULATION */
954 1064

  
955
void do_fnmadd (void)
1065
/* fnmadd - fnmadd. */
1066
uint64_t helper_fnmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
956 1067
{
957
    if (unlikely(float64_is_signaling_nan(FT0) ||
958
                 float64_is_signaling_nan(FT1) ||
959
                 float64_is_signaling_nan(FT2))) {
1068
    CPU_DoubleU farg1, farg2, farg3;
1069

  
1070
    farg1.ll = arg1;
1071
    farg2.ll = arg2;
1072
    farg3.ll = arg3;
1073

  
1074
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1075
                 float64_is_signaling_nan(farg2.d) ||
1076
                 float64_is_signaling_nan(farg3.d))) {
960 1077
        /* sNaN operation */
961
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1078
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
962 1079
    } else {
963 1080
#if USE_PRECISE_EMULATION
964 1081
#ifdef FLOAT128
965 1082
        /* This is the way the PowerPC specification defines it */
966 1083
        float128 ft0_128, ft1_128;
967 1084

  
968
        ft0_128 = float64_to_float128(FT0, &env->fp_status);
969
        ft1_128 = float64_to_float128(FT1, &env->fp_status);
1085
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1086
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
970 1087
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
971
        ft1_128 = float64_to_float128(FT2, &env->fp_status);
1088
        ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
972 1089
        ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
973
        FT0 = float128_to_float64(ft0_128, &env->fp_status);
1090
        farg1.d= float128_to_float64(ft0_128, &env->fp_status);
974 1091
#else
975 1092
        /* This is OK on x86 hosts */
976
        FT0 = (FT0 * FT1) + FT2;
1093
        farg1.d = (farg1.d * farg2.d) + farg3.d;
977 1094
#endif
978 1095
#else
979
        FT0 = float64_mul(FT0, FT1, &env->fp_status);
980
        FT0 = float64_add(FT0, FT2, &env->fp_status);
1096
        farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1097
        farg1.d = float64_add(farg1.d, farg3.d, &env->fp_status);
981 1098
#endif
982
        if (likely(!isnan(FT0)))
983
            FT0 = float64_chs(FT0);
1099
        if (likely(!isnan(farg1.d)))
1100
            farg1.d = float64_chs(farg1.d);
984 1101
    }
1102
    return farg1.ll;
985 1103
}
986 1104

  
987
void do_fnmsub (void)
1105
/* fnmsub - fnmsub. */
1106
uint64_t helper_fnmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
988 1107
{
989
    if (unlikely(float64_is_signaling_nan(FT0) ||
990
                 float64_is_signaling_nan(FT1) ||
991
                 float64_is_signaling_nan(FT2))) {
1108
    CPU_DoubleU farg1, farg2, farg3;
1109

  
1110
    farg1.ll = arg1;
1111
    farg2.ll = arg2;
1112
    farg3.ll = arg3;
1113

  
1114
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1115
                 float64_is_signaling_nan(farg2.d) ||
1116
                 float64_is_signaling_nan(farg3.d))) {
992 1117
        /* sNaN operation */
993
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1118
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
994 1119
    } else {
995 1120
#if USE_PRECISE_EMULATION
996 1121
#ifdef FLOAT128
997 1122
        /* This is the way the PowerPC specification defines it */
998 1123
        float128 ft0_128, ft1_128;
999 1124

  
1000
        ft0_128 = float64_to_float128(FT0, &env->fp_status);
1001
        ft1_128 = float64_to_float128(FT1, &env->fp_status);
1125
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1126
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1002 1127
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1003
        ft1_128 = float64_to_float128(FT2, &env->fp_status);
1128
        ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1004 1129
        ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
1005
        FT0 = float128_to_float64(ft0_128, &env->fp_status);
1130
        farg1.d = float128_to_float64(ft0_128, &env->fp_status);
1006 1131
#else
1007 1132
        /* This is OK on x86 hosts */
1008
        FT0 = (FT0 * FT1) - FT2;
1133
        farg1.d = (farg1.d * farg2.d) - farg3.d;
1009 1134
#endif
1010 1135
#else
1011
        FT0 = float64_mul(FT0, FT1, &env->fp_status);
1012
        FT0 = float64_sub(FT0, FT2, &env->fp_status);
1136
        farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1137
        farg1.d = float64_sub(farg1.d, farg3.d, &env->fp_status);
1013 1138
#endif
1014
        if (likely(!isnan(FT0)))
1015
            FT0 = float64_chs(FT0);
1139
        if (likely(!isnan(farg1.d)))
1140
            farg1.d = float64_chs(farg1.d);
1016 1141
    }
1142
    return farg1.ll;
1017 1143
}
1018 1144

  
1019
#if USE_PRECISE_EMULATION
1020
void do_frsp (void)
1145

  
1146
/* frsp - frsp. */
1147
uint64_t helper_frsp (uint64_t arg)
1021 1148
{
1022
    if (unlikely(float64_is_signaling_nan(FT0))) {
1149
    CPU_DoubleU farg;
1150
    farg.ll = arg;
1151

  
1152
#if USE_PRECISE_EMULATION
1153
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1023 1154
        /* sNaN square root */
1024
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1155
       farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1025 1156
    } else {
1026
        FT0 = float64_to_float32(FT0, &env->fp_status);
1157
       fard.d = float64_to_float32(farg.d, &env->fp_status);
1027 1158
    }
1159
#else
1160
    farg.d = float64_to_float32(farg.d, &env->fp_status);
1161
#endif
1162
    return farg.ll;
1028 1163
}
1029
#endif /* USE_PRECISE_EMULATION */
1030 1164

  
1031
void do_fsqrt (void)
1165
/* fsqrt - fsqrt. */
1166
uint64_t helper_fsqrt (uint64_t arg)
1032 1167
{
1033
    if (unlikely(float64_is_signaling_nan(FT0))) {
1168
    CPU_DoubleU farg;
1169
    farg.ll = arg;
1170

  
1171
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1034 1172
        /* sNaN square root */
1035
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1036
    } else if (unlikely(fpisneg(FT0) && !iszero(FT0))) {
1173
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1174
    } else if (unlikely(fpisneg(farg.d) && !iszero(farg.d))) {
1037 1175
        /* Square root of a negative nonzero number */
1038
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
1176
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
1039 1177
    } else {
1040
        FT0 = float64_sqrt(FT0, &env->fp_status);
1178
        farg.d = float64_sqrt(farg.d, &env->fp_status);
1041 1179
    }
1180
    return farg.ll;
1042 1181
}
1043 1182

  
1044
void do_fre (void)
1183
/* fre - fre. */
1184
uint64_t helper_fre (uint64_t arg)
1045 1185
{
1046
    CPU_DoubleU p;
1186
    CPU_DoubleU farg;
1187
    farg.ll = arg;
1047 1188

  
1048
    if (unlikely(float64_is_signaling_nan(FT0))) {
1189
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1049 1190
        /* sNaN reciprocal */
1050
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1051
    } else if (unlikely(iszero(FT0))) {
1191
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1192
    } else if (unlikely(iszero(farg.d))) {
1052 1193
        /* Zero reciprocal */
1053
        float_zero_divide_excp();
1054
    } else if (likely(isnormal(FT0))) {
1055
        FT0 = float64_div(1.0, FT0, &env->fp_status);
1194
        farg.ll = float_zero_divide_excp(1.0, farg.d);
1195
    } else if (likely(isnormal(farg.d))) {
1196
        farg.d = float64_div(1.0, farg.d, &env->fp_status);
1056 1197
    } else {
1057
        p.d = FT0;
1058
        if (p.ll == 0x8000000000000000ULL) {
1059
            p.ll = 0xFFF0000000000000ULL;
1060
        } else if (p.ll == 0x0000000000000000ULL) {
1061
            p.ll = 0x7FF0000000000000ULL;
1062
        } else if (isnan(FT0)) {
1063
            p.ll = 0x7FF8000000000000ULL;
1064
        } else if (fpisneg(FT0)) {
1065
            p.ll = 0x8000000000000000ULL;
1198
        if (farg.ll == 0x8000000000000000ULL) {
1199
            farg.ll = 0xFFF0000000000000ULL;
1200
        } else if (farg.ll == 0x0000000000000000ULL) {
1201
            farg.ll = 0x7FF0000000000000ULL;
1202
        } else if (isnan(farg.d)) {
1203
            farg.ll = 0x7FF8000000000000ULL;
1204
        } else if (fpisneg(farg.d)) {
1205
            farg.ll = 0x8000000000000000ULL;
1066 1206
        } else {
1067
            p.ll = 0x0000000000000000ULL;
1207
            farg.ll = 0x0000000000000000ULL;
1068 1208
        }
1069
        FT0 = p.d;
1070 1209
    }
1210
    return farg.d;
1071 1211
}
1072 1212

  
1073
void do_fres (void)
1213
/* fres - fres. */
1214
uint64_t helper_fres (uint64_t arg)
1074 1215
{
1075
    CPU_DoubleU p;
1216
    CPU_DoubleU farg;
1217
    farg.ll = arg;
1076 1218

  
1077
    if (unlikely(float64_is_signaling_nan(FT0))) {
1219
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1078 1220
        /* sNaN reciprocal */
1079
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1080
    } else if (unlikely(iszero(FT0))) {
1221
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1222
    } else if (unlikely(iszero(farg.d))) {
1081 1223
        /* Zero reciprocal */
1082
        float_zero_divide_excp();
1083
    } else if (likely(isnormal(FT0))) {
1224
        farg.ll = float_zero_divide_excp(1.0, farg.d);
1225
    } else if (likely(isnormal(farg.d))) {
1084 1226
#if USE_PRECISE_EMULATION
1085
        FT0 = float64_div(1.0, FT0, &env->fp_status);
1086
        FT0 = float64_to_float32(FT0, &env->fp_status);
1227
        farg.d = float64_div(1.0, farg.d, &env->fp_status);
1228
        farg.d = float64_to_float32(farg.d, &env->fp_status);
1087 1229
#else
1088
        FT0 = float32_div(1.0, FT0, &env->fp_status);
1230
        farg.d = float32_div(1.0, farg.d, &env->fp_status);
1089 1231
#endif
1090 1232
    } else {
1091
        p.d = FT0;
1092
        if (p.ll == 0x8000000000000000ULL) {
1093
            p.ll = 0xFFF0000000000000ULL;
1094
        } else if (p.ll == 0x0000000000000000ULL) {
1095
            p.ll = 0x7FF0000000000000ULL;
1096
        } else if (isnan(FT0)) {
1097
            p.ll = 0x7FF8000000000000ULL;
1098
        } else if (fpisneg(FT0)) {
1099
            p.ll = 0x8000000000000000ULL;
1233
        if (farg.ll == 0x8000000000000000ULL) {
1234
            farg.ll = 0xFFF0000000000000ULL;
1235
        } else if (farg.ll == 0x0000000000000000ULL) {
1236
            farg.ll = 0x7FF0000000000000ULL;
1237
        } else if (isnan(farg.d)) {
1238
            farg.ll = 0x7FF8000000000000ULL;
1239
        } else if (fpisneg(farg.d)) {
1240
            farg.ll = 0x8000000000000000ULL;
1100 1241
        } else {
1101
            p.ll = 0x0000000000000000ULL;
1242
            farg.ll = 0x0000000000000000ULL;
1102 1243
        }
1103
        FT0 = p.d;
1104 1244
    }
1245
    return farg.ll;
1105 1246
}
1106 1247

  
1107
void do_frsqrte (void)
1248
/* frsqrte  - frsqrte. */
1249
uint64_t helper_frsqrte (uint64_t arg)
1108 1250
{
1109
    CPU_DoubleU p;
1251
    CPU_DoubleU farg;
1252
    farg.ll = arg;
1110 1253

  
1111
    if (unlikely(float64_is_signaling_nan(FT0))) {
1254
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1112 1255
        /* sNaN reciprocal square root */
1113
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1114
    } else if (unlikely(fpisneg(FT0) && !iszero(FT0))) {
1256
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1257
    } else if (unlikely(fpisneg(farg.d) && !iszero(farg.d))) {
1115 1258
        /* Reciprocal square root of a negative nonzero number */
1116
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
1117
    } else if (likely(isnormal(FT0))) {
1118
        FT0 = float64_sqrt(FT0, &env->fp_status);
1119
        FT0 = float32_div(1.0, FT0, &env->fp_status);
1259
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
1260
    } else if (likely(isnormal(farg.d))) {
1261
        farg.d = float64_sqrt(farg.d, &env->fp_status);
1262
        farg.d = float32_div(1.0, farg.d, &env->fp_status);
1120 1263
    } else {
1121
        p.d = FT0;
1122
        if (p.ll == 0x8000000000000000ULL) {
1123
            p.ll = 0xFFF0000000000000ULL;
1124
        } else if (p.ll == 0x0000000000000000ULL) {
1125
            p.ll = 0x7FF0000000000000ULL;
1126
        } else if (isnan(FT0)) {
1127
            p.ll |= 0x000FFFFFFFFFFFFFULL;
1128
        } else if (fpisneg(FT0)) {
1129
            p.ll = 0x7FF8000000000000ULL;
1264
        if (farg.ll == 0x8000000000000000ULL) {
1265
            farg.ll = 0xFFF0000000000000ULL;
1266
        } else if (farg.ll == 0x0000000000000000ULL) {
1267
            farg.ll = 0x7FF0000000000000ULL;
1268
        } else if (isnan(farg.d)) {
1269
            farg.ll |= 0x000FFFFFFFFFFFFFULL;
1270
        } else if (fpisneg(farg.d)) {
1271
            farg.ll = 0x7FF8000000000000ULL;
1130 1272
        } else {
1131
            p.ll = 0x0000000000000000ULL;
1273
            farg.ll = 0x0000000000000000ULL;
1132 1274
        }
1133
        FT0 = p.d;
1134 1275
    }
1276
    return farg.ll;
1135 1277
}
1136 1278

  
1137
void do_fsel (void)
1279
/* fsel - fsel. */
1280
uint64_t helper_fsel (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1138 1281
{
1139
    if (!fpisneg(FT0) || iszero(FT0))
1140
        FT0 = FT1;
1282
    CPU_DoubleU farg1, farg2, farg3;
1283

  
1284
    farg1.ll = arg1;
1285
    farg2.ll = arg2;
1286
    farg3.ll = arg3;
1287

  
1288
    if (!fpisneg(farg1.d) || iszero(farg1.d))
1289
        return farg2.ll;
1141 1290
    else
1142
        FT0 = FT2;
1291
        return farg2.ll;
1143 1292
}
1144 1293

  
1145
uint32_t helper_fcmpu (void)
1294
uint32_t helper_fcmpu (uint64_t arg1, uint64_t arg2)
1146 1295
{
1296
    CPU_DoubleU farg1, farg2;
1147 1297
    uint32_t ret = 0;
1298
    farg1.ll = arg1;
1299
    farg2.ll = arg2;
1148 1300

  
1149
    if (unlikely(float64_is_signaling_nan(FT0) ||
1150
                 float64_is_signaling_nan(FT1))) {
1301
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1302
                 float64_is_signaling_nan(farg2.d))) {
1151 1303
        /* sNaN comparison */
1152 1304
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1153 1305
    } else {
1154
        if (float64_lt(FT0, FT1, &env->fp_status)) {
1306
        if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
1155 1307
            ret = 0x08UL;
1156
        } else if (!float64_le(FT0, FT1, &env->fp_status)) {
1308
        } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
1157 1309
            ret = 0x04UL;
1158 1310
        } else {
1159 1311
            ret = 0x02UL;
......
1164 1316
    return ret;
1165 1317
}
1166 1318

  
1167
uint32_t helper_fcmpo (void)
1319
uint32_t helper_fcmpo (uint64_t arg1, uint64_t arg2)
1168 1320
{
1321
    CPU_DoubleU farg1, farg2;
1169 1322
    uint32_t ret = 0;
1323
    farg1.ll = arg1;
1324
    farg2.ll = arg2;
1170 1325

  
1171
    if (unlikely(float64_is_nan(FT0) ||
1172
                 float64_is_nan(FT1))) {
1173
        if (float64_is_signaling_nan(FT0) ||
1174
            float64_is_signaling_nan(FT1)) {
1326
    if (unlikely(float64_is_nan(farg1.d) ||
1327
                 float64_is_nan(farg2.d))) {
1328
        if (float64_is_signaling_nan(farg1.d) ||
1329
            float64_is_signaling_nan(farg2.d)) {
1175 1330
            /* sNaN comparison */
1176 1331
            fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN |
1177 1332
                                  POWERPC_EXCP_FP_VXVC);
......
1180 1335
            fload_invalid_op_excp(POWERPC_EXCP_FP_VXVC);
1181 1336
        }
1182 1337
    } else {
1183
        if (float64_lt(FT0, FT1, &env->fp_status)) {
1338
        if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
1184 1339
            ret = 0x08UL;
1185
        } else if (!float64_le(FT0, FT1, &env->fp_status)) {
1340
        } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
1186 1341
            ret = 0x04UL;
1187 1342
        } else {
1188 1343
            ret = 0x02UL;
b/target-ppc/translate.c
75 75
#else
76 76
static TCGv_i64 cpu_T64[3];
77 77
#endif
78
static TCGv_i64 cpu_FT[3];
78
static TCGv_i64 cpu_FT[2];
79 79
static TCGv_i64 cpu_AVRh[3], cpu_AVRl[3];
80 80

  
81 81
#include "gen-icount.h"
......
120 120
                                       offsetof(CPUState, ft0), "FT0");
121 121
    cpu_FT[1] = tcg_global_mem_new_i64(TCG_AREG0,
122 122
                                       offsetof(CPUState, ft1), "FT1");
123
    cpu_FT[2] = tcg_global_mem_new_i64(TCG_AREG0,
124
                                       offsetof(CPUState, ft2), "FT2");
125 123

  
126 124
    cpu_AVRh[0] = tcg_global_mem_new_i64(TCG_AREG0,
127 125
                                     offsetof(CPUState, avr0.u64[0]), "AVR0H");
......
245 243
#endif
246 244
}
247 245

  
248
static always_inline void gen_compute_fprf (int set_fprf, int set_rc)
246
static always_inline void gen_compute_fprf (TCGv arg, int set_fprf, int set_rc)
249 247
{
248
    TCGv t0 = tcg_temp_new_i32();
249

  
250 250
    if (set_fprf != 0) {
251 251
        /* This case might be optimized later */
252 252
#if defined(OPTIMIZE_FPRF_UPDATE)
253 253
        *gen_fprf_ptr++ = gen_opc_ptr;
254 254
#endif
255
        gen_op_compute_fprf(1);
255
        tcg_gen_movi_tl(t0, 1);
256
        gen_helper_compute_fprf(t0, arg, t0);
256 257
        if (unlikely(set_rc)) {
257
            tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_T[0]);
258
            tcg_gen_andi_i32(cpu_crf[1], cpu_crf[1], 0xf);
258
            tcg_gen_movi_i32(cpu_crf[1], t0);
259 259
        }
260
        gen_op_float_check_status();
260
        gen_helper_float_check_status();
261 261
    } else if (unlikely(set_rc)) {
262 262
        /* We always need to compute fpcc */
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff