| @@ -165,6 +165,26 @@ static void asm_emit_opcode(int token, uint32_t opcode) { · 164 unmodified lines |
| 165 | 165 | gen_le32((condition_code_of_token(token) << 28) | opcode); |
| 166 | 166 | } |
| 167 | 167 | |
| 168 | +static void asm_emit_coprocessor_opcode(uint32_t high_nibble, uint8_t cp_number, uint8_t cp_opcode, uint8_t cp_destination_register, uint8_t cp_n_operand_register, uint8_t cp_m_operand_register, uint8_t cp_opcode2, int inter_processor_transfer) |
| 169 | +{ |
| 170 | + uint32_t opcode = 0xe000000; |
| 171 | + if (inter_processor_transfer) |
| 172 | + opcode |= 1 << 4; |
| 173 | + //assert(cp_opcode < 16); |
| 174 | + opcode |= cp_opcode << 20; |
| 175 | + //assert(cp_n_operand_register < 16); |
| 176 | + opcode |= cp_n_operand_register << 16; |
| 177 | + //assert(cp_destination_register < 16); |
| 178 | + opcode |= cp_destination_register << 12; |
| 179 | + //assert(cp_number < 16); |
| 180 | + opcode |= cp_number << 8; |
| 181 | + //assert(cp_information < 8); |
| 182 | + opcode |= cp_opcode2 << 5; |
| 183 | + //assert(cp_m_operand_register < 16); |
| 184 | + opcode |= cp_m_operand_register; |
| 185 | + gen_le32((high_nibble << 28) | opcode); |
| 186 | +} |
| 187 | + |
| 168 | 188 | static void asm_nullary_opcode(int token) |
| 169 | 189 | { |
| 170 | 190 | switch (ARM_INSTRUCTION_GROUP(token)) { |
| @@ -309,6 +329,60 @@ static void asm_binary_opcode(TCCState *s1, int token) · 138 unmodified lines |
| 309 | 329 | } |
| 310 | 330 | } |
| 311 | 331 | |
| 332 | +static void asm_coprocessor_opcode(TCCState *s1, int token) { |
| 333 | + uint8_t coprocessor; |
| 334 | + Operand opcode1; |
| 335 | + Operand opcode2; |
| 336 | + uint8_t registers[3]; |
| 337 | + unsigned int i; |
| 338 | + |
| 339 | + if (tok >= TOK_ASM_p0 && tok <= TOK_ASM_p15) { |
| 340 | + coprocessor = tok - TOK_ASM_p0; |
| 341 | + next(); |
| 342 | + } else { |
| 343 | + expect("'p<number>'"); |
| 344 | + return; |
| 345 | + } |
| 346 | + |
| 347 | + if (tok == ',') |
| 348 | + next(); |
| 349 | + else |
| 350 | + expect("','"); |
| 351 | + |
| 352 | + parse_operand(s1, &opcode1); |
| 353 | + if (opcode1.type != OP_IM8 || opcode1.e.v > 15) { |
| 354 | + tcc_error("opcode1 of instruction '%s' must be an immediate value between 0 and 15", get_tok_str(token, NULL)); |
| 355 | + return; |
| 356 | + } |
| 357 | + |
| 358 | + for (i = 0; i < 3; ++i) { |
| 359 | + if (tok == ',') |
| 360 | + next(); |
| 361 | + else |
| 362 | + expect("','"); |
| 363 | + if (tok >= TOK_ASM_c0 && tok <= TOK_ASM_c15) { |
| 364 | + registers[i] = tok - TOK_ASM_c0; |
| 365 | + next(); |
| 366 | + } else { |
| 367 | + expect("'c<number>"); |
| 368 | + return; |
| 369 | + } |
| 370 | + } |
| 371 | + if (tok == ',') { |
| 372 | + next(); |
| 373 | + parse_operand(s1, &opcode2); |
| 374 | + } else { |
| 375 | + opcode2.type = OP_IM8; |
| 376 | + opcode2.e.v = 0; |
| 377 | + } |
| 378 | + if (opcode2.type != OP_IM8 || opcode2.e.v > 15) { |
| 379 | + tcc_error("opcode2 of instruction '%s' must be an immediate value between 0 and 15", get_tok_str(token, NULL)); |
| 380 | + return; |
| 381 | + } |
| 382 | + |
| 383 | + asm_emit_coprocessor_opcode(condition_code_of_token(token), coprocessor, opcode1.e.v, registers[0], registers[1], registers[2], opcode2.e.v, 0); |
| 384 | +} |
| 385 | + |
| 312 | 386 | /* data processing and single data transfer instructions only */ |
| 313 | 387 | #define ENCODE_RN(register_index) ((register_index) << 16) |
| 314 | 388 | #define ENCODE_RD(register_index) ((register_index) << 12) |
| @@ -1468,6 +1542,9 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) · 1153 unmodified lines |
| 1468 | 1542 | case TOK_ASM_umlaleq: |
| 1469 | 1543 | case TOK_ASM_umlalseq: |
| 1470 | 1544 | return asm_long_multiplication_opcode(s1, token); |
| 1545 | + |
| 1546 | + case TOK_ASM_cdpeq: |
| 1547 | + return asm_coprocessor_opcode(s1, token); |
| 1471 | 1548 | default: |
| 1472 | 1549 | expect("known instruction"); |
| 1473 | 1550 | } |