| @@ -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 | 229 | ST_FUNC void asm_opcode(TCCState *s1, int token) |
| 175 | 230 | { |
| 176 | 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 | 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 | 246 | case TOK_ASM_nopeq: |
| 189 | 247 | case TOK_ASM_wfeeq: |
| 190 | 248 | case TOK_ASM_wfieq: |