History

arm-asm: Support bigger immediates for data processing instructions

Danny Milosavljevic committed 5 years ago

Commit d66c1551 parent 14b79731 file · +40 −17Browse files

Unified · Split

arm-asm.c+40−17
@@ -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 value604 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 -> difficult608 0001 = EOR - Rd:= Op1 EOR Op2 -> difficult
593 0011 = RSB - Rd:= Op2 - Op1 -> difficult609 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 -> difficult613 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 Op2616 case 0x0: // AND - Rd:= Op1 AND Op2
602 opcode = 0xe << 21; // BIC617 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 - Op2620 case 0x2: // SUB - Rd:= Op1 - Op2
606 opcode = 0x4 << 21; // ADD621 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 + Op2624 case 0x4: // ADD - Rd:= Op1 + Op2
610 opcode = 0x2 << 21; // SUB625 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 + C628 case 0x5: // ADC - Rd:= Op1 + Op2 + C
614 opcode = 0x6 << 21; // SBC629 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 + C632 case 0x6: // SBC - Rd:= Op1 - Op2 + C
618 opcode = 0x5 << 21; // ADC633 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 - Op2636 case 0xa: // CMP - CC on: Op1 - Op2
623 opcode = 0xb << 21; // CMN637 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 + Op2640 case 0xb: // CMN - CC on: Op1 + Op2
627 opcode = 0xa << 21; // CMP641 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:= Op2644 case 0xd: // MOV - Rd:= Op2
632 opcode = 0xf << 21; // MVN645 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 Op2648 case 0xe: // BIC - Rd:= Op1 AND NOT Op2
637 opcode = 0x0 << 21; // AND649 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 Op2652 case 0xf: // MVN - Rd:= NOT Op2
642 opcode = 0xd << 21; // MOV653 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");

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t