summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/ARM/ARMInstrInfo.td50
-rw-r--r--llvm/lib/Target/ARM/ARMInstrThumb.td41
-rw-r--r--llvm/lib/Target/ARM/ARMInstrThumb2.td10
-rw-r--r--llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp28
-rw-r--r--llvm/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp15
5 files changed, 93 insertions, 51 deletions
diff --git a/llvm/lib/Target/ARM/ARMInstrInfo.td b/llvm/lib/Target/ARM/ARMInstrInfo.td
index e2a66eb56cf..060376b0a27 100644
--- a/llvm/lib/Target/ARM/ARMInstrInfo.td
+++ b/llvm/lib/Target/ARM/ARMInstrInfo.td
@@ -418,34 +418,35 @@ def brtarget : Operand<OtherVT> {
let DecoderMethod = "DecodeT2BROperand";
}
-// FIXME: get rid of this one?
-def uncondbrtarget : Operand<OtherVT> {
- let EncoderMethod = "getUnconditionalBranchTargetOpValue";
- let OperandType = "OPERAND_PCREL";
+// Branches targeting ARM-mode must be divisible by 4 if they're a raw
+// immediate.
+def ARMBranchTarget : AsmOperandClass {
+ let Name = "ARMBranchTarget";
}
-// Branch target for ARM. Handles conditional/unconditional
-def br_target : Operand<OtherVT> {
- let EncoderMethod = "getARMBranchTargetOpValue";
- let OperandType = "OPERAND_PCREL";
+// Branches targeting Thumb-mode must be divisible by 2 if they're a raw
+// immediate.
+def ThumbBranchTarget : AsmOperandClass {
+ let Name = "ThumbBranchTarget";
}
-// Call target.
-// FIXME: rename bltarget to t2_bl_target?
-def bltarget : Operand<i32> {
- // Encoded the same as branch targets.
- let EncoderMethod = "getBranchTargetOpValue";
+def arm_br_target : Operand<OtherVT> {
+ let ParserMatchClass = ARMBranchTarget;
+ let EncoderMethod = "getARMBranchTargetOpValue";
let OperandType = "OPERAND_PCREL";
}
// Call target for ARM. Handles conditional/unconditional
// FIXME: rename bl_target to t2_bltarget?
-def bl_target : Operand<i32> {
+def arm_bl_target : Operand<i32> {
+ let ParserMatchClass = ARMBranchTarget;
let EncoderMethod = "getARMBLTargetOpValue";
let OperandType = "OPERAND_PCREL";
}
-def blx_target : Operand<i32> {
+// Target for BLX *from* ARM mode.
+def arm_blx_target : Operand<i32> {
+ let ParserMatchClass = ThumbBranchTarget;
let EncoderMethod = "getARMBLXTargetOpValue";
let OperandType = "OPERAND_PCREL";
}
@@ -2208,7 +2209,7 @@ let isCall = 1,
// at least be a pseudo instruction expanding to the predicated version
// at MC lowering time.
Defs = [LR], Uses = [SP] in {
- def BL : ABXI<0b1011, (outs), (ins bl_target:$func),
+ def BL : ABXI<0b1011, (outs), (ins arm_bl_target:$func),
IIC_Br, "bl\t$func",
[(ARMcall tglobaladdr:$func)]>,
Requires<[IsARM]>, Sched<[WriteBrL]> {
@@ -2218,7 +2219,7 @@ let isCall = 1,
let DecoderMethod = "DecodeBranchImmInstruction";
}
- def BL_pred : ABI<0b1011, (outs), (ins bl_target:$func),
+ def BL_pred : ABI<0b1011, (outs), (ins arm_bl_target:$func),
IIC_Br, "bl", "\t$func",
[(ARMcall_pred tglobaladdr:$func)]>,
Requires<[IsARM]>, Sched<[WriteBrL]> {
@@ -2259,7 +2260,7 @@ let isCall = 1,
// mov lr, pc; b if callee is marked noreturn to avoid confusing the
// return stack predictor.
- def BMOVPCB_CALL : ARMPseudoInst<(outs), (ins bl_target:$func),
+ def BMOVPCB_CALL : ARMPseudoInst<(outs), (ins arm_bl_target:$func),
8, IIC_Br, [(ARMcall_nolink tglobaladdr:$func)]>,
Requires<[IsARM]>, Sched<[WriteBr]>;
}
@@ -2267,7 +2268,7 @@ let isCall = 1,
let isBranch = 1, isTerminator = 1 in {
// FIXME: should be able to write a pattern for ARMBrcond, but can't use
// a two-value operand where a dag node expects two operands. :(
- def Bcc : ABI<0b1010, (outs), (ins br_target:$target),
+ def Bcc : ABI<0b1010, (outs), (ins arm_br_target:$target),
IIC_Br, "b", "\t$target",
[/*(ARMbrcond bb:$target, imm:$cc, CCR:$ccr)*/]>,
Sched<[WriteBr]> {
@@ -2282,8 +2283,9 @@ let isBranch = 1, isTerminator = 1 in {
// FIXME: We shouldn't need this pseudo at all. Just using Bcc directly
// should be sufficient.
// FIXME: Is B really a Barrier? That doesn't seem right.
- def B : ARMPseudoExpand<(outs), (ins br_target:$target), 4, IIC_Br,
- [(br bb:$target)], (Bcc br_target:$target, (ops 14, zero_reg))>,
+ def B : ARMPseudoExpand<(outs), (ins arm_br_target:$target), 4, IIC_Br,
+ [(br bb:$target)], (Bcc arm_br_target:$target,
+ (ops 14, zero_reg))>,
Sched<[WriteBr]>;
let Size = 4, isNotDuplicable = 1, isIndirectBranch = 1 in {
@@ -2310,7 +2312,7 @@ let isBranch = 1, isTerminator = 1 in {
}
// BLX (immediate)
-def BLXi : AXI<(outs), (ins blx_target:$target), BrMiscFrm, NoItinerary,
+def BLXi : AXI<(outs), (ins arm_blx_target:$target), BrMiscFrm, NoItinerary,
"blx\t$target", []>,
Requires<[IsARM, HasV5T]>, Sched<[WriteBrL]> {
let Inst{31-25} = 0b1111101;
@@ -2340,9 +2342,9 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [SP] in {
def TCRETURNri : PseudoInst<(outs), (ins tcGPR:$dst), IIC_Br, []>,
Sched<[WriteBr]>;
- def TAILJMPd : ARMPseudoExpand<(outs), (ins br_target:$dst),
+ def TAILJMPd : ARMPseudoExpand<(outs), (ins arm_br_target:$dst),
4, IIC_Br, [],
- (Bcc br_target:$dst, (ops 14, zero_reg))>,
+ (Bcc arm_br_target:$dst, (ops 14, zero_reg))>,
Requires<[IsARM]>, Sched<[WriteBr]>;
def TAILJMPr : ARMPseudoExpand<(outs), (ins tcGPR:$dst),
diff --git a/llvm/lib/Target/ARM/ARMInstrThumb.td b/llvm/lib/Target/ARM/ARMInstrThumb.td
index 5d4698f6a8b..bec1ea8763d 100644
--- a/llvm/lib/Target/ARM/ARMInstrThumb.td
+++ b/llvm/lib/Target/ARM/ARMInstrThumb.td
@@ -125,26 +125,38 @@ def t_adrlabel : Operand<i32> {
let ParserMatchClass = UnsignedOffset_b8s2;
}
-def t_bcctarget : Operand<i32> {
- let EncoderMethod = "getThumbBCCTargetOpValue";
- let DecoderMethod = "DecodeThumbBCCTargetOperand";
-}
-def t_cbtarget : Operand<i32> {
- let EncoderMethod = "getThumbCBTargetOpValue";
- let DecoderMethod = "DecodeThumbCmpBROperand";
+def thumb_br_target : Operand<OtherVT> {
+ let ParserMatchClass = ThumbBranchTarget;
+ let EncoderMethod = "getThumbBranchTargetOpValue";
+ let OperandType = "OPERAND_PCREL";
}
-def t_bltarget : Operand<i32> {
+def thumb_bl_target : Operand<i32> {
+ let ParserMatchClass = ThumbBranchTarget;
let EncoderMethod = "getThumbBLTargetOpValue";
let DecoderMethod = "DecodeThumbBLTargetOperand";
}
-def t_blxtarget : Operand<i32> {
+// Target for BLX *from* thumb mode.
+def thumb_blx_target : Operand<i32> {
+ let ParserMatchClass = ARMBranchTarget;
let EncoderMethod = "getThumbBLXTargetOpValue";
let DecoderMethod = "DecodeThumbBLXOffset";
}
+def thumb_bcc_target : Operand<OtherVT> {
+ let ParserMatchClass = ThumbBranchTarget;
+ let EncoderMethod = "getThumbBCCTargetOpValue";
+ let DecoderMethod = "DecodeThumbBCCTargetOperand";
+}
+
+def thumb_cb_target : Operand<OtherVT> {
+ let ParserMatchClass = ThumbBranchTarget;
+ let EncoderMethod = "getThumbCBTargetOpValue";
+ let DecoderMethod = "DecodeThumbCmpBROperand";
+}
+
// t_addrmode_pc := <label> => pc + imm8 * 4
//
def t_addrmode_pc : MemOperand {
@@ -471,7 +483,7 @@ let isCall = 1,
Defs = [LR], Uses = [SP] in {
// Also used for Thumb2
def tBL : TIx2<0b11110, 0b11, 1,
- (outs), (ins pred:$p, t_bltarget:$func), IIC_Br,
+ (outs), (ins pred:$p, thumb_bl_target:$func), IIC_Br,
"bl${p}\t$func",
[(ARMcall tglobaladdr:$func)]>,
Requires<[IsThumb]>, Sched<[WriteBrL]> {
@@ -485,7 +497,7 @@ let isCall = 1,
// ARMv5T and above, also used for Thumb2
def tBLXi : TIx2<0b11110, 0b11, 0,
- (outs), (ins pred:$p, t_blxtarget:$func), IIC_Br,
+ (outs), (ins pred:$p, thumb_blx_target:$func), IIC_Br,
"blx${p}\t$func", []>,
Requires<[IsThumb, HasV5T, IsNotMClass]>, Sched<[WriteBrL]> {
bits<24> func;
@@ -540,8 +552,9 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
// Just a pseudo for a tBL instruction. Needed to let regalloc know about
// the clobber of LR.
let Defs = [LR] in
- def tBfar : tPseudoExpand<(outs), (ins t_bltarget:$target, pred:$p),
- 4, IIC_Br, [], (tBL pred:$p, t_bltarget:$target)>,
+ def tBfar : tPseudoExpand<(outs), (ins thumb_bl_target:$target, pred:$p),
+ 4, IIC_Br, [],
+ (tBL pred:$p, thumb_bl_target:$target)>,
Sched<[WriteBrTbl]>;
def tBR_JTr : tPseudoInst<(outs),
@@ -557,7 +570,7 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
// FIXME: should be able to write a pattern for ARMBrcond, but can't use
// a two-value operand where a dag node expects two operands. :(
let isBranch = 1, isTerminator = 1 in
- def tBcc : T1I<(outs), (ins t_bcctarget:$target, pred:$p), IIC_Br,
+ def tBcc : T1I<(outs), (ins thumb_bcc_target:$target, pred:$p), IIC_Br,
"b${p}\t$target",
[/*(ARMbrcond bb:$target, imm:$cc)*/]>,
T1BranchCond<{1,1,0,1}>, Sched<[WriteBr]> {
diff --git a/llvm/lib/Target/ARM/ARMInstrThumb2.td b/llvm/lib/Target/ARM/ARMInstrThumb2.td
index 93fde91d9d2..55e5308be40 100644
--- a/llvm/lib/Target/ARM/ARMInstrThumb2.td
+++ b/llvm/lib/Target/ARM/ARMInstrThumb2.td
@@ -3524,7 +3524,7 @@ def t2LDMIA_RET: t2PseudoExpand<(outs GPR:$wb), (ins GPR:$Rn, pred:$p,
let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
let isPredicable = 1 in
-def t2B : T2I<(outs), (ins uncondbrtarget:$target), IIC_Br,
+def t2B : T2I<(outs), (ins thumb_br_target:$target), IIC_Br,
"b", ".w\t$target",
[(br bb:$target)]>, Sched<[WriteBr]>,
Requires<[IsThumb, HasV8MBaseline]> {
@@ -3617,9 +3617,9 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
// IOS version.
let Uses = [SP] in
def tTAILJMPd: tPseudoExpand<(outs),
- (ins uncondbrtarget:$dst, pred:$p),
+ (ins thumb_br_target:$dst, pred:$p),
4, IIC_Br, [],
- (t2B uncondbrtarget:$dst, pred:$p)>,
+ (t2B thumb_br_target:$dst, pred:$p)>,
Requires<[IsThumb2, IsMachO]>, Sched<[WriteBr]>;
}
@@ -3655,7 +3655,7 @@ def t2BXJ : T2I<(outs), (ins GPRnopc:$func), NoItinerary, "bxj", "\t$func", []>,
// Compare and branch on zero / non-zero
let isBranch = 1, isTerminator = 1 in {
- def tCBZ : T1I<(outs), (ins tGPR:$Rn, t_cbtarget:$target), IIC_Br,
+ def tCBZ : T1I<(outs), (ins tGPR:$Rn, thumb_cb_target:$target), IIC_Br,
"cbz\t$Rn, $target", []>,
T1Misc<{0,0,?,1,?,?,?}>,
Requires<[IsThumb, HasV8MBaseline]>, Sched<[WriteBr]> {
@@ -3667,7 +3667,7 @@ let isBranch = 1, isTerminator = 1 in {
let Inst{2-0} = Rn;
}
- def tCBNZ : T1I<(outs), (ins tGPR:$Rn, t_cbtarget:$target), IIC_Br,
+ def tCBNZ : T1I<(outs), (ins tGPR:$Rn, thumb_cb_target:$target), IIC_Br,
"cbnz\t$Rn, $target", []>,
T1Misc<{1,0,?,1,?,?,?}>,
Requires<[IsThumb, HasV8MBaseline]>, Sched<[WriteBr]> {
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index b3b0dffb6c9..d368e2349b3 100644
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -676,6 +676,24 @@ public:
bool isImm() const override {
return Kind == k_Immediate;
}
+
+ bool isARMBranchTarget() const {
+ if (!isImm()) return false;
+
+ if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()))
+ return CE->getValue() % 4 == 0;
+ return true;
+ }
+
+
+ bool isThumbBranchTarget() const {
+ if (!isImm()) return false;
+
+ if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()))
+ return CE->getValue() % 2 == 0;
+ return true;
+ }
+
// 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>
@@ -1728,6 +1746,16 @@ public:
Inst.addOperand(MCOperand::createExpr(Expr));
}
+ void addARMBranchTargetOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ addExpr(Inst, getImm());
+ }
+
+ void addThumbBranchTargetOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ addExpr(Inst, getImm());
+ }
+
void addCondCodeOperands(MCInst &Inst, unsigned N) const {
assert(N == 2 && "Invalid number of operands!");
Inst.addOperand(MCOperand::createImm(unsigned(getCondCode())));
diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp
index 1b40655fbe1..9fca13eeea9 100644
--- a/llvm/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp
+++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp
@@ -120,11 +120,11 @@ public:
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
- /// getUnconditionalBranchTargetOpValue - Return encoding info for 24-bit
+ /// getThumbBranchTargetOpValue - Return encoding info for 24-bit
/// immediate Thumb2 direct branch target.
- uint32_t getUnconditionalBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const;
+ uint32_t getThumbBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
/// getARMBranchTargetOpValue - Return encoding info for 24-bit immediate
/// branch target.
@@ -750,10 +750,9 @@ getARMBLXTargetOpValue(const MCInst &MI, unsigned OpIdx,
/// getUnconditionalBranchTargetOpValue - Return encoding info for 24-bit
/// immediate branch target.
-uint32_t ARMMCCodeEmitter::
-getUnconditionalBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const {
+uint32_t ARMMCCodeEmitter::getThumbBranchTargetOpValue(
+ const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
unsigned Val = 0;
const MCOperand MO = MI.getOperand(OpIdx);
OpenPOWER on IntegriCloud