| @@ -77,6 +77,20 @@ static int asm_parse_vfp_regvar(int t, int double_precision) · 76 unmodified lines |
| 77 | 77 | return -1; |
| 78 | 78 | } |
| 79 | 79 | |
| 80 | +static int asm_parse_vfp_status_regvar(int t) |
| 81 | +{ |
| 82 | + switch (t) { |
| 83 | + case TOK_ASM_fpsid: |
| 84 | + return 0; |
| 85 | + case TOK_ASM_fpscr: |
| 86 | + return 1; |
| 87 | + case TOK_ASM_fpexc: |
| 88 | + return 8; |
| 89 | + default: |
| 90 | + return -1; |
| 91 | + } |
| 92 | +} |
| 93 | + |
| 80 | 94 | /* Parse a text containing operand and store the result in OP */ |
| 81 | 95 | static void parse_operand(TCCState *s1, Operand *op) |
| 82 | 96 | { |
| @@ -1915,10 +1929,6 @@ static void asm_floating_point_data_processing_opcode(TCCState *s1, int token) { · 1832 unmodified lines |
| 1915 | 1929 | VMOV Rd, Dn[0] |
| 1916 | 1930 | VMOV Dn[1], Rd |
| 1917 | 1931 | VMOV Rd, Dn[1] |
| 1918 | | − |
| 1919 | | − VMSR <sysreg>, Rd |
| 1920 | | − VMRS Rd, <sysreg> |
| 1921 | | − VMRS APSR_nzcv, FPSCR |
| 1922 | 1932 | */ |
| 1923 | 1933 | |
| 1924 | 1934 | switch (ARM_INSTRUCTION_GROUP(token)) { |
| @@ -2110,6 +2120,68 @@ static void asm_floating_point_data_processing_opcode(TCCState *s1, int token) { · 185 unmodified lines |
| 2110 | 2120 | |
| 2111 | 2121 | 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); |
| 2112 | 2122 | } |
| 2123 | + |
| 2124 | +static void asm_floating_point_status_register_opcode(TCCState* s1, int token) |
| 2125 | +{ |
| 2126 | + uint8_t coprocessor = CP_SINGLE_PRECISION_FLOAT; |
| 2127 | + uint8_t opcode; |
| 2128 | + int vfp_sys_reg = -1; |
| 2129 | + Operand arm_operand; |
| 2130 | + switch (ARM_INSTRUCTION_GROUP(token)) { |
| 2131 | + case TOK_ASM_vmrseq: |
| 2132 | + opcode = 0xf; |
| 2133 | + if (tok == TOK_ASM_apsr_nzcv) { |
| 2134 | + arm_operand.type = OP_REG32; |
| 2135 | + arm_operand.reg = 15; // not PC |
| 2136 | + next(); // skip apsr_nzcv |
| 2137 | + } else { |
| 2138 | + parse_operand(s1, &arm_operand); |
| 2139 | + if (arm_operand.type == OP_REG32 && arm_operand.reg == 15) { |
| 2140 | + tcc_error("'%s' does not support 'pc' as operand", get_tok_str(token, NULL)); |
| 2141 | + return; |
| 2142 | + } |
| 2143 | + } |
| 2144 | + |
| 2145 | + if (tok != ',') |
| 2146 | + expect("','"); |
| 2147 | + else |
| 2148 | + next(); // skip ',' |
| 2149 | + vfp_sys_reg = asm_parse_vfp_status_regvar(tok); |
| 2150 | + next(); // skip vfp sys reg |
| 2151 | + if (arm_operand.type == OP_REG32 && arm_operand.reg == 15 && vfp_sys_reg != 1) { |
| 2152 | + tcc_error("'%s' only supports the variant 'vmrs apsr_nzcv, fpscr' here", get_tok_str(token, NULL)); |
| 2153 | + return; |
| 2154 | + } |
| 2155 | + break; |
| 2156 | + case TOK_ASM_vmsreq: |
| 2157 | + opcode = 0xe; |
| 2158 | + vfp_sys_reg = asm_parse_vfp_status_regvar(tok); |
| 2159 | + next(); // skip vfp sys reg |
| 2160 | + if (tok != ',') |
| 2161 | + expect("','"); |
| 2162 | + else |
| 2163 | + next(); // skip ',' |
| 2164 | + parse_operand(s1, &arm_operand); |
| 2165 | + if (arm_operand.type == OP_REG32 && arm_operand.reg == 15) { |
| 2166 | + tcc_error("'%s' does not support 'pc' as operand", get_tok_str(token, NULL)); |
| 2167 | + return; |
| 2168 | + } |
| 2169 | + break; |
| 2170 | + default: |
| 2171 | + expect("floating point status register instruction"); |
| 2172 | + return; |
| 2173 | + } |
| 2174 | + if (vfp_sys_reg == -1) { |
| 2175 | + expect("VFP system register"); |
| 2176 | + return; |
| 2177 | + } |
| 2178 | + if (arm_operand.type != OP_REG32) { |
| 2179 | + expect("ARM register"); |
| 2180 | + return; |
| 2181 | + } |
| 2182 | + asm_emit_coprocessor_opcode(condition_code_of_token(token), coprocessor, opcode, arm_operand.reg, vfp_sys_reg, 0x10, 0, 0); |
| 2183 | +} |
| 2184 | + |
| 2113 | 2185 | #endif |
| 2114 | 2186 | |
| 2115 | 2187 | static void asm_misc_single_data_transfer_opcode(TCCState *s1, int token) |
| @@ -2518,6 +2590,11 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) · 402 unmodified lines |
| 2518 | 2590 | case TOK_ASM_vstmdbeq: |
| 2519 | 2591 | asm_floating_point_block_data_transfer_opcode(s1, token); |
| 2520 | 2592 | return; |
| 2593 | + |
| 2594 | + case TOK_ASM_vmsreq: |
| 2595 | + case TOK_ASM_vmrseq: |
| 2596 | + asm_floating_point_status_register_opcode(s1, token); |
| 2597 | + return; |
| 2521 | 2598 | #endif |
| 2522 | 2599 | |
| 2523 | 2600 | default: |