From: Mihai Popa Date: Wed, 3 Jul 2013 09:21:44 +0000 (+0000) Subject: This corrects the implementation of Thumb ADR instruction. There are three issues: X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=b81b477cd4392a51112c3af0659ea9fc176e74f1;p=oota-llvm.git This corrects the implementation of Thumb ADR instruction. There are three issues: 1. it should accept only 4-byte aligned addresses 2. the maximum offset should be 1020 3. it should be encoded with the offset scaled by two bits git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@185528 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 2492c4eda11..4d550eee8b6 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -458,7 +458,7 @@ def AdrLabelAsmOperand : AsmOperandClass { let Name = "AdrLabel"; } def adrlabel : Operand { let EncoderMethod = "getAdrLabelOpValue"; let ParserMatchClass = AdrLabelAsmOperand; - let PrintMethod = "printAdrLabelOperand"; + let PrintMethod = "printAdrLabelOperand<0>"; } def neon_vcvt_imm32 : Operand { diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index 1fff41db27b..a0edaba04e8 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -69,11 +69,6 @@ def thumb_immshifted_shamt : SDNodeXFormgetTargetConstant(V, MVT::i32); }]>; -// ADR instruction labels. -def t_adrlabel : Operand { - let EncoderMethod = "getThumbAdrLabelOpValue"; -} - // Scaled 4 immediate. def t_imm0_1020s4_asmoperand: AsmOperandClass { let Name = "Imm0_1020s4"; } def t_imm0_1020s4 : Operand { @@ -97,12 +92,27 @@ def t_imm0_508s4_neg : Operand { // Define Thumb specific addressing modes. +// unsigned 8-bit, 2-scaled memory offset +class OperandUnsignedOffset_b8s2 : AsmOperandClass { + let Name = "UnsignedOffset_b8s2"; + let PredicateMethod = "isUnsignedOffset<8, 2>"; +} + +def UnsignedOffset_b8s2 : OperandUnsignedOffset_b8s2; + let OperandType = "OPERAND_PCREL" in { def t_brtarget : Operand { let EncoderMethod = "getThumbBRTargetOpValue"; let DecoderMethod = "DecodeThumbBROperand"; } +// ADR instruction labels. +def t_adrlabel : Operand { + let EncoderMethod = "getThumbAdrLabelOpValue"; + let PrintMethod = "printAdrLabelOperand<2>"; + let ParserMatchClass = UnsignedOffset_b8s2; +} + def t_bcctarget : Operand { let EncoderMethod = "getThumbBCCTargetOpValue"; let DecoderMethod = "DecodeThumbBCCTargetOperand"; @@ -505,6 +515,7 @@ let isBranch = 1, isTerminator = 1 in let Inst{7-0} = target; } + // Tail calls let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in { // IOS versions. diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index fa87fb9f3c1..d71824e3c65 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -173,7 +173,7 @@ def t2ldr_pcrel_imm12 : Operand { // ADR instruction labels. def t2adrlabel : Operand { let EncoderMethod = "getT2AdrLabelOpValue"; - let PrintMethod = "printAdrLabelOperand"; + let PrintMethod = "printAdrLabelOperand<0>"; } // t2addrmode_posimm8 := reg + imm8 diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 8595ce34322..c270ed034b2 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -629,6 +629,20 @@ public: bool isITMask() const { return Kind == k_ITCondMask; } bool isITCondCode() const { return Kind == k_CondCode; } bool isImm() const { return Kind == k_Immediate; } + // checks whether this operand is an unsigned offset which fits is a field + // of specified width and scaled by a specific number of bits + template + bool isUnsignedOffset() const { + if (!isImm()) return false; + if (dyn_cast(Imm.Val)) return true; + if (const MCConstantExpr *CE = dyn_cast(Imm.Val)) { + int64_t Val = CE->getValue(); + int64_t Align = 1LL << scale; + int64_t Max = Align * ((1LL << width) - 1); + return ((Val % Align) == 0) && (Val >= 0) && (Val <= Max); + } + return false; + } bool isFPImm() const { if (!isImm()) return false; const MCConstantExpr *CE = dyn_cast(getImm()); @@ -1707,6 +1721,17 @@ public: Inst.addOperand(MCOperand::CreateImm(-CE->getValue())); } + void addUnsignedOffset_b8s2Operands(MCInst &Inst, unsigned N) const { + if(const MCConstantExpr *CE = dyn_cast(getImm())) { + Inst.addOperand(MCOperand::CreateImm(CE->getValue() >> 2)); + return; + } + + const MCSymbolRefExpr *SR = dyn_cast(Imm.Val); + assert(SR && "Unknown value type!"); + Inst.addOperand(MCOperand::CreateExpr(SR)); + } + void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); // The operand is actually a so_imm, but we have its bitwise diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp index 1797c6c3814..97da232cf08 100644 --- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp +++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp @@ -900,6 +900,7 @@ void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum, llvm_unreachable("Unhandled PC-relative pseudo-instruction!"); } +template void ARMInstPrinter::printAdrLabelOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O) { const MCOperand &MO = MI->getOperand(OpNum); @@ -909,7 +910,7 @@ void ARMInstPrinter::printAdrLabelOperand(const MCInst *MI, unsigned OpNum, return; } - int32_t OffImm = (int32_t)MO.getImm(); + int32_t OffImm = (int32_t)MO.getImm() << scale; O << markup(" void printAdrLabelOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printThumbSRImm(const MCInst *MI, unsigned OpNum, raw_ostream &O); diff --git a/test/MC/ARM/basic-thumb-instructions.s b/test/MC/ARM/basic-thumb-instructions.s index 22e21da88e4..b48db9a4d8e 100644 --- a/test/MC/ARM/basic-thumb-instructions.s +++ b/test/MC/ARM/basic-thumb-instructions.s @@ -85,11 +85,15 @@ _func: @ ADR @------------------------------------------------------------------------------ adr r2, _baz - adr r2, #3 + adr r5, #0 + adr r2, #4 + adr r3, #1020 @ CHECK: adr r2, _baz @ encoding: [A,0xa2] @ fixup A - offset: 0, value: _baz, kind: fixup_thumb_adr_pcrel_10 -@ CHECK: adr r2, #3 @ encoding: [0x03,0xa2] +@ CHECK: adr r5, #0 @ encoding: [0x00,0xa5] +@ CHECK: adr r2, #4 @ encoding: [0x01,0xa2] +@ CHECK: adr r3, #1020 @ encoding: [0xff,0xa3] @------------------------------------------------------------------------------ @ ASR (immediate) diff --git a/test/MC/ARM/basic-thumb2-instructions.s b/test/MC/ARM/basic-thumb2-instructions.s index b529a26ade8..c331d5d522b 100644 --- a/test/MC/ARM/basic-thumb2-instructions.s +++ b/test/MC/ARM/basic-thumb2-instructions.s @@ -134,12 +134,14 @@ _func: @------------------------------------------------------------------------------ subw r11, pc, #3270 + adr.w r2, #3 adr.w r11, #-826 adr.w r1, #-0x0 -@ CHECK: subw r11, pc, #3270 @ encoding: [0xaf,0xf6,0xc6,0x4b] -@ CHECK: adr.w r11, #-826 @ encoding: [0xaf,0xf2,0x3a,0x3b] -@ CHECK: adr.w r1, #-0 @ encoding: [0xaf,0xf2,0x00,0x01] +@ CHECK: subw r11, pc, #3270 @ encoding: [0xaf,0xf6,0xc6,0x4b] +@ CHECK: adr.w r2, #3 @ encoding: [0x0f,0xf2,0x03,0x02] +@ CHECK: adr.w r11, #-826 @ encoding: [0xaf,0xf2,0x3a,0x3b] +@ CHECK: adr.w r1, #-0 @ encoding: [0xaf,0xf2,0x00,0x01] @------------------------------------------------------------------------------ @ AND (immediate) diff --git a/test/MC/Disassembler/ARM/thumb1.txt b/test/MC/Disassembler/ARM/thumb1.txt index 7362d9b9b2d..a129abba70f 100644 --- a/test/MC/Disassembler/ARM/thumb1.txt +++ b/test/MC/Disassembler/ARM/thumb1.txt @@ -54,8 +54,12 @@ #------------------------------------------------------------------------------ # ADR #------------------------------------------------------------------------------ -# CHECK: adr r2, #3 +# CHECK: adr r5, #0 +# CHECK: adr r2, #12 +# CHECK: adr r3, #1020 +0x00 0xa5 0x03 0xa2 +0xff 0xa3 #------------------------------------------------------------------------------ # ASR (immediate)