History

arm-asm: Add vmla, vmls, vnmls, vnmla, vmul, vnmul, vadd, vsub, vdiv, vneg, vabs, vsqrt, vcmp, vcmpe

Danny Milosavljevic committed 5 years ago

Commit b82e52a1 parent 104037a3 files · +343 −2Browse files

Unified · Split

3 files
  1. arm-asm.c +289 −1
  2. arm-tok.h +38 −0
  3. tests/arm-asm-testsuite.sh +16 −1
arm-asm.c+289−1
@@ -1465,7 +1465,6 @@ static int asm_parse_vfp_regvar(int t, int double_precision) · 1464 unmodified lines
1465 return -1;1465 return -1;
1466}1466}
1467 1467
1468
1469static void asm_floating_point_single_data_transfer_opcode(TCCState *s1, int token)1468static void asm_floating_point_single_data_transfer_opcode(TCCState *s1, int token)
1470{1469{
1471 Operand ops[3];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 else1647 else
1649 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);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.
1652static 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
1700static 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#endif1908#endif
1652 1909
1653static void asm_misc_single_data_transfer_opcode(TCCState *s1, int token)1910static 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 asm_floating_point_single_data_transfer_opcode(s1, token);2270 asm_floating_point_single_data_transfer_opcode(s1, token);
2014 return;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 case TOK_ASM_vpusheq:2304 case TOK_ASM_vpusheq:
2017 case TOK_ASM_vpopeq:2305 case TOK_ASM_vpopeq:
2018 case TOK_ASM_vldmeq:2306 case TOK_ASM_vldmeq:
arm-tok.h+38−0
@@ -153,6 +153,29 @@ · 152 unmodified lines
153 DEF(TOK_ASM_ ## x, #x) \153 DEF(TOK_ASM_ ## x, #x) \
154 DEF(TOK_ASM_ ## x ## rsvd, #x "rsvd")154 DEF(TOK_ASM_ ## x ## rsvd, #x "rsvd")
155 155
156/* Note: condition code is 4 bits */
157#define DEF_ASM_CONDED_WITH_SUFFIX(x, y) \
158 DEF(TOK_ASM_ ## x ## eq ## _ ## y, #x "eq." #y) \
159 DEF(TOK_ASM_ ## x ## ne ## _ ## y, #x "ne." #y) \
160 DEF(TOK_ASM_ ## x ## cs ## _ ## y, #x "cs." #y) \
161 DEF(TOK_ASM_ ## x ## cc ## _ ## y, #x "cc." #y) \
162 DEF(TOK_ASM_ ## x ## mi ## _ ## y, #x "mi." #y) \
163 DEF(TOK_ASM_ ## x ## pl ## _ ## y, #x "pl." #y) \
164 DEF(TOK_ASM_ ## x ## vs ## _ ## y, #x "vs." #y) \
165 DEF(TOK_ASM_ ## x ## vc ## _ ## y, #x "vc." #y) \
166 DEF(TOK_ASM_ ## x ## hi ## _ ## y, #x "hi." #y) \
167 DEF(TOK_ASM_ ## x ## ls ## _ ## y, #x "ls." #y) \
168 DEF(TOK_ASM_ ## x ## ge ## _ ## y, #x "ge." #y) \
169 DEF(TOK_ASM_ ## x ## lt ## _ ## y, #x "lt." #y) \
170 DEF(TOK_ASM_ ## x ## gt ## _ ## y, #x "gt." #y) \
171 DEF(TOK_ASM_ ## x ## le ## _ ## y, #x "le." #y) \
172 DEF(TOK_ASM_ ## x ## _ ## y, #x "." #y) \
173 DEF(TOK_ASM_ ## x ## rsvd ## _ ## y, #x "rsvd." #y)
174
175#define DEF_ASM_CONDED_VFP_F32_F64(x) \
176 DEF_ASM_CONDED_WITH_SUFFIX(x, f32) \
177 DEF_ASM_CONDED_WITH_SUFFIX(x, f64)
178
156/* Note: add new tokens after nop (MUST always use DEF_ASM_CONDED) */179/* Note: add new tokens after nop (MUST always use DEF_ASM_CONDED) */
157 180
158 DEF_ASM_CONDED(nop)181 DEF_ASM_CONDED(nop)
@@ -286,6 +309,21 @@ · 127 unmodified lines
286 DEF_ASM_CONDED(vldr)309 DEF_ASM_CONDED(vldr)
287 DEF_ASM_CONDED(vstr)310 DEF_ASM_CONDED(vstr)
288 311
312 DEF_ASM_CONDED_VFP_F32_F64(vmla)
313 DEF_ASM_CONDED_VFP_F32_F64(vmls)
314 DEF_ASM_CONDED_VFP_F32_F64(vnmls)
315 DEF_ASM_CONDED_VFP_F32_F64(vnmla)
316 DEF_ASM_CONDED_VFP_F32_F64(vmul)
317 DEF_ASM_CONDED_VFP_F32_F64(vnmul)
318 DEF_ASM_CONDED_VFP_F32_F64(vadd)
319 DEF_ASM_CONDED_VFP_F32_F64(vsub)
320 DEF_ASM_CONDED_VFP_F32_F64(vdiv)
321 DEF_ASM_CONDED_VFP_F32_F64(vneg)
322 DEF_ASM_CONDED_VFP_F32_F64(vabs)
323 DEF_ASM_CONDED_VFP_F32_F64(vsqrt)
324 DEF_ASM_CONDED_VFP_F32_F64(vcmp)
325 DEF_ASM_CONDED_VFP_F32_F64(vcmpe)
326
289 DEF_ASM_CONDED(vpush)327 DEF_ASM_CONDED(vpush)
290 DEF_ASM_CONDED(vpop)328 DEF_ASM_CONDED(vpop)
291 DEF_ASM_CONDED(vldm)329 DEF_ASM_CONDED(vldm)
tests/arm-asm-testsuite.sh+16−1
@@ -5,7 +5,16 @@ set -e · 4 unmodified lines
5# Note: "{r3}" is definitely different--but would complicate the assembler.5# Note: "{r3}" is definitely different--but would complicate the assembler.
6 6
7state="`mktemp -d`"7state="`mktemp -d`"
8cat ../arm-tok.h |grep DEF_ASM |grep -v 'not useful' |grep -v '#define' |grep -v '/[*]' |sed -e 's;^[ ]*DEF_ASM[^(]*(\(.*\)).*$;\1;' | egrep -v '^((r|c|p|s|d)[0-9]+|fp|ip|sp|lr|pc|asl)$' | while read s8cat ../arm-tok.h | \
9 grep DEF_ASM | \
10 grep -v 'not useful' | \
11 grep -v '#define' | \
12 grep -v '/[*]' | \
13 grep -v 'DEF_ASM_CONDED_WITH_SUFFIX(x' | \
14 sed -e 's;^[ ]*DEF_ASM_CONDED_VFP_F32_F64[^(]*(\(.*\)).*$; DEF_ASM_CONDED(\1.f32)\
15 DEF_ASM_CONDED(\1.f64);g' | \
16 sed -e 's;^[ ]*DEF_ASM[^(]*(\(.*\)).*$;\1;g' | \
17 egrep -v '^((r|c|p|s|d)[0-9]+|fp|ip|sp|lr|pc|asl)$' | while read s
9do18do
10 as_opts=""19 as_opts=""
11 if [ "${s#v}" != "${s}" ]20 if [ "${s#v}" != "${s}" ]
@@ -132,6 +141,12 @@ do · 120 unmodified lines
132 "{d4}" \141 "{d4}" \
133 "{s4-s31}" \142 "{s4-s31}" \
134 "{s4}" \143 "{s4}" \
144 "s2, s3, s4" \
145 "s2, s3" \
146 "d2, d3, d4" \
147 "d2, d3" \
148 "s2, #0" \
149 "d2, #0" \
135 ""150 ""
136 do151 do
137 #echo ".syntax unified" > a.s152 #echo ".syntax unified" > a.s

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t