| @@ -165,6 +165,26 @@ static void asm_emit_opcode(int token, uint32_t opcode) { · 164 unmodified lines |
| 165 | gen_le32((condition_code_of_token(token) << 28) | opcode); | 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 | static void asm_nullary_opcode(int token) | 188 | static void asm_nullary_opcode(int token) |
| 169 | { | 189 | { |
| 170 | switch (ARM_INSTRUCTION_GROUP(token)) { | 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 | /* data processing and single data transfer instructions only */ | 386 | /* data processing and single data transfer instructions only */ |
| 313 | #define ENCODE_RN(register_index) ((register_index) << 16) | 387 | #define ENCODE_RN(register_index) ((register_index) << 16) |
| 314 | #define ENCODE_RD(register_index) ((register_index) << 12) | 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 | case TOK_ASM_umlaleq: | 1542 | case TOK_ASM_umlaleq: |
| 1469 | case TOK_ASM_umlalseq: | 1543 | case TOK_ASM_umlalseq: |
| 1470 | return asm_long_multiplication_opcode(s1, token); | 1544 | return asm_long_multiplication_opcode(s1, token); |
| | 1545 | |
| | 1546 | case TOK_ASM_cdpeq: |
| | 1547 | return asm_coprocessor_opcode(s1, token); |
| 1471 | default: | 1548 | default: |
| 1472 | expect("known instruction"); | 1549 | expect("known instruction"); |
| 1473 | } | 1550 | } |