Unified · Split
| @@ -466,8 +466,9 @@ static void asm_data_processing_opcode(TCCState *s1, int token) · 465 unmodified lines | ||
| 466 | 466 | int nb_shift = 0; |
| 467 | 467 | uint32_t operands = 0; |
| 468 | 468 | |
| 469 | − /* 16 entries per instruction for the different condition codes */ | |
| 469 | + /* modulo 16 entries per instruction for the different condition codes */ | |
| 470 | 470 | uint32_t opcode_idx = (ARM_INSTRUCTION_GROUP(token) - TOK_ASM_andeq) >> 4; |
| 471 | + uint32_t opcode_nos = opcode_idx >> 1; // without "s"; "OpCode" in ARM docs | |
| 471 | 472 | |
| 472 | 473 | for (nb_ops = 0; nb_ops < sizeof(ops)/sizeof(ops[0]); ) { |
| 473 | 474 | if (tok == TOK_ASM_asl || tok == TOK_ASM_lsl || tok == TOK_ASM_lsr || tok == TOK_ASM_asr || tok == TOK_ASM_ror || tok == TOK_ASM_rrx) |
| @@ -517,6 +518,11 @@ static void asm_data_processing_opcode(TCCState *s1, int token) · 43 unmodified lines | ||
| 517 | 518 | memcpy(&ops[2], &ops[1], sizeof(ops[1])); // move ops[2] |
| 518 | 519 | memcpy(&ops[1], &ops[0], sizeof(ops[0])); // ops[1] was implicit |
| 519 | 520 | nb_ops = 3; |
| 521 | + } else if (nb_ops == 3) { | |
| 522 | + if (opcode_nos == 0xd || opcode_nos == 0xf || opcode_nos == 0xa || opcode_nos == 0xb || opcode_nos == 0x8 || opcode_nos == 0x9) { // mov, mvn, cmp, cmn, tst, teq | |
| 523 | + tcc_error("'%s' cannot be used with three operands", get_tok_str(token, NULL)); | |
| 524 | + return; | |
| 525 | + } | |
| 520 | 526 | } |
| 521 | 527 | if (nb_ops != 3) { |
| 522 | 528 | expect("two or three operands"); |
| @@ -533,16 +539,16 @@ static void asm_data_processing_opcode(TCCState *s1, int token) · 10 unmodified lines | ||
| 533 | 539 | // bits 24...21: "OpCode"--see below |
| 534 | 540 | |
| 535 | 541 | /* operations in the token list are ordered by opcode */ |
| 536 | − opcode = (opcode_idx >> 1) << 21; // drop "s" | |
| 542 | + opcode = opcode_nos << 21; // drop "s" | |
| 537 | 543 | if (ops[0].type != OP_REG32) |
| 538 | 544 | expect("(destination operand) register"); |
| 539 | − else if (opcode == 0xa << 21 || opcode == 0xb << 21 || opcode == 0x8 << 21 || opcode == 0x9 << 21 ) // cmp, cmn, tst, teq | |
| 545 | + else if (opcode_nos == 0xa || opcode_nos == 0xb || opcode_nos == 0x8 || opcode_nos == 0x9) // cmp, cmn, tst, teq | |
| 540 | 546 | operands |= ENCODE_SET_CONDITION_CODES; // force S set, otherwise it's a completely different instruction. |
| 541 | 547 | else |
| 542 | 548 | operands |= ENCODE_RD(ops[0].reg); |
| 543 | 549 | if (ops[1].type != OP_REG32) |
| 544 | 550 | expect("(first source operand) register"); |
| 545 | − else if (!(opcode == 0xd << 21 || opcode == 0xf << 21)) // not: mov, mvn (those have only one source operand) | |
| 551 | + else if (!(opcode_nos == 0xd || opcode_nos == 0xf)) // not: mov, mvn (those have only one source operand) | |
| 546 | 552 | operands |= ENCODE_RN(ops[1].reg); |
| 547 | 553 | switch (ops[2].type) { |
| 548 | 554 | case OP_REG32: |
| @@ -562,7 +568,7 @@ static void asm_data_processing_opcode(TCCState *s1, int token) · 13 unmodified lines | ||
| 562 | 568 | 1001 = TEQ - CC on: Op1 EOR Op2 -> difficult |
| 563 | 569 | 1100 = ORR - Rd:= Op1 OR Op2 -> difficult |
| 564 | 570 | */ |
| 565 | − switch (opcode_idx >> 1) { // "OpCode" in ARM docs | |
| 571 | + switch (opcode_nos) { | |
| 566 | 572 | #if 0 |
| 567 | 573 | case 0x0: // AND - Rd:= Op1 AND Op2 |
| 568 | 574 | opcode = 0xe << 21; // BIC |