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
41 OPT_IM8,41 OPT_IM8,
42 OPT_IM8N,42 OPT_IM8N,
43 OPT_IM32,43 OPT_IM32,
44 OPT_VREG32,
45 OPT_VREG64,
44};46};
45#define OP_REG32 (1 << OPT_REG32)47#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)
47#define OP_IM32 (1 << OPT_IM32)51#define OP_IM32 (1 << OPT_IM32)
48#define OP_IM8 (1 << OPT_IM8)52#define OP_IM8 (1 << OPT_IM8)
49#define OP_IM8N (1 << OPT_IM8N)53#define OP_IM8N (1 << OPT_IM8N)
@@ -58,6 +62,21 @@ typedef struct Operand { · 8 unmodified lines
58 };62 };
59} Operand;63} Operand;
60 64
65/* Read the VFP register referred to by token T.
66 If OK, returns its number.
67 If not OK, returns -1. */
68static 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
61/* Parse a text containing operand and store the result in OP */80/* Parse a text containing operand and store the result in OP */
62static void parse_operand(TCCState *s1, Operand *op)81static void parse_operand(TCCState *s1, Operand *op)
63{82{
@@ -111,6 +130,14 @@ static void parse_operand(TCCState *s1, Operand *op) · 47 unmodified lines
111 next(); // skip register name130 next(); // skip register name
112 op->type = OP_REG32;131 op->type = OP_REG32;
113 op->reg = (uint8_t) reg;132 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;
114 } else141 } else
115 expect("operand");142 expect("operand");
116}143}
@@ -1450,41 +1477,25 @@ static void asm_coprocessor_data_transfer_opcode(TCCState *s1, int token) · 1333 unmodified lines
1450#define CP_SINGLE_PRECISION_FLOAT 101477#define CP_SINGLE_PRECISION_FLOAT 10
1451#define CP_DOUBLE_PRECISION_FLOAT 111478#define CP_DOUBLE_PRECISION_FLOAT 11
1452 1479
1453/* Read the VFP register referred to by T.
1454 If OK, returns its number.
1455 If not OK, returns -1. */
1456static 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
1468static void asm_floating_point_single_data_transfer_opcode(TCCState *s1, int token)1480static void asm_floating_point_single_data_transfer_opcode(TCCState *s1, int token)
1469{1481{
1470 Operand ops[3];1482 Operand ops[3];
1471 uint8_t coprocessor = 0;1483 uint8_t coprocessor = 0;
1472 uint8_t coprocessor_destination_register = 0;1484 uint8_t coprocessor_destination_register = 0;
1473 int long_transfer = 0;1485 int long_transfer = 0;
1474 int reg;
1475 // Note: vldr p1, c0, [r4, #4] ; simple offset: r0 = *(int*)(r4+4); r4 unchanged1486 // Note: vldr p1, c0, [r4, #4] ; simple offset: r0 = *(int*)(r4+4); r4 unchanged
1476 // Note: Not allowed: vldr p2, c0, [r4, #4]! ; pre-indexed: r0 = *(int*)(r4+4); r4 = r4+41487 // Note: Not allowed: vldr p2, c0, [r4, #4]! ; pre-indexed: r0 = *(int*)(r4+4); r4 = r4+4
1477 // Note: Not allowed: vldr p3, c0, [r4], #4 ; post-indexed: r0 = *(int*)(r4+0); r4 = r4+41488 // Note: Not allowed: vldr p3, c0, [r4], #4 ; post-indexed: r0 = *(int*)(r4+0); r4 = r4+4
1478 1489
1479 if ((reg = asm_parse_vfp_regvar(tok, 0)) != -1) {1490 parse_operand(s1, &ops[0]);
1491 if (ops[0].type == OP_VREG32) {
1480 coprocessor = CP_SINGLE_PRECISION_FLOAT;1492 coprocessor = CP_SINGLE_PRECISION_FLOAT;
1481 coprocessor_destination_register = reg;1493 coprocessor_destination_register = ops[0].reg;
1482 long_transfer = coprocessor_destination_register & 1;1494 long_transfer = coprocessor_destination_register & 1;
1483 coprocessor_destination_register >>= 1;1495 coprocessor_destination_register >>= 1;
1484 next();1496 } else if (ops[0].type == OP_VREG64) {
1485 } else if ((reg = asm_parse_vfp_regvar(tok, 1)) != -1) {
1486 coprocessor = CP_DOUBLE_PRECISION_FLOAT;1497 coprocessor = CP_DOUBLE_PRECISION_FLOAT;
1487 coprocessor_destination_register = reg;1498 coprocessor_destination_register = ops[0].reg;
1488 next();1499 next();
1489 } else {1500 } else {
1490 expect("floating point register");1501 expect("floating point register");
@@ -1809,10 +1820,8 @@ static void asm_floating_point_data_processing_opcode(TCCState *s1, int token) { · 318 unmodified lines
1809 uint8_t coprocessor = CP_SINGLE_PRECISION_FLOAT;1820 uint8_t coprocessor = CP_SINGLE_PRECISION_FLOAT;
1810 uint8_t opcode1 = 0;1821 uint8_t opcode1 = 0;
1811 uint8_t opcode2 = 0; // (0 || 2) | register selection1822 uint8_t opcode2 = 0; // (0 || 2) | register selection
1812 uint8_t operands[3];1823 Operand ops[3];
1813 uint8_t nb_operands = 0;1824 uint8_t nb_ops = 0;
1814 int operand_1_register = 1;
1815 int reg;
1816 1825
1817/* TODO:1826/* TODO:
1818 Instruction opcode opcode2 Reason1827 Instruction opcode opcode2 Reason
@@ -1861,51 +1870,40 @@ static void asm_floating_point_data_processing_opcode(TCCState *s1, int token) { · 42 unmodified lines
1861 coprocessor = CP_DOUBLE_PRECISION_FLOAT;1870 coprocessor = CP_DOUBLE_PRECISION_FLOAT;
1862 }1871 }
1863 1872
1864 for (nb_operands = 0; nb_operands < 3; ) {1873 for (nb_ops = 0; nb_ops < 3; ) {
1865 if (nb_operands == 1 && (tok == '#' || tok == '$')) {1874 if (nb_ops == 1 && (tok == '#' || tok == '$')) {
1866 asm_floating_point_immediate_data_processing_opcode_tail(s1, token, coprocessor, operands[0]);1875 asm_floating_point_immediate_data_processing_opcode_tail(s1, token, coprocessor, ops[0].reg);
1867 return;1876 return;
1868 }1877 }
1869 if (coprocessor == CP_SINGLE_PRECISION_FLOAT) {1878 parse_operand(s1, &ops[nb_ops]);
1870 if ((reg = asm_parse_vfp_regvar(tok, 0)) != -1) {1879 if (ops[nb_ops].type == OP_VREG32) {
1871 operands[nb_operands] = reg;1880 if (coprocessor != CP_SINGLE_PRECISION_FLOAT) {
1872 next();
1873 } else {
1874 expect("'s<number>'");1881 expect("'s<number>'");
1875 return;1882 return;
1876 }1883 }
1877 } else if (coprocessor == CP_DOUBLE_PRECISION_FLOAT) {1884 } else if (ops[nb_ops].type == OP_VREG64) {
1878 if ((reg = asm_parse_vfp_regvar(tok, 1)) != -1) {1885 if (coprocessor != CP_DOUBLE_PRECISION_FLOAT) {
1879 operands[nb_operands] = reg;
1880 next();
1881 } else {
1882 expect("'d<number>'");1886 expect("'d<number>'");
1883 return;1887 return;
1884 }1888 }
1885 } else if ((reg = asm_parse_vfp_regvar(tok, 0)) != -1) {1889 } else {
1886 coprocessor = CP_SINGLE_PRECISION_FLOAT;1890 expect("floating point register");
1887 operands[nb_operands] = reg;1891 return;
1888 next();1892 }
1889 } else if ((reg = asm_parse_vfp_regvar(tok, 1)) != -1) {1893 ++nb_ops;
1890 coprocessor = CP_DOUBLE_PRECISION_FLOAT;
1891 operands[nb_operands] = reg;
1892 next();
1893 } else
1894 tcc_internal_error("unknown coprocessor");
1895 ++nb_operands;
1896 if (tok == ',')1894 if (tok == ',')
1897 next();1895 next();
1898 else1896 else
1899 break;1897 break;
1900 }1898 }
1901 1899
1902 if (nb_operands == 2) { // implicit1900 if (nb_ops == 2) { // implicit
1903 operands[2] = operands[1];1901 memcpy(&ops[2], &ops[1], sizeof(ops[1])); // move ops[2]
1904 operands[1] = operands[0];1902 memcpy(&ops[1], &ops[0], sizeof(ops[0])); // ops[1] was implicit
1905 nb_operands = 3;1903 nb_ops = 3;
1906 }1904 }
1907 if (nb_operands < 3) {1905 if (nb_ops < 3) {
1908 tcc_error("Not enough operands for '%s' (%u)", get_tok_str(token, NULL), nb_operands);1906 tcc_error("Not enough operands for '%s' (%u)", get_tok_str(token, NULL), nb_ops);
1909 return;1907 return;
1910 }1908 }
1911 1909
@@ -1959,43 +1957,44 @@ static void asm_floating_point_data_processing_opcode(TCCState *s1, int token) { · 47 unmodified lines
1959 case TOK_ASM_vnegeq_f64:1957 case TOK_ASM_vnegeq_f64:
1960 opcode1 = 11; // Other" instruction1958 opcode1 = 11; // Other" instruction
1961 opcode2 = 2;1959 opcode2 = 2;
1962 operands[1] = 1;1960 ops[1].type = OP_IM8;
1963 operand_1_register = 0;1961 ops[1].e.v = 1;
1964 break;1962 break;
1965 case TOK_ASM_vabseq_f32:1963 case TOK_ASM_vabseq_f32:
1966 case TOK_ASM_vabseq_f64:1964 case TOK_ASM_vabseq_f64:
1967 opcode1 = 11; // "Other" instruction1965 opcode1 = 11; // "Other" instruction
1968 opcode2 = 6;1966 opcode2 = 6;
1969 operands[1] = 0;1967 ops[1].type = OP_IM8;
1970 operand_1_register = 0;1968 ops[1].e.v = 0;
1971 break;1969 break;
1972 case TOK_ASM_vsqrteq_f32:1970 case TOK_ASM_vsqrteq_f32:
1973 case TOK_ASM_vsqrteq_f64:1971 case TOK_ASM_vsqrteq_f64:
1974 opcode1 = 11; // "Other" instruction1972 opcode1 = 11; // "Other" instruction
1975 opcode2 = 6;1973 opcode2 = 6;
1976 operands[1] = 1;1974 ops[1].type = OP_IM8;
1977 operand_1_register = 0;1975 ops[1].e.v = 1;
1978 break;1976 break;
1979 case TOK_ASM_vcmpeq_f32:1977 case TOK_ASM_vcmpeq_f32:
1980 case TOK_ASM_vcmpeq_f64:1978 case TOK_ASM_vcmpeq_f64:
1981 opcode1 = 11; // "Other" instruction1979 opcode1 = 11; // "Other" instruction
1982 opcode2 = 2;1980 opcode2 = 2;
1983 operands[1] = 4;1981 ops[1].type = OP_IM8;
1984 operand_1_register = 0;1982 ops[1].e.v = 4;
1985 break;1983 break;
1986 case TOK_ASM_vcmpeeq_f32:1984 case TOK_ASM_vcmpeeq_f32:
1987 case TOK_ASM_vcmpeeq_f64:1985 case TOK_ASM_vcmpeeq_f64:
1988 opcode1 = 11; // "Other" instruction1986 opcode1 = 11; // "Other" instruction
1989 opcode2 = 6;1987 opcode2 = 6;
1990 operands[1] = 4;1988 ops[1].type = OP_IM8;
1991 operand_1_register = 0;1989 ops[1].e.v = 4;
1992 break;1990 break;
1993 case TOK_ASM_vmoveq_f32:1991 case TOK_ASM_vmoveq_f32:
1994 case TOK_ASM_vmoveq_f64:1992 case TOK_ASM_vmoveq_f64:
1993 // FIXME: Check for ARM registers--and allow only very little.
1995 opcode1 = 11; // "Other" instruction1994 opcode1 = 11; // "Other" instruction
1996 opcode2 = 2;1995 opcode2 = 2;
1997 operands[1] = 0;1996 ops[1].type = OP_IM8;
1998 operand_1_register = 0;1997 ops[1].e.v = 0;
1999 break;1998 break;
2000 // TODO: vcvt; vcvtr1999 // TODO: vcvt; vcvtr
2001 default:2000 default:
@@ -2004,22 +2003,26 @@ static void asm_floating_point_data_processing_opcode(TCCState *s1, int token) { · 2 unmodified lines
2004 }2003 }
2005 2004
2006 if (coprocessor == CP_SINGLE_PRECISION_FLOAT) {2005 if (coprocessor == CP_SINGLE_PRECISION_FLOAT) {
2007 if (operands[2] & 1)2006 if (ops[2].type == OP_VREG32) {
2008 opcode2 |= 1;2007 if (ops[2].reg & 1)
2009 operands[2] >>= 1;2008 opcode2 |= 1;
2009 ops[2].reg >>= 1;
2010 }
2010 2011
2011 if (operand_1_register) {2012 if (ops[1].type == OP_VREG32) {
2012 if (operands[1] & 1)2013 if (ops[1].reg & 1)
2013 opcode2 |= 4;2014 opcode2 |= 4;
2014 operands[1] >>= 1;2015 ops[1].reg >>= 1;
2015 }2016 }
2016 2017
2017 if (operands[0] & 1)2018 if (ops[0].type == OP_VREG32) {
2018 opcode1 |= 4;2019 if (ops[0].reg & 1)
2019 operands[0] >>= 1;2020 opcode1 |= 4;
2021 ops[0].reg >>= 1;
2022 }
2020 }2023 }
2021 2024
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);
2023}2026}
2024#endif2027#endif
2025 2028

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