Commit fd4a04ebb220b1ada72275297fc12cb85e89bbfb

Authored by ths
1 parent 34ae7b51

- Move FPU exception handling into helper functions, since they are big.

- Fix FP-conditional branches.
- Check FPU register mode at runtime, not translation time, as the F64
  status bit can change.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2828 c046a42c-6fe2-441c-8c8c-71466251a162
target-mips/cpu.h
... ... @@ -81,9 +81,9 @@ struct CPUMIPSState {
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)
... ...
target-mips/exec.h
... ... @@ -165,4 +165,75 @@ void cpu_mips_update_irq (CPUState *env);
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__) */
... ...
target-mips/op.c
... ... @@ -1609,47 +1609,25 @@ void op_cp1_enabled(void)
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,38 +1653,7 @@ void op_cfc1 (void)
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,45 +1709,31 @@ void op_mthc1 (void)
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,81 +1746,55 @@ FLOAT_OP(cvtps, s)
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,177 +1824,34 @@ FLOAT_OP(puu, ps)
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,26 +1950,19 @@ FLOAT_OP(movn, ps)
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,10 +1974,7 @@ FLOAT_BINOP(div)
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,249 +2144,77 @@ FLOAT_OP(alnv, ps)
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,17 +2390,6 @@ void op_save_pc (void)
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)) &&
... ...
target-mips/op_helper.c
... ... @@ -598,3 +598,544 @@ void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr)
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))
... ...
target-mips/translate.c
... ... @@ -491,7 +491,7 @@ FGEN32(gen_op_load_fpr_WTH2, gen_op_load_fpr_WTH2_fpr);
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,7 +511,7 @@ static GenOpFunc1 * cond ## type ## _ ## fmt ## _table[16] = { \
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,11 +525,10 @@ typedef struct DisasContext {
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;
... ... @@ -628,11 +627,21 @@ static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
628 627 }
629 628 }
630 629  
631   -static inline void save_fpu_state (DisasContext *ctx)
  630 +static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
632 631 {
633   - if (ctx->fp_status != ctx->saved_fp_status) {
634   - gen_op_save_fp_status(ctx->fp_status);
635   - ctx->saved_fp_status = ctx->fp_status;
  632 + ctx->saved_hflags = ctx->hflags;
  633 + switch (ctx->hflags & MIPS_HFLAG_BMASK) {
  634 + case MIPS_HFLAG_BR:
  635 + gen_op_restore_breg_target();
  636 + break;
  637 + case MIPS_HFLAG_B:
  638 + ctx->btarget = env->btarget;
  639 + break;
  640 + case MIPS_HFLAG_BC:
  641 + case MIPS_HFLAG_BL:
  642 + ctx->btarget = env->btarget;
  643 + gen_op_restore_bcond();
  644 + break;
636 645 }
637 646 }
638 647  
... ... @@ -4293,20 +4302,20 @@ static void gen_compute_branch1 (DisasContext *ctx, uint32_t op,
4293 4302 gen_op_save_bcond();
4294 4303 break;
4295 4304 case OPC_BC1FANY2:
4296   - gen_op_bc1fany2(cc);
4297   - opn = "bc1fany2";
  4305 + gen_op_bc1any2f(cc);
  4306 + opn = "bc1any2f";
4298 4307 goto not_likely;
4299 4308 case OPC_BC1TANY2:
4300   - gen_op_bc1tany2(cc);
4301   - opn = "bc1tany2";
  4309 + gen_op_bc1any2t(cc);
  4310 + opn = "bc1any2t";
4302 4311 goto not_likely;
4303 4312 case OPC_BC1FANY4:
4304   - gen_op_bc1fany4(cc);
4305   - opn = "bc1fany4";
  4313 + gen_op_bc1any4f(cc);
  4314 + opn = "bc1any4f";
4306 4315 goto not_likely;
4307 4316 case OPC_BC1TANY4:
4308   - gen_op_bc1tany4(cc);
4309   - opn = "bc1tany4";
  4317 + gen_op_bc1any4t(cc);
  4318 + opn = "bc1any4t";
4310 4319 not_likely:
4311 4320 ctx->hflags |= MIPS_HFLAG_BC;
4312 4321 gen_op_set_bcond();
... ... @@ -4323,27 +4332,6 @@ static void gen_compute_branch1 (DisasContext *ctx, uint32_t op,
4323 4332  
4324 4333 /* Coprocessor 1 (FPU) */
4325 4334  
4326   -/* verify if floating point register is valid; an operation is not defined
4327   - * if bit 0 of any register specification is set and the FR bit in the
4328   - * Status register equals zero, since the register numbers specify an
4329   - * even-odd pair of adjacent coprocessor general registers. When the FR bit
4330   - * in the Status register equals one, both even and odd register numbers
4331   - * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
4332   - *
4333   - * Multiple 64 bit wide registers can be checked by calling
4334   - * CHECK_FR(ctx, freg1 | freg2 | ... | fregN);
4335   - *
4336   - * FIXME: This is broken for R2, it needs to be checked at runtime, not
4337   - * at translation time.
4338   - */
4339   -#define CHECK_FR(ctx, freg) do { \
4340   - if (!((ctx)->CP0_Status & (1 << CP0St_FR)) && ((freg) & 1)) { \
4341   - MIPS_INVAL("FPU mode"); \
4342   - generate_exception (ctx, EXCP_RI); \
4343   - return; \
4344   - } \
4345   - } while(0)
4346   -
4347 4335 #define FOP(func, fmt) (((fmt) << 21) | (func))
4348 4336  
4349 4337 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
... ... @@ -4388,14 +4376,14 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
4388 4376 opn = "dmtc1";
4389 4377 break;
4390 4378 case OPC_MFHC1:
4391   - CHECK_FR(ctx, fs);
  4379 + gen_op_cp1_registers(fs);
4392 4380 GEN_LOAD_FREG_FTN(WTH0, fs);
4393 4381 gen_op_mfhc1();
4394 4382 GEN_STORE_TN_REG(rt, T0);
4395 4383 opn = "mfhc1";
4396 4384 break;
4397 4385 case OPC_MTHC1:
4398   - CHECK_FR(ctx, fs);
  4386 + gen_op_cp1_registers(fs);
4399 4387 GEN_LOAD_REG_TN(T0, rt);
4400 4388 gen_op_mthc1();
4401 4389 GEN_STORE_FTN_FREG(fs, WTH0);
... ... @@ -4546,28 +4534,28 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4546 4534 opn = "neg.s";
4547 4535 break;
4548 4536 case FOP(8, 16):
4549   - CHECK_FR(ctx, fs);
  4537 + gen_op_cp1_registers(fs);
4550 4538 GEN_LOAD_FREG_FTN(WT0, fs);
4551 4539 gen_op_float_roundl_s();
4552 4540 GEN_STORE_FTN_FREG(fd, DT2);
4553 4541 opn = "round.l.s";
4554 4542 break;
4555 4543 case FOP(9, 16):
4556   - CHECK_FR(ctx, fs);
  4544 + gen_op_cp1_registers(fs);
4557 4545 GEN_LOAD_FREG_FTN(WT0, fs);
4558 4546 gen_op_float_truncl_s();
4559 4547 GEN_STORE_FTN_FREG(fd, DT2);
4560 4548 opn = "trunc.l.s";
4561 4549 break;
4562 4550 case FOP(10, 16):
4563   - CHECK_FR(ctx, fs);
  4551 + gen_op_cp1_registers(fs);
4564 4552 GEN_LOAD_FREG_FTN(WT0, fs);
4565 4553 gen_op_float_ceill_s();
4566 4554 GEN_STORE_FTN_FREG(fd, DT2);
4567 4555 opn = "ceil.l.s";
4568 4556 break;
4569 4557 case FOP(11, 16):
4570   - CHECK_FR(ctx, fs);
  4558 + gen_op_cp1_registers(fs);
4571 4559 GEN_LOAD_FREG_FTN(WT0, fs);
4572 4560 gen_op_float_floorl_s();
4573 4561 GEN_STORE_FTN_FREG(fd, DT2);
... ... @@ -4622,7 +4610,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4622 4610 opn = "movn.s";
4623 4611 break;
4624 4612 case FOP(33, 16):
4625   - CHECK_FR(ctx, fd);
  4613 + gen_op_cp1_registers(fd);
4626 4614 GEN_LOAD_FREG_FTN(WT0, fs);
4627 4615 gen_op_float_cvtd_s();
4628 4616 GEN_STORE_FTN_FREG(fd, DT2);
... ... @@ -4635,14 +4623,14 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4635 4623 opn = "cvt.w.s";
4636 4624 break;
4637 4625 case FOP(37, 16):
4638   - CHECK_FR(ctx, fs | fd);
  4626 + gen_op_cp1_registers(fs | fd);
4639 4627 GEN_LOAD_FREG_FTN(WT0, fs);
4640 4628 gen_op_float_cvtl_s();
4641 4629 GEN_STORE_FTN_FREG(fd, DT2);
4642 4630 opn = "cvt.l.s";
4643 4631 break;
4644 4632 case FOP(38, 16):
4645   - CHECK_FR(ctx, fs | ft | fd);
  4633 + gen_op_cp1_registers(fs | ft | fd);
4646 4634 GEN_LOAD_FREG_FTN(WT1, fs);
4647 4635 GEN_LOAD_FREG_FTN(WT0, ft);
4648 4636 gen_op_float_cvtps_s();
... ... @@ -4676,7 +4664,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4676 4664 }
4677 4665 break;
4678 4666 case FOP(0, 17):
4679   - CHECK_FR(ctx, fs | ft | fd);
  4667 + gen_op_cp1_registers(fs | ft | fd);
4680 4668 GEN_LOAD_FREG_FTN(DT0, fs);
4681 4669 GEN_LOAD_FREG_FTN(DT1, ft);
4682 4670 gen_op_float_add_d();
... ... @@ -4685,7 +4673,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4685 4673 optype = BINOP;
4686 4674 break;
4687 4675 case FOP(1, 17):
4688   - CHECK_FR(ctx, fs | ft | fd);
  4676 + gen_op_cp1_registers(fs | ft | fd);
4689 4677 GEN_LOAD_FREG_FTN(DT0, fs);
4690 4678 GEN_LOAD_FREG_FTN(DT1, ft);
4691 4679 gen_op_float_sub_d();
... ... @@ -4694,7 +4682,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4694 4682 optype = BINOP;
4695 4683 break;
4696 4684 case FOP(2, 17):
4697   - CHECK_FR(ctx, fs | ft | fd);
  4685 + gen_op_cp1_registers(fs | ft | fd);
4698 4686 GEN_LOAD_FREG_FTN(DT0, fs);
4699 4687 GEN_LOAD_FREG_FTN(DT1, ft);
4700 4688 gen_op_float_mul_d();
... ... @@ -4703,7 +4691,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4703 4691 optype = BINOP;
4704 4692 break;
4705 4693 case FOP(3, 17):
4706   - CHECK_FR(ctx, fs | ft | fd);
  4694 + gen_op_cp1_registers(fs | ft | fd);
4707 4695 GEN_LOAD_FREG_FTN(DT0, fs);
4708 4696 GEN_LOAD_FREG_FTN(DT1, ft);
4709 4697 gen_op_float_div_d();
... ... @@ -4712,84 +4700,84 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4712 4700 optype = BINOP;
4713 4701 break;
4714 4702 case FOP(4, 17):
4715   - CHECK_FR(ctx, fs | fd);
  4703 + gen_op_cp1_registers(fs | fd);
4716 4704 GEN_LOAD_FREG_FTN(DT0, fs);
4717 4705 gen_op_float_sqrt_d();
4718 4706 GEN_STORE_FTN_FREG(fd, DT2);
4719 4707 opn = "sqrt.d";
4720 4708 break;
4721 4709 case FOP(5, 17):
4722   - CHECK_FR(ctx, fs | fd);
  4710 + gen_op_cp1_registers(fs | fd);
4723 4711 GEN_LOAD_FREG_FTN(DT0, fs);
4724 4712 gen_op_float_abs_d();
4725 4713 GEN_STORE_FTN_FREG(fd, DT2);
4726 4714 opn = "abs.d";
4727 4715 break;
4728 4716 case FOP(6, 17):
4729   - CHECK_FR(ctx, fs | fd);
  4717 + gen_op_cp1_registers(fs | fd);
4730 4718 GEN_LOAD_FREG_FTN(DT0, fs);
4731 4719 gen_op_float_mov_d();
4732 4720 GEN_STORE_FTN_FREG(fd, DT2);
4733 4721 opn = "mov.d";
4734 4722 break;
4735 4723 case FOP(7, 17):
4736   - CHECK_FR(ctx, fs | fd);
  4724 + gen_op_cp1_registers(fs | fd);
4737 4725 GEN_LOAD_FREG_FTN(DT0, fs);
4738 4726 gen_op_float_chs_d();
4739 4727 GEN_STORE_FTN_FREG(fd, DT2);
4740 4728 opn = "neg.d";
4741 4729 break;
4742 4730 case FOP(8, 17):
4743   - CHECK_FR(ctx, fs);
  4731 + gen_op_cp1_registers(fs);
4744 4732 GEN_LOAD_FREG_FTN(DT0, fs);
4745 4733 gen_op_float_roundl_d();
4746 4734 GEN_STORE_FTN_FREG(fd, DT2);
4747 4735 opn = "round.l.d";
4748 4736 break;
4749 4737 case FOP(9, 17):
4750   - CHECK_FR(ctx, fs);
  4738 + gen_op_cp1_registers(fs);
4751 4739 GEN_LOAD_FREG_FTN(DT0, fs);
4752 4740 gen_op_float_truncl_d();
4753 4741 GEN_STORE_FTN_FREG(fd, DT2);
4754 4742 opn = "trunc.l.d";
4755 4743 break;
4756 4744 case FOP(10, 17):
4757   - CHECK_FR(ctx, fs);
  4745 + gen_op_cp1_registers(fs);
4758 4746 GEN_LOAD_FREG_FTN(DT0, fs);
4759 4747 gen_op_float_ceill_d();
4760 4748 GEN_STORE_FTN_FREG(fd, DT2);
4761 4749 opn = "ceil.l.d";
4762 4750 break;
4763 4751 case FOP(11, 17):
4764   - CHECK_FR(ctx, fs);
  4752 + gen_op_cp1_registers(fs);
4765 4753 GEN_LOAD_FREG_FTN(DT0, fs);
4766 4754 gen_op_float_floorl_d();
4767 4755 GEN_STORE_FTN_FREG(fd, DT2);
4768 4756 opn = "floor.l.d";
4769 4757 break;
4770 4758 case FOP(12, 17):
4771   - CHECK_FR(ctx, fs);
  4759 + gen_op_cp1_registers(fs);
4772 4760 GEN_LOAD_FREG_FTN(DT0, fs);
4773 4761 gen_op_float_roundw_d();
4774 4762 GEN_STORE_FTN_FREG(fd, WT2);
4775 4763 opn = "round.w.d";
4776 4764 break;
4777 4765 case FOP(13, 17):
4778   - CHECK_FR(ctx, fs);
  4766 + gen_op_cp1_registers(fs);
4779 4767 GEN_LOAD_FREG_FTN(DT0, fs);
4780 4768 gen_op_float_truncw_d();
4781 4769 GEN_STORE_FTN_FREG(fd, WT2);
4782 4770 opn = "trunc.w.d";
4783 4771 break;
4784 4772 case FOP(14, 17):
4785   - CHECK_FR(ctx, fs);
  4773 + gen_op_cp1_registers(fs);
4786 4774 GEN_LOAD_FREG_FTN(DT0, fs);
4787 4775 gen_op_float_ceilw_d();
4788 4776 GEN_STORE_FTN_FREG(fd, WT2);
4789 4777 opn = "ceil.w.d";
4790 4778 break;
4791 4779 case FOP(15, 17):
4792   - CHECK_FR(ctx, fs);
  4780 + gen_op_cp1_registers(fs);
4793 4781 GEN_LOAD_FREG_FTN(DT0, fs);
4794 4782 gen_op_float_floorw_d();
4795 4783 GEN_STORE_FTN_FREG(fd, WT2);
... ... @@ -4835,7 +4823,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4835 4823 case FOP(61, 17):
4836 4824 case FOP(62, 17):
4837 4825 case FOP(63, 17):
4838   - CHECK_FR(ctx, fs | ft);
  4826 + gen_op_cp1_registers(fs | ft);
4839 4827 GEN_LOAD_FREG_FTN(DT0, fs);
4840 4828 GEN_LOAD_FREG_FTN(DT1, ft);
4841 4829 if (ctx->opcode & (1 << 6)) {
... ... @@ -4847,21 +4835,21 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4847 4835 }
4848 4836 break;
4849 4837 case FOP(32, 17):
4850   - CHECK_FR(ctx, fs);
  4838 + gen_op_cp1_registers(fs);
4851 4839 GEN_LOAD_FREG_FTN(DT0, fs);
4852 4840 gen_op_float_cvts_d();
4853 4841 GEN_STORE_FTN_FREG(fd, WT2);
4854 4842 opn = "cvt.s.d";
4855 4843 break;
4856 4844 case FOP(36, 17):
4857   - CHECK_FR(ctx, fs);
  4845 + gen_op_cp1_registers(fs);
4858 4846 GEN_LOAD_FREG_FTN(DT0, fs);
4859 4847 gen_op_float_cvtw_d();
4860 4848 GEN_STORE_FTN_FREG(fd, WT2);
4861 4849 opn = "cvt.w.d";
4862 4850 break;
4863 4851 case FOP(37, 17):
4864   - CHECK_FR(ctx, fs | fd);
  4852 + gen_op_cp1_registers(fs | fd);
4865 4853 GEN_LOAD_FREG_FTN(DT0, fs);
4866 4854 gen_op_float_cvtl_d();
4867 4855 GEN_STORE_FTN_FREG(fd, DT2);
... ... @@ -4874,21 +4862,21 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4874 4862 opn = "cvt.s.w";
4875 4863 break;
4876 4864 case FOP(33, 20):
4877   - CHECK_FR(ctx, fd);
  4865 + gen_op_cp1_registers(fd);
4878 4866 GEN_LOAD_FREG_FTN(WT0, fs);
4879 4867 gen_op_float_cvtd_w();
4880 4868 GEN_STORE_FTN_FREG(fd, DT2);
4881 4869 opn = "cvt.d.w";
4882 4870 break;
4883 4871 case FOP(32, 21):
4884   - CHECK_FR(ctx, fs);
  4872 + gen_op_cp1_registers(fs);
4885 4873 GEN_LOAD_FREG_FTN(DT0, fs);
4886 4874 gen_op_float_cvts_l();
4887 4875 GEN_STORE_FTN_FREG(fd, WT2);
4888 4876 opn = "cvt.s.l";
4889 4877 break;
4890 4878 case FOP(33, 21):
4891   - CHECK_FR(ctx, fs | fd);
  4879 + gen_op_cp1_registers(fs | fd);
4892 4880 GEN_LOAD_FREG_FTN(DT0, fs);
4893 4881 gen_op_float_cvtd_l();
4894 4882 GEN_STORE_FTN_FREG(fd, DT2);
... ... @@ -4896,7 +4884,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4896 4884 break;
4897 4885 case FOP(38, 20):
4898 4886 case FOP(38, 21):
4899   - CHECK_FR(ctx, fs | fd);
  4887 + gen_op_cp1_registers(fs | fd);
4900 4888 GEN_LOAD_FREG_FTN(WT0, fs);
4901 4889 GEN_LOAD_FREG_FTN(WTH0, fs);
4902 4890 gen_op_float_cvtps_pw();
... ... @@ -4905,7 +4893,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4905 4893 opn = "cvt.ps.pw";
4906 4894 break;
4907 4895 case FOP(0, 22):
4908   - CHECK_FR(ctx, fs | ft | fd);
  4896 + gen_op_cp1_registers(fs | ft | fd);
4909 4897 GEN_LOAD_FREG_FTN(WT0, fs);
4910 4898 GEN_LOAD_FREG_FTN(WTH0, fs);
4911 4899 GEN_LOAD_FREG_FTN(WT1, ft);
... ... @@ -4916,7 +4904,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4916 4904 opn = "add.ps";
4917 4905 break;
4918 4906 case FOP(1, 22):
4919   - CHECK_FR(ctx, fs | ft | fd);
  4907 + gen_op_cp1_registers(fs | ft | fd);
4920 4908 GEN_LOAD_FREG_FTN(WT0, fs);
4921 4909 GEN_LOAD_FREG_FTN(WTH0, fs);
4922 4910 GEN_LOAD_FREG_FTN(WT1, ft);
... ... @@ -4927,7 +4915,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4927 4915 opn = "sub.ps";
4928 4916 break;
4929 4917 case FOP(2, 22):
4930   - CHECK_FR(ctx, fs | ft | fd);
  4918 + gen_op_cp1_registers(fs | ft | fd);
4931 4919 GEN_LOAD_FREG_FTN(WT0, fs);
4932 4920 GEN_LOAD_FREG_FTN(WTH0, fs);
4933 4921 GEN_LOAD_FREG_FTN(WT1, ft);
... ... @@ -4938,7 +4926,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4938 4926 opn = "mul.ps";
4939 4927 break;
4940 4928 case FOP(5, 22):
4941   - CHECK_FR(ctx, fs | fd);
  4929 + gen_op_cp1_registers(fs | fd);
4942 4930 GEN_LOAD_FREG_FTN(WT0, fs);
4943 4931 GEN_LOAD_FREG_FTN(WTH0, fs);
4944 4932 gen_op_float_abs_ps();
... ... @@ -4947,7 +4935,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4947 4935 opn = "abs.ps";
4948 4936 break;
4949 4937 case FOP(6, 22):
4950   - CHECK_FR(ctx, fs | fd);
  4938 + gen_op_cp1_registers(fs | fd);
4951 4939 GEN_LOAD_FREG_FTN(WT0, fs);
4952 4940 GEN_LOAD_FREG_FTN(WTH0, fs);
4953 4941 gen_op_float_mov_ps();
... ... @@ -4956,7 +4944,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4956 4944 opn = "mov.ps";
4957 4945 break;
4958 4946 case FOP(7, 22):
4959   - CHECK_FR(ctx, fs | fd);
  4947 + gen_op_cp1_registers(fs | fd);
4960 4948 GEN_LOAD_FREG_FTN(WT0, fs);
4961 4949 GEN_LOAD_FREG_FTN(WTH0, fs);
4962 4950 gen_op_float_chs_ps();
... ... @@ -4998,7 +4986,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4998 4986 opn = "movn.ps";
4999 4987 break;
5000 4988 case FOP(24, 22):
5001   - CHECK_FR(ctx, fs | fd | ft);
  4989 + gen_op_cp1_registers(fs | fd | ft);
5002 4990 GEN_LOAD_FREG_FTN(WT0, fs);
5003 4991 GEN_LOAD_FREG_FTN(WTH0, fs);
5004 4992 GEN_LOAD_FREG_FTN(WT1, ft);
... ... @@ -5009,14 +4997,14 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
5009 4997 opn = "addr.ps";
5010 4998 break;
5011 4999 case FOP(32, 22):
5012   - CHECK_FR(ctx, fs);
  5000 + gen_op_cp1_registers(fs);
5013 5001 GEN_LOAD_FREG_FTN(WTH0, fs);
5014 5002 gen_op_float_cvts_pu();
5015 5003 GEN_STORE_FTN_FREG(fd, WT2);
5016 5004 opn = "cvt.s.pu";
5017 5005 break;
5018 5006 case FOP(36, 22):
5019   - CHECK_FR(ctx, fs | fd);
  5007 + gen_op_cp1_registers(fs | fd);
5020 5008 GEN_LOAD_FREG_FTN(WT0, fs);
5021 5009 GEN_LOAD_FREG_FTN(WTH0, fs);
5022 5010 gen_op_float_cvtpw_ps();
... ... @@ -5025,14 +5013,14 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
5025 5013 opn = "cvt.pw.ps";
5026 5014 break;
5027 5015 case FOP(40, 22):
5028   - CHECK_FR(ctx, fs);
  5016 + gen_op_cp1_registers(fs);
5029 5017 GEN_LOAD_FREG_FTN(WT0, fs);
5030 5018 gen_op_float_cvts_pl();
5031 5019 GEN_STORE_FTN_FREG(fd, WT2);
5032 5020 opn = "cvt.s.pl";
5033 5021 break;
5034 5022 case FOP(44, 22):
5035   - CHECK_FR(ctx, fs | ft | fd);
  5023 + gen_op_cp1_registers(fs | ft | fd);
5036 5024 GEN_LOAD_FREG_FTN(WT0, fs);
5037 5025 GEN_LOAD_FREG_FTN(WT1, ft);
5038 5026 gen_op_float_pll_ps();
... ... @@ -5040,7 +5028,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
5040 5028 opn = "pll.ps";
5041 5029 break;
5042 5030 case FOP(45, 22):
5043   - CHECK_FR(ctx, fs | ft | fd);
  5031 + gen_op_cp1_registers(fs | ft | fd);
5044 5032 GEN_LOAD_FREG_FTN(WT0, fs);
5045 5033 GEN_LOAD_FREG_FTN(WTH1, ft);
5046 5034 gen_op_float_plu_ps();
... ... @@ -5048,7 +5036,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
5048 5036 opn = "plu.ps";
5049 5037 break;
5050 5038 case FOP(46, 22):
5051   - CHECK_FR(ctx, fs | ft | fd);
  5039 + gen_op_cp1_registers(fs | ft | fd);
5052 5040 GEN_LOAD_FREG_FTN(WTH0, fs);
5053 5041 GEN_LOAD_FREG_FTN(WT1, ft);
5054 5042 gen_op_float_pul_ps();
... ... @@ -5056,7 +5044,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
5056 5044 opn = "pul.ps";
5057 5045 break;
5058 5046 case FOP(47, 22):
5059   - CHECK_FR(ctx, fs | ft | fd);
  5047 + gen_op_cp1_registers(fs | ft | fd);
5060 5048 GEN_LOAD_FREG_FTN(WTH0, fs);
5061 5049 GEN_LOAD_FREG_FTN(WTH1, ft);
5062 5050 gen_op_float_puu_ps();
... ... @@ -5079,7 +5067,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
5079 5067 case FOP(61, 22):
5080 5068 case FOP(62, 22):
5081 5069 case FOP(63, 22):
5082   - CHECK_FR(ctx, fs | ft);
  5070 + gen_op_cp1_registers(fs | ft);
5083 5071 GEN_LOAD_FREG_FTN(WT0, fs);
5084 5072 GEN_LOAD_FREG_FTN(WTH0, fs);
5085 5073 GEN_LOAD_FREG_FTN(WT1, ft);
... ... @@ -5166,7 +5154,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, int fd,
5166 5154 const char *opn = "flt3_arith";
5167 5155  
5168 5156 /* All of those work only on 64bit FPUs. */
5169   - CHECK_FR(ctx, fd | fr | fs | ft);
  5157 + gen_op_cp1_registers(fd | fr | fs | ft);
5170 5158 switch (opc) {
5171 5159 case OPC_ALNV_PS:
5172 5160 GEN_LOAD_REG_TN(T0, fr);
... ... @@ -5874,26 +5862,12 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
5874 5862 ctx.bstate = BS_NONE;
5875 5863 /* Restore delay slot state from the tb context. */
5876 5864 ctx.hflags = tb->flags;
5877   - ctx.saved_hflags = ctx.hflags;
5878   - switch (ctx.hflags & MIPS_HFLAG_BMASK) {
5879   - case MIPS_HFLAG_BR:
5880   - gen_op_restore_breg_target();
5881   - break;
5882   - case MIPS_HFLAG_B:
5883   - ctx.btarget = env->btarget;
5884   - break;
5885   - case MIPS_HFLAG_BC:
5886   - case MIPS_HFLAG_BL:
5887   - ctx.btarget = env->btarget;
5888   - gen_op_restore_bcond();
5889   - break;
5890   - }
  5865 + restore_cpu_state(env, &ctx);
5891 5866 #if defined(CONFIG_USER_ONLY)
5892 5867 ctx.mem_idx = 0;
5893 5868 #else
5894 5869 ctx.mem_idx = !((ctx.hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM);
5895 5870 #endif
5896   - ctx.CP0_Status = env->CP0_Status;
5897 5871 #ifdef DEBUG_DISAS
5898 5872 if (loglevel & CPU_LOG_TB_CPU) {
5899 5873 fprintf(logfile, "------------------------------------------------\n");
... ...