| @@ -1465,7 +1465,6 @@ static int asm_parse_vfp_regvar(int t, int double_precision) · 1464 unmodified lines |
| 1465 | 1465 | return -1; |
| 1466 | 1466 | } |
| 1467 | 1467 | |
| 1468 | | − |
| 1469 | 1468 | static void asm_floating_point_single_data_transfer_opcode(TCCState *s1, int token) |
| 1470 | 1469 | { |
| 1471 | 1470 | Operand ops[3]; |
| @@ -1648,6 +1647,264 @@ static void asm_floating_point_block_data_transfer_opcode(TCCState *s1, int toke · 176 unmodified lines |
| 1648 | 1647 | else |
| 1649 | 1648 | asm_emit_coprocessor_data_transfer(condition_code_of_token(token), coprocessor, first_regset_register, &ops[0], &offset, 0, preincrement, op0_exclam, extra_register_bit, load); |
| 1650 | 1649 | } |
| 1650 | + |
| 1651 | +// Not standalone. |
| 1652 | +static void asm_floating_point_immediate_data_processing_opcode_tail(TCCState *s1, int token, uint8_t coprocessor, uint8_t CRd) { |
| 1653 | + uint8_t opcode1 = 0; |
| 1654 | + uint8_t opcode2 = 0; |
| 1655 | + uint8_t operands[3] = {0, 0, 0}; |
| 1656 | + Operand operand; |
| 1657 | + |
| 1658 | + operands[0] = CRd; |
| 1659 | + |
| 1660 | + parse_operand(s1, &operand); |
| 1661 | + if (operand.type != OP_IM8 && operand.type != OP_IM8N) { |
| 1662 | + expect("Immediate value"); |
| 1663 | + return; |
| 1664 | + } |
| 1665 | + |
| 1666 | + opcode1 = 11; // "Other" instruction |
| 1667 | + switch (ARM_INSTRUCTION_GROUP(token)) { |
| 1668 | + case TOK_ASM_vcmpeq_f32: |
| 1669 | + case TOK_ASM_vcmpeq_f64: |
| 1670 | + opcode2 = 2; |
| 1671 | + operands[1] = 5; |
| 1672 | + if (operand.e.v) { |
| 1673 | + expect("Immediate value 0"); |
| 1674 | + return; |
| 1675 | + } |
| 1676 | + break; |
| 1677 | + case TOK_ASM_vcmpeeq_f32: |
| 1678 | + case TOK_ASM_vcmpeeq_f64: |
| 1679 | + opcode2 = 6; |
| 1680 | + operands[1] = 5; |
| 1681 | + if (operand.e.v) { |
| 1682 | + expect("Immediate value 0"); |
| 1683 | + return; |
| 1684 | + } |
| 1685 | + break; |
| 1686 | + default: |
| 1687 | + expect("known floating point with immediate instruction"); |
| 1688 | + return; |
| 1689 | + } |
| 1690 | + |
| 1691 | + if (coprocessor == CP_SINGLE_PRECISION_FLOAT) { |
| 1692 | + if (operands[0] & 1) |
| 1693 | + opcode1 |= 4; |
| 1694 | + operands[0] >>= 1; |
| 1695 | + } |
| 1696 | + |
| 1697 | + asm_emit_coprocessor_opcode(condition_code_of_token(token), coprocessor, opcode1, operands[0], operands[1], operands[2], opcode2, 0); |
| 1698 | +} |
| 1699 | + |
| 1700 | +static void asm_floating_point_data_processing_opcode(TCCState *s1, int token) { |
| 1701 | + uint8_t coprocessor = CP_SINGLE_PRECISION_FLOAT; |
| 1702 | + uint8_t opcode1 = 0; |
| 1703 | + uint8_t opcode2 = 0; // (0 || 2) | register selection |
| 1704 | + uint8_t operands[3]; |
| 1705 | + uint8_t nb_operands = 0; |
| 1706 | + int operand_1_register = 1; |
| 1707 | + int reg; |
| 1708 | + |
| 1709 | +/* TODO: |
| 1710 | + Instruction opcode opcode2 Reason |
| 1711 | + ============================================================= |
| 1712 | + - 1?00 ?1? Undefined |
| 1713 | + VFNMS 1?01 ?0? Must be unconditional |
| 1714 | + VFNMA 1?01 ?1? Must be unconditional |
| 1715 | + VFMA 1?10 ?0? Must be unconditional |
| 1716 | + VFMS 1?10 ?1? Must be unconditional |
| 1717 | + |
| 1718 | + VCVT* |
| 1719 | + |
| 1720 | + VMOV Fd, Fm |
| 1721 | + VMOV Sn, Rd |
| 1722 | + VMOV Rd, Sn |
| 1723 | + VMOV Sn, Sm, Rd, Rn |
| 1724 | + VMOV Rd, Rn, Sn, Sm |
| 1725 | + VMOV Dm, Rd, Rn |
| 1726 | + VMOV Rd, Rn, Dm |
| 1727 | + VMOV Dn[0], Rd |
| 1728 | + VMOV Rd, Dn[0] |
| 1729 | + VMOV Dn[1], Rd |
| 1730 | + VMOV Rd, Dn[1] |
| 1731 | + |
| 1732 | + VMSR <sysreg>, Rd |
| 1733 | + VMRS Rd, <sysreg> |
| 1734 | + VMRS APSR_nzcv, FPSCR |
| 1735 | +*/ |
| 1736 | + |
| 1737 | + switch (ARM_INSTRUCTION_GROUP(token)) { |
| 1738 | + case TOK_ASM_vmlaeq_f64: |
| 1739 | + case TOK_ASM_vmlseq_f64: |
| 1740 | + case TOK_ASM_vnmlseq_f64: |
| 1741 | + case TOK_ASM_vnmlaeq_f64: |
| 1742 | + case TOK_ASM_vmuleq_f64: |
| 1743 | + case TOK_ASM_vnmuleq_f64: |
| 1744 | + case TOK_ASM_vaddeq_f64: |
| 1745 | + case TOK_ASM_vsubeq_f64: |
| 1746 | + case TOK_ASM_vdiveq_f64: |
| 1747 | + case TOK_ASM_vnegeq_f64: |
| 1748 | + case TOK_ASM_vabseq_f64: |
| 1749 | + case TOK_ASM_vsqrteq_f64: |
| 1750 | + case TOK_ASM_vcmpeq_f64: |
| 1751 | + case TOK_ASM_vcmpeeq_f64: |
| 1752 | + coprocessor = CP_DOUBLE_PRECISION_FLOAT; |
| 1753 | + } |
| 1754 | + |
| 1755 | + for (nb_operands = 0; nb_operands < 3; ) { |
| 1756 | + if (nb_operands == 1 && (tok == '#' || tok == '$')) { |
| 1757 | + asm_floating_point_immediate_data_processing_opcode_tail(s1, token, coprocessor, operands[0]); |
| 1758 | + return; |
| 1759 | + } |
| 1760 | + if (coprocessor == CP_SINGLE_PRECISION_FLOAT) { |
| 1761 | + if ((reg = asm_parse_vfp_regvar(tok, 0)) != -1) { |
| 1762 | + operands[nb_operands] = reg; |
| 1763 | + next(); |
| 1764 | + } else { |
| 1765 | + expect("'s<number>'"); |
| 1766 | + return; |
| 1767 | + } |
| 1768 | + } else if (coprocessor == CP_DOUBLE_PRECISION_FLOAT) { |
| 1769 | + if ((reg = asm_parse_vfp_regvar(tok, 1)) != -1) { |
| 1770 | + operands[nb_operands] = reg; |
| 1771 | + next(); |
| 1772 | + } else { |
| 1773 | + expect("'d<number>'"); |
| 1774 | + return; |
| 1775 | + } |
| 1776 | + } else if ((reg = asm_parse_vfp_regvar(tok, 0)) != -1) { |
| 1777 | + coprocessor = CP_SINGLE_PRECISION_FLOAT; |
| 1778 | + operands[nb_operands] = reg; |
| 1779 | + next(); |
| 1780 | + } else if ((reg = asm_parse_vfp_regvar(tok, 1)) != -1) { |
| 1781 | + coprocessor = CP_DOUBLE_PRECISION_FLOAT; |
| 1782 | + operands[nb_operands] = reg; |
| 1783 | + next(); |
| 1784 | + } else |
| 1785 | + tcc_internal_error("unknown coprocessor"); |
| 1786 | + ++nb_operands; |
| 1787 | + if (tok == ',') |
| 1788 | + next(); |
| 1789 | + else |
| 1790 | + break; |
| 1791 | + } |
| 1792 | + |
| 1793 | + if (nb_operands == 2) { // implicit |
| 1794 | + operands[2] = operands[1]; |
| 1795 | + operands[1] = operands[0]; |
| 1796 | + nb_operands = 3; |
| 1797 | + } |
| 1798 | + if (nb_operands < 3) { |
| 1799 | + tcc_error("Not enough operands for '%s' (%u)", get_tok_str(token, NULL), nb_operands); |
| 1800 | + return; |
| 1801 | + } |
| 1802 | + |
| 1803 | + switch (ARM_INSTRUCTION_GROUP(token)) { |
| 1804 | + case TOK_ASM_vmlaeq_f32: |
| 1805 | + case TOK_ASM_vmlaeq_f64: |
| 1806 | + opcode1 = 0; |
| 1807 | + opcode2 = 0; |
| 1808 | + break; |
| 1809 | + case TOK_ASM_vmlseq_f32: |
| 1810 | + case TOK_ASM_vmlseq_f64: |
| 1811 | + opcode1 = 0; |
| 1812 | + opcode2 = 2; |
| 1813 | + break; |
| 1814 | + case TOK_ASM_vnmlseq_f32: |
| 1815 | + case TOK_ASM_vnmlseq_f64: |
| 1816 | + opcode1 = 1; |
| 1817 | + opcode2 = 0; |
| 1818 | + break; |
| 1819 | + case TOK_ASM_vnmlaeq_f32: |
| 1820 | + case TOK_ASM_vnmlaeq_f64: |
| 1821 | + opcode1 = 1; |
| 1822 | + opcode2 = 2; |
| 1823 | + break; |
| 1824 | + case TOK_ASM_vmuleq_f32: |
| 1825 | + case TOK_ASM_vmuleq_f64: |
| 1826 | + opcode1 = 2; |
| 1827 | + opcode2 = 0; |
| 1828 | + break; |
| 1829 | + case TOK_ASM_vnmuleq_f32: |
| 1830 | + case TOK_ASM_vnmuleq_f64: |
| 1831 | + opcode1 = 2; |
| 1832 | + opcode2 = 2; |
| 1833 | + break; |
| 1834 | + case TOK_ASM_vaddeq_f32: |
| 1835 | + case TOK_ASM_vaddeq_f64: |
| 1836 | + opcode1 = 3; |
| 1837 | + opcode2 = 0; |
| 1838 | + break; |
| 1839 | + case TOK_ASM_vsubeq_f32: |
| 1840 | + case TOK_ASM_vsubeq_f64: |
| 1841 | + opcode1 = 3; |
| 1842 | + opcode2 = 2; |
| 1843 | + break; |
| 1844 | + case TOK_ASM_vdiveq_f32: |
| 1845 | + case TOK_ASM_vdiveq_f64: |
| 1846 | + opcode1 = 8; |
| 1847 | + opcode2 = 0; |
| 1848 | + break; |
| 1849 | + case TOK_ASM_vnegeq_f32: |
| 1850 | + case TOK_ASM_vnegeq_f64: |
| 1851 | + opcode1 = 11; // Other" instruction |
| 1852 | + opcode2 = 2; |
| 1853 | + operands[1] = 1; |
| 1854 | + operand_1_register = 0; |
| 1855 | + break; |
| 1856 | + case TOK_ASM_vabseq_f32: |
| 1857 | + case TOK_ASM_vabseq_f64: |
| 1858 | + opcode1 = 11; // "Other" instruction |
| 1859 | + opcode2 = 6; |
| 1860 | + operands[1] = 0; |
| 1861 | + operand_1_register = 0; |
| 1862 | + break; |
| 1863 | + case TOK_ASM_vsqrteq_f32: |
| 1864 | + case TOK_ASM_vsqrteq_f64: |
| 1865 | + opcode1 = 11; // "Other" instruction |
| 1866 | + opcode2 = 6; |
| 1867 | + operands[1] = 1; |
| 1868 | + operand_1_register = 0; |
| 1869 | + break; |
| 1870 | + case TOK_ASM_vcmpeq_f32: |
| 1871 | + case TOK_ASM_vcmpeq_f64: |
| 1872 | + opcode1 = 11; // "Other" instruction |
| 1873 | + opcode2 = 2; |
| 1874 | + operands[1] = 4; |
| 1875 | + operand_1_register = 0; |
| 1876 | + break; |
| 1877 | + case TOK_ASM_vcmpeeq_f32: |
| 1878 | + case TOK_ASM_vcmpeeq_f64: |
| 1879 | + opcode1 = 11; // "Other" instruction |
| 1880 | + opcode2 = 6; |
| 1881 | + operands[1] = 4; |
| 1882 | + operand_1_register = 0; |
| 1883 | + break; |
| 1884 | + // TODO: vcvt; vcvtr |
| 1885 | + default: |
| 1886 | + expect("known floating point instruction"); |
| 1887 | + return; |
| 1888 | + } |
| 1889 | + |
| 1890 | + if (coprocessor == CP_SINGLE_PRECISION_FLOAT) { |
| 1891 | + if (operands[2] & 1) |
| 1892 | + opcode2 |= 1; |
| 1893 | + operands[2] >>= 1; |
| 1894 | + |
| 1895 | + if (operand_1_register) { |
| 1896 | + if (operands[1] & 1) |
| 1897 | + opcode2 |= 4; |
| 1898 | + operands[1] >>= 1; |
| 1899 | + } |
| 1900 | + |
| 1901 | + if (operands[0] & 1) |
| 1902 | + opcode1 |= 4; |
| 1903 | + operands[0] >>= 1; |
| 1904 | + } |
| 1905 | + |
| 1906 | + asm_emit_coprocessor_opcode(condition_code_of_token(token), coprocessor, opcode1, operands[0], operands[1], operands[2], opcode2, 0); |
| 1907 | +} |
| 1651 | 1908 | #endif |
| 1652 | 1909 | |
| 1653 | 1910 | static void asm_misc_single_data_transfer_opcode(TCCState *s1, int token) |
| @@ -2013,6 +2270,37 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) · 359 unmodified lines |
| 2013 | 2270 | asm_floating_point_single_data_transfer_opcode(s1, token); |
| 2014 | 2271 | return; |
| 2015 | 2272 | |
| 2273 | + case TOK_ASM_vmlaeq_f32: |
| 2274 | + case TOK_ASM_vmlseq_f32: |
| 2275 | + case TOK_ASM_vnmlseq_f32: |
| 2276 | + case TOK_ASM_vnmlaeq_f32: |
| 2277 | + case TOK_ASM_vmuleq_f32: |
| 2278 | + case TOK_ASM_vnmuleq_f32: |
| 2279 | + case TOK_ASM_vaddeq_f32: |
| 2280 | + case TOK_ASM_vsubeq_f32: |
| 2281 | + case TOK_ASM_vdiveq_f32: |
| 2282 | + case TOK_ASM_vnegeq_f32: |
| 2283 | + case TOK_ASM_vabseq_f32: |
| 2284 | + case TOK_ASM_vsqrteq_f32: |
| 2285 | + case TOK_ASM_vcmpeq_f32: |
| 2286 | + case TOK_ASM_vcmpeeq_f32: |
| 2287 | + case TOK_ASM_vmlaeq_f64: |
| 2288 | + case TOK_ASM_vmlseq_f64: |
| 2289 | + case TOK_ASM_vnmlseq_f64: |
| 2290 | + case TOK_ASM_vnmlaeq_f64: |
| 2291 | + case TOK_ASM_vmuleq_f64: |
| 2292 | + case TOK_ASM_vnmuleq_f64: |
| 2293 | + case TOK_ASM_vaddeq_f64: |
| 2294 | + case TOK_ASM_vsubeq_f64: |
| 2295 | + case TOK_ASM_vdiveq_f64: |
| 2296 | + case TOK_ASM_vnegeq_f64: |
| 2297 | + case TOK_ASM_vabseq_f64: |
| 2298 | + case TOK_ASM_vsqrteq_f64: |
| 2299 | + case TOK_ASM_vcmpeq_f64: |
| 2300 | + case TOK_ASM_vcmpeeq_f64: |
| 2301 | + asm_floating_point_data_processing_opcode(s1, token); |
| 2302 | + return; |
| 2303 | + |
| 2016 | 2304 | case TOK_ASM_vpusheq: |
| 2017 | 2305 | case TOK_ASM_vpopeq: |
| 2018 | 2306 | case TOK_ASM_vldmeq: |