Revision fd4a04eb
b/target-mips/cpu.h | ||
---|---|---|
81 | 81 |
#define FCR0_REV 0 |
82 | 82 |
/* fcsr */ |
83 | 83 |
uint32_t fcr31; |
84 |
#define SET_FP_COND(num,env) do { (env->fcr31) |= ((num) ? (1 << ((num) + 24)) : (1 << ((num) + 23))); } while(0)
|
|
85 |
#define CLEAR_FP_COND(num,env) do { (env->fcr31) &= ~((num) ? (1 << ((num) + 24)) : (1 << ((num) + 23))); } while(0)
|
|
86 |
#define IS_FP_COND_SET(num,env) (((env->fcr31) & ((num) ? (1 << ((num) + 24)) : (1 << ((num) + 23)))) != 0)
|
|
84 |
#define SET_FP_COND(num,env) do { ((env)->fcr31) |= ((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0)
|
|
85 |
#define CLEAR_FP_COND(num,env) do { ((env)->fcr31) &= ~((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0)
|
|
86 |
#define GET_FP_COND(env) ((((env)->fcr31 >> 24) & 0xfe) | (((env)->fcr31 >> 23) & 0x1))
|
|
87 | 87 |
#define GET_FP_CAUSE(reg) (((reg) >> 12) & 0x3f) |
88 | 88 |
#define GET_FP_ENABLE(reg) (((reg) >> 7) & 0x1f) |
89 | 89 |
#define GET_FP_FLAGS(reg) (((reg) >> 2) & 0x1f) |
b/target-mips/exec.h | ||
---|---|---|
165 | 165 |
void cpu_mips_clock_init (CPUState *env); |
166 | 166 |
void cpu_mips_tlb_flush (CPUState *env, int flush_global); |
167 | 167 |
|
168 |
void do_ctc1 (void); |
|
169 |
void do_float_cvtd_s(void); |
|
170 |
void do_float_cvtd_w(void); |
|
171 |
void do_float_cvtd_l(void); |
|
172 |
void do_float_cvtl_d(void); |
|
173 |
void do_float_cvtl_s(void); |
|
174 |
void do_float_cvtps_pw(void); |
|
175 |
void do_float_cvtpw_ps(void); |
|
176 |
void do_float_cvts_d(void); |
|
177 |
void do_float_cvts_w(void); |
|
178 |
void do_float_cvts_l(void); |
|
179 |
void do_float_cvts_pl(void); |
|
180 |
void do_float_cvts_pu(void); |
|
181 |
void do_float_cvtw_s(void); |
|
182 |
void do_float_cvtw_d(void); |
|
183 |
void do_float_roundl_d(void); |
|
184 |
void do_float_roundl_s(void); |
|
185 |
void do_float_roundw_d(void); |
|
186 |
void do_float_roundw_s(void); |
|
187 |
void do_float_truncl_d(void); |
|
188 |
void do_float_truncl_s(void); |
|
189 |
void do_float_truncw_d(void); |
|
190 |
void do_float_truncw_s(void); |
|
191 |
void do_float_ceill_d(void); |
|
192 |
void do_float_ceill_s(void); |
|
193 |
void do_float_ceilw_d(void); |
|
194 |
void do_float_ceilw_s(void); |
|
195 |
void do_float_floorl_d(void); |
|
196 |
void do_float_floorl_s(void); |
|
197 |
void do_float_floorw_d(void); |
|
198 |
void do_float_floorw_s(void); |
|
199 |
void do_float_add_d(void); |
|
200 |
void do_float_add_s(void); |
|
201 |
void do_float_add_ps(void); |
|
202 |
void do_float_sub_d(void); |
|
203 |
void do_float_sub_s(void); |
|
204 |
void do_float_sub_ps(void); |
|
205 |
void do_float_mul_d(void); |
|
206 |
void do_float_mul_s(void); |
|
207 |
void do_float_mul_ps(void); |
|
208 |
void do_float_div_d(void); |
|
209 |
void do_float_div_s(void); |
|
210 |
void do_float_div_ps(void); |
|
211 |
void do_float_addr_ps(void); |
|
212 |
|
|
213 |
#define CMP_OPS(op) \ |
|
214 |
void do_cmp_d_ ## op(long cc); \ |
|
215 |
void do_cmpabs_d_ ## op(long cc); \ |
|
216 |
void do_cmp_s_ ## op(long cc); \ |
|
217 |
void do_cmpabs_s_ ## op(long cc); \ |
|
218 |
void do_cmp_ps_ ## op(long cc); \ |
|
219 |
void do_cmpabs_ps_ ## op(long cc); |
|
220 |
|
|
221 |
CMP_OPS(f) |
|
222 |
CMP_OPS(un) |
|
223 |
CMP_OPS(eq) |
|
224 |
CMP_OPS(ueq) |
|
225 |
CMP_OPS(olt) |
|
226 |
CMP_OPS(ult) |
|
227 |
CMP_OPS(ole) |
|
228 |
CMP_OPS(ule) |
|
229 |
CMP_OPS(sf) |
|
230 |
CMP_OPS(ngle) |
|
231 |
CMP_OPS(seq) |
|
232 |
CMP_OPS(ngl) |
|
233 |
CMP_OPS(lt) |
|
234 |
CMP_OPS(nge) |
|
235 |
CMP_OPS(le) |
|
236 |
CMP_OPS(ngt) |
|
237 |
#undef CMP_OPS |
|
238 |
|
|
168 | 239 |
#endif /* !defined(__QEMU_MIPS_EXEC_H__) */ |
b/target-mips/op.c | ||
---|---|---|
1609 | 1609 |
RETURN(); |
1610 | 1610 |
} |
1611 | 1611 |
|
1612 |
/* convert MIPS rounding mode in FCR31 to IEEE library */ |
|
1613 |
unsigned int ieee_rm[] = { |
|
1614 |
float_round_nearest_even, |
|
1615 |
float_round_to_zero, |
|
1616 |
float_round_up, |
|
1617 |
float_round_down |
|
1618 |
}; |
|
1619 |
|
|
1620 |
#define RESTORE_ROUNDING_MODE \ |
|
1621 |
set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status) |
|
1622 |
|
|
1623 |
inline char ieee_ex_to_mips(char xcpt) |
|
1624 |
{ |
|
1625 |
return (xcpt & float_flag_inexact) >> 5 | |
|
1626 |
(xcpt & float_flag_underflow) >> 3 | |
|
1627 |
(xcpt & float_flag_overflow) >> 1 | |
|
1628 |
(xcpt & float_flag_divbyzero) << 1 | |
|
1629 |
(xcpt & float_flag_invalid) << 4; |
|
1630 |
} |
|
1631 |
|
|
1632 |
inline char mips_ex_to_ieee(char xcpt) |
|
1633 |
{ |
|
1634 |
return (xcpt & FP_INEXACT) << 5 | |
|
1635 |
(xcpt & FP_UNDERFLOW) << 3 | |
|
1636 |
(xcpt & FP_OVERFLOW) << 1 | |
|
1637 |
(xcpt & FP_DIV0) >> 1 | |
|
1638 |
(xcpt & FP_INVALID) >> 4; |
|
1639 |
} |
|
1640 |
|
|
1641 |
inline void update_fcr31(void) |
|
1612 |
/* |
|
1613 |
* Verify if floating point register is valid; an operation is not defined |
|
1614 |
* if bit 0 of any register specification is set and the FR bit in the |
|
1615 |
* Status register equals zero, since the register numbers specify an |
|
1616 |
* even-odd pair of adjacent coprocessor general registers. When the FR bit |
|
1617 |
* in the Status register equals one, both even and odd register numbers |
|
1618 |
* are valid. This limitation exists only for 64 bit wide (d,l,ps) registers. |
|
1619 |
* |
|
1620 |
* Multiple 64 bit wide registers can be checked by calling |
|
1621 |
* gen_op_cp1_registers(freg1 | freg2 | ... | fregN); |
|
1622 |
*/ |
|
1623 |
void op_cp1_registers(void) |
|
1642 | 1624 |
{ |
1643 |
int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->fp_status)); |
|
1644 |
|
|
1645 |
SET_FP_CAUSE(env->fcr31, tmp); |
|
1646 |
if (GET_FP_ENABLE(env->fcr31) & tmp) |
|
1647 |
CALL_FROM_TB1(do_raise_exception, EXCP_FPE); |
|
1648 |
else |
|
1649 |
UPDATE_FP_FLAGS(env->fcr31, tmp); |
|
1625 |
if (!(env->CP0_Status & (1 << CP0St_FR)) && (PARAM1 & 1)) { |
|
1626 |
CALL_FROM_TB1(do_raise_exception, EXCP_RI); |
|
1627 |
} |
|
1628 |
RETURN(); |
|
1650 | 1629 |
} |
1651 | 1630 |
|
1652 |
|
|
1653 | 1631 |
void op_cfc1 (void) |
1654 | 1632 |
{ |
1655 | 1633 |
switch (T1) { |
... | ... | |
1675 | 1653 |
|
1676 | 1654 |
void op_ctc1 (void) |
1677 | 1655 |
{ |
1678 |
switch(T1) { |
|
1679 |
case 25: |
|
1680 |
if (T0 & 0xffffff00) |
|
1681 |
goto leave; |
|
1682 |
env->fcr31 = (env->fcr31 & 0x017fffff) | ((T0 & 0xfe) << 24) | |
|
1683 |
((T0 & 0x1) << 23); |
|
1684 |
break; |
|
1685 |
case 26: |
|
1686 |
if (T0 & 0x007c0000) |
|
1687 |
goto leave; |
|
1688 |
env->fcr31 = (env->fcr31 & 0xfffc0f83) | (T0 & 0x0003f07c); |
|
1689 |
break; |
|
1690 |
case 28: |
|
1691 |
if (T0 & 0x007c0000) |
|
1692 |
goto leave; |
|
1693 |
env->fcr31 = (env->fcr31 & 0xfefff07c) | (T0 & 0x00000f83) | |
|
1694 |
((T0 & 0x4) << 22); |
|
1695 |
break; |
|
1696 |
case 31: |
|
1697 |
if (T0 & 0x007c0000) |
|
1698 |
goto leave; |
|
1699 |
env->fcr31 = T0; |
|
1700 |
break; |
|
1701 |
default: |
|
1702 |
goto leave; |
|
1703 |
} |
|
1704 |
/* set rounding mode */ |
|
1705 |
RESTORE_ROUNDING_MODE; |
|
1706 |
set_float_exception_flags(0, &env->fp_status); |
|
1707 |
if ((GET_FP_ENABLE(env->fcr31) | 0x20) & GET_FP_CAUSE(env->fcr31)) |
|
1708 |
CALL_FROM_TB1(do_raise_exception, EXCP_FPE); |
|
1709 |
leave: |
|
1656 |
CALL_FROM_TB0(do_ctc1); |
|
1710 | 1657 |
DEBUG_FPU_STATE(); |
1711 | 1658 |
RETURN(); |
1712 | 1659 |
} |
... | ... | |
1762 | 1709 |
|
1763 | 1710 |
FLOAT_OP(cvtd, s) |
1764 | 1711 |
{ |
1765 |
set_float_exception_flags(0, &env->fp_status); |
|
1766 |
FDT2 = float32_to_float64(FST0, &env->fp_status); |
|
1767 |
update_fcr31(); |
|
1712 |
CALL_FROM_TB0(do_float_cvtd_s); |
|
1768 | 1713 |
DEBUG_FPU_STATE(); |
1769 | 1714 |
RETURN(); |
1770 | 1715 |
} |
1771 | 1716 |
FLOAT_OP(cvtd, w) |
1772 | 1717 |
{ |
1773 |
set_float_exception_flags(0, &env->fp_status); |
|
1774 |
FDT2 = int32_to_float64(WT0, &env->fp_status); |
|
1775 |
update_fcr31(); |
|
1718 |
CALL_FROM_TB0(do_float_cvtd_w); |
|
1776 | 1719 |
DEBUG_FPU_STATE(); |
1777 | 1720 |
RETURN(); |
1778 | 1721 |
} |
1779 | 1722 |
FLOAT_OP(cvtd, l) |
1780 | 1723 |
{ |
1781 |
set_float_exception_flags(0, &env->fp_status); |
|
1782 |
FDT2 = int64_to_float64(DT0, &env->fp_status); |
|
1783 |
update_fcr31(); |
|
1724 |
CALL_FROM_TB0(do_float_cvtd_l); |
|
1784 | 1725 |
DEBUG_FPU_STATE(); |
1785 | 1726 |
RETURN(); |
1786 | 1727 |
} |
1787 | 1728 |
FLOAT_OP(cvtl, d) |
1788 | 1729 |
{ |
1789 |
set_float_exception_flags(0, &env->fp_status); |
|
1790 |
DT2 = float64_to_int64(FDT0, &env->fp_status); |
|
1791 |
update_fcr31(); |
|
1792 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
1793 |
DT2 = 0x7fffffffffffffffULL; |
|
1730 |
CALL_FROM_TB0(do_float_cvtl_d); |
|
1794 | 1731 |
DEBUG_FPU_STATE(); |
1795 | 1732 |
RETURN(); |
1796 | 1733 |
} |
1797 | 1734 |
FLOAT_OP(cvtl, s) |
1798 | 1735 |
{ |
1799 |
set_float_exception_flags(0, &env->fp_status); |
|
1800 |
DT2 = float32_to_int64(FST0, &env->fp_status); |
|
1801 |
update_fcr31(); |
|
1802 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
1803 |
DT2 = 0x7fffffffffffffffULL; |
|
1736 |
CALL_FROM_TB0(do_float_cvtl_s); |
|
1804 | 1737 |
DEBUG_FPU_STATE(); |
1805 | 1738 |
RETURN(); |
1806 | 1739 |
} |
... | ... | |
1813 | 1746 |
} |
1814 | 1747 |
FLOAT_OP(cvtps, pw) |
1815 | 1748 |
{ |
1816 |
set_float_exception_flags(0, &env->fp_status); |
|
1817 |
FST2 = int32_to_float32(WT0, &env->fp_status); |
|
1818 |
FSTH2 = int32_to_float32(WTH0, &env->fp_status); |
|
1819 |
update_fcr31(); |
|
1749 |
CALL_FROM_TB0(do_float_cvtps_pw); |
|
1820 | 1750 |
DEBUG_FPU_STATE(); |
1821 | 1751 |
RETURN(); |
1822 | 1752 |
} |
1823 | 1753 |
FLOAT_OP(cvtpw, ps) |
1824 | 1754 |
{ |
1825 |
set_float_exception_flags(0, &env->fp_status); |
|
1826 |
WT2 = float32_to_int32(FST0, &env->fp_status); |
|
1827 |
WTH2 = float32_to_int32(FSTH0, &env->fp_status); |
|
1828 |
update_fcr31(); |
|
1829 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
1830 |
WT2 = 0x7fffffff; |
|
1755 |
CALL_FROM_TB0(do_float_cvtpw_ps); |
|
1831 | 1756 |
DEBUG_FPU_STATE(); |
1832 | 1757 |
RETURN(); |
1833 | 1758 |
} |
1834 | 1759 |
FLOAT_OP(cvts, d) |
1835 | 1760 |
{ |
1836 |
set_float_exception_flags(0, &env->fp_status); |
|
1837 |
FST2 = float64_to_float32(FDT0, &env->fp_status); |
|
1838 |
update_fcr31(); |
|
1761 |
CALL_FROM_TB0(do_float_cvts_d); |
|
1839 | 1762 |
DEBUG_FPU_STATE(); |
1840 | 1763 |
RETURN(); |
1841 | 1764 |
} |
1842 | 1765 |
FLOAT_OP(cvts, w) |
1843 | 1766 |
{ |
1844 |
set_float_exception_flags(0, &env->fp_status); |
|
1845 |
FST2 = int32_to_float32(WT0, &env->fp_status); |
|
1846 |
update_fcr31(); |
|
1767 |
CALL_FROM_TB0(do_float_cvts_w); |
|
1847 | 1768 |
DEBUG_FPU_STATE(); |
1848 | 1769 |
RETURN(); |
1849 | 1770 |
} |
1850 | 1771 |
FLOAT_OP(cvts, l) |
1851 | 1772 |
{ |
1852 |
set_float_exception_flags(0, &env->fp_status); |
|
1853 |
FST2 = int64_to_float32(DT0, &env->fp_status); |
|
1854 |
update_fcr31(); |
|
1773 |
CALL_FROM_TB0(do_float_cvts_l); |
|
1855 | 1774 |
DEBUG_FPU_STATE(); |
1856 | 1775 |
RETURN(); |
1857 | 1776 |
} |
1858 | 1777 |
FLOAT_OP(cvts, pl) |
1859 | 1778 |
{ |
1860 |
set_float_exception_flags(0, &env->fp_status); |
|
1861 |
WT2 = WT0; |
|
1862 |
update_fcr31(); |
|
1779 |
CALL_FROM_TB0(do_float_cvts_pl); |
|
1863 | 1780 |
DEBUG_FPU_STATE(); |
1864 | 1781 |
RETURN(); |
1865 | 1782 |
} |
1866 | 1783 |
FLOAT_OP(cvts, pu) |
1867 | 1784 |
{ |
1868 |
set_float_exception_flags(0, &env->fp_status); |
|
1869 |
WT2 = WTH0; |
|
1870 |
update_fcr31(); |
|
1785 |
CALL_FROM_TB0(do_float_cvts_pu); |
|
1871 | 1786 |
DEBUG_FPU_STATE(); |
1872 | 1787 |
RETURN(); |
1873 | 1788 |
} |
1874 | 1789 |
FLOAT_OP(cvtw, s) |
1875 | 1790 |
{ |
1876 |
set_float_exception_flags(0, &env->fp_status); |
|
1877 |
WT2 = float32_to_int32(FST0, &env->fp_status); |
|
1878 |
update_fcr31(); |
|
1879 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
1880 |
WT2 = 0x7fffffff; |
|
1791 |
CALL_FROM_TB0(do_float_cvtw_s); |
|
1881 | 1792 |
DEBUG_FPU_STATE(); |
1882 | 1793 |
RETURN(); |
1883 | 1794 |
} |
1884 | 1795 |
FLOAT_OP(cvtw, d) |
1885 | 1796 |
{ |
1886 |
set_float_exception_flags(0, &env->fp_status); |
|
1887 |
WT2 = float64_to_int32(FDT0, &env->fp_status); |
|
1888 |
update_fcr31(); |
|
1889 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
1890 |
WT2 = 0x7fffffff; |
|
1797 |
CALL_FROM_TB0(do_float_cvtw_d); |
|
1891 | 1798 |
DEBUG_FPU_STATE(); |
1892 | 1799 |
RETURN(); |
1893 | 1800 |
} |
... | ... | |
1917 | 1824 |
RETURN(); |
1918 | 1825 |
} |
1919 | 1826 |
|
1920 |
FLOAT_OP(roundl, d) |
|
1921 |
{ |
|
1922 |
set_float_rounding_mode(float_round_nearest_even, &env->fp_status); |
|
1923 |
DT2 = float64_round_to_int(FDT0, &env->fp_status); |
|
1924 |
RESTORE_ROUNDING_MODE; |
|
1925 |
update_fcr31(); |
|
1926 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
1927 |
DT2 = 0x7fffffffffffffffULL; |
|
1928 |
DEBUG_FPU_STATE(); |
|
1929 |
RETURN(); |
|
1930 |
} |
|
1931 |
FLOAT_OP(roundl, s) |
|
1932 |
{ |
|
1933 |
set_float_rounding_mode(float_round_nearest_even, &env->fp_status); |
|
1934 |
DT2 = float32_round_to_int(FST0, &env->fp_status); |
|
1935 |
RESTORE_ROUNDING_MODE; |
|
1936 |
update_fcr31(); |
|
1937 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
1938 |
DT2 = 0x7fffffffffffffffULL; |
|
1939 |
DEBUG_FPU_STATE(); |
|
1940 |
RETURN(); |
|
1941 |
} |
|
1942 |
FLOAT_OP(roundw, d) |
|
1943 |
{ |
|
1944 |
set_float_rounding_mode(float_round_nearest_even, &env->fp_status); |
|
1945 |
WT2 = float64_round_to_int(FDT0, &env->fp_status); |
|
1946 |
RESTORE_ROUNDING_MODE; |
|
1947 |
update_fcr31(); |
|
1948 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
1949 |
WT2 = 0x7fffffff; |
|
1950 |
DEBUG_FPU_STATE(); |
|
1951 |
RETURN(); |
|
1952 |
} |
|
1953 |
FLOAT_OP(roundw, s) |
|
1954 |
{ |
|
1955 |
set_float_rounding_mode(float_round_nearest_even, &env->fp_status); |
|
1956 |
WT2 = float32_round_to_int(FST0, &env->fp_status); |
|
1957 |
RESTORE_ROUNDING_MODE; |
|
1958 |
update_fcr31(); |
|
1959 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
1960 |
WT2 = 0x7fffffff; |
|
1961 |
DEBUG_FPU_STATE(); |
|
1962 |
RETURN(); |
|
1827 |
#define FLOAT_ROUNDOP(op, ttype, stype) \ |
|
1828 |
FLOAT_OP(op ## ttype, stype) \ |
|
1829 |
{ \ |
|
1830 |
CALL_FROM_TB0(do_float_ ## op ## ttype ## _ ## stype); \ |
|
1831 |
DEBUG_FPU_STATE(); \ |
|
1832 |
RETURN(); \ |
|
1963 | 1833 |
} |
1964 | 1834 |
|
1965 |
FLOAT_OP(truncl, d) |
|
1966 |
{ |
|
1967 |
DT2 = float64_to_int64_round_to_zero(FDT0, &env->fp_status); |
|
1968 |
update_fcr31(); |
|
1969 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
1970 |
DT2 = 0x7fffffffffffffffULL; |
|
1971 |
DEBUG_FPU_STATE(); |
|
1972 |
RETURN(); |
|
1973 |
} |
|
1974 |
FLOAT_OP(truncl, s) |
|
1975 |
{ |
|
1976 |
DT2 = float32_to_int64_round_to_zero(FST0, &env->fp_status); |
|
1977 |
update_fcr31(); |
|
1978 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
1979 |
DT2 = 0x7fffffffffffffffULL; |
|
1980 |
DEBUG_FPU_STATE(); |
|
1981 |
RETURN(); |
|
1982 |
} |
|
1983 |
FLOAT_OP(truncw, d) |
|
1984 |
{ |
|
1985 |
WT2 = float64_to_int32_round_to_zero(FDT0, &env->fp_status); |
|
1986 |
update_fcr31(); |
|
1987 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
1988 |
WT2 = 0x7fffffff; |
|
1989 |
DEBUG_FPU_STATE(); |
|
1990 |
RETURN(); |
|
1991 |
} |
|
1992 |
FLOAT_OP(truncw, s) |
|
1993 |
{ |
|
1994 |
WT2 = float32_to_int32_round_to_zero(FST0, &env->fp_status); |
|
1995 |
update_fcr31(); |
|
1996 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
1997 |
WT2 = 0x7fffffff; |
|
1998 |
DEBUG_FPU_STATE(); |
|
1999 |
RETURN(); |
|
2000 |
} |
|
1835 |
FLOAT_ROUNDOP(round, l, d) |
|
1836 |
FLOAT_ROUNDOP(round, l, s) |
|
1837 |
FLOAT_ROUNDOP(round, w, d) |
|
1838 |
FLOAT_ROUNDOP(round, w, s) |
|
2001 | 1839 |
|
2002 |
FLOAT_OP(ceill, d) |
|
2003 |
{ |
|
2004 |
set_float_rounding_mode(float_round_up, &env->fp_status); |
|
2005 |
DT2 = float64_round_to_int(FDT0, &env->fp_status); |
|
2006 |
RESTORE_ROUNDING_MODE; |
|
2007 |
update_fcr31(); |
|
2008 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
2009 |
DT2 = 0x7fffffffffffffffULL; |
|
2010 |
DEBUG_FPU_STATE(); |
|
2011 |
RETURN(); |
|
2012 |
} |
|
2013 |
FLOAT_OP(ceill, s) |
|
2014 |
{ |
|
2015 |
set_float_rounding_mode(float_round_up, &env->fp_status); |
|
2016 |
DT2 = float32_round_to_int(FST0, &env->fp_status); |
|
2017 |
RESTORE_ROUNDING_MODE; |
|
2018 |
update_fcr31(); |
|
2019 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
2020 |
DT2 = 0x7fffffffffffffffULL; |
|
2021 |
DEBUG_FPU_STATE(); |
|
2022 |
RETURN(); |
|
2023 |
} |
|
2024 |
FLOAT_OP(ceilw, d) |
|
2025 |
{ |
|
2026 |
set_float_rounding_mode(float_round_up, &env->fp_status); |
|
2027 |
WT2 = float64_round_to_int(FDT0, &env->fp_status); |
|
2028 |
RESTORE_ROUNDING_MODE; |
|
2029 |
update_fcr31(); |
|
2030 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
2031 |
WT2 = 0x7fffffff; |
|
2032 |
DEBUG_FPU_STATE(); |
|
2033 |
RETURN(); |
|
2034 |
} |
|
2035 |
FLOAT_OP(ceilw, s) |
|
2036 |
{ |
|
2037 |
set_float_rounding_mode(float_round_up, &env->fp_status); |
|
2038 |
WT2 = float32_round_to_int(FST0, &env->fp_status); |
|
2039 |
RESTORE_ROUNDING_MODE; |
|
2040 |
update_fcr31(); |
|
2041 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
2042 |
WT2 = 0x7fffffff; |
|
2043 |
DEBUG_FPU_STATE(); |
|
2044 |
RETURN(); |
|
2045 |
} |
|
1840 |
FLOAT_ROUNDOP(trunc, l, d) |
|
1841 |
FLOAT_ROUNDOP(trunc, l, s) |
|
1842 |
FLOAT_ROUNDOP(trunc, w, d) |
|
1843 |
FLOAT_ROUNDOP(trunc, w, s) |
|
2046 | 1844 |
|
2047 |
FLOAT_OP(floorl, d) |
|
2048 |
{ |
|
2049 |
set_float_rounding_mode(float_round_down, &env->fp_status); |
|
2050 |
DT2 = float64_round_to_int(FDT0, &env->fp_status); |
|
2051 |
RESTORE_ROUNDING_MODE; |
|
2052 |
update_fcr31(); |
|
2053 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
2054 |
DT2 = 0x7fffffffffffffffULL; |
|
2055 |
DEBUG_FPU_STATE(); |
|
2056 |
RETURN(); |
|
2057 |
} |
|
2058 |
FLOAT_OP(floorl, s) |
|
2059 |
{ |
|
2060 |
set_float_rounding_mode(float_round_down, &env->fp_status); |
|
2061 |
DT2 = float32_round_to_int(FST0, &env->fp_status); |
|
2062 |
RESTORE_ROUNDING_MODE; |
|
2063 |
update_fcr31(); |
|
2064 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
2065 |
DT2 = 0x7fffffffffffffffULL; |
|
2066 |
DEBUG_FPU_STATE(); |
|
2067 |
RETURN(); |
|
2068 |
} |
|
2069 |
FLOAT_OP(floorw, d) |
|
2070 |
{ |
|
2071 |
set_float_rounding_mode(float_round_down, &env->fp_status); |
|
2072 |
WT2 = float64_round_to_int(FDT0, &env->fp_status); |
|
2073 |
RESTORE_ROUNDING_MODE; |
|
2074 |
update_fcr31(); |
|
2075 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
2076 |
WT2 = 0x7fffffff; |
|
2077 |
DEBUG_FPU_STATE(); |
|
2078 |
RETURN(); |
|
2079 |
} |
|
2080 |
FLOAT_OP(floorw, s) |
|
2081 |
{ |
|
2082 |
set_float_rounding_mode(float_round_down, &env->fp_status); |
|
2083 |
WT2 = float32_round_to_int(FST0, &env->fp_status); |
|
2084 |
RESTORE_ROUNDING_MODE; |
|
2085 |
update_fcr31(); |
|
2086 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
2087 |
WT2 = 0x7fffffff; |
|
2088 |
DEBUG_FPU_STATE(); |
|
2089 |
RETURN(); |
|
2090 |
} |
|
1845 |
FLOAT_ROUNDOP(ceil, l, d) |
|
1846 |
FLOAT_ROUNDOP(ceil, l, s) |
|
1847 |
FLOAT_ROUNDOP(ceil, w, d) |
|
1848 |
FLOAT_ROUNDOP(ceil, w, s) |
|
1849 |
|
|
1850 |
FLOAT_ROUNDOP(floor, l, d) |
|
1851 |
FLOAT_ROUNDOP(floor, l, s) |
|
1852 |
FLOAT_ROUNDOP(floor, w, d) |
|
1853 |
FLOAT_ROUNDOP(floor, w, s) |
|
1854 |
#undef FLOAR_ROUNDOP |
|
2091 | 1855 |
|
2092 | 1856 |
FLOAT_OP(movf, d) |
2093 | 1857 |
{ |
... | ... | |
2186 | 1950 |
#define FLOAT_BINOP(name) \ |
2187 | 1951 |
FLOAT_OP(name, d) \ |
2188 | 1952 |
{ \ |
2189 |
set_float_exception_flags(0, &env->fp_status); \ |
|
2190 |
FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status); \ |
|
2191 |
update_fcr31(); \ |
|
1953 |
CALL_FROM_TB0(do_float_ ## name ## _d); \ |
|
2192 | 1954 |
DEBUG_FPU_STATE(); \ |
2193 | 1955 |
RETURN(); \ |
2194 | 1956 |
} \ |
2195 | 1957 |
FLOAT_OP(name, s) \ |
2196 | 1958 |
{ \ |
2197 |
set_float_exception_flags(0, &env->fp_status); \ |
|
2198 |
FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \ |
|
2199 |
update_fcr31(); \ |
|
1959 |
CALL_FROM_TB0(do_float_ ## name ## _s); \ |
|
2200 | 1960 |
DEBUG_FPU_STATE(); \ |
2201 | 1961 |
RETURN(); \ |
2202 | 1962 |
} \ |
2203 | 1963 |
FLOAT_OP(name, ps) \ |
2204 | 1964 |
{ \ |
2205 |
set_float_exception_flags(0, &env->fp_status); \ |
|
2206 |
FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \ |
|
2207 |
FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fp_status); \ |
|
2208 |
update_fcr31(); \ |
|
1965 |
CALL_FROM_TB0(do_float_ ## name ## _ps); \ |
|
2209 | 1966 |
DEBUG_FPU_STATE(); \ |
2210 | 1967 |
RETURN(); \ |
2211 | 1968 |
} |
... | ... | |
2217 | 1974 |
|
2218 | 1975 |
FLOAT_OP(addr, ps) |
2219 | 1976 |
{ |
2220 |
set_float_exception_flags(0, &env->fp_status); |
|
2221 |
FST2 = float32_add (FST0, FSTH0, &env->fp_status); |
|
2222 |
FSTH2 = float32_add (FST1, FSTH1, &env->fp_status); |
|
2223 |
update_fcr31(); |
|
1977 |
CALL_FROM_TB0(do_float_addr_ps); |
|
2224 | 1978 |
DEBUG_FPU_STATE(); |
2225 | 1979 |
RETURN(); |
2226 | 1980 |
} |
... | ... | |
2390 | 2144 |
|
2391 | 2145 |
extern void dump_fpu_s(CPUState *env); |
2392 | 2146 |
|
2393 |
#define FOP_COND_D(op, cond) \ |
|
2394 |
void op_cmp_d_ ## op (void) \ |
|
2395 |
{ \ |
|
2396 |
int c = cond; \ |
|
2397 |
update_fcr31(); \ |
|
2398 |
if (c) \ |
|
2399 |
SET_FP_COND(PARAM1, env); \ |
|
2400 |
else \ |
|
2401 |
CLEAR_FP_COND(PARAM1, env); \ |
|
2402 |
DEBUG_FPU_STATE(); \ |
|
2403 |
RETURN(); \ |
|
2404 |
} \ |
|
2405 |
void op_cmpabs_d_ ## op (void) \ |
|
2406 |
{ \ |
|
2407 |
int c; \ |
|
2408 |
FDT0 &= ~(1ULL << 63); \ |
|
2409 |
FDT1 &= ~(1ULL << 63); \ |
|
2410 |
c = cond; \ |
|
2411 |
update_fcr31(); \ |
|
2412 |
if (c) \ |
|
2413 |
SET_FP_COND(PARAM1, env); \ |
|
2414 |
else \ |
|
2415 |
CLEAR_FP_COND(PARAM1, env); \ |
|
2416 |
DEBUG_FPU_STATE(); \ |
|
2417 |
RETURN(); \ |
|
2418 |
} |
|
2419 |
|
|
2420 |
int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM) |
|
2421 |
{ |
|
2422 |
if (float64_is_signaling_nan(a) || |
|
2423 |
float64_is_signaling_nan(b) || |
|
2424 |
(sig && (float64_is_nan(a) || float64_is_nan(b)))) { |
|
2425 |
float_raise(float_flag_invalid, status); |
|
2426 |
return 1; |
|
2427 |
} else if (float64_is_nan(a) || float64_is_nan(b)) { |
|
2428 |
return 1; |
|
2429 |
} else { |
|
2430 |
return 0; |
|
2431 |
} |
|
2432 |
} |
|
2433 |
|
|
2434 |
/* NOTE: the comma operator will make "cond" to eval to false, |
|
2435 |
* but float*_is_unordered() is still called. */ |
|
2436 |
FOP_COND_D(f, (float64_is_unordered(0, FDT1, FDT0, &env->fp_status), 0)) |
|
2437 |
FOP_COND_D(un, float64_is_unordered(0, FDT1, FDT0, &env->fp_status)) |
|
2438 |
FOP_COND_D(eq, !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_eq(FDT0, FDT1, &env->fp_status)) |
|
2439 |
FOP_COND_D(ueq, float64_is_unordered(0, FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status)) |
|
2440 |
FOP_COND_D(olt, !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_lt(FDT0, FDT1, &env->fp_status)) |
|
2441 |
FOP_COND_D(ult, float64_is_unordered(0, FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status)) |
|
2442 |
FOP_COND_D(ole, !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_le(FDT0, FDT1, &env->fp_status)) |
|
2443 |
FOP_COND_D(ule, float64_is_unordered(0, FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status)) |
|
2444 |
/* NOTE: the comma operator will make "cond" to eval to false, |
|
2445 |
* but float*_is_unordered() is still called. */ |
|
2446 |
FOP_COND_D(sf, (float64_is_unordered(1, FDT1, FDT0, &env->fp_status), 0)) |
|
2447 |
FOP_COND_D(ngle,float64_is_unordered(1, FDT1, FDT0, &env->fp_status)) |
|
2448 |
FOP_COND_D(seq, !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_eq(FDT0, FDT1, &env->fp_status)) |
|
2449 |
FOP_COND_D(ngl, float64_is_unordered(1, FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status)) |
|
2450 |
FOP_COND_D(lt, !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_lt(FDT0, FDT1, &env->fp_status)) |
|
2451 |
FOP_COND_D(nge, float64_is_unordered(1, FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status)) |
|
2452 |
FOP_COND_D(le, !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_le(FDT0, FDT1, &env->fp_status)) |
|
2453 |
FOP_COND_D(ngt, float64_is_unordered(1, FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status)) |
|
2454 |
|
|
2455 |
#define FOP_COND_S(op, cond) \ |
|
2456 |
void op_cmp_s_ ## op (void) \ |
|
2457 |
{ \ |
|
2458 |
int c = cond; \ |
|
2459 |
update_fcr31(); \ |
|
2460 |
if (c) \ |
|
2461 |
SET_FP_COND(PARAM1, env); \ |
|
2462 |
else \ |
|
2463 |
CLEAR_FP_COND(PARAM1, env); \ |
|
2464 |
DEBUG_FPU_STATE(); \ |
|
2465 |
RETURN(); \ |
|
2466 |
} \ |
|
2467 |
void op_cmpabs_s_ ## op (void) \ |
|
2468 |
{ \ |
|
2469 |
int c; \ |
|
2470 |
FST0 &= ~(1 << 31); \ |
|
2471 |
FST1 &= ~(1 << 31); \ |
|
2472 |
c = cond; \ |
|
2473 |
update_fcr31(); \ |
|
2474 |
if (c) \ |
|
2475 |
SET_FP_COND(PARAM1, env); \ |
|
2476 |
else \ |
|
2477 |
CLEAR_FP_COND(PARAM1, env); \ |
|
2478 |
DEBUG_FPU_STATE(); \ |
|
2479 |
RETURN(); \ |
|
2480 |
} |
|
2481 |
|
|
2482 |
flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM) |
|
2483 |
{ |
|
2484 |
extern flag float32_is_nan(float32 a); |
|
2485 |
if (float32_is_signaling_nan(a) || |
|
2486 |
float32_is_signaling_nan(b) || |
|
2487 |
(sig && (float32_is_nan(a) || float32_is_nan(b)))) { |
|
2488 |
float_raise(float_flag_invalid, status); |
|
2489 |
return 1; |
|
2490 |
} else if (float32_is_nan(a) || float32_is_nan(b)) { |
|
2491 |
return 1; |
|
2492 |
} else { |
|
2493 |
return 0; |
|
2494 |
} |
|
2495 |
} |
|
2496 |
|
|
2497 |
/* NOTE: the comma operator will make "cond" to eval to false, |
|
2498 |
* but float*_is_unordered() is still called. */ |
|
2499 |
FOP_COND_S(f, (float32_is_unordered(0, FST1, FST0, &env->fp_status), 0)) |
|
2500 |
FOP_COND_S(un, float32_is_unordered(0, FST1, FST0, &env->fp_status)) |
|
2501 |
FOP_COND_S(eq, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status)) |
|
2502 |
FOP_COND_S(ueq, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status)) |
|
2503 |
FOP_COND_S(olt, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status)) |
|
2504 |
FOP_COND_S(ult, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status)) |
|
2505 |
FOP_COND_S(ole, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status)) |
|
2506 |
FOP_COND_S(ule, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status)) |
|
2507 |
/* NOTE: the comma operator will make "cond" to eval to false, |
|
2508 |
* but float*_is_unordered() is still called. */ |
|
2509 |
FOP_COND_S(sf, (float32_is_unordered(1, FST1, FST0, &env->fp_status), 0)) |
|
2510 |
FOP_COND_S(ngle,float32_is_unordered(1, FST1, FST0, &env->fp_status)) |
|
2511 |
FOP_COND_S(seq, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status)) |
|
2512 |
FOP_COND_S(ngl, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status)) |
|
2513 |
FOP_COND_S(lt, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status)) |
|
2514 |
FOP_COND_S(nge, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status)) |
|
2515 |
FOP_COND_S(le, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status)) |
|
2516 |
FOP_COND_S(ngt, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status)) |
|
2517 |
|
|
2518 |
#define FOP_COND_PS(op, condl, condh) \ |
|
2519 |
void op_cmp_ps_ ## op (void) \ |
|
2520 |
{ \ |
|
2521 |
int cl = condl; \ |
|
2522 |
int ch = condh; \ |
|
2523 |
update_fcr31(); \ |
|
2524 |
if (cl) \ |
|
2525 |
SET_FP_COND(PARAM1, env); \ |
|
2526 |
else \ |
|
2527 |
CLEAR_FP_COND(PARAM1, env); \ |
|
2528 |
if (ch) \ |
|
2529 |
SET_FP_COND(PARAM1 + 1, env); \ |
|
2530 |
else \ |
|
2531 |
CLEAR_FP_COND(PARAM1 + 1, env); \ |
|
2532 |
DEBUG_FPU_STATE(); \ |
|
2533 |
RETURN(); \ |
|
2534 |
} \ |
|
2535 |
void op_cmpabs_ps_ ## op (void) \ |
|
2536 |
{ \ |
|
2537 |
int cl, ch; \ |
|
2538 |
FST0 &= ~(1 << 31); \ |
|
2539 |
FSTH0 &= ~(1 << 31); \ |
|
2540 |
FST1 &= ~(1 << 31); \ |
|
2541 |
FSTH1 &= ~(1 << 31); \ |
|
2542 |
cl = condl; \ |
|
2543 |
ch = condh; \ |
|
2544 |
update_fcr31(); \ |
|
2545 |
if (cl) \ |
|
2546 |
SET_FP_COND(PARAM1, env); \ |
|
2547 |
else \ |
|
2548 |
CLEAR_FP_COND(PARAM1, env); \ |
|
2549 |
if (ch) \ |
|
2550 |
SET_FP_COND(PARAM1 + 1, env); \ |
|
2551 |
else \ |
|
2552 |
CLEAR_FP_COND(PARAM1 + 1, env); \ |
|
2553 |
DEBUG_FPU_STATE(); \ |
|
2554 |
RETURN(); \ |
|
2555 |
} |
|
2556 |
|
|
2557 |
/* NOTE: the comma operator will make "cond" to eval to false, |
|
2558 |
* but float*_is_unordered() is still called. */ |
|
2559 |
FOP_COND_PS(f, (float32_is_unordered(0, FST1, FST0, &env->fp_status), 0), |
|
2560 |
(float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status), 0)) |
|
2561 |
FOP_COND_PS(un, float32_is_unordered(0, FST1, FST0, &env->fp_status), |
|
2562 |
float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status)) |
|
2563 |
FOP_COND_PS(eq, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status), |
|
2564 |
!float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_eq(FSTH0, FSTH1, &env->fp_status)) |
|
2565 |
FOP_COND_PS(ueq, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status), |
|
2566 |
float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) || float32_eq(FSTH0, FSTH1, &env->fp_status)) |
|
2567 |
FOP_COND_PS(olt, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status), |
|
2568 |
!float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_lt(FSTH0, FSTH1, &env->fp_status)) |
|
2569 |
FOP_COND_PS(ult, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status), |
|
2570 |
float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) || float32_lt(FSTH0, FSTH1, &env->fp_status)) |
|
2571 |
FOP_COND_PS(ole, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status), |
|
2572 |
!float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_le(FSTH0, FSTH1, &env->fp_status)) |
|
2573 |
FOP_COND_PS(ule, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status), |
|
2574 |
float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) || float32_le(FSTH0, FSTH1, &env->fp_status)) |
|
2575 |
/* NOTE: the comma operator will make "cond" to eval to false, |
|
2576 |
* but float*_is_unordered() is still called. */ |
|
2577 |
FOP_COND_PS(sf, (float32_is_unordered(1, FST1, FST0, &env->fp_status), 0), |
|
2578 |
(float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status), 0)) |
|
2579 |
FOP_COND_PS(ngle,float32_is_unordered(1, FST1, FST0, &env->fp_status), |
|
2580 |
float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status)) |
|
2581 |
FOP_COND_PS(seq, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status), |
|
2582 |
!float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_eq(FSTH0, FSTH1, &env->fp_status)) |
|
2583 |
FOP_COND_PS(ngl, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status), |
|
2584 |
float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) || float32_eq(FSTH0, FSTH1, &env->fp_status)) |
|
2585 |
FOP_COND_PS(lt, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status), |
|
2586 |
!float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_lt(FSTH0, FSTH1, &env->fp_status)) |
|
2587 |
FOP_COND_PS(nge, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status), |
|
2588 |
float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) || float32_lt(FSTH0, FSTH1, &env->fp_status)) |
|
2589 |
FOP_COND_PS(le, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status), |
|
2590 |
!float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_le(FSTH0, FSTH1, &env->fp_status)) |
|
2591 |
FOP_COND_PS(ngt, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status), |
|
2592 |
float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) || float32_le(FSTH0, FSTH1, &env->fp_status)) |
|
2147 |
#define CMP_OP(fmt, op) \ |
|
2148 |
void OPPROTO op_cmp ## _ ## fmt ## _ ## op(void) \ |
|
2149 |
{ \ |
|
2150 |
CALL_FROM_TB1(do_cmp ## _ ## fmt ## _ ## op, PARAM1); \ |
|
2151 |
DEBUG_FPU_STATE(); \ |
|
2152 |
RETURN(); \ |
|
2153 |
} \ |
|
2154 |
void OPPROTO op_cmpabs ## _ ## fmt ## _ ## op(void) \ |
|
2155 |
{ \ |
|
2156 |
CALL_FROM_TB1(do_cmpabs ## _ ## fmt ## _ ## op, PARAM1); \ |
|
2157 |
DEBUG_FPU_STATE(); \ |
|
2158 |
RETURN(); \ |
|
2159 |
} |
|
2160 |
#define CMP_OPS(op) \ |
|
2161 |
CMP_OP(d, op) \ |
|
2162 |
CMP_OP(s, op) \ |
|
2163 |
CMP_OP(ps, op) |
|
2164 |
|
|
2165 |
CMP_OPS(f) |
|
2166 |
CMP_OPS(un) |
|
2167 |
CMP_OPS(eq) |
|
2168 |
CMP_OPS(ueq) |
|
2169 |
CMP_OPS(olt) |
|
2170 |
CMP_OPS(ult) |
|
2171 |
CMP_OPS(ole) |
|
2172 |
CMP_OPS(ule) |
|
2173 |
CMP_OPS(sf) |
|
2174 |
CMP_OPS(ngle) |
|
2175 |
CMP_OPS(seq) |
|
2176 |
CMP_OPS(ngl) |
|
2177 |
CMP_OPS(lt) |
|
2178 |
CMP_OPS(nge) |
|
2179 |
CMP_OPS(le) |
|
2180 |
CMP_OPS(ngt) |
|
2181 |
#undef CMP_OPS |
|
2182 |
#undef CMP_OP |
|
2593 | 2183 |
|
2594 | 2184 |
void op_bc1f (void) |
2595 | 2185 |
{ |
2596 |
T0 = !IS_FP_COND_SET(PARAM1, env);
|
|
2186 |
T0 = !!(~GET_FP_COND(env) & (0x1 << PARAM1));
|
|
2597 | 2187 |
DEBUG_FPU_STATE(); |
2598 | 2188 |
RETURN(); |
2599 | 2189 |
} |
2600 |
void op_bc1fany2 (void)
|
|
2190 |
void op_bc1any2f (void)
|
|
2601 | 2191 |
{ |
2602 |
T0 = (!IS_FP_COND_SET(PARAM1, env) || |
|
2603 |
!IS_FP_COND_SET(PARAM1 + 1, env)); |
|
2192 |
T0 = !!(~GET_FP_COND(env) & (0x3 << PARAM1)); |
|
2604 | 2193 |
DEBUG_FPU_STATE(); |
2605 | 2194 |
RETURN(); |
2606 | 2195 |
} |
2607 |
void op_bc1fany4 (void)
|
|
2196 |
void op_bc1any4f (void)
|
|
2608 | 2197 |
{ |
2609 |
T0 = (!IS_FP_COND_SET(PARAM1, env) || |
|
2610 |
!IS_FP_COND_SET(PARAM1 + 1, env) || |
|
2611 |
!IS_FP_COND_SET(PARAM1 + 2, env) || |
|
2612 |
!IS_FP_COND_SET(PARAM1 + 3, env)); |
|
2198 |
T0 = !!(~GET_FP_COND(env) & (0xf << PARAM1)); |
|
2613 | 2199 |
DEBUG_FPU_STATE(); |
2614 | 2200 |
RETURN(); |
2615 | 2201 |
} |
2616 | 2202 |
|
2617 | 2203 |
void op_bc1t (void) |
2618 | 2204 |
{ |
2619 |
T0 = IS_FP_COND_SET(PARAM1, env);
|
|
2205 |
T0 = !!(GET_FP_COND(env) & (0x1 << PARAM1));
|
|
2620 | 2206 |
DEBUG_FPU_STATE(); |
2621 | 2207 |
RETURN(); |
2622 | 2208 |
} |
2623 |
void op_bc1tany2 (void)
|
|
2209 |
void op_bc1any2t (void)
|
|
2624 | 2210 |
{ |
2625 |
T0 = (IS_FP_COND_SET(PARAM1, env) || |
|
2626 |
IS_FP_COND_SET(PARAM1 + 1, env)); |
|
2211 |
T0 = !!(GET_FP_COND(env) & (0x3 << PARAM1)); |
|
2627 | 2212 |
DEBUG_FPU_STATE(); |
2628 | 2213 |
RETURN(); |
2629 | 2214 |
} |
2630 |
void op_bc1tany4 (void)
|
|
2215 |
void op_bc1any4t (void)
|
|
2631 | 2216 |
{ |
2632 |
T0 = (IS_FP_COND_SET(PARAM1, env) || |
|
2633 |
IS_FP_COND_SET(PARAM1 + 1, env) || |
|
2634 |
IS_FP_COND_SET(PARAM1 + 2, env) || |
|
2635 |
IS_FP_COND_SET(PARAM1 + 3, env)); |
|
2217 |
T0 = !!(GET_FP_COND(env) & (0xf << PARAM1)); |
|
2636 | 2218 |
DEBUG_FPU_STATE(); |
2637 | 2219 |
RETURN(); |
2638 | 2220 |
} |
... | ... | |
2808 | 2390 |
RETURN(); |
2809 | 2391 |
} |
2810 | 2392 |
|
2811 |
void op_save_fp_status (void) |
|
2812 |
{ |
|
2813 |
union fps { |
|
2814 |
uint32_t i; |
|
2815 |
float_status f; |
|
2816 |
} fps; |
|
2817 |
fps.i = PARAM1; |
|
2818 |
env->fp_status = fps.f; |
|
2819 |
RETURN(); |
|
2820 |
} |
|
2821 |
|
|
2822 | 2393 |
void op_interrupt_restart (void) |
2823 | 2394 |
{ |
2824 | 2395 |
if (!(env->CP0_Status & (1 << CP0St_EXL)) && |
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)) |
b/target-mips/translate.c | ||
---|---|---|
491 | 491 |
FGEN32(gen_op_store_fpr_WTH2, gen_op_store_fpr_WTH2_fpr); |
492 | 492 |
|
493 | 493 |
#define FOP_CONDS(type, fmt) \ |
494 |
static GenOpFunc1 * cond ## type ## _ ## fmt ## _table[16] = { \
|
|
494 |
static GenOpFunc1 * gen_op_cmp ## type ## _ ## fmt ## _table[16] = { \
|
|
495 | 495 |
gen_op_cmp ## type ## _ ## fmt ## _f, \ |
496 | 496 |
gen_op_cmp ## type ## _ ## fmt ## _un, \ |
497 | 497 |
gen_op_cmp ## type ## _ ## fmt ## _eq, \ |
... | ... | |
511 | 511 |
}; \ |
512 | 512 |
static inline void gen_cmp ## type ## _ ## fmt(int n, long cc) \ |
513 | 513 |
{ \ |
514 |
cond ## type ## _ ## fmt ## _table[n](cc); \
|
|
514 |
gen_op_cmp ## type ## _ ## fmt ## _table[n](cc); \
|
|
515 | 515 |
} |
516 | 516 |
|
517 | 517 |
FOP_CONDS(, d) |
... | ... | |
525 | 525 |
struct TranslationBlock *tb; |
526 | 526 |
target_ulong pc, saved_pc; |
527 | 527 |
uint32_t opcode; |
528 |
uint32_t fp_status, saved_fp_status;
|
|
528 |
uint32_t fp_status; |
|
529 | 529 |
/* Routine used to access memory */ |
530 | 530 |
int mem_idx; |
531 | 531 |
uint32_t hflags, saved_hflags; |
532 |
uint32_t CP0_Status; |
|
533 | 532 |
int bstate; |
534 | 533 |
target_ulong btarget; |
535 | 534 |
} DisasContext; |
Also available in: Unified diff