summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Target/ARM/ARMInstrThumb.td43
-rw-r--r--lib/Target/ARM/ARMInstrThumb2.td2
-rw-r--r--lib/Target/ARM/AsmParser/ARMAsmParser.cpp40
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp2
4 files changed, 62 insertions, 25 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;
}