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,6 +135,36 @@ typedef union {
135 uint64_t ll; 135 uint64_t ll;
136 } CPU_DoubleU; 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 /* CPU memory access without any memory or io remapping */ 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,6 +5421,50 @@ int float ## s ## _compare_quiet( float ## s a, float ## s b STATUS_PARAM ) \
5421 COMPARE(32, 0xff) 5421 COMPARE(32, 0xff)
5422 COMPARE(64, 0x7ff) 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 /* Multiply A by 2 raised to the power N. */ 5468 /* Multiply A by 2 raised to the power N. */
5425 float32 float32_scalbn( float32 a, int n STATUS_PARAM ) 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,6 +415,8 @@ int float128_lt( float128, float128 STATUS_PARAM );
415 int float128_eq_signaling( float128, float128 STATUS_PARAM ); 415 int float128_eq_signaling( float128, float128 STATUS_PARAM );
416 int float128_le_quiet( float128, float128 STATUS_PARAM ); 416 int float128_le_quiet( float128, float128 STATUS_PARAM );
417 int float128_lt_quiet( float128, float128 STATUS_PARAM ); 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 int float128_is_nan( float128 ); 420 int float128_is_nan( float128 );
419 int float128_is_signaling_nan( float128 ); 421 int float128_is_signaling_nan( float128 );
420 float128 float128_scalbn( float128, int STATUS_PARAM ); 422 float128 float128_scalbn( float128, int STATUS_PARAM );
qemu-tech.texi
@@ -212,8 +212,7 @@ Current QEMU limitations: @@ -212,8 +212,7 @@ Current QEMU limitations:
212 212
213 @item IPC syscalls are missing. 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 @item Atomic instructions are not correctly implemented. 217 @item Atomic instructions are not correctly implemented.
219 218
target-sparc/cpu.h
@@ -222,6 +222,9 @@ typedef struct CPUSPARCState { @@ -222,6 +222,9 @@ typedef struct CPUSPARCState {
222 /* temporary float registers */ 222 /* temporary float registers */
223 float32 ft0, ft1; 223 float32 ft0, ft1;
224 float64 dt0, dt1; 224 float64 dt0, dt1;
  225 +#if defined(CONFIG_USER_ONLY)
  226 + float128 qt0, qt1;
  227 +#endif
225 float_status fp_status; 228 float_status fp_status;
226 #if defined(TARGET_SPARC64) 229 #if defined(TARGET_SPARC64)
227 #define MAXTL 4 230 #define MAXTL 4
target-sparc/exec.h
@@ -41,6 +41,10 @@ register uint32_t T2 asm(AREG3); @@ -41,6 +41,10 @@ register uint32_t T2 asm(AREG3);
41 #define FT1 (env->ft1) 41 #define FT1 (env->ft1)
42 #define DT0 (env->dt0) 42 #define DT0 (env->dt0)
43 #define DT1 (env->dt1) 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 #include "cpu.h" 49 #include "cpu.h"
46 #include "exec-all.h" 50 #include "exec-all.h"
@@ -65,6 +69,13 @@ void do_fcmps(void); @@ -65,6 +69,13 @@ void do_fcmps(void);
65 void do_fcmpd(void); 69 void do_fcmpd(void);
66 void do_fcmpes(void); 70 void do_fcmpes(void);
67 void do_fcmped(void); 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 #ifdef TARGET_SPARC64 79 #ifdef TARGET_SPARC64
69 void do_fabsd(void); 80 void do_fabsd(void);
70 void do_fcmps_fcc1(void); 81 void do_fcmps_fcc1(void);
@@ -79,6 +90,14 @@ void do_fcmpes_fcc2(void); @@ -79,6 +90,14 @@ void do_fcmpes_fcc2(void);
79 void do_fcmped_fcc2(void); 90 void do_fcmped_fcc2(void);
80 void do_fcmpes_fcc3(void); 91 void do_fcmpes_fcc3(void);
81 void do_fcmped_fcc3(void); 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 void do_popc(); 101 void do_popc();
83 void do_wrpstate(); 102 void do_wrpstate();
84 void do_done(); 103 void do_done();
target-sparc/fop_template.h
@@ -77,5 +77,52 @@ void OPPROTO glue(op_store_DT1_fpr_fpr, REGNAME)(void) @@ -77,5 +77,52 @@ void OPPROTO glue(op_store_DT1_fpr_fpr, REGNAME)(void)
77 *p = u.l.upper; 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 #undef REG 127 #undef REG
81 #undef REGNAME 128 #undef REGNAME
target-sparc/op.c
@@ -1581,6 +1581,7 @@ void OPPROTO op_clear_ieee_excp_and_FTT(void) @@ -1581,6 +1581,7 @@ void OPPROTO op_clear_ieee_excp_and_FTT(void)
1581 1581
1582 #define F_OP(name, p) void OPPROTO op_f##name##p(void) 1582 #define F_OP(name, p) void OPPROTO op_f##name##p(void)
1583 1583
  1584 +#if defined(CONFIG_USER_ONLY)
1584 #define F_BINOP(name) \ 1585 #define F_BINOP(name) \
1585 F_OP(name, s) \ 1586 F_OP(name, s) \
1586 { \ 1587 { \
@@ -1593,7 +1594,28 @@ void OPPROTO op_clear_ieee_excp_and_FTT(void) @@ -1593,7 +1594,28 @@ void OPPROTO op_clear_ieee_excp_and_FTT(void)
1593 set_float_exception_flags(0, &env->fp_status); \ 1594 set_float_exception_flags(0, &env->fp_status); \
1594 DT0 = float64_ ## name (DT0, DT1, &env->fp_status); \ 1595 DT0 = float64_ ## name (DT0, DT1, &env->fp_status); \
1595 check_ieee_exceptions(); \ 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 F_BINOP(add); 1620 F_BINOP(add);
1599 F_BINOP(sub); 1621 F_BINOP(sub);
@@ -1610,6 +1632,18 @@ void OPPROTO op_fsmuld(void) @@ -1610,6 +1632,18 @@ void OPPROTO op_fsmuld(void)
1610 check_ieee_exceptions(); 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 #define F_HELPER(name) \ 1647 #define F_HELPER(name) \
1614 F_OP(name, s) \ 1648 F_OP(name, s) \
1615 { \ 1649 { \
@@ -1618,7 +1652,22 @@ void OPPROTO op_fsmuld(void) @@ -1618,7 +1652,22 @@ void OPPROTO op_fsmuld(void)
1618 F_OP(name, d) \ 1652 F_OP(name, d) \
1619 { \ 1653 { \
1620 do_f##name##d(); \ 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 F_HELPER(sqrt); 1672 F_HELPER(sqrt);
1624 1673
@@ -1646,6 +1695,18 @@ F_OP(abs, d) @@ -1646,6 +1695,18 @@ F_OP(abs, d)
1646 do_fabsd(); 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 void OPPROTO op_fcmps_fcc1(void) 1710 void OPPROTO op_fcmps_fcc1(void)
1650 { 1711 {
1651 do_fcmps_fcc1(); 1712 do_fcmps_fcc1();
@@ -1706,6 +1767,38 @@ void OPPROTO op_fcmped_fcc3(void) @@ -1706,6 +1767,38 @@ void OPPROTO op_fcmped_fcc3(void)
1706 do_fcmped_fcc3(); 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 #endif 1802 #endif
1710 1803
1711 /* Integer to float conversion. */ 1804 /* Integer to float conversion. */
@@ -1729,6 +1822,15 @@ F_OP(ito, d) @@ -1729,6 +1822,15 @@ F_OP(ito, d)
1729 check_ieee_exceptions(); 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 #ifdef TARGET_SPARC64 1834 #ifdef TARGET_SPARC64
1733 F_OP(xto, s) 1835 F_OP(xto, s)
1734 { 1836 {
@@ -1743,6 +1845,14 @@ F_OP(xto, d) @@ -1743,6 +1845,14 @@ F_OP(xto, d)
1743 DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status); 1845 DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
1744 check_ieee_exceptions(); 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 #endif 1856 #endif
1747 #endif 1857 #endif
1748 #undef F_HELPER 1858 #undef F_HELPER
@@ -1762,6 +1872,36 @@ void OPPROTO op_fstod(void) @@ -1762,6 +1872,36 @@ void OPPROTO op_fstod(void)
1762 check_ieee_exceptions(); 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 /* Float to integer conversion. */ 1905 /* Float to integer conversion. */
1766 void OPPROTO op_fstoi(void) 1906 void OPPROTO op_fstoi(void)
1767 { 1907 {
@@ -1777,6 +1917,15 @@ void OPPROTO op_fdtoi(void) @@ -1777,6 +1917,15 @@ void OPPROTO op_fdtoi(void)
1777 check_ieee_exceptions(); 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 #ifdef TARGET_SPARC64 1929 #ifdef TARGET_SPARC64
1781 void OPPROTO op_fstox(void) 1930 void OPPROTO op_fstox(void)
1782 { 1931 {
@@ -1792,6 +1941,15 @@ void OPPROTO op_fdtox(void) @@ -1792,6 +1941,15 @@ void OPPROTO op_fdtox(void)
1792 check_ieee_exceptions(); 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 void OPPROTO op_fmovs_cc(void) 1953 void OPPROTO op_fmovs_cc(void)
1796 { 1954 {
1797 if (T2) 1955 if (T2)
@@ -1804,6 +1962,14 @@ void OPPROTO op_fmovd_cc(void) @@ -1804,6 +1962,14 @@ void OPPROTO op_fmovd_cc(void)
1804 DT0 = DT1; 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 void OPPROTO op_mov_cc(void) 1973 void OPPROTO op_mov_cc(void)
1808 { 1974 {
1809 if (T2) 1975 if (T2)
target-sparc/op_helper.c
@@ -97,6 +97,13 @@ void do_fabsd(void) @@ -97,6 +97,13 @@ void do_fabsd(void)
97 { 97 {
98 DT0 = float64_abs(DT1); 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 #endif 107 #endif
101 108
102 void do_fsqrts(void) 109 void do_fsqrts(void)
@@ -113,6 +120,15 @@ void do_fsqrtd(void) @@ -113,6 +120,15 @@ void do_fsqrtd(void)
113 check_ieee_exceptions(); 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 #define GEN_FCMP(name, size, reg1, reg2, FS, TRAP) \ 132 #define GEN_FCMP(name, size, reg1, reg2, FS, TRAP) \
117 void glue(do_, name) (void) \ 133 void glue(do_, name) (void) \
118 { \ 134 { \
@@ -148,6 +164,11 @@ GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0); @@ -148,6 +164,11 @@ GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
148 GEN_FCMP(fcmpes, float32, FT0, FT1, 0, 1); 164 GEN_FCMP(fcmpes, float32, FT0, FT1, 0, 1);
149 GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1); 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 #ifdef TARGET_SPARC64 172 #ifdef TARGET_SPARC64
152 GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22, 0); 173 GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22, 0);
153 GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0); 174 GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
@@ -166,6 +187,14 @@ GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1); @@ -166,6 +187,14 @@ GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
166 187
167 GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1); 188 GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1);
168 GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1); 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 #endif 198 #endif
170 199
171 #ifndef TARGET_SPARC64 200 #ifndef TARGET_SPARC64
@@ -1374,6 +1403,11 @@ void helper_ldf_asi(int asi, int size, int rd) @@ -1374,6 +1403,11 @@ void helper_ldf_asi(int asi, int size, int rd)
1374 case 8: 1403 case 8:
1375 *((int64_t *)&DT0) = T1; 1404 *((int64_t *)&DT0) = T1;
1376 break; 1405 break;
  1406 +#if defined(CONFIG_USER_ONLY)
  1407 + case 16:
  1408 + // XXX
  1409 + break;
  1410 +#endif
1377 } 1411 }
1378 T1 = tmp_T1; 1412 T1 = tmp_T1;
1379 } 1413 }
@@ -1417,6 +1451,11 @@ void helper_stf_asi(int asi, int size, int rd) @@ -1417,6 +1451,11 @@ void helper_stf_asi(int asi, int size, int rd)
1417 case 8: 1451 case 8:
1418 T1 = *((int64_t *)&DT0); 1452 T1 = *((int64_t *)&DT0);
1419 break; 1453 break;
  1454 +#if defined(CONFIG_USER_ONLY)
  1455 + case 16:
  1456 + // XXX
  1457 + break;
  1458 +#endif
1420 } 1459 }
1421 helper_st_asi(asi, size); 1460 helper_st_asi(asi, size);
1422 T1 = tmp_T1; 1461 T1 = tmp_T1;
target-sparc/op_mem.h
@@ -85,6 +85,28 @@ void OPPROTO glue(op_lddf, MEMSUFFIX) (void) @@ -85,6 +85,28 @@ void OPPROTO glue(op_lddf, MEMSUFFIX) (void)
85 DT0 = glue(ldfq, MEMSUFFIX)(ADDR(T0)); 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 #ifdef TARGET_SPARC64 110 #ifdef TARGET_SPARC64
89 void OPPROTO glue(op_lduw, MEMSUFFIX)(void) 111 void OPPROTO glue(op_lduw, MEMSUFFIX)(void)
90 { 112 {
target-sparc/translate.c
@@ -25,7 +25,6 @@ @@ -25,7 +25,6 @@
25 Rest of V9 instructions, VIS instructions 25 Rest of V9 instructions, VIS instructions
26 NPC/PC static optimisations (use JUMP_TB when possible) 26 NPC/PC static optimisations (use JUMP_TB when possible)
27 Optimize synthetic instructions 27 Optimize synthetic instructions
28 - 128-bit float  
29 */ 28 */
30 29
31 #include <stdarg.h> 30 #include <stdarg.h>
@@ -93,8 +92,10 @@ enum { @@ -93,8 +92,10 @@ enum {
93 92
94 #ifdef TARGET_SPARC64 93 #ifdef TARGET_SPARC64
95 #define DFPREG(r) (((r & 1) << 5) | (r & 0x1e)) 94 #define DFPREG(r) (((r & 1) << 5) | (r & 0x1e))
  95 +#define QFPREG(r) (((r & 1) << 5) | (r & 0x1c))
96 #else 96 #else
97 #define DFPREG(r) (r & 0x1e) 97 #define DFPREG(r) (r & 0x1e)
  98 +#define QFPREG(r) (r & 0x1c)
98 #endif 99 #endif
99 100
100 #ifdef USE_DIRECT_JUMP 101 #ifdef USE_DIRECT_JUMP
@@ -351,6 +352,13 @@ GEN32(gen_op_load_fpr_DT1, gen_op_load_fpr_DT1_fprf); @@ -351,6 +352,13 @@ GEN32(gen_op_load_fpr_DT1, gen_op_load_fpr_DT1_fprf);
351 GEN32(gen_op_store_DT0_fpr, gen_op_store_DT0_fpr_fprf); 352 GEN32(gen_op_store_DT0_fpr, gen_op_store_DT0_fpr_fprf);
352 GEN32(gen_op_store_DT1_fpr, gen_op_store_DT1_fpr_fprf); 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 /* moves */ 362 /* moves */
355 #ifdef CONFIG_USER_ONLY 363 #ifdef CONFIG_USER_ONLY
356 #define supervisor(dc) 0 364 #define supervisor(dc) 0
@@ -1060,6 +1068,15 @@ static GenOpFunc * const gen_fcmpd[4] = { @@ -1060,6 +1068,15 @@ static GenOpFunc * const gen_fcmpd[4] = {
1060 gen_op_fcmpd_fcc3, 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 static GenOpFunc * const gen_fcmpes[4] = { 1080 static GenOpFunc * const gen_fcmpes[4] = {
1064 gen_op_fcmpes, 1081 gen_op_fcmpes,
1065 gen_op_fcmpes_fcc1, 1082 gen_op_fcmpes_fcc1,
@@ -1074,6 +1091,14 @@ static GenOpFunc * const gen_fcmped[4] = { @@ -1074,6 +1091,14 @@ static GenOpFunc * const gen_fcmped[4] = {
1074 gen_op_fcmped_fcc3, 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 #endif 1102 #endif
1078 1103
1079 static int gen_trap_ifnofpu(DisasContext * dc) 1104 static int gen_trap_ifnofpu(DisasContext * dc)
@@ -1484,7 +1509,14 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1484,7 +1509,14 @@ static void disas_sparc_insn(DisasContext * dc)
1484 gen_op_store_DT0_fpr(DFPREG(rd)); 1509 gen_op_store_DT0_fpr(DFPREG(rd));
1485 break; 1510 break;
1486 case 0x2b: /* fsqrtq */ 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 goto nfpu_insn; 1518 goto nfpu_insn;
  1519 +#endif
1488 case 0x41: 1520 case 0x41:
1489 gen_op_load_fpr_FT0(rs1); 1521 gen_op_load_fpr_FT0(rs1);
1490 gen_op_load_fpr_FT1(rs2); 1522 gen_op_load_fpr_FT1(rs2);
@@ -1498,7 +1530,15 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1498,7 +1530,15 @@ static void disas_sparc_insn(DisasContext * dc)
1498 gen_op_store_DT0_fpr(DFPREG(rd)); 1530 gen_op_store_DT0_fpr(DFPREG(rd));
1499 break; 1531 break;
1500 case 0x43: /* faddq */ 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 goto nfpu_insn; 1540 goto nfpu_insn;
  1541 +#endif
1502 case 0x45: 1542 case 0x45:
1503 gen_op_load_fpr_FT0(rs1); 1543 gen_op_load_fpr_FT0(rs1);
1504 gen_op_load_fpr_FT1(rs2); 1544 gen_op_load_fpr_FT1(rs2);
@@ -1512,7 +1552,15 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1512,7 +1552,15 @@ static void disas_sparc_insn(DisasContext * dc)
1512 gen_op_store_DT0_fpr(DFPREG(rd)); 1552 gen_op_store_DT0_fpr(DFPREG(rd));
1513 break; 1553 break;
1514 case 0x47: /* fsubq */ 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 goto nfpu_insn; 1562 goto nfpu_insn;
  1563 +#endif
1516 case 0x49: 1564 case 0x49:
1517 gen_op_load_fpr_FT0(rs1); 1565 gen_op_load_fpr_FT0(rs1);
1518 gen_op_load_fpr_FT1(rs2); 1566 gen_op_load_fpr_FT1(rs2);
@@ -1526,7 +1574,15 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1526,7 +1574,15 @@ static void disas_sparc_insn(DisasContext * dc)
1526 gen_op_store_DT0_fpr(rd); 1574 gen_op_store_DT0_fpr(rd);
1527 break; 1575 break;
1528 case 0x4b: /* fmulq */ 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 goto nfpu_insn; 1584 goto nfpu_insn;
  1585 +#endif
1530 case 0x4d: 1586 case 0x4d:
1531 gen_op_load_fpr_FT0(rs1); 1587 gen_op_load_fpr_FT0(rs1);
1532 gen_op_load_fpr_FT1(rs2); 1588 gen_op_load_fpr_FT1(rs2);
@@ -1540,7 +1596,15 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1540,7 +1596,15 @@ static void disas_sparc_insn(DisasContext * dc)
1540 gen_op_store_DT0_fpr(DFPREG(rd)); 1596 gen_op_store_DT0_fpr(DFPREG(rd));
1541 break; 1597 break;
1542 case 0x4f: /* fdivq */ 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 goto nfpu_insn; 1606 goto nfpu_insn;
  1607 +#endif
1544 case 0x69: 1608 case 0x69:
1545 gen_op_load_fpr_FT0(rs1); 1609 gen_op_load_fpr_FT0(rs1);
1546 gen_op_load_fpr_FT1(rs2); 1610 gen_op_load_fpr_FT1(rs2);
@@ -1548,7 +1612,15 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1548,7 +1612,15 @@ static void disas_sparc_insn(DisasContext * dc)
1548 gen_op_store_DT0_fpr(DFPREG(rd)); 1612 gen_op_store_DT0_fpr(DFPREG(rd));
1549 break; 1613 break;
1550 case 0x6e: /* fdmulq */ 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 goto nfpu_insn; 1622 goto nfpu_insn;
  1623 +#endif
1552 case 0xc4: 1624 case 0xc4:
1553 gen_op_load_fpr_FT1(rs2); 1625 gen_op_load_fpr_FT1(rs2);
1554 gen_op_fitos(); 1626 gen_op_fitos();
@@ -1560,7 +1632,14 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1560,7 +1632,14 @@ static void disas_sparc_insn(DisasContext * dc)
1560 gen_op_store_FT0_fpr(rd); 1632 gen_op_store_FT0_fpr(rd);
1561 break; 1633 break;
1562 case 0xc7: /* fqtos */ 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 goto nfpu_insn; 1641 goto nfpu_insn;
  1642 +#endif
1564 case 0xc8: 1643 case 0xc8:
1565 gen_op_load_fpr_FT1(rs2); 1644 gen_op_load_fpr_FT1(rs2);
1566 gen_op_fitod(); 1645 gen_op_fitod();
@@ -1572,13 +1651,41 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1572,13 +1651,41 @@ static void disas_sparc_insn(DisasContext * dc)
1572 gen_op_store_DT0_fpr(DFPREG(rd)); 1651 gen_op_store_DT0_fpr(DFPREG(rd));
1573 break; 1652 break;
1574 case 0xcb: /* fqtod */ 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 goto nfpu_insn; 1660 goto nfpu_insn;
  1661 +#endif
1576 case 0xcc: /* fitoq */ 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 goto nfpu_insn; 1669 goto nfpu_insn;
  1670 +#endif
1578 case 0xcd: /* fstoq */ 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 goto nfpu_insn; 1678 goto nfpu_insn;
  1679 +#endif
1580 case 0xce: /* fdtoq */ 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 goto nfpu_insn; 1687 goto nfpu_insn;
  1688 +#endif
1582 case 0xd1: 1689 case 0xd1:
1583 gen_op_load_fpr_FT1(rs2); 1690 gen_op_load_fpr_FT1(rs2);
1584 gen_op_fstoi(); 1691 gen_op_fstoi();
@@ -1590,22 +1697,55 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1590,22 +1697,55 @@ static void disas_sparc_insn(DisasContext * dc)
1590 gen_op_store_FT0_fpr(rd); 1697 gen_op_store_FT0_fpr(rd);
1591 break; 1698 break;
1592 case 0xd3: /* fqtoi */ 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 goto nfpu_insn; 1706 goto nfpu_insn;
  1707 +#endif
1594 #ifdef TARGET_SPARC64 1708 #ifdef TARGET_SPARC64
1595 case 0x2: /* V9 fmovd */ 1709 case 0x2: /* V9 fmovd */
1596 gen_op_load_fpr_DT0(DFPREG(rs2)); 1710 gen_op_load_fpr_DT0(DFPREG(rs2));
1597 gen_op_store_DT0_fpr(DFPREG(rd)); 1711 gen_op_store_DT0_fpr(DFPREG(rd));
1598 break; 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 case 0x6: /* V9 fnegd */ 1721 case 0x6: /* V9 fnegd */
1600 gen_op_load_fpr_DT1(DFPREG(rs2)); 1722 gen_op_load_fpr_DT1(DFPREG(rs2));
1601 gen_op_fnegd(); 1723 gen_op_fnegd();
1602 gen_op_store_DT0_fpr(DFPREG(rd)); 1724 gen_op_store_DT0_fpr(DFPREG(rd));
1603 break; 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 case 0xa: /* V9 fabsd */ 1735 case 0xa: /* V9 fabsd */
1605 gen_op_load_fpr_DT1(DFPREG(rs2)); 1736 gen_op_load_fpr_DT1(DFPREG(rs2));
1606 gen_op_fabsd(); 1737 gen_op_fabsd();
1607 gen_op_store_DT0_fpr(DFPREG(rd)); 1738 gen_op_store_DT0_fpr(DFPREG(rd));
1608 break; 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 case 0x81: /* V9 fstox */ 1749 case 0x81: /* V9 fstox */
1610 gen_op_load_fpr_FT1(rs2); 1750 gen_op_load_fpr_FT1(rs2);
1611 gen_op_fstox(); 1751 gen_op_fstox();
@@ -1616,6 +1756,15 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1616,6 +1756,15 @@ static void disas_sparc_insn(DisasContext * dc)
1616 gen_op_fdtox(); 1756 gen_op_fdtox();
1617 gen_op_store_DT0_fpr(DFPREG(rd)); 1757 gen_op_store_DT0_fpr(DFPREG(rd));
1618 break; 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 case 0x84: /* V9 fxtos */ 1768 case 0x84: /* V9 fxtos */
1620 gen_op_load_fpr_DT1(DFPREG(rs2)); 1769 gen_op_load_fpr_DT1(DFPREG(rs2));
1621 gen_op_fxtos(); 1770 gen_op_fxtos();
@@ -1626,13 +1775,16 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1626,13 +1775,16 @@ static void disas_sparc_insn(DisasContext * dc)
1626 gen_op_fxtod(); 1775 gen_op_fxtod();
1627 gen_op_store_DT0_fpr(DFPREG(rd)); 1776 gen_op_store_DT0_fpr(DFPREG(rd));
1628 break; 1777 break;
1629 - case 0x3: /* V9 fmovq */  
1630 - case 0x7: /* V9 fnegq */  
1631 - case 0xb: /* V9 fabsq */  
1632 - case 0x83: /* V9 fqtox */  
1633 case 0x8c: /* V9 fxtoq */ 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 goto nfpu_insn; 1785 goto nfpu_insn;
1635 #endif 1786 #endif
  1787 +#endif
1636 default: 1788 default:
1637 goto illegal_insn; 1789 goto illegal_insn;
1638 } 1790 }
@@ -1670,7 +1822,20 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1670,7 +1822,20 @@ static void disas_sparc_insn(DisasContext * dc)
1670 gen_op_store_DT0_fpr(rd); 1822 gen_op_store_DT0_fpr(rd);
1671 break; 1823 break;
1672 } else if ((xop & 0x11f) == 0x007) { // V9 fmovqr 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 goto nfpu_insn; 1837 goto nfpu_insn;
  1838 +#endif
1674 } 1839 }
1675 #endif 1840 #endif
1676 switch (xop) { 1841 switch (xop) {
@@ -1694,7 +1859,18 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1694,7 +1859,18 @@ static void disas_sparc_insn(DisasContext * dc)
1694 gen_op_store_DT0_fpr(rd); 1859 gen_op_store_DT0_fpr(rd);
1695 break; 1860 break;
1696 case 0x003: /* V9 fmovqcc %fcc0 */ 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 goto nfpu_insn; 1872 goto nfpu_insn;
  1873 +#endif
1698 case 0x041: /* V9 fmovscc %fcc1 */ 1874 case 0x041: /* V9 fmovscc %fcc1 */
1699 cond = GET_FIELD_SP(insn, 14, 17); 1875 cond = GET_FIELD_SP(insn, 14, 17);
1700 gen_op_load_fpr_FT0(rd); 1876 gen_op_load_fpr_FT0(rd);
@@ -1714,7 +1890,18 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1714,7 +1890,18 @@ static void disas_sparc_insn(DisasContext * dc)
1714 gen_op_store_DT0_fpr(rd); 1890 gen_op_store_DT0_fpr(rd);
1715 break; 1891 break;
1716 case 0x043: /* V9 fmovqcc %fcc1 */ 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 goto nfpu_insn; 1903 goto nfpu_insn;
  1904 +#endif
1718 case 0x081: /* V9 fmovscc %fcc2 */ 1905 case 0x081: /* V9 fmovscc %fcc2 */
1719 cond = GET_FIELD_SP(insn, 14, 17); 1906 cond = GET_FIELD_SP(insn, 14, 17);
1720 gen_op_load_fpr_FT0(rd); 1907 gen_op_load_fpr_FT0(rd);
@@ -1734,7 +1921,18 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1734,7 +1921,18 @@ static void disas_sparc_insn(DisasContext * dc)
1734 gen_op_store_DT0_fpr(rd); 1921 gen_op_store_DT0_fpr(rd);
1735 break; 1922 break;
1736 case 0x083: /* V9 fmovqcc %fcc2 */ 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 goto nfpu_insn; 1934 goto nfpu_insn;
  1935 +#endif
1738 case 0x0c1: /* V9 fmovscc %fcc3 */ 1936 case 0x0c1: /* V9 fmovscc %fcc3 */
1739 cond = GET_FIELD_SP(insn, 14, 17); 1937 cond = GET_FIELD_SP(insn, 14, 17);
1740 gen_op_load_fpr_FT0(rd); 1938 gen_op_load_fpr_FT0(rd);
@@ -1754,7 +1952,18 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1754,7 +1952,18 @@ static void disas_sparc_insn(DisasContext * dc)
1754 gen_op_store_DT0_fpr(rd); 1952 gen_op_store_DT0_fpr(rd);
1755 break; 1953 break;
1756 case 0x0c3: /* V9 fmovqcc %fcc3 */ 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 goto nfpu_insn; 1965 goto nfpu_insn;
  1966 +#endif
1758 case 0x101: /* V9 fmovscc %icc */ 1967 case 0x101: /* V9 fmovscc %icc */
1759 cond = GET_FIELD_SP(insn, 14, 17); 1968 cond = GET_FIELD_SP(insn, 14, 17);
1760 gen_op_load_fpr_FT0(rd); 1969 gen_op_load_fpr_FT0(rd);
@@ -1774,7 +1983,18 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1774,7 +1983,18 @@ static void disas_sparc_insn(DisasContext * dc)
1774 gen_op_store_DT0_fpr(rd); 1983 gen_op_store_DT0_fpr(rd);
1775 break; 1984 break;
1776 case 0x103: /* V9 fmovqcc %icc */ 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 goto nfpu_insn; 1996 goto nfpu_insn;
  1997 +#endif
1778 case 0x181: /* V9 fmovscc %xcc */ 1998 case 0x181: /* V9 fmovscc %xcc */
1779 cond = GET_FIELD_SP(insn, 14, 17); 1999 cond = GET_FIELD_SP(insn, 14, 17);
1780 gen_op_load_fpr_FT0(rd); 2000 gen_op_load_fpr_FT0(rd);
@@ -1794,9 +2014,20 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1794,9 +2014,20 @@ static void disas_sparc_insn(DisasContext * dc)
1794 gen_op_store_DT0_fpr(rd); 2014 gen_op_store_DT0_fpr(rd);
1795 break; 2015 break;
1796 case 0x183: /* V9 fmovqcc %xcc */ 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 goto nfpu_insn; 2027 goto nfpu_insn;
1798 #endif 2028 #endif
1799 - case 0x51: /* V9 %fcc */ 2029 +#endif
  2030 + case 0x51: /* fcmps, V9 %fcc */
1800 gen_op_load_fpr_FT0(rs1); 2031 gen_op_load_fpr_FT0(rs1);
1801 gen_op_load_fpr_FT1(rs2); 2032 gen_op_load_fpr_FT1(rs2);
1802 #ifdef TARGET_SPARC64 2033 #ifdef TARGET_SPARC64
@@ -1805,7 +2036,7 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1805,7 +2036,7 @@ static void disas_sparc_insn(DisasContext * dc)
1805 gen_op_fcmps(); 2036 gen_op_fcmps();
1806 #endif 2037 #endif
1807 break; 2038 break;
1808 - case 0x52: /* V9 %fcc */ 2039 + case 0x52: /* fcmpd, V9 %fcc */
1809 gen_op_load_fpr_DT0(DFPREG(rs1)); 2040 gen_op_load_fpr_DT0(DFPREG(rs1));
1810 gen_op_load_fpr_DT1(DFPREG(rs2)); 2041 gen_op_load_fpr_DT1(DFPREG(rs2));
1811 #ifdef TARGET_SPARC64 2042 #ifdef TARGET_SPARC64
@@ -1814,8 +2045,19 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1814,8 +2045,19 @@ static void disas_sparc_insn(DisasContext * dc)
1814 gen_op_fcmpd(); 2045 gen_op_fcmpd();
1815 #endif 2046 #endif
1816 break; 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 goto nfpu_insn; 2059 goto nfpu_insn;
  2060 +#endif
1819 case 0x55: /* fcmpes, V9 %fcc */ 2061 case 0x55: /* fcmpes, V9 %fcc */
1820 gen_op_load_fpr_FT0(rs1); 2062 gen_op_load_fpr_FT0(rs1);
1821 gen_op_load_fpr_FT1(rs2); 2063 gen_op_load_fpr_FT1(rs2);
@@ -1834,8 +2076,19 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1834,8 +2076,19 @@ static void disas_sparc_insn(DisasContext * dc)
1834 gen_op_fcmped(); 2076 gen_op_fcmped();
1835 #endif 2077 #endif
1836 break; 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 goto nfpu_insn; 2090 goto nfpu_insn;
  2091 +#endif
1839 default: 2092 default:
1840 goto illegal_insn; 2093 goto illegal_insn;
1841 } 2094 }
@@ -3095,8 +3348,14 @@ static void disas_sparc_insn(DisasContext * dc) @@ -3095,8 +3348,14 @@ static void disas_sparc_insn(DisasContext * dc)
3095 case 0x3d: /* V9 prefetcha, no effect */ 3348 case 0x3d: /* V9 prefetcha, no effect */
3096 goto skip_move; 3349 goto skip_move;
3097 case 0x32: /* V9 ldqfa */ 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 goto nfpu_insn; 3356 goto nfpu_insn;
3099 #endif 3357 #endif
  3358 +#endif
3100 default: 3359 default:
3101 goto illegal_insn; 3360 goto illegal_insn;
3102 } 3361 }
@@ -3119,7 +3378,14 @@ static void disas_sparc_insn(DisasContext * dc) @@ -3119,7 +3378,14 @@ static void disas_sparc_insn(DisasContext * dc)
3119 gen_op_ldfsr(); 3378 gen_op_ldfsr();
3120 break; 3379 break;
3121 case 0x22: /* load quad fpreg */ 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 goto nfpu_insn; 3387 goto nfpu_insn;
  3388 +#endif
3123 case 0x23: /* load double fpreg */ 3389 case 0x23: /* load double fpreg */
3124 gen_op_check_align_T0_7(); 3390 gen_op_check_align_T0_7();
3125 gen_op_ldst(lddf); 3391 gen_op_ldst(lddf);
@@ -3225,14 +3491,29 @@ static void disas_sparc_insn(DisasContext * dc) @@ -3225,14 +3491,29 @@ static void disas_sparc_insn(DisasContext * dc)
3225 gen_op_stfsr(); 3491 gen_op_stfsr();
3226 gen_op_ldst(stf); 3492 gen_op_ldst(stf);
3227 break; 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 if (!supervisor(dc)) 3510 if (!supervisor(dc))
3231 goto priv_insn; 3511 goto priv_insn;
3232 if (gen_trap_ifnofpu(dc)) 3512 if (gen_trap_ifnofpu(dc))
3233 goto jmp_insn; 3513 goto jmp_insn;
3234 goto nfq_insn; 3514 goto nfq_insn;
3235 #endif 3515 #endif
  3516 +#endif
3236 case 0x27: 3517 case 0x27:
3237 gen_op_check_align_T0_7(); 3518 gen_op_check_align_T0_7();
3238 gen_op_load_fpr_DT0(DFPREG(rd)); 3519 gen_op_load_fpr_DT0(DFPREG(rd));
@@ -3249,6 +3530,15 @@ static void disas_sparc_insn(DisasContext * dc) @@ -3249,6 +3530,15 @@ static void disas_sparc_insn(DisasContext * dc)
3249 gen_op_load_fpr_FT0(rd); 3530 gen_op_load_fpr_FT0(rd);
3250 gen_stf_asi(insn, 4); 3531 gen_stf_asi(insn, 4);
3251 break; 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 case 0x37: /* V9 stdfa */ 3542 case 0x37: /* V9 stdfa */
3253 gen_op_check_align_T0_3(); 3543 gen_op_check_align_T0_3();
3254 gen_op_load_fpr_DT0(DFPREG(rd)); 3544 gen_op_load_fpr_DT0(DFPREG(rd));
@@ -3268,8 +3558,6 @@ static void disas_sparc_insn(DisasContext * dc) @@ -3268,8 +3558,6 @@ static void disas_sparc_insn(DisasContext * dc)
3268 gen_casx_asi(insn); 3558 gen_casx_asi(insn);
3269 gen_movl_T1_reg(rd); 3559 gen_movl_T1_reg(rd);
3270 break; 3560 break;
3271 - case 0x36: /* V9 stqfa */  
3272 - goto nfpu_insn;  
3273 #else 3561 #else
3274 case 0x34: /* stc */ 3562 case 0x34: /* stc */
3275 case 0x35: /* stcsr */ 3563 case 0x35: /* stcsr */
@@ -3311,19 +3599,19 @@ static void disas_sparc_insn(DisasContext * dc) @@ -3311,19 +3599,19 @@ static void disas_sparc_insn(DisasContext * dc)
3311 gen_op_exception(TT_PRIV_INSN); 3599 gen_op_exception(TT_PRIV_INSN);
3312 dc->is_br = 1; 3600 dc->is_br = 1;
3313 return; 3601 return;
3314 -#endif  
3315 nfpu_insn: 3602 nfpu_insn:
3316 save_state(dc); 3603 save_state(dc);
3317 gen_op_fpexception_im(FSR_FTT_UNIMPFPOP); 3604 gen_op_fpexception_im(FSR_FTT_UNIMPFPOP);
3318 dc->is_br = 1; 3605 dc->is_br = 1;
3319 return; 3606 return;
3320 -#if !defined(CONFIG_USER_ONLY) 3607 +#ifndef TARGET_SPARC64
3321 nfq_insn: 3608 nfq_insn:
3322 save_state(dc); 3609 save_state(dc);
3323 gen_op_fpexception_im(FSR_FTT_SEQ_ERROR); 3610 gen_op_fpexception_im(FSR_FTT_SEQ_ERROR);
3324 dc->is_br = 1; 3611 dc->is_br = 1;
3325 return; 3612 return;
3326 #endif 3613 #endif
  3614 +#endif
3327 #ifndef TARGET_SPARC64 3615 #ifndef TARGET_SPARC64
3328 ncp_insn: 3616 ncp_insn:
3329 save_state(dc); 3617 save_state(dc);