Commit 1f587329169765299448c1becd6a633a204ead29

Authored by blueswir1
1 parent 5cc9878d

128-bit float support for user mode


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3740 c046a42c-6fe2-441c-8c8c-71466251a162
cpu-all.h
... ... @@ -135,6 +135,36 @@ typedef union {
135 135 uint64_t ll;
136 136 } CPU_DoubleU;
137 137  
  138 +#ifdef TARGET_SPARC
  139 +typedef union {
  140 + float128 q;
  141 +#if defined(WORDS_BIGENDIAN) \
  142 + || (defined(__arm__) && !defined(__VFP_FP__) && !defined(CONFIG_SOFTFLOAT))
  143 + struct {
  144 + uint32_t upmost;
  145 + uint32_t upper;
  146 + uint32_t lower;
  147 + uint32_t lowest;
  148 + } l;
  149 + struct {
  150 + uint64_t upper;
  151 + uint64_t lower;
  152 + } ll;
  153 +#else
  154 + struct {
  155 + uint32_t lowest;
  156 + uint32_t lower;
  157 + uint32_t upper;
  158 + uint32_t upmost;
  159 + } l;
  160 + struct {
  161 + uint64_t lower;
  162 + uint64_t upper;
  163 + } ll;
  164 +#endif
  165 +} CPU_QuadU;
  166 +#endif
  167 +
138 168 /* CPU memory access without any memory or io remapping */
139 169  
140 170 /*
... ...
fpu/softfloat.c
... ... @@ -5421,6 +5421,50 @@ int float ## s ## _compare_quiet( float ## s a, float ## s b STATUS_PARAM ) \
5421 5421 COMPARE(32, 0xff)
5422 5422 COMPARE(64, 0x7ff)
5423 5423  
  5424 +INLINE int float128_compare_internal( float128 a, float128 b,
  5425 + int is_quiet STATUS_PARAM )
  5426 +{
  5427 + flag aSign, bSign;
  5428 +
  5429 + if (( ( extractFloat128Exp( a ) == 0x7fff ) &&
  5430 + ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) ||
  5431 + ( ( extractFloat128Exp( b ) == 0x7fff ) &&
  5432 + ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )) {
  5433 + if (!is_quiet ||
  5434 + float128_is_signaling_nan( a ) ||
  5435 + float128_is_signaling_nan( b ) ) {
  5436 + float_raise( float_flag_invalid STATUS_VAR);
  5437 + }
  5438 + return float_relation_unordered;
  5439 + }
  5440 + aSign = extractFloat128Sign( a );
  5441 + bSign = extractFloat128Sign( b );
  5442 + if ( aSign != bSign ) {
  5443 + if ( ( ( ( a.high | b.high )<<1 ) | a.low | b.low ) == 0 ) {
  5444 + /* zero case */
  5445 + return float_relation_equal;
  5446 + } else {
  5447 + return 1 - (2 * aSign);
  5448 + }
  5449 + } else {
  5450 + if (a.low == b.low && a.high == b.high) {
  5451 + return float_relation_equal;
  5452 + } else {
  5453 + return 1 - 2 * (aSign ^ ( lt128( a.high, a.low, b.high, b.low ) ));
  5454 + }
  5455 + }
  5456 +}
  5457 +
  5458 +int float128_compare( float128 a, float128 b STATUS_PARAM )
  5459 +{
  5460 + return float128_compare_internal(a, b, 0 STATUS_VAR);
  5461 +}
  5462 +
  5463 +int float128_compare_quiet( float128 a, float128 b STATUS_PARAM )
  5464 +{
  5465 + return float128_compare_internal(a, b, 1 STATUS_VAR);
  5466 +}
  5467 +
5424 5468 /* Multiply A by 2 raised to the power N. */
5425 5469 float32 float32_scalbn( float32 a, int n STATUS_PARAM )
5426 5470 {
... ...
fpu/softfloat.h
... ... @@ -415,6 +415,8 @@ int float128_lt( float128, float128 STATUS_PARAM );
415 415 int float128_eq_signaling( float128, float128 STATUS_PARAM );
416 416 int float128_le_quiet( float128, float128 STATUS_PARAM );
417 417 int float128_lt_quiet( float128, float128 STATUS_PARAM );
  418 +int float128_compare( float128, float128 STATUS_PARAM );
  419 +int float128_compare_quiet( float128, float128 STATUS_PARAM );
418 420 int float128_is_nan( float128 );
419 421 int float128_is_signaling_nan( float128 );
420 422 float128 float128_scalbn( float128, int STATUS_PARAM );
... ...
qemu-tech.texi
... ... @@ -212,8 +212,7 @@ Current QEMU limitations:
212 212  
213 213 @item IPC syscalls are missing.
214 214  
215   -@item 128-bit floating point operations are not supported, though none of the
216   -real CPUs implement them either. Floating point exception support is untested.
  215 +@item Floating point exception support is buggy.
217 216  
218 217 @item Atomic instructions are not correctly implemented.
219 218  
... ...
target-sparc/cpu.h
... ... @@ -222,6 +222,9 @@ typedef struct CPUSPARCState {
222 222 /* temporary float registers */
223 223 float32 ft0, ft1;
224 224 float64 dt0, dt1;
  225 +#if defined(CONFIG_USER_ONLY)
  226 + float128 qt0, qt1;
  227 +#endif
225 228 float_status fp_status;
226 229 #if defined(TARGET_SPARC64)
227 230 #define MAXTL 4
... ...
target-sparc/exec.h
... ... @@ -41,6 +41,10 @@ register uint32_t T2 asm(AREG3);
41 41 #define FT1 (env->ft1)
42 42 #define DT0 (env->dt0)
43 43 #define DT1 (env->dt1)
  44 +#if defined(CONFIG_USER_ONLY)
  45 +#define QT0 (env->qt0)
  46 +#define QT1 (env->qt1)
  47 +#endif
44 48  
45 49 #include "cpu.h"
46 50 #include "exec-all.h"
... ... @@ -65,6 +69,13 @@ void do_fcmps(void);
65 69 void do_fcmpd(void);
66 70 void do_fcmpes(void);
67 71 void do_fcmped(void);
  72 +#if defined(CONFIG_USER_ONLY)
  73 +void do_fitoq(void);
  74 +void do_fabsq(void);
  75 +void do_fsqrtq(void);
  76 +void do_fcmpq(void);
  77 +void do_fcmpeq(void);
  78 +#endif
68 79 #ifdef TARGET_SPARC64
69 80 void do_fabsd(void);
70 81 void do_fcmps_fcc1(void);
... ... @@ -79,6 +90,14 @@ void do_fcmpes_fcc2(void);
79 90 void do_fcmped_fcc2(void);
80 91 void do_fcmpes_fcc3(void);
81 92 void do_fcmped_fcc3(void);
  93 +#if defined(CONFIG_USER_ONLY)
  94 +void do_fcmpq_fcc1(void);
  95 +void do_fcmpq_fcc2(void);
  96 +void do_fcmpq_fcc3(void);
  97 +void do_fcmpeq_fcc1(void);
  98 +void do_fcmpeq_fcc2(void);
  99 +void do_fcmpeq_fcc3(void);
  100 +#endif
82 101 void do_popc();
83 102 void do_wrpstate();
84 103 void do_done();
... ...
target-sparc/fop_template.h
... ... @@ -77,5 +77,52 @@ void OPPROTO glue(op_store_DT1_fpr_fpr, REGNAME)(void)
77 77 *p = u.l.upper;
78 78 }
79 79  
  80 +#if defined(CONFIG_USER_ONLY)
  81 +/* quad floating point registers moves */
  82 +void OPPROTO glue(op_load_fpr_QT0_fpr, REGNAME)(void)
  83 +{
  84 + CPU_QuadU u;
  85 + uint32_t *p = (uint32_t *)&REG;
  86 + u.l.lowest = *(p + 3);
  87 + u.l.lower = *(p + 2);
  88 + u.l.upper = *(p + 1);
  89 + u.l.upmost = *p;
  90 + QT0 = u.q;
  91 +}
  92 +
  93 +void OPPROTO glue(op_store_QT0_fpr_fpr, REGNAME)(void)
  94 +{
  95 + CPU_QuadU u;
  96 + uint32_t *p = (uint32_t *)&REG;
  97 + u.q = QT0;
  98 + *(p + 3) = u.l.lowest;
  99 + *(p + 2) = u.l.lower;
  100 + *(p + 1) = u.l.upper;
  101 + *p = u.l.upmost;
  102 +}
  103 +
  104 +void OPPROTO glue(op_load_fpr_QT1_fpr, REGNAME)(void)
  105 +{
  106 + CPU_QuadU u;
  107 + uint32_t *p = (uint32_t *)&REG;
  108 + u.l.lowest = *(p + 3);
  109 + u.l.lower = *(p + 2);
  110 + u.l.upper = *(p + 1);
  111 + u.l.upmost = *p;
  112 + QT1 = u.q;
  113 +}
  114 +
  115 +void OPPROTO glue(op_store_QT1_fpr_fpr, REGNAME)(void)
  116 +{
  117 + CPU_QuadU u;
  118 + uint32_t *p = (uint32_t *)&REG;
  119 + u.q = QT1;
  120 + *(p + 3) = u.l.lowest;
  121 + *(p + 2) = u.l.lower;
  122 + *(p + 1) = u.l.upper;
  123 + *p = u.l.upmost;
  124 +}
  125 +#endif
  126 +
80 127 #undef REG
81 128 #undef REGNAME
... ...
target-sparc/op.c
... ... @@ -1581,6 +1581,7 @@ void OPPROTO op_clear_ieee_excp_and_FTT(void)
1581 1581  
1582 1582 #define F_OP(name, p) void OPPROTO op_f##name##p(void)
1583 1583  
  1584 +#if defined(CONFIG_USER_ONLY)
1584 1585 #define F_BINOP(name) \
1585 1586 F_OP(name, s) \
1586 1587 { \
... ... @@ -1593,7 +1594,28 @@ void OPPROTO op_clear_ieee_excp_and_FTT(void)
1593 1594 set_float_exception_flags(0, &env->fp_status); \
1594 1595 DT0 = float64_ ## name (DT0, DT1, &env->fp_status); \
1595 1596 check_ieee_exceptions(); \
  1597 + } \
  1598 + F_OP(name, q) \
  1599 + { \
  1600 + set_float_exception_flags(0, &env->fp_status); \
  1601 + QT0 = float128_ ## name (QT0, QT1, &env->fp_status); \
  1602 + check_ieee_exceptions(); \
1596 1603 }
  1604 +#else
  1605 +#define F_BINOP(name) \
  1606 + F_OP(name, s) \
  1607 + { \
  1608 + set_float_exception_flags(0, &env->fp_status); \
  1609 + FT0 = float32_ ## name (FT0, FT1, &env->fp_status); \
  1610 + check_ieee_exceptions(); \
  1611 + } \
  1612 + F_OP(name, d) \
  1613 + { \
  1614 + set_float_exception_flags(0, &env->fp_status); \
  1615 + DT0 = float64_ ## name (DT0, DT1, &env->fp_status); \
  1616 + check_ieee_exceptions(); \
  1617 + }
  1618 +#endif
1597 1619  
1598 1620 F_BINOP(add);
1599 1621 F_BINOP(sub);
... ... @@ -1610,6 +1632,18 @@ void OPPROTO op_fsmuld(void)
1610 1632 check_ieee_exceptions();
1611 1633 }
1612 1634  
  1635 +#if defined(CONFIG_USER_ONLY)
  1636 +void OPPROTO op_fdmulq(void)
  1637 +{
  1638 + set_float_exception_flags(0, &env->fp_status);
  1639 + QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
  1640 + float64_to_float128(DT1, &env->fp_status),
  1641 + &env->fp_status);
  1642 + check_ieee_exceptions();
  1643 +}
  1644 +#endif
  1645 +
  1646 +#if defined(CONFIG_USER_ONLY)
1613 1647 #define F_HELPER(name) \
1614 1648 F_OP(name, s) \
1615 1649 { \
... ... @@ -1618,7 +1652,22 @@ void OPPROTO op_fsmuld(void)
1618 1652 F_OP(name, d) \
1619 1653 { \
1620 1654 do_f##name##d(); \
  1655 + } \
  1656 + F_OP(name, q) \
  1657 + { \
  1658 + do_f##name##q(); \
1621 1659 }
  1660 +#else
  1661 +#define F_HELPER(name) \
  1662 + F_OP(name, s) \
  1663 + { \
  1664 + do_f##name##s(); \
  1665 + } \
  1666 + F_OP(name, d) \
  1667 + { \
  1668 + do_f##name##d(); \
  1669 + }
  1670 +#endif
1622 1671  
1623 1672 F_HELPER(sqrt);
1624 1673  
... ... @@ -1646,6 +1695,18 @@ F_OP(abs, d)
1646 1695 do_fabsd();
1647 1696 }
1648 1697  
  1698 +#if defined(CONFIG_USER_ONLY)
  1699 +F_OP(neg, q)
  1700 +{
  1701 + QT0 = float128_chs(QT1);
  1702 +}
  1703 +
  1704 +F_OP(abs, q)
  1705 +{
  1706 + do_fabsd();
  1707 +}
  1708 +#endif
  1709 +
1649 1710 void OPPROTO op_fcmps_fcc1(void)
1650 1711 {
1651 1712 do_fcmps_fcc1();
... ... @@ -1706,6 +1767,38 @@ void OPPROTO op_fcmped_fcc3(void)
1706 1767 do_fcmped_fcc3();
1707 1768 }
1708 1769  
  1770 +#if defined(CONFIG_USER_ONLY)
  1771 +void OPPROTO op_fcmpq_fcc1(void)
  1772 +{
  1773 + do_fcmpq_fcc1();
  1774 +}
  1775 +
  1776 +void OPPROTO op_fcmpq_fcc2(void)
  1777 +{
  1778 + do_fcmpq_fcc2();
  1779 +}
  1780 +
  1781 +void OPPROTO op_fcmpq_fcc3(void)
  1782 +{
  1783 + do_fcmpq_fcc3();
  1784 +}
  1785 +
  1786 +void OPPROTO op_fcmpeq_fcc1(void)
  1787 +{
  1788 + do_fcmpeq_fcc1();
  1789 +}
  1790 +
  1791 +void OPPROTO op_fcmpeq_fcc2(void)
  1792 +{
  1793 + do_fcmpeq_fcc2();
  1794 +}
  1795 +
  1796 +void OPPROTO op_fcmpeq_fcc3(void)
  1797 +{
  1798 + do_fcmpeq_fcc3();
  1799 +}
  1800 +#endif
  1801 +
1709 1802 #endif
1710 1803  
1711 1804 /* Integer to float conversion. */
... ... @@ -1729,6 +1822,15 @@ F_OP(ito, d)
1729 1822 check_ieee_exceptions();
1730 1823 }
1731 1824  
  1825 +#if defined(CONFIG_USER_ONLY)
  1826 +F_OP(ito, q)
  1827 +{
  1828 + set_float_exception_flags(0, &env->fp_status);
  1829 + QT0 = int32_to_float128(*((int32_t *)&FT1), &env->fp_status);
  1830 + check_ieee_exceptions();
  1831 +}
  1832 +#endif
  1833 +
1732 1834 #ifdef TARGET_SPARC64
1733 1835 F_OP(xto, s)
1734 1836 {
... ... @@ -1743,6 +1845,14 @@ F_OP(xto, d)
1743 1845 DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
1744 1846 check_ieee_exceptions();
1745 1847 }
  1848 +#if defined(CONFIG_USER_ONLY)
  1849 +F_OP(xto, q)
  1850 +{
  1851 + set_float_exception_flags(0, &env->fp_status);
  1852 + QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
  1853 + check_ieee_exceptions();
  1854 +}
  1855 +#endif
1746 1856 #endif
1747 1857 #endif
1748 1858 #undef F_HELPER
... ... @@ -1762,6 +1872,36 @@ void OPPROTO op_fstod(void)
1762 1872 check_ieee_exceptions();
1763 1873 }
1764 1874  
  1875 +#if defined(CONFIG_USER_ONLY)
  1876 +void OPPROTO op_fqtos(void)
  1877 +{
  1878 + set_float_exception_flags(0, &env->fp_status);
  1879 + FT0 = float128_to_float32(QT1, &env->fp_status);
  1880 + check_ieee_exceptions();
  1881 +}
  1882 +
  1883 +void OPPROTO op_fstoq(void)
  1884 +{
  1885 + set_float_exception_flags(0, &env->fp_status);
  1886 + QT0 = float32_to_float128(FT1, &env->fp_status);
  1887 + check_ieee_exceptions();
  1888 +}
  1889 +
  1890 +void OPPROTO op_fqtod(void)
  1891 +{
  1892 + set_float_exception_flags(0, &env->fp_status);
  1893 + DT0 = float128_to_float64(QT1, &env->fp_status);
  1894 + check_ieee_exceptions();
  1895 +}
  1896 +
  1897 +void OPPROTO op_fdtoq(void)
  1898 +{
  1899 + set_float_exception_flags(0, &env->fp_status);
  1900 + QT0 = float64_to_float128(DT1, &env->fp_status);
  1901 + check_ieee_exceptions();
  1902 +}
  1903 +#endif
  1904 +
1765 1905 /* Float to integer conversion. */
1766 1906 void OPPROTO op_fstoi(void)
1767 1907 {
... ... @@ -1777,6 +1917,15 @@ void OPPROTO op_fdtoi(void)
1777 1917 check_ieee_exceptions();
1778 1918 }
1779 1919  
  1920 +#if defined(CONFIG_USER_ONLY)
  1921 +void OPPROTO op_fqtoi(void)
  1922 +{
  1923 + set_float_exception_flags(0, &env->fp_status);
  1924 + *((int32_t *)&FT0) = float128_to_int32_round_to_zero(QT1, &env->fp_status);
  1925 + check_ieee_exceptions();
  1926 +}
  1927 +#endif
  1928 +
1780 1929 #ifdef TARGET_SPARC64
1781 1930 void OPPROTO op_fstox(void)
1782 1931 {
... ... @@ -1792,6 +1941,15 @@ void OPPROTO op_fdtox(void)
1792 1941 check_ieee_exceptions();
1793 1942 }
1794 1943  
  1944 +#if defined(CONFIG_USER_ONLY)
  1945 +void OPPROTO op_fqtox(void)
  1946 +{
  1947 + set_float_exception_flags(0, &env->fp_status);
  1948 + *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
  1949 + check_ieee_exceptions();
  1950 +}
  1951 +#endif
  1952 +
1795 1953 void OPPROTO op_fmovs_cc(void)
1796 1954 {
1797 1955 if (T2)
... ... @@ -1804,6 +1962,14 @@ void OPPROTO op_fmovd_cc(void)
1804 1962 DT0 = DT1;
1805 1963 }
1806 1964  
  1965 +#if defined(CONFIG_USER_ONLY)
  1966 +void OPPROTO op_fmovq_cc(void)
  1967 +{
  1968 + if (T2)
  1969 + QT0 = QT1;
  1970 +}
  1971 +#endif
  1972 +
1807 1973 void OPPROTO op_mov_cc(void)
1808 1974 {
1809 1975 if (T2)
... ...
target-sparc/op_helper.c
... ... @@ -97,6 +97,13 @@ void do_fabsd(void)
97 97 {
98 98 DT0 = float64_abs(DT1);
99 99 }
  100 +
  101 +#if defined(CONFIG_USER_ONLY)
  102 +void do_fabsq(void)
  103 +{
  104 + QT0 = float128_abs(QT1);
  105 +}
  106 +#endif
100 107 #endif
101 108  
102 109 void do_fsqrts(void)
... ... @@ -113,6 +120,15 @@ void do_fsqrtd(void)
113 120 check_ieee_exceptions();
114 121 }
115 122  
  123 +#if defined(CONFIG_USER_ONLY)
  124 +void do_fsqrtq(void)
  125 +{
  126 + set_float_exception_flags(0, &env->fp_status);
  127 + QT0 = float128_sqrt(QT1, &env->fp_status);
  128 + check_ieee_exceptions();
  129 +}
  130 +#endif
  131 +
116 132 #define GEN_FCMP(name, size, reg1, reg2, FS, TRAP) \
117 133 void glue(do_, name) (void) \
118 134 { \
... ... @@ -148,6 +164,11 @@ GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
148 164 GEN_FCMP(fcmpes, float32, FT0, FT1, 0, 1);
149 165 GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
150 166  
  167 +#ifdef CONFIG_USER_ONLY
  168 +GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
  169 +GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
  170 +#endif
  171 +
151 172 #ifdef TARGET_SPARC64
152 173 GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22, 0);
153 174 GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
... ... @@ -166,6 +187,14 @@ GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
166 187  
167 188 GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1);
168 189 GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
  190 +#ifdef CONFIG_USER_ONLY
  191 +GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
  192 +GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
  193 +GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
  194 +GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
  195 +GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
  196 +GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
  197 +#endif
169 198 #endif
170 199  
171 200 #ifndef TARGET_SPARC64
... ... @@ -1374,6 +1403,11 @@ void helper_ldf_asi(int asi, int size, int rd)
1374 1403 case 8:
1375 1404 *((int64_t *)&DT0) = T1;
1376 1405 break;
  1406 +#if defined(CONFIG_USER_ONLY)
  1407 + case 16:
  1408 + // XXX
  1409 + break;
  1410 +#endif
1377 1411 }
1378 1412 T1 = tmp_T1;
1379 1413 }
... ... @@ -1417,6 +1451,11 @@ void helper_stf_asi(int asi, int size, int rd)
1417 1451 case 8:
1418 1452 T1 = *((int64_t *)&DT0);
1419 1453 break;
  1454 +#if defined(CONFIG_USER_ONLY)
  1455 + case 16:
  1456 + // XXX
  1457 + break;
  1458 +#endif
1420 1459 }
1421 1460 helper_st_asi(asi, size);
1422 1461 T1 = tmp_T1;
... ...
target-sparc/op_mem.h
... ... @@ -85,6 +85,28 @@ void OPPROTO glue(op_lddf, MEMSUFFIX) (void)
85 85 DT0 = glue(ldfq, MEMSUFFIX)(ADDR(T0));
86 86 }
87 87  
  88 +#if defined(CONFIG_USER_ONLY)
  89 +void OPPROTO glue(op_ldqf, MEMSUFFIX) (void)
  90 +{
  91 + // XXX add 128 bit load
  92 + CPU_QuadU u;
  93 +
  94 + u.ll.upper = glue(ldq, MEMSUFFIX)(ADDR(T0));
  95 + u.ll.lower = glue(ldq, MEMSUFFIX)(ADDR(T0 + 8));
  96 + QT0 = u.q;
  97 +}
  98 +
  99 +void OPPROTO glue(op_stqf, MEMSUFFIX) (void)
  100 +{
  101 + // XXX add 128 bit store
  102 + CPU_QuadU u;
  103 +
  104 + u.q = QT0;
  105 + glue(stq, MEMSUFFIX)(ADDR(T0), u.ll.upper);
  106 + glue(stq, MEMSUFFIX)(ADDR(T0 + 8), u.ll.lower);
  107 +}
  108 +#endif
  109 +
88 110 #ifdef TARGET_SPARC64
89 111 void OPPROTO glue(op_lduw, MEMSUFFIX)(void)
90 112 {
... ...
target-sparc/translate.c
... ... @@ -25,7 +25,6 @@
25 25 Rest of V9 instructions, VIS instructions
26 26 NPC/PC static optimisations (use JUMP_TB when possible)
27 27 Optimize synthetic instructions
28   - 128-bit float
29 28 */
30 29  
31 30 #include <stdarg.h>
... ... @@ -93,8 +92,10 @@ enum {
93 92  
94 93 #ifdef TARGET_SPARC64
95 94 #define DFPREG(r) (((r & 1) << 5) | (r & 0x1e))
  95 +#define QFPREG(r) (((r & 1) << 5) | (r & 0x1c))
96 96 #else
97 97 #define DFPREG(r) (r & 0x1e)
  98 +#define QFPREG(r) (r & 0x1c)
98 99 #endif
99 100  
100 101 #ifdef USE_DIRECT_JUMP
... ... @@ -351,6 +352,13 @@ GEN32(gen_op_load_fpr_DT1, gen_op_load_fpr_DT1_fprf);
351 352 GEN32(gen_op_store_DT0_fpr, gen_op_store_DT0_fpr_fprf);
352 353 GEN32(gen_op_store_DT1_fpr, gen_op_store_DT1_fpr_fprf);
353 354  
  355 +#if defined(CONFIG_USER_ONLY)
  356 +GEN32(gen_op_load_fpr_QT0, gen_op_load_fpr_QT0_fprf);
  357 +GEN32(gen_op_load_fpr_QT1, gen_op_load_fpr_QT1_fprf);
  358 +GEN32(gen_op_store_QT0_fpr, gen_op_store_QT0_fpr_fprf);
  359 +GEN32(gen_op_store_QT1_fpr, gen_op_store_QT1_fpr_fprf);
  360 +#endif
  361 +
354 362 /* moves */
355 363 #ifdef CONFIG_USER_ONLY
356 364 #define supervisor(dc) 0
... ... @@ -1060,6 +1068,15 @@ static GenOpFunc * const gen_fcmpd[4] = {
1060 1068 gen_op_fcmpd_fcc3,
1061 1069 };
1062 1070  
  1071 +#if defined(CONFIG_USER_ONLY)
  1072 +static GenOpFunc * const gen_fcmpq[4] = {
  1073 + gen_op_fcmpq,
  1074 + gen_op_fcmpq_fcc1,
  1075 + gen_op_fcmpq_fcc2,
  1076 + gen_op_fcmpq_fcc3,
  1077 +};
  1078 +#endif
  1079 +
1063 1080 static GenOpFunc * const gen_fcmpes[4] = {
1064 1081 gen_op_fcmpes,
1065 1082 gen_op_fcmpes_fcc1,
... ... @@ -1074,6 +1091,14 @@ static GenOpFunc * const gen_fcmped[4] = {
1074 1091 gen_op_fcmped_fcc3,
1075 1092 };
1076 1093  
  1094 +#if defined(CONFIG_USER_ONLY)
  1095 +static GenOpFunc * const gen_fcmpeq[4] = {
  1096 + gen_op_fcmpeq,
  1097 + gen_op_fcmpeq_fcc1,
  1098 + gen_op_fcmpeq_fcc2,
  1099 + gen_op_fcmpeq_fcc3,
  1100 +};
  1101 +#endif
1077 1102 #endif
1078 1103  
1079 1104 static int gen_trap_ifnofpu(DisasContext * dc)
... ... @@ -1484,7 +1509,14 @@ static void disas_sparc_insn(DisasContext * dc)
1484 1509 gen_op_store_DT0_fpr(DFPREG(rd));
1485 1510 break;
1486 1511 case 0x2b: /* fsqrtq */
  1512 +#if defined(CONFIG_USER_ONLY)
  1513 + gen_op_load_fpr_QT1(QFPREG(rs2));
  1514 + gen_op_fsqrtq();
  1515 + gen_op_store_QT0_fpr(QFPREG(rd));
  1516 + break;
  1517 +#else
1487 1518 goto nfpu_insn;
  1519 +#endif
1488 1520 case 0x41:
1489 1521 gen_op_load_fpr_FT0(rs1);
1490 1522 gen_op_load_fpr_FT1(rs2);
... ... @@ -1498,7 +1530,15 @@ static void disas_sparc_insn(DisasContext * dc)
1498 1530 gen_op_store_DT0_fpr(DFPREG(rd));
1499 1531 break;
1500 1532 case 0x43: /* faddq */
  1533 +#if defined(CONFIG_USER_ONLY)
  1534 + gen_op_load_fpr_QT0(QFPREG(rs1));
  1535 + gen_op_load_fpr_QT1(QFPREG(rs2));
  1536 + gen_op_faddq();
  1537 + gen_op_store_QT0_fpr(QFPREG(rd));
  1538 + break;
  1539 +#else
1501 1540 goto nfpu_insn;
  1541 +#endif
1502 1542 case 0x45:
1503 1543 gen_op_load_fpr_FT0(rs1);
1504 1544 gen_op_load_fpr_FT1(rs2);
... ... @@ -1512,7 +1552,15 @@ static void disas_sparc_insn(DisasContext * dc)
1512 1552 gen_op_store_DT0_fpr(DFPREG(rd));
1513 1553 break;
1514 1554 case 0x47: /* fsubq */
  1555 +#if defined(CONFIG_USER_ONLY)
  1556 + gen_op_load_fpr_QT0(QFPREG(rs1));
  1557 + gen_op_load_fpr_QT1(QFPREG(rs2));
  1558 + gen_op_fsubq();
  1559 + gen_op_store_QT0_fpr(QFPREG(rd));
  1560 + break;
  1561 +#else
1515 1562 goto nfpu_insn;
  1563 +#endif
1516 1564 case 0x49:
1517 1565 gen_op_load_fpr_FT0(rs1);
1518 1566 gen_op_load_fpr_FT1(rs2);
... ... @@ -1526,7 +1574,15 @@ static void disas_sparc_insn(DisasContext * dc)
1526 1574 gen_op_store_DT0_fpr(rd);
1527 1575 break;
1528 1576 case 0x4b: /* fmulq */
  1577 +#if defined(CONFIG_USER_ONLY)
  1578 + gen_op_load_fpr_QT0(QFPREG(rs1));
  1579 + gen_op_load_fpr_QT1(QFPREG(rs2));
  1580 + gen_op_fmulq();
  1581 + gen_op_store_QT0_fpr(QFPREG(rd));
  1582 + break;
  1583 +#else
1529 1584 goto nfpu_insn;
  1585 +#endif
1530 1586 case 0x4d:
1531 1587 gen_op_load_fpr_FT0(rs1);
1532 1588 gen_op_load_fpr_FT1(rs2);
... ... @@ -1540,7 +1596,15 @@ static void disas_sparc_insn(DisasContext * dc)
1540 1596 gen_op_store_DT0_fpr(DFPREG(rd));
1541 1597 break;
1542 1598 case 0x4f: /* fdivq */
  1599 +#if defined(CONFIG_USER_ONLY)
  1600 + gen_op_load_fpr_QT0(QFPREG(rs1));
  1601 + gen_op_load_fpr_QT1(QFPREG(rs2));
  1602 + gen_op_fdivq();
  1603 + gen_op_store_QT0_fpr(QFPREG(rd));
  1604 + break;
  1605 +#else
1543 1606 goto nfpu_insn;
  1607 +#endif
1544 1608 case 0x69:
1545 1609 gen_op_load_fpr_FT0(rs1);
1546 1610 gen_op_load_fpr_FT1(rs2);
... ... @@ -1548,7 +1612,15 @@ static void disas_sparc_insn(DisasContext * dc)
1548 1612 gen_op_store_DT0_fpr(DFPREG(rd));
1549 1613 break;
1550 1614 case 0x6e: /* fdmulq */
  1615 +#if defined(CONFIG_USER_ONLY)
  1616 + gen_op_load_fpr_DT0(DFPREG(rs1));
  1617 + gen_op_load_fpr_DT1(DFPREG(rs2));
  1618 + gen_op_fdmulq();
  1619 + gen_op_store_QT0_fpr(QFPREG(rd));
  1620 + break;
  1621 +#else
1551 1622 goto nfpu_insn;
  1623 +#endif
1552 1624 case 0xc4:
1553 1625 gen_op_load_fpr_FT1(rs2);
1554 1626 gen_op_fitos();
... ... @@ -1560,7 +1632,14 @@ static void disas_sparc_insn(DisasContext * dc)
1560 1632 gen_op_store_FT0_fpr(rd);
1561 1633 break;
1562 1634 case 0xc7: /* fqtos */
  1635 +#if defined(CONFIG_USER_ONLY)
  1636 + gen_op_load_fpr_QT1(QFPREG(rs2));
  1637 + gen_op_fqtos();
  1638 + gen_op_store_FT0_fpr(rd);
  1639 + break;
  1640 +#else
1563 1641 goto nfpu_insn;
  1642 +#endif
1564 1643 case 0xc8:
1565 1644 gen_op_load_fpr_FT1(rs2);
1566 1645 gen_op_fitod();
... ... @@ -1572,13 +1651,41 @@ static void disas_sparc_insn(DisasContext * dc)
1572 1651 gen_op_store_DT0_fpr(DFPREG(rd));
1573 1652 break;
1574 1653 case 0xcb: /* fqtod */
  1654 +#if defined(CONFIG_USER_ONLY)
  1655 + gen_op_load_fpr_QT1(QFPREG(rs2));
  1656 + gen_op_fqtod();
  1657 + gen_op_store_DT0_fpr(DFPREG(rd));
  1658 + break;
  1659 +#else
1575 1660 goto nfpu_insn;
  1661 +#endif
1576 1662 case 0xcc: /* fitoq */
  1663 +#if defined(CONFIG_USER_ONLY)
  1664 + gen_op_load_fpr_FT1(rs2);
  1665 + gen_op_fitoq();
  1666 + gen_op_store_QT0_fpr(QFPREG(rd));
  1667 + break;
  1668 +#else
1577 1669 goto nfpu_insn;
  1670 +#endif
1578 1671 case 0xcd: /* fstoq */
  1672 +#if defined(CONFIG_USER_ONLY)
  1673 + gen_op_load_fpr_FT1(rs2);
  1674 + gen_op_fstoq();
  1675 + gen_op_store_QT0_fpr(QFPREG(rd));
  1676 + break;
  1677 +#else
1579 1678 goto nfpu_insn;
  1679 +#endif
1580 1680 case 0xce: /* fdtoq */
  1681 +#if defined(CONFIG_USER_ONLY)
  1682 + gen_op_load_fpr_DT1(DFPREG(rs2));
  1683 + gen_op_fdtoq();
  1684 + gen_op_store_QT0_fpr(QFPREG(rd));
  1685 + break;
  1686 +#else
1581 1687 goto nfpu_insn;
  1688 +#endif
1582 1689 case 0xd1:
1583 1690 gen_op_load_fpr_FT1(rs2);
1584 1691 gen_op_fstoi();
... ... @@ -1590,22 +1697,55 @@ static void disas_sparc_insn(DisasContext * dc)
1590 1697 gen_op_store_FT0_fpr(rd);
1591 1698 break;
1592 1699 case 0xd3: /* fqtoi */
  1700 +#if defined(CONFIG_USER_ONLY)
  1701 + gen_op_load_fpr_QT1(QFPREG(rs2));
  1702 + gen_op_fqtoi();
  1703 + gen_op_store_FT0_fpr(rd);
  1704 + break;
  1705 +#else
1593 1706 goto nfpu_insn;
  1707 +#endif
1594 1708 #ifdef TARGET_SPARC64
1595 1709 case 0x2: /* V9 fmovd */
1596 1710 gen_op_load_fpr_DT0(DFPREG(rs2));
1597 1711 gen_op_store_DT0_fpr(DFPREG(rd));
1598 1712 break;
  1713 + case 0x3: /* V9 fmovq */
  1714 +#if defined(CONFIG_USER_ONLY)
  1715 + gen_op_load_fpr_QT0(QFPREG(rs2));
  1716 + gen_op_store_QT0_fpr(QFPREG(rd));
  1717 + break;
  1718 +#else
  1719 + goto nfpu_insn;
  1720 +#endif
1599 1721 case 0x6: /* V9 fnegd */
1600 1722 gen_op_load_fpr_DT1(DFPREG(rs2));
1601 1723 gen_op_fnegd();
1602 1724 gen_op_store_DT0_fpr(DFPREG(rd));
1603 1725 break;
  1726 + case 0x7: /* V9 fnegq */
  1727 +#if defined(CONFIG_USER_ONLY)
  1728 + gen_op_load_fpr_QT1(QFPREG(rs2));
  1729 + gen_op_fnegq();
  1730 + gen_op_store_QT0_fpr(QFPREG(rd));
  1731 + break;
  1732 +#else
  1733 + goto nfpu_insn;
  1734 +#endif
1604 1735 case 0xa: /* V9 fabsd */
1605 1736 gen_op_load_fpr_DT1(DFPREG(rs2));
1606 1737 gen_op_fabsd();
1607 1738 gen_op_store_DT0_fpr(DFPREG(rd));
1608 1739 break;
  1740 + case 0xb: /* V9 fabsq */
  1741 +#if defined(CONFIG_USER_ONLY)
  1742 + gen_op_load_fpr_QT1(QFPREG(rs2));
  1743 + gen_op_fabsq();
  1744 + gen_op_store_QT0_fpr(QFPREG(rd));
  1745 + break;
  1746 +#else
  1747 + goto nfpu_insn;
  1748 +#endif
1609 1749 case 0x81: /* V9 fstox */
1610 1750 gen_op_load_fpr_FT1(rs2);
1611 1751 gen_op_fstox();
... ... @@ -1616,6 +1756,15 @@ static void disas_sparc_insn(DisasContext * dc)
1616 1756 gen_op_fdtox();
1617 1757 gen_op_store_DT0_fpr(DFPREG(rd));
1618 1758 break;
  1759 + case 0x83: /* V9 fqtox */
  1760 +#if defined(CONFIG_USER_ONLY)
  1761 + gen_op_load_fpr_QT1(QFPREG(rs2));
  1762 + gen_op_fqtox();
  1763 + gen_op_store_DT0_fpr(DFPREG(rd));
  1764 + break;
  1765 +#else
  1766 + goto nfpu_insn;
  1767 +#endif
1619 1768 case 0x84: /* V9 fxtos */
1620 1769 gen_op_load_fpr_DT1(DFPREG(rs2));
1621 1770 gen_op_fxtos();
... ... @@ -1626,13 +1775,16 @@ static void disas_sparc_insn(DisasContext * dc)
1626 1775 gen_op_fxtod();
1627 1776 gen_op_store_DT0_fpr(DFPREG(rd));
1628 1777 break;
1629   - case 0x3: /* V9 fmovq */
1630   - case 0x7: /* V9 fnegq */
1631   - case 0xb: /* V9 fabsq */
1632   - case 0x83: /* V9 fqtox */
1633 1778 case 0x8c: /* V9 fxtoq */
  1779 +#if defined(CONFIG_USER_ONLY)
  1780 + gen_op_load_fpr_DT1(DFPREG(rs2));
  1781 + gen_op_fxtoq();
  1782 + gen_op_store_QT0_fpr(QFPREG(rd));
  1783 + break;
  1784 +#else
1634 1785 goto nfpu_insn;
1635 1786 #endif
  1787 +#endif
1636 1788 default:
1637 1789 goto illegal_insn;
1638 1790 }
... ... @@ -1670,7 +1822,20 @@ static void disas_sparc_insn(DisasContext * dc)
1670 1822 gen_op_store_DT0_fpr(rd);
1671 1823 break;
1672 1824 } else if ((xop & 0x11f) == 0x007) { // V9 fmovqr
  1825 +#if defined(CONFIG_USER_ONLY)
  1826 + cond = GET_FIELD_SP(insn, 14, 17);
  1827 + gen_op_load_fpr_QT0(QFPREG(rd));
  1828 + gen_op_load_fpr_QT1(QFPREG(rs2));
  1829 + flush_T2(dc);
  1830 + rs1 = GET_FIELD(insn, 13, 17);
  1831 + gen_movl_reg_T0(rs1);
  1832 + gen_cond_reg(cond);
  1833 + gen_op_fmovq_cc();
  1834 + gen_op_store_QT0_fpr(QFPREG(rd));
  1835 + break;
  1836 +#else
1673 1837 goto nfpu_insn;
  1838 +#endif
1674 1839 }
1675 1840 #endif
1676 1841 switch (xop) {
... ... @@ -1694,7 +1859,18 @@ static void disas_sparc_insn(DisasContext * dc)
1694 1859 gen_op_store_DT0_fpr(rd);
1695 1860 break;
1696 1861 case 0x003: /* V9 fmovqcc %fcc0 */
  1862 +#if defined(CONFIG_USER_ONLY)
  1863 + cond = GET_FIELD_SP(insn, 14, 17);
  1864 + gen_op_load_fpr_QT0(QFPREG(rd));
  1865 + gen_op_load_fpr_QT1(QFPREG(rs2));
  1866 + flush_T2(dc);
  1867 + gen_fcond[0][cond]();
  1868 + gen_op_fmovq_cc();
  1869 + gen_op_store_QT0_fpr(QFPREG(rd));
  1870 + break;
  1871 +#else
1697 1872 goto nfpu_insn;
  1873 +#endif
1698 1874 case 0x041: /* V9 fmovscc %fcc1 */
1699 1875 cond = GET_FIELD_SP(insn, 14, 17);
1700 1876 gen_op_load_fpr_FT0(rd);
... ... @@ -1714,7 +1890,18 @@ static void disas_sparc_insn(DisasContext * dc)
1714 1890 gen_op_store_DT0_fpr(rd);
1715 1891 break;
1716 1892 case 0x043: /* V9 fmovqcc %fcc1 */
  1893 +#if defined(CONFIG_USER_ONLY)
  1894 + cond = GET_FIELD_SP(insn, 14, 17);
  1895 + gen_op_load_fpr_QT0(QFPREG(rd));
  1896 + gen_op_load_fpr_QT1(QFPREG(rs2));
  1897 + flush_T2(dc);
  1898 + gen_fcond[1][cond]();
  1899 + gen_op_fmovq_cc();
  1900 + gen_op_store_QT0_fpr(QFPREG(rd));
  1901 + break;
  1902 +#else
1717 1903 goto nfpu_insn;
  1904 +#endif
1718 1905 case 0x081: /* V9 fmovscc %fcc2 */
1719 1906 cond = GET_FIELD_SP(insn, 14, 17);
1720 1907 gen_op_load_fpr_FT0(rd);
... ... @@ -1734,7 +1921,18 @@ static void disas_sparc_insn(DisasContext * dc)
1734 1921 gen_op_store_DT0_fpr(rd);
1735 1922 break;
1736 1923 case 0x083: /* V9 fmovqcc %fcc2 */
  1924 +#if defined(CONFIG_USER_ONLY)
  1925 + cond = GET_FIELD_SP(insn, 14, 17);
  1926 + gen_op_load_fpr_QT0(rd);
  1927 + gen_op_load_fpr_QT1(rs2);
  1928 + flush_T2(dc);
  1929 + gen_fcond[2][cond]();
  1930 + gen_op_fmovq_cc();
  1931 + gen_op_store_QT0_fpr(rd);
  1932 + break;
  1933 +#else
1737 1934 goto nfpu_insn;
  1935 +#endif
1738 1936 case 0x0c1: /* V9 fmovscc %fcc3 */
1739 1937 cond = GET_FIELD_SP(insn, 14, 17);
1740 1938 gen_op_load_fpr_FT0(rd);
... ... @@ -1754,7 +1952,18 @@ static void disas_sparc_insn(DisasContext * dc)
1754 1952 gen_op_store_DT0_fpr(rd);
1755 1953 break;
1756 1954 case 0x0c3: /* V9 fmovqcc %fcc3 */
  1955 +#if defined(CONFIG_USER_ONLY)
  1956 + cond = GET_FIELD_SP(insn, 14, 17);
  1957 + gen_op_load_fpr_QT0(QFPREG(rd));
  1958 + gen_op_load_fpr_QT1(QFPREG(rs2));
  1959 + flush_T2(dc);
  1960 + gen_fcond[3][cond]();
  1961 + gen_op_fmovq_cc();
  1962 + gen_op_store_QT0_fpr(QFPREG(rd));
  1963 + break;
  1964 +#else
1757 1965 goto nfpu_insn;
  1966 +#endif
1758 1967 case 0x101: /* V9 fmovscc %icc */
1759 1968 cond = GET_FIELD_SP(insn, 14, 17);
1760 1969 gen_op_load_fpr_FT0(rd);
... ... @@ -1774,7 +1983,18 @@ static void disas_sparc_insn(DisasContext * dc)
1774 1983 gen_op_store_DT0_fpr(rd);
1775 1984 break;
1776 1985 case 0x103: /* V9 fmovqcc %icc */
  1986 +#if defined(CONFIG_USER_ONLY)
  1987 + cond = GET_FIELD_SP(insn, 14, 17);
  1988 + gen_op_load_fpr_QT0(rd);
  1989 + gen_op_load_fpr_QT1(rs2);
  1990 + flush_T2(dc);
  1991 + gen_cond[0][cond]();
  1992 + gen_op_fmovq_cc();
  1993 + gen_op_store_QT0_fpr(rd);
  1994 + break;
  1995 +#else
1777 1996 goto nfpu_insn;
  1997 +#endif
1778 1998 case 0x181: /* V9 fmovscc %xcc */
1779 1999 cond = GET_FIELD_SP(insn, 14, 17);
1780 2000 gen_op_load_fpr_FT0(rd);
... ... @@ -1794,9 +2014,20 @@ static void disas_sparc_insn(DisasContext * dc)
1794 2014 gen_op_store_DT0_fpr(rd);
1795 2015 break;
1796 2016 case 0x183: /* V9 fmovqcc %xcc */
  2017 +#if defined(CONFIG_USER_ONLY)
  2018 + cond = GET_FIELD_SP(insn, 14, 17);
  2019 + gen_op_load_fpr_QT0(rd);
  2020 + gen_op_load_fpr_QT1(rs2);
  2021 + flush_T2(dc);
  2022 + gen_cond[1][cond]();
  2023 + gen_op_fmovq_cc();
  2024 + gen_op_store_QT0_fpr(rd);
  2025 + break;
  2026 +#else
1797 2027 goto nfpu_insn;
1798 2028 #endif
1799   - case 0x51: /* V9 %fcc */
  2029 +#endif
  2030 + case 0x51: /* fcmps, V9 %fcc */
1800 2031 gen_op_load_fpr_FT0(rs1);
1801 2032 gen_op_load_fpr_FT1(rs2);
1802 2033 #ifdef TARGET_SPARC64
... ... @@ -1805,7 +2036,7 @@ static void disas_sparc_insn(DisasContext * dc)
1805 2036 gen_op_fcmps();
1806 2037 #endif
1807 2038 break;
1808   - case 0x52: /* V9 %fcc */
  2039 + case 0x52: /* fcmpd, V9 %fcc */
1809 2040 gen_op_load_fpr_DT0(DFPREG(rs1));
1810 2041 gen_op_load_fpr_DT1(DFPREG(rs2));
1811 2042 #ifdef TARGET_SPARC64
... ... @@ -1814,8 +2045,19 @@ static void disas_sparc_insn(DisasContext * dc)
1814 2045 gen_op_fcmpd();
1815 2046 #endif
1816 2047 break;
1817   - case 0x53: /* fcmpq */
  2048 + case 0x53: /* fcmpq, V9 %fcc */
  2049 +#if defined(CONFIG_USER_ONLY)
  2050 + gen_op_load_fpr_QT0(QFPREG(rs1));
  2051 + gen_op_load_fpr_QT1(QFPREG(rs2));
  2052 +#ifdef TARGET_SPARC64
  2053 + gen_fcmpq[rd & 3]();
  2054 +#else
  2055 + gen_op_fcmpq();
  2056 +#endif
  2057 + break;
  2058 +#else /* !defined(CONFIG_USER_ONLY) */
1818 2059 goto nfpu_insn;
  2060 +#endif
1819 2061 case 0x55: /* fcmpes, V9 %fcc */
1820 2062 gen_op_load_fpr_FT0(rs1);
1821 2063 gen_op_load_fpr_FT1(rs2);
... ... @@ -1834,8 +2076,19 @@ static void disas_sparc_insn(DisasContext * dc)
1834 2076 gen_op_fcmped();
1835 2077 #endif
1836 2078 break;
1837   - case 0x57: /* fcmpeq */
  2079 + case 0x57: /* fcmpeq, V9 %fcc */
  2080 +#if defined(CONFIG_USER_ONLY)
  2081 + gen_op_load_fpr_QT0(QFPREG(rs1));
  2082 + gen_op_load_fpr_QT1(QFPREG(rs2));
  2083 +#ifdef TARGET_SPARC64
  2084 + gen_fcmpeq[rd & 3]();
  2085 +#else
  2086 + gen_op_fcmpeq();
  2087 +#endif
  2088 + break;
  2089 +#else/* !defined(CONFIG_USER_ONLY) */
1838 2090 goto nfpu_insn;
  2091 +#endif
1839 2092 default:
1840 2093 goto illegal_insn;
1841 2094 }
... ... @@ -3095,8 +3348,14 @@ static void disas_sparc_insn(DisasContext * dc)
3095 3348 case 0x3d: /* V9 prefetcha, no effect */
3096 3349 goto skip_move;
3097 3350 case 0x32: /* V9 ldqfa */
  3351 +#if defined(CONFIG_USER_ONLY)
  3352 + gen_op_check_align_T0_3();
  3353 + gen_ldf_asi(insn, 16);
  3354 + goto skip_move;
  3355 +#else
3098 3356 goto nfpu_insn;
3099 3357 #endif
  3358 +#endif
3100 3359 default:
3101 3360 goto illegal_insn;
3102 3361 }
... ... @@ -3119,7 +3378,14 @@ static void disas_sparc_insn(DisasContext * dc)
3119 3378 gen_op_ldfsr();
3120 3379 break;
3121 3380 case 0x22: /* load quad fpreg */
  3381 +#if defined(CONFIG_USER_ONLY)
  3382 + gen_op_check_align_T0_7();
  3383 + gen_op_ldst(ldqf);
  3384 + gen_op_store_QT0_fpr(QFPREG(rd));
  3385 + break;
  3386 +#else
3122 3387 goto nfpu_insn;
  3388 +#endif
3123 3389 case 0x23: /* load double fpreg */
3124 3390 gen_op_check_align_T0_7();
3125 3391 gen_op_ldst(lddf);
... ... @@ -3225,14 +3491,29 @@ static void disas_sparc_insn(DisasContext * dc)
3225 3491 gen_op_stfsr();
3226 3492 gen_op_ldst(stf);
3227 3493 break;
3228   -#if !defined(CONFIG_USER_ONLY)
3229   - case 0x26: /* stdfq */
  3494 + case 0x26:
  3495 +#ifdef TARGET_SPARC64
  3496 +#if defined(CONFIG_USER_ONLY)
  3497 + /* V9 stqf, store quad fpreg */
  3498 + gen_op_check_align_T0_7();
  3499 + gen_op_load_fpr_QT0(QFPREG(rd));
  3500 + gen_op_ldst(stqf);
  3501 + break;
  3502 +#else
  3503 + goto nfpu_insn;
  3504 +#endif
  3505 +#else /* !TARGET_SPARC64 */
  3506 + /* stdfq, store floating point queue */
  3507 +#if defined(CONFIG_USER_ONLY)
  3508 + goto illegal_insn;
  3509 +#else
3230 3510 if (!supervisor(dc))
3231 3511 goto priv_insn;
3232 3512 if (gen_trap_ifnofpu(dc))
3233 3513 goto jmp_insn;
3234 3514 goto nfq_insn;
3235 3515 #endif
  3516 +#endif
3236 3517 case 0x27:
3237 3518 gen_op_check_align_T0_7();
3238 3519 gen_op_load_fpr_DT0(DFPREG(rd));
... ... @@ -3249,6 +3530,15 @@ static void disas_sparc_insn(DisasContext * dc)
3249 3530 gen_op_load_fpr_FT0(rd);
3250 3531 gen_stf_asi(insn, 4);
3251 3532 break;
  3533 + case 0x36: /* V9 stqfa */
  3534 +#if defined(CONFIG_USER_ONLY)
  3535 + gen_op_check_align_T0_7();
  3536 + gen_op_load_fpr_QT0(QFPREG(rd));
  3537 + gen_stf_asi(insn, 16);
  3538 + break;
  3539 +#else
  3540 + goto nfpu_insn;
  3541 +#endif
3252 3542 case 0x37: /* V9 stdfa */
3253 3543 gen_op_check_align_T0_3();
3254 3544 gen_op_load_fpr_DT0(DFPREG(rd));
... ... @@ -3268,8 +3558,6 @@ static void disas_sparc_insn(DisasContext * dc)
3268 3558 gen_casx_asi(insn);
3269 3559 gen_movl_T1_reg(rd);
3270 3560 break;
3271   - case 0x36: /* V9 stqfa */
3272   - goto nfpu_insn;
3273 3561 #else
3274 3562 case 0x34: /* stc */
3275 3563 case 0x35: /* stcsr */
... ... @@ -3311,19 +3599,19 @@ static void disas_sparc_insn(DisasContext * dc)
3311 3599 gen_op_exception(TT_PRIV_INSN);
3312 3600 dc->is_br = 1;
3313 3601 return;
3314   -#endif
3315 3602 nfpu_insn:
3316 3603 save_state(dc);
3317 3604 gen_op_fpexception_im(FSR_FTT_UNIMPFPOP);
3318 3605 dc->is_br = 1;
3319 3606 return;
3320   -#if !defined(CONFIG_USER_ONLY)
  3607 +#ifndef TARGET_SPARC64
3321 3608 nfq_insn:
3322 3609 save_state(dc);
3323 3610 gen_op_fpexception_im(FSR_FTT_SEQ_ERROR);
3324 3611 dc->is_br = 1;
3325 3612 return;
3326 3613 #endif
  3614 +#endif
3327 3615 #ifndef TARGET_SPARC64
3328 3616 ncp_insn:
3329 3617 save_state(dc);
... ...