Revision af12906f target-ppc/op_helper.c
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; |
Also available in: Unified diff