diff options
-rw-r--r-- | lib/Target/ARM/ARMInstrThumb.td | 43 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrThumb2.td | 2 | ||||
-rw-r--r-- | lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 40 | ||||
-rw-r--r-- | lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp | 2 | ||||
-rw-r--r-- | test/CodeGen/ARM/fast-isel-pic.ll | 8 | ||||
-rw-r--r-- | test/CodeGen/ARM/indirectbr.ll | 6 | ||||
-rw-r--r-- | test/CodeGen/ARM/load-global.ll | 2 | ||||
-rw-r--r-- | test/CodeGen/ARM/machine-licm.ll | 2 | ||||
-rw-r--r-- | test/CodeGen/Thumb/large-stack.ll | 6 | ||||
-rw-r--r-- | test/MC/ARM/basic-thumb2-instructions.s | 21 |
10 files changed, 93 insertions, 39 deletions
diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index a0edaba04e..e7218c6658 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -100,6 +100,13 @@ class OperandUnsignedOffset_b8s2 : AsmOperandClass { def UnsignedOffset_b8s2 : OperandUnsignedOffset_b8s2; +// thumb style PC relative operand. signed, 8 bits magnitude, +// two bits shift. can be represented as either [pc, #imm], #imm, +// or relocatable expression... +def ThumbMemPC : AsmOperandClass { + let Name = "ThumbMemPC"; +} + let OperandType = "OPERAND_PCREL" in { def t_brtarget : Operand<OtherVT> { let EncoderMethod = "getThumbBRTargetOpValue"; @@ -132,6 +139,15 @@ def t_blxtarget : Operand<i32> { let EncoderMethod = "getThumbBLXTargetOpValue"; let DecoderMethod = "DecodeThumbBLXOffset"; } + +// t_addrmode_pc := <label> => pc + imm8 * 4 +// +def t_addrmode_pc : Operand<i32> { + let EncoderMethod = "getAddrModePCOpValue"; + let DecoderMethod = "DecodeThumbAddrModePC"; + let PrintMethod = "printThumbLdrLabelOperand"; + let ParserMatchClass = ThumbMemPC; +} } // t_addrmode_rr := reg + reg @@ -228,14 +244,6 @@ def t_addrmode_sp : Operand<i32>, let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); } -// t_addrmode_pc := <label> => pc + imm8 * 4 -// -def t_addrmode_pc : Operand<i32> { - let EncoderMethod = "getAddrModePCOpValue"; - let DecoderMethod = "DecodeThumbAddrModePC"; - let PrintMethod = "printThumbLdrLabelOperand"; -} - //===----------------------------------------------------------------------===// // Miscellaneous Instructions. // @@ -640,11 +648,9 @@ def tLDRspi : T1pIs<(outs tGPR:$Rt), (ins t_addrmode_sp:$addr), IIC_iLoad_i, let Inst{7-0} = addr; } -// Load tconstpool -// FIXME: Use ldr.n to work around a darwin assembler bug. -let canFoldAsLoad = 1, isReMaterializable = 1, isCodeGenOnly = 1 in +let canFoldAsLoad = 1, isReMaterializable = 1 in def tLDRpci : T1pIs<(outs tGPR:$Rt), (ins t_addrmode_pc:$addr), IIC_iLoad_i, - "ldr", ".n\t$Rt, $addr", + "ldr", "\t$Rt, $addr", [(set tGPR:$Rt, (load (ARMWrapper tconstpool:$addr)))]>, T1Encoding<{0,1,0,0,1,?}> { // A6.2 & A8.6.59 @@ -654,17 +660,8 @@ def tLDRpci : T1pIs<(outs tGPR:$Rt), (ins t_addrmode_pc:$addr), IIC_iLoad_i, let Inst{7-0} = addr; } -// FIXME: Remove this entry when the above ldr.n workaround is fixed. -// For assembly/disassembly use only. -def tLDRpciASM : T1pIs<(outs tGPR:$Rt), (ins t_addrmode_pc:$addr), IIC_iLoad_i, - "ldr", "\t$Rt, $addr", []>, - T1Encoding<{0,1,0,0,1,?}> { - // A6.2 & A8.6.59 - bits<3> Rt; - bits<8> addr; - let Inst{10-8} = Rt; - let Inst{7-0} = addr; -} +def : tInstAlias<"ldr${p}.n $Rt, $addr", + (tLDRpci tGPR:$Rt, t_addrmode_pc:$addr, pred:$p), 0>; // A8.6.194 & A8.6.192 defm tSTR : thumb_st_rr_ri_enc<0b000, 0b0110, t_addrmode_rrs4, diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index 5a425c6922..8e5e8c1735 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -4399,7 +4399,7 @@ def t2LDRSHpcrel : t2AsmPseudo<"ldrsh${p} $Rt, $addr", (ins GPRnopc:$Rt, t2ldr_pcrel_imm12:$addr, pred:$p)>; // Version w/ the .w suffix. def : t2InstAlias<"ldr${p}.w $Rt, $addr", - (t2LDRpcrel GPRnopc:$Rt, t2ldr_pcrel_imm12:$addr, pred:$p)>; + (t2LDRpcrel GPRnopc:$Rt, t2ldr_pcrel_imm12:$addr, pred:$p), 0>; def : t2InstAlias<"ldrb${p}.w $Rt, $addr", (t2LDRBpcrel GPRnopc:$Rt, t2ldr_pcrel_imm12:$addr, pred:$p)>; def : t2InstAlias<"ldrh${p}.w $Rt, $addr", diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index fc1faffd0b..6d885a0d91 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -609,6 +609,26 @@ public: } return false; } + // checks whether this operand is a memory operand computed as an offset + // applied to PC. the offset may have 8 bits of magnitude and is represented + // with two bits of shift. textually it may be either [pc, #imm], #imm or + // relocable expression... + bool isThumbMemPC() const { + int64_t Val = 0; + if (isImm()) { + if (isa<MCSymbolRefExpr>(Imm.Val)) return true; + const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val); + if (!CE) return false; + Val = CE->getValue(); + } + else if (isMem()) { + if(!Memory.OffsetImm || Memory.OffsetRegNum) return false; + if(Memory.BaseRegNum != ARM::PC) return false; + Val = Memory.OffsetImm->getValue(); + } + else return false; + return ((Val % 4) == 0) && (Val >= -1020) && (Val <= 1020); + } bool isFPImm() const { if (!isImm()) return false; const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); @@ -1698,6 +1718,26 @@ public: Inst.addOperand(MCOperand::CreateExpr(SR)); } + void addThumbMemPCOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + if (isImm()) { + const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); + if (CE) { + Inst.addOperand(MCOperand::CreateImm(CE->getValue())); + return; + } + + const MCSymbolRefExpr *SR = dyn_cast<MCSymbolRefExpr>(Imm.Val); + assert(SR && "Unknown value type!"); + Inst.addOperand(MCOperand::CreateExpr(SR)); + return; + } + + assert(isMem() && "Unknown value type!"); + assert(isa<MCConstantExpr>(Memory.OffsetImm) && "Unknown value type!"); + Inst.addOperand(MCOperand::CreateImm(Memory.OffsetImm->getValue())); + } + 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/MCTargetDesc/ARMAsmBackend.cpp b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp index 8baa3a6ce6..b1e25d8b89 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -152,7 +152,7 @@ static unsigned getRelaxedOpcode(unsigned Op) { switch (Op) { default: return Op; case ARM::tBcc: return ARM::t2Bcc; - case ARM::tLDRpciASM: return ARM::t2LDRpci; + case ARM::tLDRpci: return ARM::t2LDRpci; case ARM::tADR: return ARM::t2ADR; case ARM::tB: return ARM::t2B; } diff --git a/test/CodeGen/ARM/fast-isel-pic.ll b/test/CodeGen/ARM/fast-isel-pic.ll index 0589f9ada8..ad0f15966f 100644 --- a/test/CodeGen/ARM/fast-isel-pic.ll +++ b/test/CodeGen/ARM/fast-isel-pic.ll @@ -13,8 +13,8 @@ entry: ; THUMB: movt [[reg0]], ; THUMB: add [[reg0]], pc ; THUMB-ELF: LoadGV -; THUMB-ELF: ldr.n r[[reg0:[0-9]+]], -; THUMB-ELF: ldr.n r[[reg1:[0-9]+]], +; THUMB-ELF: ldr r[[reg0:[0-9]+]], +; THUMB-ELF: ldr r[[reg1:[0-9]+]], ; THUMB-ELF: ldr r[[reg0]], [r[[reg0]], r[[reg1]]] ; ARM: LoadGV ; ARM: ldr [[reg1:r[0-9]+]], @@ -41,8 +41,8 @@ entry: ; THUMB: add r[[reg3]], pc ; THUMB: ldr r[[reg3]], [r[[reg3]]] ; THUMB-ELF: LoadIndirectSymbol -; THUMB-ELF: ldr.n r[[reg3:[0-9]+]], -; THUMB-ELF: ldr.n r[[reg4:[0-9]+]], +; THUMB-ELF: ldr r[[reg3:[0-9]+]], +; THUMB-ELF: ldr r[[reg4:[0-9]+]], ; THUMB-ELF: ldr r[[reg3]], [r[[reg3]], r[[reg4]]] ; ARM: LoadIndirectSymbol ; ARM: ldr [[reg4:r[0-9]+]], diff --git a/test/CodeGen/ARM/indirectbr.ll b/test/CodeGen/ARM/indirectbr.ll index 6fed8c492f..99e84a6a62 100644 --- a/test/CodeGen/ARM/indirectbr.ll +++ b/test/CodeGen/ARM/indirectbr.ll @@ -51,12 +51,12 @@ L1: ; preds = %L2, %bb2 ; ARM: ldr [[R1:r[0-9]+]], LCPI ; ARM: add [[R1b:r[0-9]+]], pc, [[R1]] ; ARM: str [[R1b]] -; THUMB: ldr.n +; THUMB: ldr ; THUMB: add -; THUMB: ldr.n [[R2:r[0-9]+]], LCPI +; THUMB: ldr [[R2:r[0-9]+]], LCPI ; THUMB: add [[R2]], pc ; THUMB: str [[R2]] -; THUMB2: ldr.n [[R2:r[0-9]+]], LCPI +; THUMB2: ldr [[R2:r[0-9]+]], LCPI ; THUMB2-NEXT: str{{(.w)?}} [[R2]] store i8* blockaddress(@foo, %L5), i8** @nextaddr, align 4 ret i32 %res.3 diff --git a/test/CodeGen/ARM/load-global.ll b/test/CodeGen/ARM/load-global.ll index 15a415df73..00ca2e8b1b 100644 --- a/test/CodeGen/ARM/load-global.ll +++ b/test/CodeGen/ARM/load-global.ll @@ -26,7 +26,7 @@ define i32 @test1() { ; PIC: .long L_G$non_lazy_ptr-(LPC0_0+8) ; PIC_T: _test1 -; PIC_T: ldr.n r0, LCPI0_0 +; PIC_T: ldr r0, LCPI0_0 ; PIC_T: add r0, pc ; PIC_T: ldr r0, [r0] ; PIC_T: ldr r0, [r0] diff --git a/test/CodeGen/ARM/machine-licm.ll b/test/CodeGen/ARM/machine-licm.ll index 87aaacfb55..fc9b22614d 100644 --- a/test/CodeGen/ARM/machine-licm.ll +++ b/test/CodeGen/ARM/machine-licm.ll @@ -40,7 +40,7 @@ bb.nph: ; preds = %entry ; ARM: .section ; THUMB: BB#1 -; THUMB: ldr.n r2, LCPI0_0 +; THUMB: ldr r2, LCPI0_0 ; THUMB: add r2, pc ; THUMB: ldr r{{[0-9]+}}, [r2] ; THUMB: LBB0_2 diff --git a/test/CodeGen/Thumb/large-stack.ll b/test/CodeGen/Thumb/large-stack.ll index 6fa623123a..fb6daa4786 100644 --- a/test/CodeGen/Thumb/large-stack.ll +++ b/test/CodeGen/Thumb/large-stack.ll @@ -10,7 +10,7 @@ define void @test1() { define void @test2() { ; CHECK-LABEL: test2: -; CHECK: ldr.n r0, LCPI +; CHECK: ldr r0, LCPI ; CHECK: add sp, r0 ; CHECK: subs r4, r7, #4 ; CHECK: mov sp, r4 @@ -20,9 +20,9 @@ define void @test2() { define i32 @test3() { ; CHECK-LABEL: test3: -; CHECK: ldr.n r1, LCPI +; CHECK: ldr r1, LCPI ; CHECK: add sp, r1 -; CHECK: ldr.n r1, LCPI +; CHECK: ldr r1, LCPI ; CHECK: add r1, sp ; CHECK: subs r4, r7, #4 ; CHECK: mov sp, r4 diff --git a/test/MC/ARM/basic-thumb2-instructions.s b/test/MC/ARM/basic-thumb2-instructions.s index 2bd9a13338..43e03c9833 100644 --- a/test/MC/ARM/basic-thumb2-instructions.s +++ b/test/MC/ARM/basic-thumb2-instructions.s @@ -772,6 +772,23 @@ _func: @ CHECK: ldr.w lr, _strcmp-4 @ encoding: [0x5f'A',0xf8'A',A,0xe0'A'] @ CHECK: @ fixup A - offset: 0, value: _strcmp-4, kind: fixup_t2_ldst_pcrel_12 + ldr r4, [pc, #1020] + ldr r3, [pc, #-1020] + ldr r6, [pc, #1024] + ldr r0, [pc, #-1024] + ldr r2, [pc, #4095] + ldr r1, [pc, #-4095] + ldr.n r8, [pc, #132] + ldr.w r8, [pc, #132] + +@ CHECK: ldr r4, [pc, #1020] @ encoding: [0xff,0x4c] +@ CHECK: ldr r3, [pc, #-1020] @ encoding: [0x01,0x4b] +@ CHECK: ldr.w r6, [pc, #1024] @ encoding: [0xdf,0xf8,0x00,0x64] +@ CHECK: ldr.w r0, [pc, #-1024] @ encoding: [0x5f,0xf8,0x00,0x04] +@ CHECK: ldr.w r2, [pc, #4095] @ encoding: [0xdf,0xf8,0xff,0x2f] +@ CHECK: ldr.w r1, [pc, #-4095] @ encoding: [0x5f,0xf8,0xff,0x1f] +@ CHECK: ldr r8, [pc, #132] @ encoding: [0x21,0x48] +@ CHECK: ldr.w r8, [pc, #132] @ encoding: [0xdf,0xf8,0x84,0x80] @------------------------------------------------------------------------------ @ LDR(register) @@ -3569,5 +3586,5 @@ _func: @ CHECK: ldrsh.w r11, [pc, #-22] @ encoding: [0x3f,0xf9,0x16,0xb0] @ rdar://12596361 - ldr r1, [pc, #12] -@ CHECK: ldr.n r1, [pc, #12] @ encoding: [0x03,0x49] + ldr r1, [pc, #12] +@ CHECK: ldr r1, [pc, #12] @ encoding: [0x03,0x49] |