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;
|