diff options
author | Mihai Popa <mihail.popa@gmail.com> | 2013-07-03 09:21:44 +0000 |
---|---|---|
committer | Mihai Popa <mihail.popa@gmail.com> | 2013-07-03 09:21:44 +0000 |
commit | b81b477cd4392a51112c3af0659ea9fc176e74f1 (patch) | |
tree | cf756fe65576dcd08809d3b7db34079776a0a7bc | |
parent | a10c01a6c62792be825c562314a646437b21bfec (diff) | |
download | external_llvm-b81b477cd4392a51112c3af0659ea9fc176e74f1.zip external_llvm-b81b477cd4392a51112c3af0659ea9fc176e74f1.tar.gz external_llvm-b81b477cd4392a51112c3af0659ea9fc176e74f1.tar.bz2 |
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
-rw-r--r-- | lib/Target/ARM/ARMInstrInfo.td | 2 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrThumb.td | 21 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrThumb2.td | 2 | ||||
-rw-r--r-- | lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 25 | ||||
-rw-r--r-- | lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp | 3 | ||||
-rw-r--r-- | lib/Target/ARM/InstPrinter/ARMInstPrinter.h | 1 | ||||
-rw-r--r-- | test/MC/ARM/basic-thumb-instructions.s | 8 | ||||
-rw-r--r-- | test/MC/ARM/basic-thumb2-instructions.s | 8 | ||||
-rw-r--r-- | test/MC/Disassembler/ARM/thumb1.txt | 6 |
9 files changed, 62 insertions, 14 deletions
diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 2492c4e..4d550ee 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<i32> { let EncoderMethod = "getAdrLabelOpValue"; let ParserMatchClass = AdrLabelAsmOperand; - let PrintMethod = "printAdrLabelOperand"; + let PrintMethod = "printAdrLabelOperand<0>"; } def neon_vcvt_imm32 : Operand<i32> { diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index 1fff41d..a0edaba 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -69,11 +69,6 @@ def thumb_immshifted_shamt : SDNodeXForm<imm, [{ return CurDAG->getTargetConstant(V, MVT::i32); }]>; -// ADR instruction labels. -def t_adrlabel : Operand<i32> { - let EncoderMethod = "getThumbAdrLabelOpValue"; -} - // Scaled 4 immediate. def t_imm0_1020s4_asmoperand: AsmOperandClass { let Name = "Imm0_1020s4"; } def t_imm0_1020s4 : Operand<i32> { @@ -97,12 +92,27 @@ def t_imm0_508s4_neg : Operand<i32> { // 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<OtherVT> { let EncoderMethod = "getThumbBRTargetOpValue"; let DecoderMethod = "DecodeThumbBROperand"; } +// ADR instruction labels. +def t_adrlabel : Operand<i32> { + let EncoderMethod = "getThumbAdrLabelOpValue"; + let PrintMethod = "printAdrLabelOperand<2>"; + let ParserMatchClass = UnsignedOffset_b8s2; +} + def t_bcctarget : Operand<i32> { 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 fa87fb9..d71824e 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -173,7 +173,7 @@ def t2ldr_pcrel_imm12 : Operand<i32> { // ADR instruction labels. def t2adrlabel : Operand<i32> { 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 8595ce3..c270ed0 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<unsigned width, unsigned scale> + bool isUnsignedOffset() const { + if (!isImm()) return false; + if (dyn_cast<MCSymbolRefExpr>(Imm.Val)) return true; + if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(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<MCConstantExpr>(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<MCConstantExpr>(getImm())) { + Inst.addOperand(MCOperand::CreateImm(CE->getValue() >> 2)); + return; + } + + const MCSymbolRefExpr *SR = dyn_cast<MCSymbolRefExpr>(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 1797c6c..97da232 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<unsigned scale> 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("<imm:"); if (OffImm == INT32_MIN) diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.h b/lib/Target/ARM/InstPrinter/ARMInstPrinter.h index a3ea640..15ae8d1 100644 --- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.h +++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.h @@ -76,6 +76,7 @@ public: void printPKHLSLShiftImm(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printPKHASRShiftImm(const MCInst *MI, unsigned OpNum, raw_ostream &O); + template <unsigned scale> 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 22e21da..b48db9a 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 b529a26..c331d5d 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 7362d9b..a129abb 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) |