Revision 7c58044c target-ppc/translate.c
b/target-ppc/translate.c | ||
---|---|---|
32 | 32 |
//#define PPC_DEBUG_DISAS |
33 | 33 |
//#define DEBUG_MEMORY_ACCESSES |
34 | 34 |
//#define DO_PPC_STATISTICS |
35 |
//#define OPTIMIZE_FPRF_UPDATE |
|
35 | 36 |
|
36 | 37 |
/*****************************************************************************/ |
37 | 38 |
/* Code translation helpers */ |
... | ... | |
50 | 51 |
|
51 | 52 |
static uint16_t *gen_opc_ptr; |
52 | 53 |
static uint32_t *gen_opparam_ptr; |
54 |
#if defined(OPTIMIZE_FPRF_UPDATE) |
|
55 |
static uint16_t *gen_fprf_buf[OPC_BUF_SIZE]; |
|
56 |
static uint16_t **gen_fprf_ptr; |
|
57 |
#endif |
|
53 | 58 |
|
54 | 59 |
#include "gen-op.h" |
55 | 60 |
|
... | ... | |
117 | 122 |
GEN8(gen_op_store_T0_crf, gen_op_store_T0_crf_crf); |
118 | 123 |
GEN8(gen_op_store_T1_crf, gen_op_store_T1_crf_crf); |
119 | 124 |
|
120 |
/* Floating point condition and status register moves */ |
|
121 |
GEN8(gen_op_load_fpscr_T0, gen_op_load_fpscr_T0_fpscr); |
|
122 |
GEN8(gen_op_store_T0_fpscr, gen_op_store_T0_fpscr_fpscr); |
|
123 |
GEN8(gen_op_clear_fpscr, gen_op_clear_fpscr_fpscr); |
|
124 |
static always_inline void gen_op_store_T0_fpscri (int n, uint8_t param) |
|
125 |
{ |
|
126 |
gen_op_set_T0(param); |
|
127 |
gen_op_store_T0_fpscr(n); |
|
128 |
} |
|
129 |
|
|
130 | 125 |
/* General purpose registers moves */ |
131 | 126 |
GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr); |
132 | 127 |
GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr); |
... | ... | |
199 | 194 |
gen_op_set_Rc0(); |
200 | 195 |
} |
201 | 196 |
|
197 |
static always_inline void gen_reset_fpstatus (void) |
|
198 |
{ |
|
199 |
#ifdef CONFIG_SOFTFLOAT |
|
200 |
gen_op_reset_fpstatus(); |
|
201 |
#endif |
|
202 |
} |
|
203 |
|
|
204 |
static always_inline void gen_compute_fprf (int set_fprf, int set_rc) |
|
205 |
{ |
|
206 |
if (set_fprf != 0) { |
|
207 |
/* This case might be optimized later */ |
|
208 |
#if defined(OPTIMIZE_FPRF_UPDATE) |
|
209 |
*gen_fprf_ptr++ = gen_opc_ptr; |
|
210 |
#endif |
|
211 |
gen_op_compute_fprf(1); |
|
212 |
if (unlikely(set_rc)) |
|
213 |
gen_op_store_T0_crf(1); |
|
214 |
gen_op_float_check_status(); |
|
215 |
} else if (unlikely(set_rc)) { |
|
216 |
/* We always need to compute fpcc */ |
|
217 |
gen_op_compute_fprf(0); |
|
218 |
gen_op_store_T0_crf(1); |
|
219 |
if (set_fprf) |
|
220 |
gen_op_float_check_status(); |
|
221 |
} |
|
222 |
} |
|
223 |
|
|
224 |
static always_inline void gen_optimize_fprf (void) |
|
225 |
{ |
|
226 |
#if defined(OPTIMIZE_FPRF_UPDATE) |
|
227 |
uint16_t **ptr; |
|
228 |
|
|
229 |
for (ptr = gen_fprf_buf; ptr != (gen_fprf_ptr - 1); ptr++) |
|
230 |
*ptr = INDEX_op_nop1; |
|
231 |
gen_fprf_ptr = gen_fprf_buf; |
|
232 |
#endif |
|
233 |
} |
|
234 |
|
|
202 | 235 |
static always_inline void gen_update_nip (DisasContext *ctx, target_ulong nip) |
203 | 236 |
{ |
204 | 237 |
#if defined(TARGET_PPC64) |
... | ... | |
497 | 530 |
PPC_CACHE_DCBZ = 0x0000400000000000ULL, |
498 | 531 |
/* dcbz instruction with tunable cache line size */ |
499 | 532 |
PPC_CACHE_DCBZT = 0x0000800000000000ULL, |
533 |
/* frsqrtes extension */ |
|
534 |
PPC_FLOAT_FRSQRTES = 0x0001000000000000ULL, |
|
500 | 535 |
}; |
501 | 536 |
|
502 | 537 |
/*****************************************************************************/ |
... | ... | |
1656 | 1691 |
#endif |
1657 | 1692 |
|
1658 | 1693 |
/*** Floating-Point arithmetic ***/ |
1659 |
#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, type) \
|
|
1694 |
#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type) \
|
|
1660 | 1695 |
GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type) \ |
1661 | 1696 |
{ \ |
1662 | 1697 |
if (unlikely(!ctx->fpu_enabled)) { \ |
1663 | 1698 |
GEN_EXCP_NO_FP(ctx); \ |
1664 | 1699 |
return; \ |
1665 | 1700 |
} \ |
1666 |
gen_op_reset_scrfx(); \ |
|
1667 | 1701 |
gen_op_load_fpr_FT0(rA(ctx->opcode)); \ |
1668 | 1702 |
gen_op_load_fpr_FT1(rC(ctx->opcode)); \ |
1669 | 1703 |
gen_op_load_fpr_FT2(rB(ctx->opcode)); \ |
1704 |
gen_reset_fpstatus(); \ |
|
1670 | 1705 |
gen_op_f##op(); \ |
1671 | 1706 |
if (isfloat) { \ |
1672 | 1707 |
gen_op_frsp(); \ |
1673 | 1708 |
} \ |
1674 | 1709 |
gen_op_store_FT0_fpr(rD(ctx->opcode)); \ |
1675 |
if (unlikely(Rc(ctx->opcode) != 0)) \ |
|
1676 |
gen_op_set_Rc1(); \ |
|
1710 |
gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \ |
|
1677 | 1711 |
} |
1678 | 1712 |
|
1679 |
#define GEN_FLOAT_ACB(name, op2, type) \
|
|
1680 |
_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, type); \
|
|
1681 |
_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, type); |
|
1713 |
#define GEN_FLOAT_ACB(name, op2, set_fprf, type) \
|
|
1714 |
_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type); \
|
|
1715 |
_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type);
|
|
1682 | 1716 |
|
1683 |
#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat) \
|
|
1684 |
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \
|
|
1717 |
#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type) \
|
|
1718 |
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type) \
|
|
1685 | 1719 |
{ \ |
1686 | 1720 |
if (unlikely(!ctx->fpu_enabled)) { \ |
1687 | 1721 |
GEN_EXCP_NO_FP(ctx); \ |
1688 | 1722 |
return; \ |
1689 | 1723 |
} \ |
1690 |
gen_op_reset_scrfx(); \ |
|
1691 | 1724 |
gen_op_load_fpr_FT0(rA(ctx->opcode)); \ |
1692 | 1725 |
gen_op_load_fpr_FT1(rB(ctx->opcode)); \ |
1726 |
gen_reset_fpstatus(); \ |
|
1693 | 1727 |
gen_op_f##op(); \ |
1694 | 1728 |
if (isfloat) { \ |
1695 | 1729 |
gen_op_frsp(); \ |
1696 | 1730 |
} \ |
1697 | 1731 |
gen_op_store_FT0_fpr(rD(ctx->opcode)); \ |
1698 |
if (unlikely(Rc(ctx->opcode) != 0)) \ |
|
1699 |
gen_op_set_Rc1(); \ |
|
1732 |
gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \ |
|
1700 | 1733 |
} |
1701 |
#define GEN_FLOAT_AB(name, op2, inval) \
|
|
1702 |
_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0); \
|
|
1703 |
_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1); |
|
1734 |
#define GEN_FLOAT_AB(name, op2, inval, set_fprf, type) \
|
|
1735 |
_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
|
|
1736 |
_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
|
|
1704 | 1737 |
|
1705 |
#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat) \
|
|
1706 |
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \
|
|
1738 |
#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type) \
|
|
1739 |
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type) \
|
|
1707 | 1740 |
{ \ |
1708 | 1741 |
if (unlikely(!ctx->fpu_enabled)) { \ |
1709 | 1742 |
GEN_EXCP_NO_FP(ctx); \ |
1710 | 1743 |
return; \ |
1711 | 1744 |
} \ |
1712 |
gen_op_reset_scrfx(); \ |
|
1713 | 1745 |
gen_op_load_fpr_FT0(rA(ctx->opcode)); \ |
1714 | 1746 |
gen_op_load_fpr_FT1(rC(ctx->opcode)); \ |
1747 |
gen_reset_fpstatus(); \ |
|
1715 | 1748 |
gen_op_f##op(); \ |
1716 | 1749 |
if (isfloat) { \ |
1717 | 1750 |
gen_op_frsp(); \ |
1718 | 1751 |
} \ |
1719 | 1752 |
gen_op_store_FT0_fpr(rD(ctx->opcode)); \ |
1720 |
if (unlikely(Rc(ctx->opcode) != 0)) \ |
|
1721 |
gen_op_set_Rc1(); \ |
|
1753 |
gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \ |
|
1722 | 1754 |
} |
1723 |
#define GEN_FLOAT_AC(name, op2, inval) \
|
|
1724 |
_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0); \
|
|
1725 |
_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1); |
|
1755 |
#define GEN_FLOAT_AC(name, op2, inval, set_fprf, type) \
|
|
1756 |
_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
|
|
1757 |
_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
|
|
1726 | 1758 |
|
1727 |
#define GEN_FLOAT_B(name, op2, op3, type) \
|
|
1759 |
#define GEN_FLOAT_B(name, op2, op3, set_fprf, type) \
|
|
1728 | 1760 |
GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type) \ |
1729 | 1761 |
{ \ |
1730 | 1762 |
if (unlikely(!ctx->fpu_enabled)) { \ |
1731 | 1763 |
GEN_EXCP_NO_FP(ctx); \ |
1732 | 1764 |
return; \ |
1733 | 1765 |
} \ |
1734 |
gen_op_reset_scrfx(); \ |
|
1735 | 1766 |
gen_op_load_fpr_FT0(rB(ctx->opcode)); \ |
1767 |
gen_reset_fpstatus(); \ |
|
1736 | 1768 |
gen_op_f##name(); \ |
1737 | 1769 |
gen_op_store_FT0_fpr(rD(ctx->opcode)); \ |
1738 |
if (unlikely(Rc(ctx->opcode) != 0)) \ |
|
1739 |
gen_op_set_Rc1(); \ |
|
1770 |
gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \ |
|
1740 | 1771 |
} |
1741 | 1772 |
|
1742 |
#define GEN_FLOAT_BS(name, op1, op2, type) \
|
|
1773 |
#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type) \
|
|
1743 | 1774 |
GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type) \ |
1744 | 1775 |
{ \ |
1745 | 1776 |
if (unlikely(!ctx->fpu_enabled)) { \ |
1746 | 1777 |
GEN_EXCP_NO_FP(ctx); \ |
1747 | 1778 |
return; \ |
1748 | 1779 |
} \ |
1749 |
gen_op_reset_scrfx(); \ |
|
1750 | 1780 |
gen_op_load_fpr_FT0(rB(ctx->opcode)); \ |
1781 |
gen_reset_fpstatus(); \ |
|
1751 | 1782 |
gen_op_f##name(); \ |
1752 | 1783 |
gen_op_store_FT0_fpr(rD(ctx->opcode)); \ |
1753 |
if (unlikely(Rc(ctx->opcode) != 0)) \ |
|
1754 |
gen_op_set_Rc1(); \ |
|
1784 |
gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \ |
|
1755 | 1785 |
} |
1756 | 1786 |
|
1757 | 1787 |
/* fadd - fadds */ |
1758 |
GEN_FLOAT_AB(add, 0x15, 0x000007C0); |
|
1788 |
GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
|
|
1759 | 1789 |
/* fdiv - fdivs */ |
1760 |
GEN_FLOAT_AB(div, 0x12, 0x000007C0); |
|
1790 |
GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
|
|
1761 | 1791 |
/* fmul - fmuls */ |
1762 |
GEN_FLOAT_AC(mul, 0x19, 0x0000F800); |
|
1792 |
GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
|
|
1763 | 1793 |
|
1764 | 1794 |
/* fre */ |
1765 |
GEN_FLOAT_BS(re, 0x3F, 0x18, PPC_FLOAT_EXT); |
|
1795 |
GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
|
|
1766 | 1796 |
|
1767 | 1797 |
/* fres */ |
1768 |
GEN_FLOAT_BS(res, 0x3B, 0x18, PPC_FLOAT_FRES); |
|
1798 |
GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
|
|
1769 | 1799 |
|
1770 | 1800 |
/* frsqrte */ |
1771 |
GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, PPC_FLOAT_FRSQRTE); |
|
1801 |
GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE); |
|
1802 |
|
|
1803 |
/* frsqrtes */ |
|
1804 |
static always_inline void gen_op_frsqrtes (void) |
|
1805 |
{ |
|
1806 |
gen_op_frsqrte(); |
|
1807 |
gen_op_frsp(); |
|
1808 |
} |
|
1809 |
GEN_FLOAT_BS(rsqrtes, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTES); |
|
1772 | 1810 |
|
1773 | 1811 |
/* fsel */ |
1774 |
_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, PPC_FLOAT_FSEL); |
|
1812 |
_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
|
|
1775 | 1813 |
/* fsub - fsubs */ |
1776 |
GEN_FLOAT_AB(sub, 0x14, 0x000007C0); |
|
1814 |
GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
|
|
1777 | 1815 |
/* Optional: */ |
1778 | 1816 |
/* fsqrt */ |
1779 | 1817 |
GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT) |
... | ... | |
1782 | 1820 |
GEN_EXCP_NO_FP(ctx); |
1783 | 1821 |
return; |
1784 | 1822 |
} |
1785 |
gen_op_reset_scrfx(); |
|
1786 | 1823 |
gen_op_load_fpr_FT0(rB(ctx->opcode)); |
1824 |
gen_reset_fpstatus(); |
|
1787 | 1825 |
gen_op_fsqrt(); |
1788 | 1826 |
gen_op_store_FT0_fpr(rD(ctx->opcode)); |
1789 |
if (unlikely(Rc(ctx->opcode) != 0)) |
|
1790 |
gen_op_set_Rc1(); |
|
1827 |
gen_compute_fprf(1, Rc(ctx->opcode) != 0); |
|
1791 | 1828 |
} |
1792 | 1829 |
|
1793 | 1830 |
GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT) |
... | ... | |
1796 | 1833 |
GEN_EXCP_NO_FP(ctx); |
1797 | 1834 |
return; |
1798 | 1835 |
} |
1799 |
gen_op_reset_scrfx(); |
|
1800 | 1836 |
gen_op_load_fpr_FT0(rB(ctx->opcode)); |
1837 |
gen_reset_fpstatus(); |
|
1801 | 1838 |
gen_op_fsqrt(); |
1802 | 1839 |
gen_op_frsp(); |
1803 | 1840 |
gen_op_store_FT0_fpr(rD(ctx->opcode)); |
1804 |
if (unlikely(Rc(ctx->opcode) != 0)) |
|
1805 |
gen_op_set_Rc1(); |
|
1841 |
gen_compute_fprf(1, Rc(ctx->opcode) != 0); |
|
1806 | 1842 |
} |
1807 | 1843 |
|
1808 | 1844 |
/*** Floating-Point multiply-and-add ***/ |
1809 | 1845 |
/* fmadd - fmadds */ |
1810 |
GEN_FLOAT_ACB(madd, 0x1D, PPC_FLOAT); |
|
1846 |
GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
|
|
1811 | 1847 |
/* fmsub - fmsubs */ |
1812 |
GEN_FLOAT_ACB(msub, 0x1C, PPC_FLOAT); |
|
1848 |
GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
|
|
1813 | 1849 |
/* fnmadd - fnmadds */ |
1814 |
GEN_FLOAT_ACB(nmadd, 0x1F, PPC_FLOAT); |
|
1850 |
GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
|
|
1815 | 1851 |
/* fnmsub - fnmsubs */ |
1816 |
GEN_FLOAT_ACB(nmsub, 0x1E, PPC_FLOAT); |
|
1852 |
GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
|
|
1817 | 1853 |
|
1818 | 1854 |
/*** Floating-Point round & convert ***/ |
1819 | 1855 |
/* fctiw */ |
1820 |
GEN_FLOAT_B(ctiw, 0x0E, 0x00, PPC_FLOAT); |
|
1856 |
GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
|
|
1821 | 1857 |
/* fctiwz */ |
1822 |
GEN_FLOAT_B(ctiwz, 0x0F, 0x00, PPC_FLOAT); |
|
1858 |
GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
|
|
1823 | 1859 |
/* frsp */ |
1824 |
GEN_FLOAT_B(rsp, 0x0C, 0x00, PPC_FLOAT); |
|
1860 |
GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
|
|
1825 | 1861 |
#if defined(TARGET_PPC64) |
1826 | 1862 |
/* fcfid */ |
1827 |
GEN_FLOAT_B(cfid, 0x0E, 0x1A, PPC_64B); |
|
1863 |
GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
|
|
1828 | 1864 |
/* fctid */ |
1829 |
GEN_FLOAT_B(ctid, 0x0E, 0x19, PPC_64B); |
|
1865 |
GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
|
|
1830 | 1866 |
/* fctidz */ |
1831 |
GEN_FLOAT_B(ctidz, 0x0F, 0x19, PPC_64B); |
|
1867 |
GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B);
|
|
1832 | 1868 |
#endif |
1833 | 1869 |
|
1834 | 1870 |
/* frin */ |
1835 |
GEN_FLOAT_B(rin, 0x08, 0x0C, PPC_FLOAT_EXT); |
|
1871 |
GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
|
|
1836 | 1872 |
/* friz */ |
1837 |
GEN_FLOAT_B(riz, 0x08, 0x0D, PPC_FLOAT_EXT); |
|
1873 |
GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
|
|
1838 | 1874 |
/* frip */ |
1839 |
GEN_FLOAT_B(rip, 0x08, 0x0E, PPC_FLOAT_EXT); |
|
1875 |
GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
|
|
1840 | 1876 |
/* frim */ |
1841 |
GEN_FLOAT_B(rim, 0x08, 0x0F, PPC_FLOAT_EXT); |
|
1877 |
GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
|
|
1842 | 1878 |
|
1843 | 1879 |
/*** Floating-Point compare ***/ |
1844 | 1880 |
/* fcmpo */ |
... | ... | |
1848 | 1884 |
GEN_EXCP_NO_FP(ctx); |
1849 | 1885 |
return; |
1850 | 1886 |
} |
1851 |
gen_op_reset_scrfx(); |
|
1852 | 1887 |
gen_op_load_fpr_FT0(rA(ctx->opcode)); |
1853 | 1888 |
gen_op_load_fpr_FT1(rB(ctx->opcode)); |
1889 |
gen_reset_fpstatus(); |
|
1854 | 1890 |
gen_op_fcmpo(); |
1855 | 1891 |
gen_op_store_T0_crf(crfD(ctx->opcode)); |
1892 |
gen_op_float_check_status(); |
|
1856 | 1893 |
} |
1857 | 1894 |
|
1858 | 1895 |
/* fcmpu */ |
... | ... | |
1862 | 1899 |
GEN_EXCP_NO_FP(ctx); |
1863 | 1900 |
return; |
1864 | 1901 |
} |
1865 |
gen_op_reset_scrfx(); |
|
1866 | 1902 |
gen_op_load_fpr_FT0(rA(ctx->opcode)); |
1867 | 1903 |
gen_op_load_fpr_FT1(rB(ctx->opcode)); |
1904 |
gen_reset_fpstatus(); |
|
1868 | 1905 |
gen_op_fcmpu(); |
1869 | 1906 |
gen_op_store_T0_crf(crfD(ctx->opcode)); |
1907 |
gen_op_float_check_status(); |
|
1870 | 1908 |
} |
1871 | 1909 |
|
1872 | 1910 |
/*** Floating-point move ***/ |
1873 | 1911 |
/* fabs */ |
1874 |
GEN_FLOAT_B(abs, 0x08, 0x08, PPC_FLOAT); |
|
1912 |
/* XXX: beware that fabs never checks for NaNs nor update FPSCR */ |
|
1913 |
GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT); |
|
1875 | 1914 |
|
1876 | 1915 |
/* fmr - fmr. */ |
1916 |
/* XXX: beware that fmr never checks for NaNs nor update FPSCR */ |
|
1877 | 1917 |
GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT) |
1878 | 1918 |
{ |
1879 | 1919 |
if (unlikely(!ctx->fpu_enabled)) { |
1880 | 1920 |
GEN_EXCP_NO_FP(ctx); |
1881 | 1921 |
return; |
1882 | 1922 |
} |
1883 |
gen_op_reset_scrfx(); |
|
1884 | 1923 |
gen_op_load_fpr_FT0(rB(ctx->opcode)); |
1885 | 1924 |
gen_op_store_FT0_fpr(rD(ctx->opcode)); |
1886 |
if (unlikely(Rc(ctx->opcode) != 0)) |
|
1887 |
gen_op_set_Rc1(); |
|
1925 |
gen_compute_fprf(0, Rc(ctx->opcode) != 0); |
|
1888 | 1926 |
} |
1889 | 1927 |
|
1890 | 1928 |
/* fnabs */ |
1891 |
GEN_FLOAT_B(nabs, 0x08, 0x04, PPC_FLOAT); |
|
1929 |
/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */ |
|
1930 |
GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT); |
|
1892 | 1931 |
/* fneg */ |
1893 |
GEN_FLOAT_B(neg, 0x08, 0x01, PPC_FLOAT); |
|
1932 |
/* XXX: beware that fneg never checks for NaNs nor update FPSCR */ |
|
1933 |
GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT); |
|
1894 | 1934 |
|
1895 | 1935 |
/*** Floating-Point status & ctrl register ***/ |
1896 | 1936 |
/* mcrfs */ |
1897 | 1937 |
GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT) |
1898 | 1938 |
{ |
1939 |
int bfa; |
|
1940 |
|
|
1899 | 1941 |
if (unlikely(!ctx->fpu_enabled)) { |
1900 | 1942 |
GEN_EXCP_NO_FP(ctx); |
1901 | 1943 |
return; |
1902 | 1944 |
} |
1903 |
gen_op_load_fpscr_T0(crfS(ctx->opcode)); |
|
1945 |
gen_optimize_fprf(); |
|
1946 |
bfa = 4 * (7 - crfS(ctx->opcode)); |
|
1947 |
gen_op_load_fpscr_T0(bfa); |
|
1904 | 1948 |
gen_op_store_T0_crf(crfD(ctx->opcode)); |
1905 |
gen_op_clear_fpscr(crfS(ctx->opcode));
|
|
1949 |
gen_op_fpscr_resetbit(~(0xF << bfa));
|
|
1906 | 1950 |
} |
1907 | 1951 |
|
1908 | 1952 |
/* mffs */ |
... | ... | |
1912 | 1956 |
GEN_EXCP_NO_FP(ctx); |
1913 | 1957 |
return; |
1914 | 1958 |
} |
1915 |
gen_op_load_fpscr(); |
|
1959 |
gen_optimize_fprf(); |
|
1960 |
gen_reset_fpstatus(); |
|
1961 |
gen_op_load_fpscr_FT0(); |
|
1916 | 1962 |
gen_op_store_FT0_fpr(rD(ctx->opcode)); |
1917 |
if (unlikely(Rc(ctx->opcode) != 0)) |
|
1918 |
gen_op_set_Rc1(); |
|
1963 |
gen_compute_fprf(0, Rc(ctx->opcode) != 0); |
|
1919 | 1964 |
} |
1920 | 1965 |
|
1921 | 1966 |
/* mtfsb0 */ |
... | ... | |
1927 | 1972 |
GEN_EXCP_NO_FP(ctx); |
1928 | 1973 |
return; |
1929 | 1974 |
} |
1930 |
crb = crbD(ctx->opcode) >> 2; |
|
1931 |
gen_op_load_fpscr_T0(crb); |
|
1932 |
gen_op_andi_T0(~(1 << (crbD(ctx->opcode) & 0x03))); |
|
1933 |
gen_op_store_T0_fpscr(crb); |
|
1934 |
if (unlikely(Rc(ctx->opcode) != 0)) |
|
1935 |
gen_op_set_Rc1(); |
|
1975 |
crb = 32 - (crbD(ctx->opcode) >> 2); |
|
1976 |
gen_optimize_fprf(); |
|
1977 |
gen_reset_fpstatus(); |
|
1978 |
if (likely(crb != 30 && crb != 29)) |
|
1979 |
gen_op_fpscr_resetbit(~(1 << crb)); |
|
1980 |
if (unlikely(Rc(ctx->opcode) != 0)) { |
|
1981 |
gen_op_load_fpcc(); |
|
1982 |
gen_op_set_Rc0(); |
|
1983 |
} |
|
1936 | 1984 |
} |
1937 | 1985 |
|
1938 | 1986 |
/* mtfsb1 */ |
... | ... | |
1944 | 1992 |
GEN_EXCP_NO_FP(ctx); |
1945 | 1993 |
return; |
1946 | 1994 |
} |
1947 |
crb = crbD(ctx->opcode) >> 2; |
|
1948 |
gen_op_load_fpscr_T0(crb); |
|
1949 |
gen_op_ori(1 << (crbD(ctx->opcode) & 0x03)); |
|
1950 |
gen_op_store_T0_fpscr(crb); |
|
1951 |
if (unlikely(Rc(ctx->opcode) != 0)) |
|
1952 |
gen_op_set_Rc1(); |
|
1995 |
crb = 32 - (crbD(ctx->opcode) >> 2); |
|
1996 |
gen_optimize_fprf(); |
|
1997 |
gen_reset_fpstatus(); |
|
1998 |
/* XXX: we pretend we can only do IEEE floating-point computations */ |
|
1999 |
if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) |
|
2000 |
gen_op_fpscr_setbit(crb); |
|
2001 |
if (unlikely(Rc(ctx->opcode) != 0)) { |
|
2002 |
gen_op_load_fpcc(); |
|
2003 |
gen_op_set_Rc0(); |
|
2004 |
} |
|
2005 |
/* We can raise a differed exception */ |
|
2006 |
gen_op_float_check_status(); |
|
1953 | 2007 |
} |
1954 | 2008 |
|
1955 | 2009 |
/* mtfsf */ |
... | ... | |
1959 | 2013 |
GEN_EXCP_NO_FP(ctx); |
1960 | 2014 |
return; |
1961 | 2015 |
} |
2016 |
gen_optimize_fprf(); |
|
1962 | 2017 |
gen_op_load_fpr_FT0(rB(ctx->opcode)); |
2018 |
gen_reset_fpstatus(); |
|
1963 | 2019 |
gen_op_store_fpscr(FM(ctx->opcode)); |
1964 |
if (unlikely(Rc(ctx->opcode) != 0)) |
|
1965 |
gen_op_set_Rc1(); |
|
2020 |
if (unlikely(Rc(ctx->opcode) != 0)) { |
|
2021 |
gen_op_load_fpcc(); |
|
2022 |
gen_op_set_Rc0(); |
|
2023 |
} |
|
2024 |
/* We can raise a differed exception */ |
|
2025 |
gen_op_float_check_status(); |
|
1966 | 2026 |
} |
1967 | 2027 |
|
1968 | 2028 |
/* mtfsfi */ |
1969 | 2029 |
GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT) |
1970 | 2030 |
{ |
2031 |
int bf, sh; |
|
2032 |
|
|
1971 | 2033 |
if (unlikely(!ctx->fpu_enabled)) { |
1972 | 2034 |
GEN_EXCP_NO_FP(ctx); |
1973 | 2035 |
return; |
1974 | 2036 |
} |
1975 |
gen_op_store_T0_fpscri(crbD(ctx->opcode) >> 2, FPIMM(ctx->opcode)); |
|
1976 |
if (unlikely(Rc(ctx->opcode) != 0)) |
|
1977 |
gen_op_set_Rc1(); |
|
2037 |
bf = crbD(ctx->opcode) >> 2; |
|
2038 |
sh = 7 - bf; |
|
2039 |
gen_optimize_fprf(); |
|
2040 |
gen_op_set_FT0(FPIMM(ctx->opcode) << (4 * sh)); |
|
2041 |
gen_reset_fpstatus(); |
|
2042 |
gen_op_store_fpscr(1 << sh); |
|
2043 |
if (unlikely(Rc(ctx->opcode) != 0)) { |
|
2044 |
gen_op_load_fpcc(); |
|
2045 |
gen_op_set_Rc0(); |
|
2046 |
} |
|
2047 |
/* We can raise a differed exception */ |
|
2048 |
gen_op_float_check_status(); |
|
1978 | 2049 |
} |
1979 | 2050 |
|
1980 | 2051 |
/*** Addressing modes ***/ |
... | ... | |
6717 | 6788 |
gen_opc_ptr = gen_opc_buf; |
6718 | 6789 |
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; |
6719 | 6790 |
gen_opparam_ptr = gen_opparam_buf; |
6791 |
#if defined(OPTIMIZE_FPRF_UPDATE) |
|
6792 |
gen_fprf_ptr = gen_fprf_buf; |
|
6793 |
#endif |
|
6720 | 6794 |
nb_gen_labels = 0; |
6721 | 6795 |
ctx.nip = pc_start; |
6722 | 6796 |
ctx.tb = tb; |
Also available in: Unified diff