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
14651465 return -1;
14661466 }
14671467
1468−
14691468 static void asm_floating_point_single_data_transfer_opcode(TCCState *s1, int token)
14701469 {
14711470 Operand ops[3];
@@ -1648,6 +1647,264 @@ static void asm_floating_point_block_data_transfer_opcode(TCCState *s1, int toke · 176 unmodified lines
16481647 else
16491648 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);
16501649 }
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+}
16511908 #endif
16521909
16531910 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
20132270 asm_floating_point_single_data_transfer_opcode(s1, token);
20142271 return;
20152272
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+
20162304 case TOK_ASM_vpusheq:
20172305 case TOK_ASM_vpopeq:
20182306 case TOK_ASM_vldmeq:
arm-tok.h+38−0
@@ -153,6 +153,29 @@ · 152 unmodified lines
153153 DEF(TOK_ASM_ ## x, #x) \
154154 DEF(TOK_ASM_ ## x ## rsvd, #x "rsvd")
155155
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+
156179 /* Note: add new tokens after nop (MUST always use DEF_ASM_CONDED) */
157180
158181 DEF_ASM_CONDED(nop)
@@ -286,6 +309,21 @@ · 127 unmodified lines
286309 DEF_ASM_CONDED(vldr)
287310 DEF_ASM_CONDED(vstr)
288311
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+
289327 DEF_ASM_CONDED(vpush)
290328 DEF_ASM_CONDED(vpop)
291329 DEF_ASM_CONDED(vldm)
tests/arm-asm-testsuite.sh+16−1
@@ -5,7 +5,16 @@ set -e · 4 unmodified lines
55 # Note: "{r3}" is definitely different--but would complicate the assembler.
66
77 state="`mktemp -d`"
8−cat ../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 s
8+cat ../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
918 do
1019 as_opts=""
1120 if [ "${s#v}" != "${s}" ]
@@ -132,6 +141,12 @@ do · 120 unmodified lines
132141 "{d4}" \
133142 "{s4-s31}" \
134143 "{s4}" \
144+ "s2, s3, s4" \
145+ "s2, s3" \
146+ "d2, d3, d4" \
147+ "d2, d3" \
148+ "s2, #0" \
149+ "d2, #0" \
135150 ""
136151 do
137152 #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