Revision fd4a04eb target-mips/op_helper.c
b/target-mips/op_helper.c | ||
---|---|---|
598 | 598 |
} |
599 | 599 |
|
600 | 600 |
#endif |
601 |
|
|
602 |
/* Complex FPU operations which may need stack space. */ |
|
603 |
|
|
604 |
/* convert MIPS rounding mode in FCR31 to IEEE library */ |
|
605 |
unsigned int ieee_rm[] = { |
|
606 |
float_round_nearest_even, |
|
607 |
float_round_to_zero, |
|
608 |
float_round_up, |
|
609 |
float_round_down |
|
610 |
}; |
|
611 |
|
|
612 |
#define RESTORE_ROUNDING_MODE \ |
|
613 |
set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status) |
|
614 |
|
|
615 |
void do_ctc1 (void) |
|
616 |
{ |
|
617 |
switch(T1) { |
|
618 |
case 25: |
|
619 |
if (T0 & 0xffffff00) |
|
620 |
return; |
|
621 |
env->fcr31 = (env->fcr31 & 0x017fffff) | ((T0 & 0xfe) << 24) | |
|
622 |
((T0 & 0x1) << 23); |
|
623 |
break; |
|
624 |
case 26: |
|
625 |
if (T0 & 0x007c0000) |
|
626 |
return; |
|
627 |
env->fcr31 = (env->fcr31 & 0xfffc0f83) | (T0 & 0x0003f07c); |
|
628 |
break; |
|
629 |
case 28: |
|
630 |
if (T0 & 0x007c0000) |
|
631 |
return; |
|
632 |
env->fcr31 = (env->fcr31 & 0xfefff07c) | (T0 & 0x00000f83) | |
|
633 |
((T0 & 0x4) << 22); |
|
634 |
break; |
|
635 |
case 31: |
|
636 |
if (T0 & 0x007c0000) |
|
637 |
return; |
|
638 |
env->fcr31 = T0; |
|
639 |
break; |
|
640 |
default: |
|
641 |
return; |
|
642 |
} |
|
643 |
/* set rounding mode */ |
|
644 |
RESTORE_ROUNDING_MODE; |
|
645 |
set_float_exception_flags(0, &env->fp_status); |
|
646 |
if ((GET_FP_ENABLE(env->fcr31) | 0x20) & GET_FP_CAUSE(env->fcr31)) |
|
647 |
do_raise_exception(EXCP_FPE); |
|
648 |
} |
|
649 |
|
|
650 |
inline char ieee_ex_to_mips(char xcpt) |
|
651 |
{ |
|
652 |
return (xcpt & float_flag_inexact) >> 5 | |
|
653 |
(xcpt & float_flag_underflow) >> 3 | |
|
654 |
(xcpt & float_flag_overflow) >> 1 | |
|
655 |
(xcpt & float_flag_divbyzero) << 1 | |
|
656 |
(xcpt & float_flag_invalid) << 4; |
|
657 |
} |
|
658 |
|
|
659 |
inline char mips_ex_to_ieee(char xcpt) |
|
660 |
{ |
|
661 |
return (xcpt & FP_INEXACT) << 5 | |
|
662 |
(xcpt & FP_UNDERFLOW) << 3 | |
|
663 |
(xcpt & FP_OVERFLOW) << 1 | |
|
664 |
(xcpt & FP_DIV0) >> 1 | |
|
665 |
(xcpt & FP_INVALID) >> 4; |
|
666 |
} |
|
667 |
|
|
668 |
inline void update_fcr31(void) |
|
669 |
{ |
|
670 |
int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->fp_status)); |
|
671 |
|
|
672 |
SET_FP_CAUSE(env->fcr31, tmp); |
|
673 |
if (GET_FP_ENABLE(env->fcr31) & tmp) |
|
674 |
do_raise_exception(EXCP_FPE); |
|
675 |
else |
|
676 |
UPDATE_FP_FLAGS(env->fcr31, tmp); |
|
677 |
} |
|
678 |
|
|
679 |
#define FLOAT_OP(name, p) void do_float_##name##_##p(void) |
|
680 |
|
|
681 |
FLOAT_OP(cvtd, s) |
|
682 |
{ |
|
683 |
set_float_exception_flags(0, &env->fp_status); |
|
684 |
FDT2 = float32_to_float64(FST0, &env->fp_status); |
|
685 |
update_fcr31(); |
|
686 |
} |
|
687 |
FLOAT_OP(cvtd, w) |
|
688 |
{ |
|
689 |
set_float_exception_flags(0, &env->fp_status); |
|
690 |
FDT2 = int32_to_float64(WT0, &env->fp_status); |
|
691 |
update_fcr31(); |
|
692 |
} |
|
693 |
FLOAT_OP(cvtd, l) |
|
694 |
{ |
|
695 |
set_float_exception_flags(0, &env->fp_status); |
|
696 |
FDT2 = int64_to_float64(DT0, &env->fp_status); |
|
697 |
update_fcr31(); |
|
698 |
} |
|
699 |
FLOAT_OP(cvtl, d) |
|
700 |
{ |
|
701 |
set_float_exception_flags(0, &env->fp_status); |
|
702 |
DT2 = float64_to_int64(FDT0, &env->fp_status); |
|
703 |
update_fcr31(); |
|
704 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
705 |
DT2 = 0x7fffffffffffffffULL; |
|
706 |
} |
|
707 |
FLOAT_OP(cvtl, s) |
|
708 |
{ |
|
709 |
set_float_exception_flags(0, &env->fp_status); |
|
710 |
DT2 = float32_to_int64(FST0, &env->fp_status); |
|
711 |
update_fcr31(); |
|
712 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
713 |
DT2 = 0x7fffffffffffffffULL; |
|
714 |
} |
|
715 |
|
|
716 |
FLOAT_OP(cvtps, pw) |
|
717 |
{ |
|
718 |
set_float_exception_flags(0, &env->fp_status); |
|
719 |
FST2 = int32_to_float32(WT0, &env->fp_status); |
|
720 |
FSTH2 = int32_to_float32(WTH0, &env->fp_status); |
|
721 |
update_fcr31(); |
|
722 |
} |
|
723 |
FLOAT_OP(cvtpw, ps) |
|
724 |
{ |
|
725 |
set_float_exception_flags(0, &env->fp_status); |
|
726 |
WT2 = float32_to_int32(FST0, &env->fp_status); |
|
727 |
WTH2 = float32_to_int32(FSTH0, &env->fp_status); |
|
728 |
update_fcr31(); |
|
729 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
730 |
WT2 = 0x7fffffff; |
|
731 |
} |
|
732 |
FLOAT_OP(cvts, d) |
|
733 |
{ |
|
734 |
set_float_exception_flags(0, &env->fp_status); |
|
735 |
FST2 = float64_to_float32(FDT0, &env->fp_status); |
|
736 |
update_fcr31(); |
|
737 |
} |
|
738 |
FLOAT_OP(cvts, w) |
|
739 |
{ |
|
740 |
set_float_exception_flags(0, &env->fp_status); |
|
741 |
FST2 = int32_to_float32(WT0, &env->fp_status); |
|
742 |
update_fcr31(); |
|
743 |
} |
|
744 |
FLOAT_OP(cvts, l) |
|
745 |
{ |
|
746 |
set_float_exception_flags(0, &env->fp_status); |
|
747 |
FST2 = int64_to_float32(DT0, &env->fp_status); |
|
748 |
update_fcr31(); |
|
749 |
} |
|
750 |
FLOAT_OP(cvts, pl) |
|
751 |
{ |
|
752 |
set_float_exception_flags(0, &env->fp_status); |
|
753 |
WT2 = WT0; |
|
754 |
update_fcr31(); |
|
755 |
} |
|
756 |
FLOAT_OP(cvts, pu) |
|
757 |
{ |
|
758 |
set_float_exception_flags(0, &env->fp_status); |
|
759 |
WT2 = WTH0; |
|
760 |
update_fcr31(); |
|
761 |
} |
|
762 |
FLOAT_OP(cvtw, s) |
|
763 |
{ |
|
764 |
set_float_exception_flags(0, &env->fp_status); |
|
765 |
WT2 = float32_to_int32(FST0, &env->fp_status); |
|
766 |
update_fcr31(); |
|
767 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
768 |
WT2 = 0x7fffffff; |
|
769 |
} |
|
770 |
FLOAT_OP(cvtw, d) |
|
771 |
{ |
|
772 |
set_float_exception_flags(0, &env->fp_status); |
|
773 |
WT2 = float64_to_int32(FDT0, &env->fp_status); |
|
774 |
update_fcr31(); |
|
775 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
776 |
WT2 = 0x7fffffff; |
|
777 |
} |
|
778 |
|
|
779 |
FLOAT_OP(roundl, d) |
|
780 |
{ |
|
781 |
set_float_rounding_mode(float_round_nearest_even, &env->fp_status); |
|
782 |
DT2 = float64_round_to_int(FDT0, &env->fp_status); |
|
783 |
RESTORE_ROUNDING_MODE; |
|
784 |
update_fcr31(); |
|
785 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
786 |
DT2 = 0x7fffffffffffffffULL; |
|
787 |
} |
|
788 |
FLOAT_OP(roundl, s) |
|
789 |
{ |
|
790 |
set_float_rounding_mode(float_round_nearest_even, &env->fp_status); |
|
791 |
DT2 = float32_round_to_int(FST0, &env->fp_status); |
|
792 |
RESTORE_ROUNDING_MODE; |
|
793 |
update_fcr31(); |
|
794 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
795 |
DT2 = 0x7fffffffffffffffULL; |
|
796 |
} |
|
797 |
FLOAT_OP(roundw, d) |
|
798 |
{ |
|
799 |
set_float_rounding_mode(float_round_nearest_even, &env->fp_status); |
|
800 |
WT2 = float64_round_to_int(FDT0, &env->fp_status); |
|
801 |
RESTORE_ROUNDING_MODE; |
|
802 |
update_fcr31(); |
|
803 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
804 |
WT2 = 0x7fffffff; |
|
805 |
} |
|
806 |
FLOAT_OP(roundw, s) |
|
807 |
{ |
|
808 |
set_float_rounding_mode(float_round_nearest_even, &env->fp_status); |
|
809 |
WT2 = float32_round_to_int(FST0, &env->fp_status); |
|
810 |
RESTORE_ROUNDING_MODE; |
|
811 |
update_fcr31(); |
|
812 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
813 |
WT2 = 0x7fffffff; |
|
814 |
} |
|
815 |
|
|
816 |
FLOAT_OP(truncl, d) |
|
817 |
{ |
|
818 |
DT2 = float64_to_int64_round_to_zero(FDT0, &env->fp_status); |
|
819 |
update_fcr31(); |
|
820 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
821 |
DT2 = 0x7fffffffffffffffULL; |
|
822 |
} |
|
823 |
FLOAT_OP(truncl, s) |
|
824 |
{ |
|
825 |
DT2 = float32_to_int64_round_to_zero(FST0, &env->fp_status); |
|
826 |
update_fcr31(); |
|
827 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
828 |
DT2 = 0x7fffffffffffffffULL; |
|
829 |
} |
|
830 |
FLOAT_OP(truncw, d) |
|
831 |
{ |
|
832 |
WT2 = float64_to_int32_round_to_zero(FDT0, &env->fp_status); |
|
833 |
update_fcr31(); |
|
834 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
835 |
WT2 = 0x7fffffff; |
|
836 |
} |
|
837 |
FLOAT_OP(truncw, s) |
|
838 |
{ |
|
839 |
WT2 = float32_to_int32_round_to_zero(FST0, &env->fp_status); |
|
840 |
update_fcr31(); |
|
841 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
842 |
WT2 = 0x7fffffff; |
|
843 |
} |
|
844 |
|
|
845 |
FLOAT_OP(ceill, d) |
|
846 |
{ |
|
847 |
set_float_rounding_mode(float_round_up, &env->fp_status); |
|
848 |
DT2 = float64_round_to_int(FDT0, &env->fp_status); |
|
849 |
RESTORE_ROUNDING_MODE; |
|
850 |
update_fcr31(); |
|
851 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
852 |
DT2 = 0x7fffffffffffffffULL; |
|
853 |
} |
|
854 |
FLOAT_OP(ceill, s) |
|
855 |
{ |
|
856 |
set_float_rounding_mode(float_round_up, &env->fp_status); |
|
857 |
DT2 = float32_round_to_int(FST0, &env->fp_status); |
|
858 |
RESTORE_ROUNDING_MODE; |
|
859 |
update_fcr31(); |
|
860 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
861 |
DT2 = 0x7fffffffffffffffULL; |
|
862 |
} |
|
863 |
FLOAT_OP(ceilw, d) |
|
864 |
{ |
|
865 |
set_float_rounding_mode(float_round_up, &env->fp_status); |
|
866 |
WT2 = float64_round_to_int(FDT0, &env->fp_status); |
|
867 |
RESTORE_ROUNDING_MODE; |
|
868 |
update_fcr31(); |
|
869 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
870 |
WT2 = 0x7fffffff; |
|
871 |
} |
|
872 |
FLOAT_OP(ceilw, s) |
|
873 |
{ |
|
874 |
set_float_rounding_mode(float_round_up, &env->fp_status); |
|
875 |
WT2 = float32_round_to_int(FST0, &env->fp_status); |
|
876 |
RESTORE_ROUNDING_MODE; |
|
877 |
update_fcr31(); |
|
878 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
879 |
WT2 = 0x7fffffff; |
|
880 |
} |
|
881 |
|
|
882 |
FLOAT_OP(floorl, d) |
|
883 |
{ |
|
884 |
set_float_rounding_mode(float_round_down, &env->fp_status); |
|
885 |
DT2 = float64_round_to_int(FDT0, &env->fp_status); |
|
886 |
RESTORE_ROUNDING_MODE; |
|
887 |
update_fcr31(); |
|
888 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
889 |
DT2 = 0x7fffffffffffffffULL; |
|
890 |
} |
|
891 |
FLOAT_OP(floorl, s) |
|
892 |
{ |
|
893 |
set_float_rounding_mode(float_round_down, &env->fp_status); |
|
894 |
DT2 = float32_round_to_int(FST0, &env->fp_status); |
|
895 |
RESTORE_ROUNDING_MODE; |
|
896 |
update_fcr31(); |
|
897 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
898 |
DT2 = 0x7fffffffffffffffULL; |
|
899 |
} |
|
900 |
FLOAT_OP(floorw, d) |
|
901 |
{ |
|
902 |
set_float_rounding_mode(float_round_down, &env->fp_status); |
|
903 |
WT2 = float64_round_to_int(FDT0, &env->fp_status); |
|
904 |
RESTORE_ROUNDING_MODE; |
|
905 |
update_fcr31(); |
|
906 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
907 |
WT2 = 0x7fffffff; |
|
908 |
} |
|
909 |
FLOAT_OP(floorw, s) |
|
910 |
{ |
|
911 |
set_float_rounding_mode(float_round_down, &env->fp_status); |
|
912 |
WT2 = float32_round_to_int(FST0, &env->fp_status); |
|
913 |
RESTORE_ROUNDING_MODE; |
|
914 |
update_fcr31(); |
|
915 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
916 |
WT2 = 0x7fffffff; |
|
917 |
} |
|
918 |
|
|
919 |
/* binary operations */ |
|
920 |
#define FLOAT_BINOP(name) \ |
|
921 |
FLOAT_OP(name, d) \ |
|
922 |
{ \ |
|
923 |
set_float_exception_flags(0, &env->fp_status); \ |
|
924 |
FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status); \ |
|
925 |
update_fcr31(); \ |
|
926 |
} \ |
|
927 |
FLOAT_OP(name, s) \ |
|
928 |
{ \ |
|
929 |
set_float_exception_flags(0, &env->fp_status); \ |
|
930 |
FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \ |
|
931 |
update_fcr31(); \ |
|
932 |
} \ |
|
933 |
FLOAT_OP(name, ps) \ |
|
934 |
{ \ |
|
935 |
set_float_exception_flags(0, &env->fp_status); \ |
|
936 |
FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \ |
|
937 |
FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fp_status); \ |
|
938 |
update_fcr31(); \ |
|
939 |
} |
|
940 |
FLOAT_BINOP(add) |
|
941 |
FLOAT_BINOP(sub) |
|
942 |
FLOAT_BINOP(mul) |
|
943 |
FLOAT_BINOP(div) |
|
944 |
#undef FLOAT_BINOP |
|
945 |
|
|
946 |
FLOAT_OP(addr, ps) |
|
947 |
{ |
|
948 |
set_float_exception_flags(0, &env->fp_status); |
|
949 |
FST2 = float32_add (FST0, FSTH0, &env->fp_status); |
|
950 |
FSTH2 = float32_add (FST1, FSTH1, &env->fp_status); |
|
951 |
update_fcr31(); |
|
952 |
} |
|
953 |
|
|
954 |
#define FOP_COND_D(op, cond) \ |
|
955 |
void do_cmp_d_ ## op (long cc) \ |
|
956 |
{ \ |
|
957 |
int c = cond; \ |
|
958 |
update_fcr31(); \ |
|
959 |
if (c) \ |
|
960 |
SET_FP_COND(cc, env); \ |
|
961 |
else \ |
|
962 |
CLEAR_FP_COND(cc, env); \ |
|
963 |
} \ |
|
964 |
void do_cmpabs_d_ ## op (long cc) \ |
|
965 |
{ \ |
|
966 |
int c; \ |
|
967 |
FDT0 &= ~(1ULL << 63); \ |
|
968 |
FDT1 &= ~(1ULL << 63); \ |
|
969 |
c = cond; \ |
|
970 |
update_fcr31(); \ |
|
971 |
if (c) \ |
|
972 |
SET_FP_COND(cc, env); \ |
|
973 |
else \ |
|
974 |
CLEAR_FP_COND(cc, env); \ |
|
975 |
} |
|
976 |
|
|
977 |
int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM) |
|
978 |
{ |
|
979 |
if (float64_is_signaling_nan(a) || |
|
980 |
float64_is_signaling_nan(b) || |
|
981 |
(sig && (float64_is_nan(a) || float64_is_nan(b)))) { |
|
982 |
float_raise(float_flag_invalid, status); |
|
983 |
return 1; |
|
984 |
} else if (float64_is_nan(a) || float64_is_nan(b)) { |
|
985 |
return 1; |
|
986 |
} else { |
|
987 |
return 0; |
|
988 |
} |
|
989 |
} |
|
990 |
|
|
991 |
/* NOTE: the comma operator will make "cond" to eval to false, |
|
992 |
* but float*_is_unordered() is still called. */ |
|
993 |
FOP_COND_D(f, (float64_is_unordered(0, FDT1, FDT0, &env->fp_status), 0)) |
|
994 |
FOP_COND_D(un, float64_is_unordered(0, FDT1, FDT0, &env->fp_status)) |
|
995 |
FOP_COND_D(eq, !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_eq(FDT0, FDT1, &env->fp_status)) |
|
996 |
FOP_COND_D(ueq, float64_is_unordered(0, FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status)) |
|
997 |
FOP_COND_D(olt, !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_lt(FDT0, FDT1, &env->fp_status)) |
|
998 |
FOP_COND_D(ult, float64_is_unordered(0, FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status)) |
|
999 |
FOP_COND_D(ole, !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_le(FDT0, FDT1, &env->fp_status)) |
|
1000 |
FOP_COND_D(ule, float64_is_unordered(0, FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status)) |
|
1001 |
/* NOTE: the comma operator will make "cond" to eval to false, |
|
1002 |
* but float*_is_unordered() is still called. */ |
|
1003 |
FOP_COND_D(sf, (float64_is_unordered(1, FDT1, FDT0, &env->fp_status), 0)) |
|
1004 |
FOP_COND_D(ngle,float64_is_unordered(1, FDT1, FDT0, &env->fp_status)) |
|
1005 |
FOP_COND_D(seq, !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_eq(FDT0, FDT1, &env->fp_status)) |
|
1006 |
FOP_COND_D(ngl, float64_is_unordered(1, FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status)) |
|
1007 |
FOP_COND_D(lt, !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_lt(FDT0, FDT1, &env->fp_status)) |
|
1008 |
FOP_COND_D(nge, float64_is_unordered(1, FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status)) |
|
1009 |
FOP_COND_D(le, !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_le(FDT0, FDT1, &env->fp_status)) |
|
1010 |
FOP_COND_D(ngt, float64_is_unordered(1, FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status)) |
|
1011 |
|
|
1012 |
#define FOP_COND_S(op, cond) \ |
|
1013 |
void do_cmp_s_ ## op (long cc) \ |
|
1014 |
{ \ |
|
1015 |
int c = cond; \ |
|
1016 |
update_fcr31(); \ |
|
1017 |
if (c) \ |
|
1018 |
SET_FP_COND(cc, env); \ |
|
1019 |
else \ |
|
1020 |
CLEAR_FP_COND(cc, env); \ |
|
1021 |
} \ |
|
1022 |
void do_cmpabs_s_ ## op (long cc) \ |
|
1023 |
{ \ |
|
1024 |
int c; \ |
|
1025 |
FST0 &= ~(1 << 31); \ |
|
1026 |
FST1 &= ~(1 << 31); \ |
|
1027 |
c = cond; \ |
|
1028 |
update_fcr31(); \ |
|
1029 |
if (c) \ |
|
1030 |
SET_FP_COND(cc, env); \ |
|
1031 |
else \ |
|
1032 |
CLEAR_FP_COND(cc, env); \ |
|
1033 |
} |
|
1034 |
|
|
1035 |
flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM) |
|
1036 |
{ |
|
1037 |
extern flag float32_is_nan(float32 a); |
|
1038 |
if (float32_is_signaling_nan(a) || |
|
1039 |
float32_is_signaling_nan(b) || |
|
1040 |
(sig && (float32_is_nan(a) || float32_is_nan(b)))) { |
|
1041 |
float_raise(float_flag_invalid, status); |
|
1042 |
return 1; |
|
1043 |
} else if (float32_is_nan(a) || float32_is_nan(b)) { |
|
1044 |
return 1; |
|
1045 |
} else { |
|
1046 |
return 0; |
|
1047 |
} |
|
1048 |
} |
|
1049 |
|
|
1050 |
/* NOTE: the comma operator will make "cond" to eval to false, |
|
1051 |
* but float*_is_unordered() is still called. */ |
|
1052 |
FOP_COND_S(f, (float32_is_unordered(0, FST1, FST0, &env->fp_status), 0)) |
|
1053 |
FOP_COND_S(un, float32_is_unordered(0, FST1, FST0, &env->fp_status)) |
|
1054 |
FOP_COND_S(eq, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status)) |
|
1055 |
FOP_COND_S(ueq, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status)) |
|
1056 |
FOP_COND_S(olt, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status)) |
|
1057 |
FOP_COND_S(ult, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status)) |
|
1058 |
FOP_COND_S(ole, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status)) |
|
1059 |
FOP_COND_S(ule, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status)) |
|
1060 |
/* NOTE: the comma operator will make "cond" to eval to false, |
|
1061 |
* but float*_is_unordered() is still called. */ |
|
1062 |
FOP_COND_S(sf, (float32_is_unordered(1, FST1, FST0, &env->fp_status), 0)) |
|
1063 |
FOP_COND_S(ngle,float32_is_unordered(1, FST1, FST0, &env->fp_status)) |
|
1064 |
FOP_COND_S(seq, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status)) |
|
1065 |
FOP_COND_S(ngl, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status)) |
|
1066 |
FOP_COND_S(lt, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status)) |
|
1067 |
FOP_COND_S(nge, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status)) |
|
1068 |
FOP_COND_S(le, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status)) |
|
1069 |
FOP_COND_S(ngt, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status)) |
|
1070 |
|
|
1071 |
#define FOP_COND_PS(op, condl, condh) \ |
|
1072 |
void do_cmp_ps_ ## op (long cc) \ |
|
1073 |
{ \ |
|
1074 |
int cl = condl; \ |
|
1075 |
int ch = condh; \ |
|
1076 |
update_fcr31(); \ |
|
1077 |
if (cl) \ |
|
1078 |
SET_FP_COND(cc, env); \ |
|
1079 |
else \ |
|
1080 |
CLEAR_FP_COND(cc, env); \ |
|
1081 |
if (ch) \ |
|
1082 |
SET_FP_COND(cc + 1, env); \ |
|
1083 |
else \ |
|
1084 |
CLEAR_FP_COND(cc + 1, env); \ |
|
1085 |
} \ |
|
1086 |
void do_cmpabs_ps_ ## op (long cc) \ |
|
1087 |
{ \ |
|
1088 |
int cl, ch; \ |
|
1089 |
FST0 &= ~(1 << 31); \ |
|
1090 |
FSTH0 &= ~(1 << 31); \ |
|
1091 |
FST1 &= ~(1 << 31); \ |
|
1092 |
FSTH1 &= ~(1 << 31); \ |
|
1093 |
cl = condl; \ |
|
1094 |
ch = condh; \ |
|
1095 |
update_fcr31(); \ |
|
1096 |
if (cl) \ |
|
1097 |
SET_FP_COND(cc, env); \ |
|
1098 |
else \ |
|
1099 |
CLEAR_FP_COND(cc, env); \ |
|
1100 |
if (ch) \ |
|
1101 |
SET_FP_COND(cc + 1, env); \ |
|
1102 |
else \ |
|
1103 |
CLEAR_FP_COND(cc + 1, env); \ |
|
1104 |
} |
|
1105 |
|
|
1106 |
/* NOTE: the comma operator will make "cond" to eval to false, |
|
1107 |
* but float*_is_unordered() is still called. */ |
|
1108 |
FOP_COND_PS(f, (float32_is_unordered(0, FST1, FST0, &env->fp_status), 0), |
|
1109 |
(float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status), 0)) |
|
1110 |
FOP_COND_PS(un, float32_is_unordered(0, FST1, FST0, &env->fp_status), |
|
1111 |
float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status)) |
|
1112 |
FOP_COND_PS(eq, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status), |
|
1113 |
!float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_eq(FSTH0, FSTH1, &env->fp_status)) |
|
1114 |
FOP_COND_PS(ueq, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status), |
|
1115 |
float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) || float32_eq(FSTH0, FSTH1, &env->fp_status)) |
|
1116 |
FOP_COND_PS(olt, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status), |
|
1117 |
!float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_lt(FSTH0, FSTH1, &env->fp_status)) |
|
1118 |
FOP_COND_PS(ult, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status), |
|
1119 |
float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) || float32_lt(FSTH0, FSTH1, &env->fp_status)) |
|
1120 |
FOP_COND_PS(ole, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status), |
|
1121 |
!float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_le(FSTH0, FSTH1, &env->fp_status)) |
|
1122 |
FOP_COND_PS(ule, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status), |
|
1123 |
float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) || float32_le(FSTH0, FSTH1, &env->fp_status)) |
|
1124 |
/* NOTE: the comma operator will make "cond" to eval to false, |
|
1125 |
* but float*_is_unordered() is still called. */ |
|
1126 |
FOP_COND_PS(sf, (float32_is_unordered(1, FST1, FST0, &env->fp_status), 0), |
|
1127 |
(float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status), 0)) |
|
1128 |
FOP_COND_PS(ngle,float32_is_unordered(1, FST1, FST0, &env->fp_status), |
|
1129 |
float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status)) |
|
1130 |
FOP_COND_PS(seq, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status), |
|
1131 |
!float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_eq(FSTH0, FSTH1, &env->fp_status)) |
|
1132 |
FOP_COND_PS(ngl, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status), |
|
1133 |
float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) || float32_eq(FSTH0, FSTH1, &env->fp_status)) |
|
1134 |
FOP_COND_PS(lt, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status), |
|
1135 |
!float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_lt(FSTH0, FSTH1, &env->fp_status)) |
|
1136 |
FOP_COND_PS(nge, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status), |
|
1137 |
float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) || float32_lt(FSTH0, FSTH1, &env->fp_status)) |
|
1138 |
FOP_COND_PS(le, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status), |
|
1139 |
!float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_le(FSTH0, FSTH1, &env->fp_status)) |
|
1140 |
FOP_COND_PS(ngt, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status), |
|
1141 |
float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) || float32_le(FSTH0, FSTH1, &env->fp_status)) |
Also available in: Unified diff