| @@ -77,6 +77,20 @@ static int asm_parse_vfp_regvar(int t, int double_precision) · 76 unmodified lines |
| 77 | return -1; | 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 | /* Parse a text containing operand and store the result in OP */ | 94 | /* Parse a text containing operand and store the result in OP */ |
| 81 | static void parse_operand(TCCState *s1, Operand *op) | 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 | VMOV Rd, Dn[0] | 1929 | VMOV Rd, Dn[0] |
| 1916 | VMOV Dn[1], Rd | 1930 | VMOV Dn[1], Rd |
| 1917 | VMOV Rd, Dn[1] | 1931 | VMOV Rd, Dn[1] |
| 1918 | | | |
| 1919 | VMSR <sysreg>, Rd | | |
| 1920 | VMRS Rd, <sysreg> | | |
| 1921 | VMRS APSR_nzcv, FPSCR | | |
| 1922 | */ | 1932 | */ |
| 1923 | | 1933 | |
| 1924 | switch (ARM_INSTRUCTION_GROUP(token)) { | 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 | 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); | 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 | #endif | 2185 | #endif |
| 2114 | | 2186 | |
| 2115 | static void asm_misc_single_data_transfer_opcode(TCCState *s1, int token) | 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 | case TOK_ASM_vstmdbeq: | 2590 | case TOK_ASM_vstmdbeq: |
| 2519 | asm_floating_point_block_data_transfer_opcode(s1, token); | 2591 | asm_floating_point_block_data_transfer_opcode(s1, token); |
| 2520 | return; | 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 | #endif | 2598 | #endif |
| 2522 | | 2599 | |
| 2523 | default: | 2600 | default: |