Unified · Split
| @@ -550,6 +550,8 @@ static void asm_data_processing_opcode(TCCState *s1, int token) · 549 unmodified lines | |||
| 550 | return; | 550 | return; |
| 551 | } else { | 551 | } else { |
| 552 | uint32_t opcode = 0; | 552 | uint32_t opcode = 0; |
| 553 | uint32_t immediate_value; | ||
| 554 | uint8_t half_immediate_rotation; | ||
| 553 | if (nb_shift && shift.type == OP_REG32) { | 555 | if (nb_shift && shift.type == OP_REG32) { |
| 554 | if ((ops[0].type == OP_REG32 && ops[0].reg == 15) || | 556 | if ((ops[0].type == OP_REG32 && ops[0].reg == 15) || |
| 555 | (ops[1].type == OP_REG32 && ops[1].reg == 15)) { | 557 | (ops[1].type == OP_REG32 && ops[1].reg == 15)) { |
| @@ -583,11 +585,25 @@ static void asm_data_processing_opcode(TCCState *s1, int token) · 27 unmodified lines | |||
| 583 | operands |= ops[2].reg; | 585 | operands |= ops[2].reg; |
| 584 | break; | 586 | break; |
| 585 | case OP_IM8: | 587 | case OP_IM8: |
| 588 | case OP_IM32: | ||
| 586 | operands |= ENCODE_IMMEDIATE_FLAG; | 589 | operands |= ENCODE_IMMEDIATE_FLAG; |
| 587 | operands |= ops[2].e.v; | 590 | immediate_value = ops[2].e.v; |
| 588 | break; | 591 | for (half_immediate_rotation = 0; half_immediate_rotation < 16; ++half_immediate_rotation) { |
| 592 | if (immediate_value >= 0x00 && immediate_value < 0x100) | ||
| 593 | break; | ||
| 594 | // rotate left by two | ||
| 595 | immediate_value = ((immediate_value & 0x3FFFFFFF) << 2) | ((immediate_value & 0xC0000000) >> 30); | ||
| 596 | } | ||
| 597 | if (half_immediate_rotation >= 16) { | ||
| 598 | /* fallthrough */ | ||
| 599 | } else { | ||
| 600 | operands |= immediate_value; | ||
| 601 | operands |= half_immediate_rotation << 8; | ||
| 602 | break; | ||
| 603 | } | ||
| 589 | case OP_IM8N: // immediate negative value | 604 | case OP_IM8N: // immediate negative value |
| 590 | operands |= ENCODE_IMMEDIATE_FLAG; | 605 | operands |= ENCODE_IMMEDIATE_FLAG; |
| 606 | immediate_value = ops[2].e.v; | ||
| 591 | /* Instruction swapping: | 607 | /* Instruction swapping: |
| 592 | 0001 = EOR - Rd:= Op1 EOR Op2 -> difficult | 608 | 0001 = EOR - Rd:= Op1 EOR Op2 -> difficult |
| 593 | 0011 = RSB - Rd:= Op2 - Op1 -> difficult | 609 | 0011 = RSB - Rd:= Op2 - Op1 -> difficult |
| @@ -597,54 +613,61 @@ static void asm_data_processing_opcode(TCCState *s1, int token) · 3 unmodified lines | |||
| 597 | 1100 = ORR - Rd:= Op1 OR Op2 -> difficult | 613 | 1100 = ORR - Rd:= Op1 OR Op2 -> difficult |
| 598 | */ | 614 | */ |
| 599 | switch (opcode_nos) { | 615 | switch (opcode_nos) { |
| 600 | #if 0 | ||
| 601 | case 0x0: // AND - Rd:= Op1 AND Op2 | 616 | case 0x0: // AND - Rd:= Op1 AND Op2 |
| 602 | opcode = 0xe << 21; // BIC | 617 | opcode = 0xe << 21; // BIC |
| 603 | operands |= (ops[2].e.v ^ 0xFF) & 0xFF; | 618 | immediate_value = ~immediate_value; |
| 604 | break; | 619 | break; |
| 605 | case 0x2: // SUB - Rd:= Op1 - Op2 | 620 | case 0x2: // SUB - Rd:= Op1 - Op2 |
| 606 | opcode = 0x4 << 21; // ADD | 621 | opcode = 0x4 << 21; // ADD |
| 607 | operands |= (-ops[2].e.v) & 0xFF; | 622 | immediate_value = -immediate_value; |
| 608 | break; | 623 | break; |
| 609 | case 0x4: // ADD - Rd:= Op1 + Op2 | 624 | case 0x4: // ADD - Rd:= Op1 + Op2 |
| 610 | opcode = 0x2 << 21; // SUB | 625 | opcode = 0x2 << 21; // SUB |
| 611 | operands |= (-ops[2].e.v) & 0xFF; | 626 | immediate_value = -immediate_value; |
| 612 | break; | 627 | break; |
| 613 | case 0x5: // ADC - Rd:= Op1 + Op2 + C | 628 | case 0x5: // ADC - Rd:= Op1 + Op2 + C |
| 614 | opcode = 0x6 << 21; // SBC | 629 | opcode = 0x6 << 21; // SBC |
| 615 | operands |= (ops[2].e.v ^ 0xFF) & 0xFF; | 630 | immediate_value = ~immediate_value; |
| 616 | break; | 631 | break; |
| 617 | case 0x6: // SBC - Rd:= Op1 - Op2 + C | 632 | case 0x6: // SBC - Rd:= Op1 - Op2 + C |
| 618 | opcode = 0x5 << 21; // ADC | 633 | opcode = 0x5 << 21; // ADC |
| 619 | operands |= (ops[2].e.v ^ 0xFF) & 0xFF; | 634 | immediate_value = ~immediate_value; |
| 620 | break; | 635 | break; |
| 621 | #endif | ||
| 622 | case 0xa: // CMP - CC on: Op1 - Op2 | 636 | case 0xa: // CMP - CC on: Op1 - Op2 |
| 623 | opcode = 0xb << 21; // CMN | 637 | opcode = 0xb << 21; // CMN |
| 624 | operands |= (-ops[2].e.v) & 0xFF; | 638 | immediate_value = -immediate_value; |
| 625 | break; | 639 | break; |
| 626 | case 0xb: // CMN - CC on: Op1 + Op2 | 640 | case 0xb: // CMN - CC on: Op1 + Op2 |
| 627 | opcode = 0xa << 21; // CMP | 641 | opcode = 0xa << 21; // CMP |
| 628 | operands |= (-ops[2].e.v) & 0xFF; | 642 | immediate_value = -immediate_value; |
| 629 | break; | 643 | break; |
| 630 | // moveq r1, r3: 0x01a01003; mov Rd, Op2 | ||
| 631 | case 0xd: // MOV - Rd:= Op2 | 644 | case 0xd: // MOV - Rd:= Op2 |
| 632 | opcode = 0xf << 21; // MVN | 645 | opcode = 0xf << 21; // MVN |
| 633 | operands |= (ops[2].e.v ^ 0xFF) & 0xFF; | 646 | immediate_value = ~immediate_value; |
| 634 | break; | 647 | break; |
| 635 | #if 0 | ||
| 636 | case 0xe: // BIC - Rd:= Op1 AND NOT Op2 | 648 | case 0xe: // BIC - Rd:= Op1 AND NOT Op2 |
| 637 | opcode = 0x0 << 21; // AND | 649 | opcode = 0x0 << 21; // AND |
| 638 | operands |= (ops[2].e.v ^ 0xFF) & 0xFF; | 650 | immediate_value = ~immediate_value; |
| 639 | break; | 651 | break; |
| 640 | #endif | ||
| 641 | case 0xf: // MVN - Rd:= NOT Op2 | 652 | case 0xf: // MVN - Rd:= NOT Op2 |
| 642 | opcode = 0xd << 21; // MOV | 653 | opcode = 0xd << 21; // MOV |
| 643 | operands |= (ops[2].e.v ^ 0xFF) & 0xFF; | 654 | immediate_value = ~immediate_value; |
| 644 | break; | 655 | break; |
| 645 | default: | 656 | default: |
| 646 | tcc_error("cannot use '%s' with a negative immediate value", get_tok_str(token, NULL)); | 657 | tcc_error("cannot use '%s' with a negative immediate value", get_tok_str(token, NULL)); |
| 647 | } | 658 | } |
| 659 | for (half_immediate_rotation = 0; half_immediate_rotation < 16; ++half_immediate_rotation) { | ||
| 660 | if (immediate_value >= 0x00 && immediate_value < 0x100) | ||
| 661 | break; | ||
| 662 | // rotate left by two | ||
| 663 | immediate_value = ((immediate_value & 0x3FFFFFFF) << 2) | ((immediate_value & 0xC0000000) >> 30); | ||
| 664 | } | ||
| 665 | if (half_immediate_rotation >= 16) { | ||
| 666 | tcc_error("immediate value 0x%X cannot be encoded into ARM immediate", (unsigned) immediate_value); | ||
| 667 | return; | ||
| 668 | } | ||
| 669 | operands |= immediate_value; | ||
| 670 | operands |= half_immediate_rotation << 8; | ||
| 648 | break; | 671 | break; |
| 649 | default: | 672 | default: |
| 650 | expect("(second source operand) register or immediate value"); | 673 | expect("(second source operand) register or immediate value"); |