Revision 927f621e translate-i386.c

b/translate-i386.c
5 5
#include <inttypes.h>
6 6
#include <assert.h>
7 7

  
8
#define IN_OP_I386
8 9
#include "cpu-i386.h"
9 10

  
10 11
static uint8_t *gen_code_ptr;
......
39 40
    int prefix;
40 41
    int aflag, dflag;
41 42
    uint8_t *pc; /* current pc */
42
    uint8_t *runtime_pc; /* current pc in the runtime generated code */
43 43
    int cc_op; /* current CC operation */
44 44
    int f_st;
45 45
} DisasContext;
......
68 68
    OP_SAR = 7,
69 69
};
70 70

  
71

  
72
static const int fp_ops[8] = {
73
#if 0
74
    OP_FADDQ, OP_FMULQ, OP_CMP, OP_CMP,
75
    OP_FSUBQ, OP_FSUBQ, OP_FDIVQ, OP_FDIVQ
76
#endif
77
};
78

  
79
extern char cc_table, rclw_table, rclb_table;
80
extern char helper_rcll_T0_T1_cc;
81
extern char __udivdi3, __umoddi3;
82

  
83 71
#include "op-i386.h"
84 72

  
85 73
/* operand size */
......
606 594
    },
607 595
};
608 596

  
597
static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
598
    gen_op_fadd_ST0_FT0,
599
    gen_op_fmul_ST0_FT0,
600
    gen_op_fcom_ST0_FT0,
601
    gen_op_fcom_ST0_FT0,
602
    gen_op_fsub_ST0_FT0,
603
    gen_op_fsubr_ST0_FT0,
604
    gen_op_fdiv_ST0_FT0,
605
    gen_op_fdivr_ST0_FT0,
606
};
607

  
608
static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
609
    gen_op_fadd_STN_ST0,
610
    gen_op_fmul_STN_ST0,
611
    NULL,
612
    NULL,
613
    gen_op_fsub_STN_ST0,
614
    gen_op_fsubr_STN_ST0,
615
    gen_op_fdiv_STN_ST0,
616
    gen_op_fdivr_STN_ST0,
617
};
618

  
609 619
static void gen_op(DisasContext *s1, int op, int ot, int d, int s)
610 620
{
611 621
    if (d != OR_TMP0)
......
1345 1355
        /**************************/
1346 1356
        /* push/pop */
1347 1357
    case 0x50 ... 0x57: /* push */
1348
        gen_op_mov_TN_reg[OT_LONG][0][(b & 7)]();
1358
        gen_op_mov_TN_reg[OT_LONG][0][b & 7]();
1349 1359
        gen_op_pushl_T0();
1350 1360
        break;
1351 1361
    case 0x58 ... 0x5f: /* pop */
1352 1362
        gen_op_popl_T0();
1353
        gen_op_mov_reg_T0[OT_LONG][reg]();
1363
        gen_op_mov_reg_T0[OT_LONG][b & 7]();
1354 1364
        break;
1355 1365
    case 0x68: /* push Iv */
1356 1366
    case 0x6a:
......
1581 1591

  
1582 1592
        /************************/
1583 1593
        /* floats */
1584
#if 0        
1585 1594
    case 0xd8 ... 0xdf: 
1586 1595
        modrm = ldub(s->pc++);
1587 1596
        mod = (modrm >> 6) & 3;
......
1597 1606
            case 0x20 ... 0x27: /* fxxxl */
1598 1607
            case 0x30 ... 0x37: /* fixxx */
1599 1608
                {
1600
                    int op1, swap;
1601
                    op1 = fp_ops[op & 7];
1602

  
1603
                    swap = 0;
1604
                    if ((op & 7) == 5 || (op & 7) == 7)
1605
                        swap = 1;
1609
                    int op1;
1610
                    op1 = op & 7;
1606 1611

  
1607 1612
                    switch(op >> 4) {
1608 1613
                    case 0:
1609
                        ot = OT_LONG;
1610
                        is_int = 0;
1614
                        gen_op_flds_FT0_A0();
1611 1615
                        break;
1612 1616
                    case 1:
1613
                        ot = OT_LONG;
1614
                        is_int = 1;
1617
                        gen_op_fildl_FT0_A0();
1615 1618
                        break;
1616 1619
                    case 2:
1617
                        ot = OT_QUAD;
1618
                        is_int = 0;
1620
                        gen_op_fldl_FT0_A0();
1619 1621
                        break;
1620 1622
                    case 3:
1621 1623
                    default:
1622
                        ot = OT_WORD;
1623
                        is_int = 1;
1624
                        gen_op_fild_FT0_A0();
1624 1625
                        break;
1625 1626
                    }
1626 1627
                    
1627
                    /* if integer, needs to convert to float */
1628
                    if (is_int) {
1629
                        /* XXX: potential loss of precision if large integer */
1630
                        gen_ld(OP_LDUB + ot, OR_TMP0, reg_addr, offset_addr);
1631
                        gen_insn2(OP_I2FL, OR_FTMP0, OR_TMP0);
1632
                    } else {
1633
                        gen_ld(OP_LDUB + ot, OR_FTMP0, reg_addr, offset_addr);
1634
                    }
1635
                    if (ot != OT_QUAD)
1636
                        op1 += OP_FADDL - OP_FADDQ;
1637

  
1638
                    if (!swap)
1639
                        gen_insn3(op1, OR_ST0, OR_ST0, OR_FTMP0);
1640
                    else
1641
                        gen_insn3(op1, OR_ST0, OR_FTMP0, OR_ST0);
1642
                        
1643
                    if ((op & 7) == 3) {
1628
                    gen_op_fp_arith_ST0_FT0[op1]();
1629
                    if (op1 == 3) {
1644 1630
                        /* fcomp needs pop */
1645
                        gen_insn0(OP_FPOP);
1631
                        gen_op_fpop();
1646 1632
                    }
1647 1633
                }
1648 1634
                break;
......
1659 1645
            case 0x3a: /* fists */
1660 1646
            case 0x3b: /* fistps */
1661 1647
                
1662
                switch(op >> 4) {
1663
                case 0:
1664
                    ot = OT_LONG;
1665
                    is_int = 0;
1666
                    break;
1667
                case 1:
1668
                    ot = OT_LONG;
1669
                    is_int = 1;
1670
                    break;
1671
                case 2:
1672
                    ot = OT_QUAD;
1673
                    is_int = 0;
1674
                    break;
1675
                case 3:
1676
                default:
1677
                    ot = OT_WORD;
1678
                    is_int = 1;
1679
                    break;
1680
                }
1681

  
1682 1648
                switch(op & 7) {
1683 1649
                case 0:
1684
                    gen_insn0(OP_FPUSH);
1685
                    if (is_int) {
1686
                        /* XXX: potential loss of precision */
1687
                        gen_ld(OP_LDUB + ot, OR_TMP0, reg_addr, offset_addr);
1688
                        gen_insn2(OP_I2FL, OR_ST0, OR_TMP0);
1689
                    } else {
1690
                        gen_ld(OP_LDUB + ot, OR_ST0, reg_addr, offset_addr);
1650
                    gen_op_fpush();
1651
                    switch(op >> 4) {
1652
                    case 0:
1653
                        gen_op_flds_ST0_A0();
1654
                        break;
1655
                    case 1:
1656
                        gen_op_fildl_ST0_A0();
1657
                        break;
1658
                    case 2:
1659
                        gen_op_fldl_ST0_A0();
1660
                        break;
1661
                    case 3:
1662
                    default:
1663
                        gen_op_fild_ST0_A0();
1664
                        break;
1691 1665
                    }
1692 1666
                    break;
1693 1667
                default:
1694
                    if (is_int) {
1695
                        gen_insn2(OP_F2IL, OR_TMP0, OR_ST0);
1696
                        gen_st(OP_STB + ot, OR_TMP0, reg_addr, offset_addr);
1697
                    } else {
1698
                        gen_st(OP_STB + ot, OR_ST0, reg_addr, offset_addr);
1668
                    switch(op >> 4) {
1669
                    case 0:
1670
                        gen_op_fsts_ST0_A0();
1671
                        break;
1672
                    case 1:
1673
                        gen_op_fistl_ST0_A0();
1674
                        break;
1675
                    case 2:
1676
                        gen_op_fstl_ST0_A0();
1677
                        break;
1678
                    case 3:
1679
                    default:
1680
                        gen_op_fist_ST0_A0();
1681
                        break;
1699 1682
                    }
1700 1683
                    if ((op & 7) == 3)
1701
                        gen_insn0(OP_FPOP);
1684
                        gen_op_fpop();
1702 1685
                    break;
1703 1686
                }
1704 1687
                break;
1688
#if 0
1705 1689
            case 0x2f: /* fnstsw mem */
1706 1690
                gen_insn3(OP_FNSTS, OR_TMP0, OR_ZERO, OR_ZERO);
1707 1691
                gen_st(OP_STW, OR_TMP0, reg_addr, offset_addr);
......
1711 1695
            case 0x3e: /* fbstp */
1712 1696
                error("float BCD not hanlded");
1713 1697
                return -1;
1698
#endif
1714 1699
            case 0x3d: /* fildll */
1715
                gen_insn0(OP_FPUSH);
1716
                gen_ld(OP_LDQ, OR_TMP0, reg_addr, offset_addr);
1717
                gen_insn2(OP_I2FQ, OR_ST0, OR_TMP0);
1700
                gen_op_fpush();
1701
                gen_op_fildll_ST0_A0();
1718 1702
                break;
1719 1703
            case 0x3f: /* fistpll */
1720
                gen_insn2(OP_F2IQ, OR_TMP0, OR_ST0);
1721
                gen_st(OP_STQ, OR_TMP0, reg_addr, offset_addr);
1722
                gen_insn0(OP_FPOP);
1704
                gen_op_fistll_ST0_A0();
1705
                gen_op_fpop();
1723 1706
                break;
1724 1707
            default:
1725 1708
                error("unhandled memory FP\n");
......
1727 1710
            }
1728 1711
        } else {
1729 1712
            /* register float ops */
1730
            opreg = rm + OR_ST0;
1713
            opreg = rm;
1731 1714

  
1732 1715
            switch(op) {
1733 1716
            case 0x08: /* fld sti */
1734
                gen_insn0(OP_FPUSH);
1735
                gen_mov(OR_ST0, OR_ST0 + ((rm + 1) & 7));
1717
                gen_op_fpush();
1718
                gen_op_fmov_ST0_STN((opreg + 1) & 7);
1736 1719
                break;
1737 1720
            case 0x09: /* fxchg sti */
1738
                gen_mov(OR_TMP0, OR_ST0);
1739
                gen_mov(OR_ST0, opreg);
1740
                gen_mov(opreg, OR_TMP0);
1721
                gen_op_fxchg_ST0_STN((opreg + 1) & 7);
1741 1722
                break;
1742 1723
            case 0x0a: /* grp d9/2 */
1743 1724
                switch(rm) {
1744 1725
                case 0: /* fnop */
1745
                    gen_insn0(OP_NOP);
1746 1726
                    break;
1747 1727
                default:
1748 1728
                    error("unhandled FP GRP d9/2\n");
......
1752 1732
            case 0x0c: /* grp d9/4 */
1753 1733
                switch(rm) {
1754 1734
                case 0: /* fchs */
1755
                    gen_insn3(OP_FSUBQ, OR_ST0, OR_ZERO, OR_ST0);
1735
                    gen_op_fchs_ST0();
1756 1736
                    break;
1757 1737
                case 1: /* fabs */
1758
                    gen_insn2(OP_FABSQ, OR_ST0, OR_ST0);
1738
                    gen_op_fabs_ST0();
1759 1739
                    break;
1760 1740
                case 4: /* ftst */
1761
                    gen_insn3(OP_CMP, OR_ZERO, OR_ST0, OR_ZERO);
1741
                    gen_op_fldz_FT0();
1742
                    gen_op_fcom_ST0_FT0();
1762 1743
                    break;
1763 1744
                case 5: /* fxam */
1764
                    gen_insn3(OP_FSPECIAL, OR_ZERO, OR_ST0, OR_ZERO);
1745
                    gen_op_fxam_ST0();
1765 1746
                    break;
1766 1747
                default:
1767 1748
                    return -1;
......
1769 1750
                break;
1770 1751
            case 0x0d: /* grp d9/5 */
1771 1752
                {
1772
                    if (rm == 7) {
1773
                        error("bad GRP d9/5");
1753
                    switch(rm) {
1754
                    case 0:
1755
                        gen_op_fld1_ST0();
1756
                        break;
1757
                    case 1:
1758
                        gen_op_fld2t_ST0();
1759
                        break;
1760
                    case 2:
1761
                        gen_op_fld2e_ST0();
1762
                        break;
1763
                    case 3:
1764
                        gen_op_fldpi_ST0();
1765
                        break;
1766
                    case 4:
1767
                        gen_op_fldlg2_ST0();
1768
                        break;
1769
                    case 5:
1770
                        gen_op_fldln2_ST0();
1771
                        break;
1772
                    case 6:
1773
                        gen_op_fldz_ST0();
1774
                        break;
1775
                    default:
1774 1776
                        return -1;
1775 1777
                    }
1776
                    /* XXX: needs constant load or symbol table */
1777
                    gen_insn0(OP_FPUSH);
1778
                    gen_ld(OP_LDQ, OR_ST0, OR_ZERO, 
1779
                               (rm * 8) + FLOAT_CONST_ADDR);
1780 1778
                }
1781 1779
                break;
1782 1780
            case 0x0e: /* grp d9/6 */
1783 1781
                switch(rm) {
1784 1782
                case 0: /* f2xm1 */
1785
                    gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ZERO);
1783
                    gen_op_f2xm1();
1786 1784
                    break;
1787 1785
                case 1: /* fyl2x */
1788
                    gen_insn3(OP_FSPECIAL, OR_ST1, OR_ST0, OR_ST1);
1789
                    gen_insn0(OP_FPOP);
1786
                    gen_op_fyl2x();
1790 1787
                    break;
1791 1788
                case 2: /* fptan */
1792
                    gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ZERO);
1793
                    gen_insn0(OP_FPUSH);
1794
                    /* load one */
1795
                    gen_ld(OP_LDQ, OR_ST0, OR_ZERO, 
1796
                               (0 * 8) + FLOAT_CONST_ADDR);
1789
                    gen_op_fptan();
1797 1790
                    break;
1798 1791
                case 3: /* fpatan */
1799
                    gen_insn3(OP_FSPECIAL, OR_ST1, OR_ST0, OR_ST1);
1800
                    gen_insn0(OP_FPOP);
1792
                    gen_op_fpatan();
1801 1793
                    break;
1802 1794
                case 4: /* fxtract */
1803
                    gen_insn0(OP_FPUSH);
1804
                    gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST1, OR_ZERO);
1805
                    gen_insn3(OP_FSPECIAL, OR_ST1, OR_ST1, OR_ZERO);
1795
                    gen_op_fxtract();
1806 1796
                    break;
1807 1797
                case 5: /* fprem1 */
1808
                    gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ST1);
1798
                    gen_op_fprem1();
1809 1799
                    break;
1810 1800
                case 6: /* fdecstp */
1811
                    gen_insn0(OP_FPUSH);
1801
                    gen_op_fdecstp();
1812 1802
                    break;
1813 1803
                default:
1814
                case 7: /* fdecstp */
1815
                    gen_insn0(OP_FPOP);
1804
                case 7: /* fincstp */
1805
                    gen_op_fincstp();
1816 1806
                    break;
1817 1807
                }
1818 1808
                break;
1819 1809
            case 0x0f: /* grp d9/7 */
1820 1810
                switch(rm) {
1821 1811
                case 0: /* fprem */
1822
                    gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ST1);
1812
                    gen_op_fprem();
1823 1813
                    break;
1824 1814
                case 1: /* fyl2xp1 */
1825
                    gen_insn3(OP_FSPECIAL, OR_ST1, OR_ST0, OR_ST1);
1826
                    gen_insn0(OP_FPOP);
1815
                    gen_op_fyl2xp1();
1816
                    break;
1817
                case 2: /* fsqrt */
1818
                    gen_op_fsqrt();
1827 1819
                    break;
1828 1820
                case 3: /* fsincos */
1829
                    gen_insn0(OP_FPUSH);
1830
                    gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST1, OR_ZERO);
1831
                    gen_insn3(OP_FSPECIAL, OR_ST1, OR_ST1, OR_ZERO);
1821
                    gen_op_fsincos();
1832 1822
                    break;
1833 1823
                case 5: /* fscale */
1834
                    gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ST1);
1824
                    gen_op_fscale();
1835 1825
                    break;
1836
                case 2: /* fsqrt */
1837 1826
                case 4: /* frndint */
1827
                    gen_op_frndint();
1828
                    break;
1838 1829
                case 6: /* fsin */
1830
                    gen_op_fsin();
1831
                    break;
1839 1832
                default:
1840 1833
                case 7: /* fcos */
1841
                    gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ZERO);
1834
                    gen_op_fcos();
1842 1835
                    break;
1843 1836
                }
1844 1837
                break;
......
1846 1839
            case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
1847 1840
            case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
1848 1841
                {
1849
                    int op1, swap;
1842
                    int op1;
1850 1843
                    
1851
                    op1 = fp_ops[op & 7];
1852
                    swap = 0;
1853
                    if ((op & 7) == 5 || (op & 7) == 7)
1854
                        swap = 1;
1844
                    op1 = op & 7;
1855 1845
                    if (op >= 0x20) {
1856
                        if (swap) 
1857
                            gen_insn3(op1, opreg, OR_ST0, opreg);
1858
                        else
1859
                            gen_insn3(op1, opreg, opreg, OR_ST0);
1846
                        gen_op_fp_arith_STN_ST0[op1](opreg);
1860 1847
                    } else {
1861
                        if (swap)
1862
                            gen_insn3(op1, OR_ST0, opreg, OR_ST0);
1863
                        else
1864
                            gen_insn3(op1, OR_ST0, OR_ST0, opreg);
1848
                        gen_op_fmov_FT0_STN(opreg);
1849
                        gen_op_fp_arith_ST0_FT0[op1]();
1865 1850
                    }
1866 1851
                    if (op >= 0x30)
1867
                        gen_insn0(OP_FPOP);
1852
                        gen_op_fpop();
1868 1853
                }
1869 1854
                break;
1870 1855
            case 0x02: /* fcom */
1871
                gen_insn3(OP_CMP, OR_ZERO, OR_ST0, opreg);
1856
                gen_op_fmov_FT0_STN(opreg);
1857
                gen_op_fcom_ST0_FT0();
1872 1858
                break;
1873 1859
            case 0x03: /* fcomp */
1874
                gen_insn3(OP_CMP, OR_ZERO, OR_ST0, opreg);
1875
                gen_insn0(OP_FPOP);
1860
                gen_op_fmov_FT0_STN(opreg);
1861
                gen_op_fcom_ST0_FT0();
1862
                gen_op_fpop();
1876 1863
                break;
1877 1864
            case 0x15: /* da/5 */
1878 1865
                switch(rm) {
1879 1866
                case 1: /* fucompp */
1880
                    gen_insn3(OP_CMP, OR_ZERO, OR_ST0, opreg);
1881
                    gen_insn0(OP_FPOP);
1882
                    gen_insn0(OP_FPOP);
1867
                    gen_op_fmov_FT0_STN(1);
1868
                    gen_op_fcom_ST0_FT0();
1869
                    gen_op_fpop();
1870
                    gen_op_fpop();
1883 1871
                    break;
1884 1872
                default:
1885 1873
                    return -1;
1886 1874
                }
1887 1875
                break;
1888 1876
            case 0x2a: /* fst sti */
1889
                gen_mov(opreg, OR_ST0);
1877
                gen_op_fmov_STN_ST0(opreg);
1890 1878
                break;
1891 1879
            case 0x2b: /* fstp sti */
1892
                gen_mov(opreg, OR_ST0);
1893
                gen_insn0(OP_FPOP);
1880
                gen_op_fmov_STN_ST0(opreg);
1881
                gen_op_fpop();
1894 1882
                break;
1895 1883
            case 0x33: /* de/3 */
1896 1884
                switch(rm) {
1897 1885
                case 1: /* fcompp */
1898
                    gen_insn3(OP_CMP, OR_ZERO, OR_ST0, opreg);
1899
                    gen_insn0(OP_FPOP);
1900
                    gen_insn0(OP_FPOP);
1886
                    gen_op_fmov_FT0_STN(1);
1887
                    gen_op_fcom_ST0_FT0();
1888
                    gen_op_fpop();
1889
                    gen_op_fpop();
1901 1890
                    break;
1902 1891
                default:
1903 1892
                    return -1;
......
1905 1894
                break;
1906 1895
            case 0x3c: /* df/4 */
1907 1896
                switch(rm) {
1897
#if 0
1908 1898
                case 0:
1909 1899
                    gen_insn3(OP_FNSTS, OR_EAX, OR_ZERO, OR_ZERO);
1910 1900
                    break;
1901
#endif
1911 1902
                default:
1912 1903
                    return -1;
1913 1904
                }
......
1918 1909
            }
1919 1910
        }
1920 1911
        break;
1921
#endif
1922 1912
        /************************/
1923 1913
        /* string ops */
1924 1914
    case 0xa4: /* movsS */

Also available in: Unified diff