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
550550 return;
551551 } else {
552552 uint32_t opcode = 0;
553+ uint32_t immediate_value;
554+ uint8_t half_immediate_rotation;
553555 if (nb_shift && shift.type == OP_REG32) {
554556 if ((ops[0].type == OP_REG32 && ops[0].reg == 15) ||
555557 (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
583585 operands |= ops[2].reg;
584586 break;
585587 case OP_IM8:
588+ case OP_IM32:
586589 operands |= ENCODE_IMMEDIATE_FLAG;
587− operands |= ops[2].e.v;
588− break;
590+ immediate_value = ops[2].e.v;
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+ }
589604 case OP_IM8N: // immediate negative value
590605 operands |= ENCODE_IMMEDIATE_FLAG;
606+ immediate_value = ops[2].e.v;
591607 /* Instruction swapping:
592608 0001 = EOR - Rd:= Op1 EOR Op2 -> difficult
593609 0011 = RSB - Rd:= Op2 - Op1 -> difficult
@@ -597,54 +613,61 @@ static void asm_data_processing_opcode(TCCState *s1, int token) · 3 unmodified lines
597613 1100 = ORR - Rd:= Op1 OR Op2 -> difficult
598614 */
599615 switch (opcode_nos) {
600−#if 0
601616 case 0x0: // AND - Rd:= Op1 AND Op2
602617 opcode = 0xe << 21; // BIC
603− operands |= (ops[2].e.v ^ 0xFF) & 0xFF;
618+ immediate_value = ~immediate_value;
604619 break;
605620 case 0x2: // SUB - Rd:= Op1 - Op2
606621 opcode = 0x4 << 21; // ADD
607− operands |= (-ops[2].e.v) & 0xFF;
622+ immediate_value = -immediate_value;
608623 break;
609624 case 0x4: // ADD - Rd:= Op1 + Op2
610625 opcode = 0x2 << 21; // SUB
611− operands |= (-ops[2].e.v) & 0xFF;
626+ immediate_value = -immediate_value;
612627 break;
613628 case 0x5: // ADC - Rd:= Op1 + Op2 + C
614629 opcode = 0x6 << 21; // SBC
615− operands |= (ops[2].e.v ^ 0xFF) & 0xFF;
630+ immediate_value = ~immediate_value;
616631 break;
617632 case 0x6: // SBC - Rd:= Op1 - Op2 + C
618633 opcode = 0x5 << 21; // ADC
619− operands |= (ops[2].e.v ^ 0xFF) & 0xFF;
634+ immediate_value = ~immediate_value;
620635 break;
621−#endif
622636 case 0xa: // CMP - CC on: Op1 - Op2
623637 opcode = 0xb << 21; // CMN
624− operands |= (-ops[2].e.v) & 0xFF;
638+ immediate_value = -immediate_value;
625639 break;
626640 case 0xb: // CMN - CC on: Op1 + Op2
627641 opcode = 0xa << 21; // CMP
628− operands |= (-ops[2].e.v) & 0xFF;
642+ immediate_value = -immediate_value;
629643 break;
630− // moveq r1, r3: 0x01a01003; mov Rd, Op2
631644 case 0xd: // MOV - Rd:= Op2
632645 opcode = 0xf << 21; // MVN
633− operands |= (ops[2].e.v ^ 0xFF) & 0xFF;
646+ immediate_value = ~immediate_value;
634647 break;
635−#if 0
636648 case 0xe: // BIC - Rd:= Op1 AND NOT Op2
637649 opcode = 0x0 << 21; // AND
638− operands |= (ops[2].e.v ^ 0xFF) & 0xFF;
650+ immediate_value = ~immediate_value;
639651 break;
640−#endif
641652 case 0xf: // MVN - Rd:= NOT Op2
642653 opcode = 0xd << 21; // MOV
643− operands |= (ops[2].e.v ^ 0xFF) & 0xFF;
654+ immediate_value = ~immediate_value;
644655 break;
645656 default:
646657 tcc_error("cannot use '%s' with a negative immediate value", get_tok_str(token, NULL));
647658 }
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;
648671 break;
649672 default:
650673 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