| @@ -171,6 +171,61 @@ static void asm_nullary_opcode(int token) · 170 unmodified lines |
| 171 | } | 171 | } |
| 172 | } | 172 | } |
| 173 | | 173 | |
| | 174 | static void asm_block_data_transfer_opcode(TCCState *s1, int token) |
| | 175 | { |
| | 176 | uint32_t opcode; |
| | 177 | int op0_exclam; |
| | 178 | Operand ops[2]; |
| | 179 | int nb_ops = 1; |
| | 180 | parse_operand(s1, &ops[0]); |
| | 181 | if (tok == '!') { |
| | 182 | op0_exclam = 1; |
| | 183 | next(); // skip '!' |
| | 184 | } |
| | 185 | if (tok == ',') { |
| | 186 | next(); // skip comma |
| | 187 | parse_operand(s1, &ops[1]); |
| | 188 | ++nb_ops; |
| | 189 | } |
| | 190 | if (nb_ops < 1) { |
| | 191 | expect("at least one operand"); |
| | 192 | return; |
| | 193 | } else if (ops[nb_ops - 1].type != OP_REGSET32) { |
| | 194 | expect("(last operand) register list"); |
| | 195 | return; |
| | 196 | } |
| | 197 | |
| | 198 | // block data transfer: 1 0 0 P U S W L << 20 (general case): |
| | 199 | // operands: |
| | 200 | // Rn: bits 19...16 base register |
| | 201 | // Register List: bits 15...0 |
| | 202 | |
| | 203 | switch (ARM_INSTRUCTION_GROUP(token)) { |
| | 204 | case TOK_ASM_pusheq: // TODO: Optimize 1-register case to: str ?, [sp, #-4]! |
| | 205 | // Instruction: 1 I=0 P=1 U=0 S=0 W=1 L=0 << 20, op 1101 |
| | 206 | // operands: |
| | 207 | // Rn: base register |
| | 208 | // Register List: bits 15...0 |
| | 209 | if (nb_ops != 1) |
| | 210 | expect("exactly one operand"); |
| | 211 | else |
| | 212 | asm_emit_opcode(token, (0x92d << 16) | ops[0].regset); // TODO: base register ? |
| | 213 | break; |
| | 214 | case TOK_ASM_popeq: // TODO: Optimize 1-register case to: ldr ?, [sp], #4 |
| | 215 | // Instruction: 1 I=0 P=0 U=1 S=0 W=0 L=1 << 20, op 1101 |
| | 216 | // operands: |
| | 217 | // Rn: base register |
| | 218 | // Register List: bits 15...0 |
| | 219 | if (nb_ops != 1) |
| | 220 | expect("exactly one operand"); |
| | 221 | else |
| | 222 | asm_emit_opcode(token, (0x8bd << 16) | ops[0].regset); // TODO: base register ? |
| | 223 | break; |
| | 224 | default: |
| | 225 | expect("block data transfer instruction"); |
| | 226 | } |
| | 227 | } |
| | 228 | |
| 174 | ST_FUNC void asm_opcode(TCCState *s1, int token) | 229 | ST_FUNC void asm_opcode(TCCState *s1, int token) |
| 175 | { | 230 | { |
| 176 | while (token == TOK_LINEFEED) { | 231 | while (token == TOK_LINEFEED) { |
| @@ -185,6 +240,9 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) · 8 unmodified lines |
| 185 | } | 240 | } |
| 186 | | 241 | |
| 187 | switch (ARM_INSTRUCTION_GROUP(token)) { | 242 | switch (ARM_INSTRUCTION_GROUP(token)) { |
| | 243 | case TOK_ASM_pusheq: |
| | 244 | case TOK_ASM_popeq: |
| | 245 | return asm_block_data_transfer_opcode(s1, token); |
| 188 | case TOK_ASM_nopeq: | 246 | case TOK_ASM_nopeq: |
| 189 | case TOK_ASM_wfeeq: | 247 | case TOK_ASM_wfeeq: |
| 190 | case TOK_ASM_wfieq: | 248 | case TOK_ASM_wfieq: |