History

arm-asm: Mostly factor out VFP register reference parsing to parse_operand

Danny Milosavljevic committed 5 years ago

Commit 90343eb1 parent 04165941 file · +81 −78Browse files

Unified · Split

arm-asm.c+81−78
@@ -41,9 +41,13 @@ enum { · 40 unmodified lines
4141 OPT_IM8,
4242 OPT_IM8N,
4343 OPT_IM32,
44+ OPT_VREG32,
45+ OPT_VREG64,
4446 };
4547 #define OP_REG32 (1 << OPT_REG32)
46−#define OP_REG (OP_REG32)
48+#define OP_VREG32 (1 << OPT_VREG32)
49+#define OP_VREG64 (1 << OPT_VREG64)
50+#define OP_REG (OP_REG32 | OP_VREG32 | OP_VREG64)
4751 #define OP_IM32 (1 << OPT_IM32)
4852 #define OP_IM8 (1 << OPT_IM8)
4953 #define OP_IM8N (1 << OPT_IM8N)
@@ -58,6 +62,21 @@ typedef struct Operand { · 8 unmodified lines
5862 };
5963 } Operand;
6064
65+/* Read the VFP register referred to by token T.
66+ If OK, returns its number.
67+ If not OK, returns -1. */
68+static int asm_parse_vfp_regvar(int t, int double_precision)
69+{
70+ if (double_precision) {
71+ if (t >= TOK_ASM_d0 && t <= TOK_ASM_d15)
72+ return t - TOK_ASM_d0;
73+ } else {
74+ if (t >= TOK_ASM_s0 && t <= TOK_ASM_s31)
75+ return t - TOK_ASM_s0;
76+ }
77+ return -1;
78+}
79+
6180 /* Parse a text containing operand and store the result in OP */
6281 static void parse_operand(TCCState *s1, Operand *op)
6382 {
@@ -111,6 +130,14 @@ static void parse_operand(TCCState *s1, Operand *op) · 47 unmodified lines
111130 next(); // skip register name
112131 op->type = OP_REG32;
113132 op->reg = (uint8_t) reg;
133+ } else if ((reg = asm_parse_vfp_regvar(tok, 0)) != -1) {
134+ next(); // skip register name
135+ op->type = OP_VREG32;
136+ op->reg = (uint8_t) reg;
137+ } else if ((reg = asm_parse_vfp_regvar(tok, 1)) != -1) {
138+ next(); // skip register name
139+ op->type = OP_VREG64;
140+ op->reg = (uint8_t) reg;
114141 } else
115142 expect("operand");
116143 }
@@ -1450,41 +1477,25 @@ static void asm_coprocessor_data_transfer_opcode(TCCState *s1, int token) · 1333 unmodified lines
14501477 #define CP_SINGLE_PRECISION_FLOAT 10
14511478 #define CP_DOUBLE_PRECISION_FLOAT 11
14521479
1453−/* Read the VFP register referred to by T.
1454− If OK, returns its number.
1455− If not OK, returns -1. */
1456−static int asm_parse_vfp_regvar(int t, int double_precision)
1457−{
1458− if (double_precision) {
1459− if (t >= TOK_ASM_d0 && t <= TOK_ASM_d15)
1460− return t - TOK_ASM_d0;
1461− } else {
1462− if (t >= TOK_ASM_s0 && t <= TOK_ASM_s31)
1463− return t - TOK_ASM_s0;
1464− }
1465− return -1;
1466−}
1467−
14681480 static void asm_floating_point_single_data_transfer_opcode(TCCState *s1, int token)
14691481 {
14701482 Operand ops[3];
14711483 uint8_t coprocessor = 0;
14721484 uint8_t coprocessor_destination_register = 0;
14731485 int long_transfer = 0;
1474− int reg;
14751486 // Note: vldr p1, c0, [r4, #4] ; simple offset: r0 = *(int*)(r4+4); r4 unchanged
14761487 // Note: Not allowed: vldr p2, c0, [r4, #4]! ; pre-indexed: r0 = *(int*)(r4+4); r4 = r4+4
14771488 // Note: Not allowed: vldr p3, c0, [r4], #4 ; post-indexed: r0 = *(int*)(r4+0); r4 = r4+4
14781489
1479− if ((reg = asm_parse_vfp_regvar(tok, 0)) != -1) {
1490+ parse_operand(s1, &ops[0]);
1491+ if (ops[0].type == OP_VREG32) {
14801492 coprocessor = CP_SINGLE_PRECISION_FLOAT;
1481− coprocessor_destination_register = reg;
1493+ coprocessor_destination_register = ops[0].reg;
14821494 long_transfer = coprocessor_destination_register & 1;
14831495 coprocessor_destination_register >>= 1;
1484− next();
1485− } else if ((reg = asm_parse_vfp_regvar(tok, 1)) != -1) {
1496+ } else if (ops[0].type == OP_VREG64) {
14861497 coprocessor = CP_DOUBLE_PRECISION_FLOAT;
1487− coprocessor_destination_register = reg;
1498+ coprocessor_destination_register = ops[0].reg;
14881499 next();
14891500 } else {
14901501 expect("floating point register");
@@ -1809,10 +1820,8 @@ static void asm_floating_point_data_processing_opcode(TCCState *s1, int token) { · 318 unmodified lines
18091820 uint8_t coprocessor = CP_SINGLE_PRECISION_FLOAT;
18101821 uint8_t opcode1 = 0;
18111822 uint8_t opcode2 = 0; // (0 || 2) | register selection
1812− uint8_t operands[3];
1813− uint8_t nb_operands = 0;
1814− int operand_1_register = 1;
1815− int reg;
1823+ Operand ops[3];
1824+ uint8_t nb_ops = 0;
18161825
18171826 /* TODO:
18181827 Instruction opcode opcode2 Reason
@@ -1861,51 +1870,40 @@ static void asm_floating_point_data_processing_opcode(TCCState *s1, int token) { · 42 unmodified lines
18611870 coprocessor = CP_DOUBLE_PRECISION_FLOAT;
18621871 }
18631872
1864− for (nb_operands = 0; nb_operands < 3; ) {
1865− if (nb_operands == 1 && (tok == '#' || tok == '$')) {
1866− asm_floating_point_immediate_data_processing_opcode_tail(s1, token, coprocessor, operands[0]);
1873+ for (nb_ops = 0; nb_ops < 3; ) {
1874+ if (nb_ops == 1 && (tok == '#' || tok == '$')) {
1875+ asm_floating_point_immediate_data_processing_opcode_tail(s1, token, coprocessor, ops[0].reg);
18671876 return;
18681877 }
1869− if (coprocessor == CP_SINGLE_PRECISION_FLOAT) {
1870− if ((reg = asm_parse_vfp_regvar(tok, 0)) != -1) {
1871− operands[nb_operands] = reg;
1872− next();
1873− } else {
1878+ parse_operand(s1, &ops[nb_ops]);
1879+ if (ops[nb_ops].type == OP_VREG32) {
1880+ if (coprocessor != CP_SINGLE_PRECISION_FLOAT) {
18741881 expect("'s<number>'");
18751882 return;
18761883 }
1877− } else if (coprocessor == CP_DOUBLE_PRECISION_FLOAT) {
1878− if ((reg = asm_parse_vfp_regvar(tok, 1)) != -1) {
1879− operands[nb_operands] = reg;
1880− next();
1881− } else {
1884+ } else if (ops[nb_ops].type == OP_VREG64) {
1885+ if (coprocessor != CP_DOUBLE_PRECISION_FLOAT) {
18821886 expect("'d<number>'");
18831887 return;
18841888 }
1885− } else if ((reg = asm_parse_vfp_regvar(tok, 0)) != -1) {
1886− coprocessor = CP_SINGLE_PRECISION_FLOAT;
1887− operands[nb_operands] = reg;
1888− next();
1889− } else if ((reg = asm_parse_vfp_regvar(tok, 1)) != -1) {
1890− coprocessor = CP_DOUBLE_PRECISION_FLOAT;
1891− operands[nb_operands] = reg;
1892− next();
1893− } else
1894− tcc_internal_error("unknown coprocessor");
1895− ++nb_operands;
1889+ } else {
1890+ expect("floating point register");
1891+ return;
1892+ }
1893+ ++nb_ops;
18961894 if (tok == ',')
18971895 next();
18981896 else
18991897 break;
19001898 }
19011899
1902− if (nb_operands == 2) { // implicit
1903− operands[2] = operands[1];
1904− operands[1] = operands[0];
1905− nb_operands = 3;
1900+ if (nb_ops == 2) { // implicit
1901+ memcpy(&ops[2], &ops[1], sizeof(ops[1])); // move ops[2]
1902+ memcpy(&ops[1], &ops[0], sizeof(ops[0])); // ops[1] was implicit
1903+ nb_ops = 3;
19061904 }
1907− if (nb_operands < 3) {
1908− tcc_error("Not enough operands for '%s' (%u)", get_tok_str(token, NULL), nb_operands);
1905+ if (nb_ops < 3) {
1906+ tcc_error("Not enough operands for '%s' (%u)", get_tok_str(token, NULL), nb_ops);
19091907 return;
19101908 }
19111909
@@ -1959,43 +1957,44 @@ static void asm_floating_point_data_processing_opcode(TCCState *s1, int token) { · 47 unmodified lines
19591957 case TOK_ASM_vnegeq_f64:
19601958 opcode1 = 11; // Other" instruction
19611959 opcode2 = 2;
1962− operands[1] = 1;
1963− operand_1_register = 0;
1960+ ops[1].type = OP_IM8;
1961+ ops[1].e.v = 1;
19641962 break;
19651963 case TOK_ASM_vabseq_f32:
19661964 case TOK_ASM_vabseq_f64:
19671965 opcode1 = 11; // "Other" instruction
19681966 opcode2 = 6;
1969− operands[1] = 0;
1970− operand_1_register = 0;
1967+ ops[1].type = OP_IM8;
1968+ ops[1].e.v = 0;
19711969 break;
19721970 case TOK_ASM_vsqrteq_f32:
19731971 case TOK_ASM_vsqrteq_f64:
19741972 opcode1 = 11; // "Other" instruction
19751973 opcode2 = 6;
1976− operands[1] = 1;
1977− operand_1_register = 0;
1974+ ops[1].type = OP_IM8;
1975+ ops[1].e.v = 1;
19781976 break;
19791977 case TOK_ASM_vcmpeq_f32:
19801978 case TOK_ASM_vcmpeq_f64:
19811979 opcode1 = 11; // "Other" instruction
19821980 opcode2 = 2;
1983− operands[1] = 4;
1984− operand_1_register = 0;
1981+ ops[1].type = OP_IM8;
1982+ ops[1].e.v = 4;
19851983 break;
19861984 case TOK_ASM_vcmpeeq_f32:
19871985 case TOK_ASM_vcmpeeq_f64:
19881986 opcode1 = 11; // "Other" instruction
19891987 opcode2 = 6;
1990− operands[1] = 4;
1991− operand_1_register = 0;
1988+ ops[1].type = OP_IM8;
1989+ ops[1].e.v = 4;
19921990 break;
19931991 case TOK_ASM_vmoveq_f32:
19941992 case TOK_ASM_vmoveq_f64:
1993+ // FIXME: Check for ARM registers--and allow only very little.
19951994 opcode1 = 11; // "Other" instruction
19961995 opcode2 = 2;
1997− operands[1] = 0;
1998− operand_1_register = 0;
1996+ ops[1].type = OP_IM8;
1997+ ops[1].e.v = 0;
19991998 break;
20001999 // TODO: vcvt; vcvtr
20012000 default:
@@ -2004,22 +2003,26 @@ static void asm_floating_point_data_processing_opcode(TCCState *s1, int token) { · 2 unmodified lines
20042003 }
20052004
20062005 if (coprocessor == CP_SINGLE_PRECISION_FLOAT) {
2007− if (operands[2] & 1)
2008− opcode2 |= 1;
2009− operands[2] >>= 1;
2006+ if (ops[2].type == OP_VREG32) {
2007+ if (ops[2].reg & 1)
2008+ opcode2 |= 1;
2009+ ops[2].reg >>= 1;
2010+ }
20102011
2011− if (operand_1_register) {
2012− if (operands[1] & 1)
2012+ if (ops[1].type == OP_VREG32) {
2013+ if (ops[1].reg & 1)
20132014 opcode2 |= 4;
2014− operands[1] >>= 1;
2015+ ops[1].reg >>= 1;
20152016 }
20162017
2017− if (operands[0] & 1)
2018− opcode1 |= 4;
2019− operands[0] >>= 1;
2018+ if (ops[0].type == OP_VREG32) {
2019+ if (ops[0].reg & 1)
2020+ opcode1 |= 4;
2021+ ops[0].reg >>= 1;
2022+ }
20202023 }
20212024
2022− asm_emit_coprocessor_opcode(condition_code_of_token(token), coprocessor, opcode1, operands[0], operands[1], operands[2], opcode2, 0);
2025+ asm_emit_coprocessor_opcode(condition_code_of_token(token), coprocessor, opcode1, ops[0].reg, (ops[1].type == OP_IM8) ? ops[1].e.v : ops[1].reg, (ops[2].type == OP_IM8) ? ops[2].e.v : ops[2].reg, opcode2, 0);
20232026 }
20242027 #endif
20252028

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