aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/ARM/ARMBaseRegisterInfo.cpp2
-rw-r--r--lib/Target/ARM/ARMISelDAGToDAG.cpp26
-rw-r--r--lib/Target/ARM/ARMInstrFormats.td117
-rw-r--r--lib/Target/ARM/ARMInstrInfo.td13
-rw-r--r--lib/Target/ARM/ARMInstrThumb.td375
-rw-r--r--lib/Target/ARM/ARMInstrThumb2.td3
-rw-r--r--lib/Target/ARM/ARMLoadStoreOptimizer.cpp2
-rw-r--r--lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp4
-rw-r--r--lib/Target/ARM/README-Thumb.txt15
-rw-r--r--lib/Target/ARM/Thumb1InstrInfo.cpp36
-rw-r--r--lib/Target/ARM/Thumb1RegisterInfo.cpp124
-rw-r--r--lib/Target/ARM/Thumb2InstrInfo.cpp9
-rw-r--r--test/CodeGen/Thumb/ispositive.ll4
-rw-r--r--test/CodeGen/Thumb/ldr_frame.ll12
14 files changed, 444 insertions, 298 deletions
diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp
index 3bea42c132..377de19456 100644
--- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp
+++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp
@@ -868,7 +868,7 @@ unsigned ARMBaseRegisterInfo::getRegisterPairOdd(unsigned Reg,
return 0;
}
-
+// FIXME: Dup in ARMBaseInstrInfo.cpp
static inline
const MachineInstrBuilder &AddDefaultPred(const MachineInstrBuilder &MIB) {
return MIB.addImm((int64_t)ARMCC::AL).addReg(0);
diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp
index abd4b59ac7..ce2a170e39 100644
--- a/lib/Target/ARM/ARMISelDAGToDAG.cpp
+++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp
@@ -459,8 +459,11 @@ bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue Op, SDValue N,
// wouldn't work without additional code to position the node within
// ISel's topological ordering in a place where ISel will process it
// normally. Instead, just explicitly issue a tMOVri8 node!
- Offset = SDValue(CurDAG->getTargetNode(ARM::tMOVi8, dl, MVT::i32,
- CurDAG->getTargetConstant(0, MVT::i32)), 0);
+ SDValue CC = CurDAG->getRegister(ARM::CPSR, MVT::i32);
+ SDValue Pred = CurDAG->getTargetConstant(0xEULL, MVT::i32);
+ SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
+ SDValue Ops[] = { CC, CurDAG->getTargetConstant(0, MVT::i32), Pred, PredReg };
+ Offset = SDValue(CurDAG->getTargetNode(ARM::tMOVi8, dl, MVT::i32, Ops,4),0);
return true;
}
@@ -871,10 +874,13 @@ SDNode *ARMDAGToDAGISel::Select(SDValue Op) {
TLI.getPointerTy());
SDNode *ResNode;
- if (Subtarget->isThumb1Only())
+ if (Subtarget->isThumb1Only()) {
+ SDValue Pred = CurDAG->getTargetConstant(0xEULL, MVT::i32);
+ SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
+ SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() };
ResNode = CurDAG->getTargetNode(ARM::tLDRcp, dl, MVT::i32, MVT::Other,
- CPIdx, CurDAG->getEntryNode());
- else {
+ Ops, 4);
+ } else {
SDValue Ops[] = {
CPIdx,
CurDAG->getRegister(0, MVT::i32),
@@ -901,11 +907,11 @@ SDNode *ARMDAGToDAGISel::Select(SDValue Op) {
return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, TFI,
CurDAG->getTargetConstant(0, MVT::i32));
} else {
+ unsigned Opc = Subtarget->hasThumb2() ? ARM::t2ADDri : ARM::ADDri;
SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32),
- getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
- CurDAG->getRegister(0, MVT::i32) };
- return CurDAG->SelectNodeTo(N, (Subtarget->hasThumb2()) ? ARM::t2ADDri : ARM::ADDri,
- MVT::i32, Ops, 5);
+ getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
+ CurDAG->getRegister(0, MVT::i32) };
+ return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
}
}
case ISD::ADD: {
@@ -922,7 +928,7 @@ SDNode *ARMDAGToDAGISel::Select(SDValue Op) {
}
if (RHSR && RHSR->getReg() == ARM::SP) {
SDValue Val = SDValue(CurDAG->getTargetNode(ARM::tMOVlor2hir, dl,
- Op.getValueType(), N0, N0), 0);
+ Op.getValueType(), N0, N0),0);
return CurDAG->SelectNodeTo(N, ARM::tADDhirr, Op.getValueType(), Val, N1);
}
break;
diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td
index 9ea4c33749..d1e7fc9bba 100644
--- a/lib/Target/ARM/ARMInstrFormats.td
+++ b/lib/Target/ARM/ARMInstrFormats.td
@@ -110,6 +110,28 @@ def IndexModePost : IndexMode<2>;
//===----------------------------------------------------------------------===//
+// ARM special operands.
+//
+
+// ARM Predicate operand. Default to 14 = always (AL). Second part is CC
+// register whose default is 0 (no register).
+def pred : PredicateOperand<OtherVT, (ops i32imm, CCR),
+ (ops (i32 14), (i32 zero_reg))> {
+ let PrintMethod = "printPredicateOperand";
+}
+
+// Conditional code result for instructions whose 's' bit is set, e.g. subs.
+def cc_out : OptionalDefOperand<OtherVT, (ops CCR), (ops (i32 zero_reg))> {
+ let PrintMethod = "printSBitModifierOperand";
+}
+
+// Same as cc_out except it defaults to setting CPSR.
+def s_cc_out : OptionalDefOperand<OtherVT, (ops CCR), (ops (i32 CPSR))> {
+ let PrintMethod = "printSBitModifierOperand";
+}
+
+//===----------------------------------------------------------------------===//
+
// ARM Instruction templates.
//
@@ -773,26 +795,26 @@ class ARMV6Pat<dag pattern, dag result> : Pat<pattern, result> {
// TI - Thumb instruction.
-class ThumbI<dag outs, dag ins, AddrMode am, SizeFlagVal sz,
+class ThumbI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
string asm, string cstr, list<dag> pattern>
: InstARM<am, sz, IndexModeNone, ThumbFrm, cstr> {
- let OutOperandList = outs;
- let InOperandList = ins;
+ let OutOperandList = oops;
+ let InOperandList = iops;
let AsmString = asm;
let Pattern = pattern;
list<Predicate> Predicates = [IsThumb];
}
-class TI<dag outs, dag ins, string asm, list<dag> pattern>
- : ThumbI<outs, ins, AddrModeNone, Size2Bytes, asm, "", pattern>;
+class TI<dag oops, dag iops, string asm, list<dag> pattern>
+ : ThumbI<oops, iops, AddrModeNone, Size2Bytes, asm, "", pattern>;
// BL, BLX(1) are translated by assembler into two instructions
-class TIx2<dag outs, dag ins, string asm, list<dag> pattern>
- : ThumbI<outs, ins, AddrModeNone, Size4Bytes, asm, "", pattern>;
+class TIx2<dag oops, dag iops, string asm, list<dag> pattern>
+ : ThumbI<oops, iops, AddrModeNone, Size4Bytes, asm, "", pattern>;
// BR_JT instructions
-class TJTI<dag outs, dag ins, string asm, list<dag> pattern>
- : ThumbI<outs, ins, AddrModeNone, SizeSpecial, asm, "", pattern>;
+class TJTI<dag oops, dag iops, string asm, list<dag> pattern>
+ : ThumbI<oops, iops, AddrModeNone, SizeSpecial, asm, "", pattern>;
// TPat - Same as Pat<>, but requires that the compiler be in Thumb mode.
class TPat<dag pattern, dag result> : Pat<pattern, result> {
@@ -804,34 +826,73 @@ class Tv5Pat<dag pattern, dag result> : Pat<pattern, result> {
}
// Thumb1 only
-class Thumb1I<dag outs, dag ins, AddrMode am, SizeFlagVal sz,
+class Thumb1I<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
string asm, string cstr, list<dag> pattern>
: InstARM<am, sz, IndexModeNone, ThumbFrm, cstr> {
- let OutOperandList = outs;
- let InOperandList = ins;
+ let OutOperandList = oops;
+ let InOperandList = iops;
let AsmString = asm;
let Pattern = pattern;
list<Predicate> Predicates = [IsThumb1Only];
}
-class T1I<dag outs, dag ins, string asm, list<dag> pattern>
- : Thumb1I<outs, ins, AddrModeNone, Size2Bytes, asm, "", pattern>;
-class T1I1<dag outs, dag ins, string asm, list<dag> pattern>
- : Thumb1I<outs, ins, AddrModeT1_1, Size2Bytes, asm, "", pattern>;
-class T1I2<dag outs, dag ins, string asm, list<dag> pattern>
- : Thumb1I<outs, ins, AddrModeT1_2, Size2Bytes, asm, "", pattern>;
-class T1I4<dag outs, dag ins, string asm, list<dag> pattern>
- : Thumb1I<outs, ins, AddrModeT1_4, Size2Bytes, asm, "", pattern>;
-class T1Is<dag outs, dag ins, string asm, list<dag> pattern>
- : Thumb1I<outs, ins, AddrModeT1_s, Size2Bytes, asm, "", pattern>;
-class T1Ix2<dag outs, dag ins, string asm, list<dag> pattern>
- : Thumb1I<outs, ins, AddrModeNone, Size4Bytes, asm, "", pattern>;
-class T1JTI<dag outs, dag ins, string asm, list<dag> pattern>
- : Thumb1I<outs, ins, AddrModeNone, SizeSpecial, asm, "", pattern>;
+class T1I<dag oops, dag iops, string asm, list<dag> pattern>
+ : Thumb1I<oops, iops, AddrModeNone, Size2Bytes, asm, "", pattern>;
+class T1Ix2<dag oops, dag iops, string asm, list<dag> pattern>
+ : Thumb1I<oops, iops, AddrModeNone, Size4Bytes, asm, "", pattern>;
+class T1JTI<dag oops, dag iops, string asm, list<dag> pattern>
+ : Thumb1I<oops, iops, AddrModeNone, SizeSpecial, asm, "", pattern>;
+
+// Two-address instructions
+class T1It<dag oops, dag iops, string asm, list<dag> pattern>
+ : Thumb1I<oops, iops, AddrModeNone, Size2Bytes, asm, "$lhs = $dst", pattern>;
+
+// Thumb1 instruction that can either be predicated or set CPSR.
+class Thumb1sI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
+ string opc, string asm, string cstr, list<dag> pattern>
+ : InstARM<am, sz, IndexModeNone, ThumbFrm, cstr> {
+ let OutOperandList = !con(oops, (ops s_cc_out:$s));
+ let InOperandList = !con(iops, (ops pred:$p));
+ let AsmString = !strconcat(opc, !strconcat("${s}${p}", asm));
+ let Pattern = pattern;
+ list<Predicate> Predicates = [IsThumb1Only];
+}
+
+class T1sI<dag oops, dag iops, string opc, string asm, list<dag> pattern>
+ : Thumb1sI<oops, iops, AddrModeNone, Size2Bytes, opc, asm, "", pattern>;
+
+// Two-address instructions
+class T1sIt<dag oops, dag iops, string opc, string asm, list<dag> pattern>
+ : Thumb1sI<oops, iops, AddrModeNone, Size2Bytes, opc, asm,
+ "$lhs = $dst", pattern>;
+
+// Thumb1 instruction that can be predicated.
+class Thumb1pI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
+ string opc, string asm, string cstr, list<dag> pattern>
+ : InstARM<am, sz, IndexModeNone, ThumbFrm, cstr> {
+ let OutOperandList = oops;
+ let InOperandList = !con(iops, (ops pred:$p));
+ let AsmString = !strconcat(opc, !strconcat("${p}", asm));
+ let Pattern = pattern;
+ list<Predicate> Predicates = [IsThumb1Only];
+}
+
+class T1pI<dag oops, dag iops, string opc, string asm, list<dag> pattern>
+ : Thumb1pI<oops, iops, AddrModeNone, Size2Bytes, opc, asm, "", pattern>;
// Two-address instructions
-class T1It<dag outs, dag ins, string asm, list<dag> pattern>
- : Thumb1I<outs, ins, AddrModeNone, Size2Bytes, asm, "$lhs = $dst", pattern>;
+class T1pIt<dag oops, dag iops, string opc, string asm, list<dag> pattern>
+ : Thumb1pI<oops, iops, AddrModeNone, Size2Bytes, opc, asm,
+ "$lhs = $dst", pattern>;
+
+class T1pI1<dag oops, dag iops, string opc, string asm, list<dag> pattern>
+ : Thumb1pI<oops, iops, AddrModeT1_1, Size2Bytes, opc, asm, "", pattern>;
+class T1pI2<dag oops, dag iops, string opc, string asm, list<dag> pattern>
+ : Thumb1pI<oops, iops, AddrModeT1_2, Size2Bytes, opc, asm, "", pattern>;
+class T1pI4<dag oops, dag iops, string opc, string asm, list<dag> pattern>
+ : Thumb1pI<oops, iops, AddrModeT1_4, Size2Bytes, opc, asm, "", pattern>;
+class T1pIs<dag oops, dag iops, string opc, string asm, list<dag> pattern>
+ : Thumb1pI<oops, iops, AddrModeT1_s, Size2Bytes, opc, asm, "", pattern>;
class T1Pat<dag pattern, dag result> : Pat<pattern, result> {
list<Predicate> Predicates = [IsThumb1Only];
diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td
index 3a29e9cae1..b3a52d65f1 100644
--- a/lib/Target/ARM/ARMInstrInfo.td
+++ b/lib/Target/ARM/ARMInstrInfo.td
@@ -316,19 +316,6 @@ def addrmodepc : Operand<i32>,
let MIOperandInfo = (ops GPR, i32imm);
}
-// ARM Predicate operand. Default to 14 = always (AL). Second part is CC
-// register whose default is 0 (no register).
-def pred : PredicateOperand<OtherVT, (ops i32imm, CCR),
- (ops (i32 14), (i32 zero_reg))> {
- let PrintMethod = "printPredicateOperand";
-}
-
-// Conditional code result for instructions whose 's' bit is set, e.g. subs.
-//
-def cc_out : OptionalDefOperand<OtherVT, (ops CCR), (ops (i32 zero_reg))> {
- let PrintMethod = "printSBitModifierOperand";
-}
-
//===----------------------------------------------------------------------===//
include "ARMInstrFormats.td"
diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td
index 433454daf5..a473a20615 100644
--- a/lib/Target/ARM/ARMInstrThumb.td
+++ b/lib/Target/ARM/ARMInstrThumb.td
@@ -155,9 +155,9 @@ def tADDspi : T1It<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs),
//
let isReturn = 1, isTerminator = 1 in {
- def tBX_RET : T1I<(outs), (ins), "bx lr", [(ARMretflag)]>;
+ def tBX_RET : TI<(outs), (ins), "bx lr", [(ARMretflag)]>;
// Alternative return instruction used by vararg functions.
- def tBX_RET_vararg : T1I<(outs), (ins tGPR:$target), "bx $target", []>;
+ def tBX_RET_vararg : TI<(outs), (ins tGPR:$target), "bx $target", []>;
}
// FIXME: remove when we have a way to marking a MI with these properties.
@@ -212,69 +212,69 @@ let isBranch = 1, isTerminator = 1 in
//
let canFoldAsLoad = 1 in
-def tLDR : T1I4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr),
- "ldr $dst, $addr",
+def tLDR : T1pI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr),
+ "ldr", " $dst, $addr",
[(set tGPR:$dst, (load t_addrmode_s4:$addr))]>;
-def tLDRB : T1I1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr),
- "ldrb $dst, $addr",
+def tLDRB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr),
+ "ldrb", " $dst, $addr",
[(set tGPR:$dst, (zextloadi8 t_addrmode_s1:$addr))]>;
-def tLDRH : T1I2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr),
- "ldrh $dst, $addr",
+def tLDRH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr),
+ "ldrh", " $dst, $addr",
[(set tGPR:$dst, (zextloadi16 t_addrmode_s2:$addr))]>;
-def tLDRSB : T1I1<(outs tGPR:$dst), (ins t_addrmode_rr:$addr),
- "ldrsb $dst, $addr",
+def tLDRSB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_rr:$addr),
+ "ldrsb", " $dst, $addr",
[(set tGPR:$dst, (sextloadi8 t_addrmode_rr:$addr))]>;
-def tLDRSH : T1I2<(outs tGPR:$dst), (ins t_addrmode_rr:$addr),
- "ldrsh $dst, $addr",
+def tLDRSH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_rr:$addr),
+ "ldrsh", " $dst, $addr",
[(set tGPR:$dst, (sextloadi16 t_addrmode_rr:$addr))]>;
let canFoldAsLoad = 1 in
-def tLDRspi : T1Is<(outs tGPR:$dst), (ins t_addrmode_sp:$addr),
- "ldr $dst, $addr",
+def tLDRspi : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr),
+ "ldr", " $dst, $addr",
[(set tGPR:$dst, (load t_addrmode_sp:$addr))]>;
// Special instruction for restore. It cannot clobber condition register
// when it's expanded by eliminateCallFramePseudoInstr().
let canFoldAsLoad = 1, mayLoad = 1 in
-def tRestore : T1Is<(outs tGPR:$dst), (ins t_addrmode_sp:$addr),
- "ldr $dst, $addr", []>;
+def tRestore : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr),
+ "ldr", " $dst, $addr", []>;
// Load tconstpool
let canFoldAsLoad = 1 in
-def tLDRpci : T1Is<(outs tGPR:$dst), (ins i32imm:$addr),
- "ldr $dst, $addr",
+def tLDRpci : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr),
+ "ldr", " $dst, $addr",
[(set tGPR:$dst, (load (ARMWrapper tconstpool:$addr)))]>;
// Special LDR for loads from non-pc-relative constpools.
let canFoldAsLoad = 1, mayLoad = 1, isReMaterializable = 1 in
-def tLDRcp : T1Is<(outs tGPR:$dst), (ins i32imm:$addr),
- "ldr $dst, $addr", []>;
+def tLDRcp : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr),
+ "ldr", " $dst, $addr", []>;
-def tSTR : T1I4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr),
- "str $src, $addr",
+def tSTR : T1pI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr),
+ "str", " $src, $addr",
[(store tGPR:$src, t_addrmode_s4:$addr)]>;
-def tSTRB : T1I1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr),
- "strb $src, $addr",
+def tSTRB : T1pI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr),
+ "strb", " $src, $addr",
[(truncstorei8 tGPR:$src, t_addrmode_s1:$addr)]>;
-def tSTRH : T1I2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr),
- "strh $src, $addr",
+def tSTRH : T1pI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr),
+ "strh", " $src, $addr",
[(truncstorei16 tGPR:$src, t_addrmode_s2:$addr)]>;
-def tSTRspi : T1Is<(outs), (ins tGPR:$src, t_addrmode_sp:$addr),
- "str $src, $addr",
+def tSTRspi : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr),
+ "str", " $src, $addr",
[(store tGPR:$src, t_addrmode_sp:$addr)]>;
let mayStore = 1 in {
// Special instruction for spill. It cannot clobber condition register
// when it's expanded by eliminateCallFramePseudoInstr().
-def tSpill : T1Is<(outs), (ins tGPR:$src, t_addrmode_sp:$addr),
- "str $src, $addr", []>;
+def tSpill : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr),
+ "str", " $src, $addr", []>;
}
//===----------------------------------------------------------------------===//
@@ -282,6 +282,7 @@ def tSpill : T1Is<(outs), (ins tGPR:$src, t_addrmode_sp:$addr),
//
// TODO: A7-44: LDMIA - load multiple
+// TODO: Allow these to be predicated
let mayLoad = 1 in
def tPOP : T1I<(outs reglist:$dst1, variable_ops), (ins),
@@ -296,216 +297,209 @@ def tPUSH : T1I<(outs), (ins reglist:$src1, variable_ops),
//
// Add with carry register
-let isCommutable = 1, Defs = [CPSR], Uses = [CPSR] in
-def tADCS : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
- "adc $dst, $rhs",
+let isCommutable = 1, Uses = [CPSR] in
+def tADC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
+ "adc", " $dst, $rhs",
[(set tGPR:$dst, (adde tGPR:$lhs, tGPR:$rhs))]>;
// Add immediate
-let Defs = [CPSR] in
-def tADDi3 : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
- "add $dst, $lhs, $rhs",
- [(set tGPR:$dst, (add tGPR:$lhs, imm0_7:$rhs))]>;
+def tADDi3 : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
+ "add", " $dst, $lhs, $rhs",
+ [(set tGPR:$dst, (add tGPR:$lhs, imm0_7:$rhs))]>;
-let Defs = [CPSR] in
-def tADDi8 : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
- "add $dst, $rhs",
- [(set tGPR:$dst, (add tGPR:$lhs, imm8_255:$rhs))]>;
+def tADDi8 : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
+ "add", " $dst, $rhs",
+ [(set tGPR:$dst, (add tGPR:$lhs, imm8_255:$rhs))]>;
// Add register
-let isCommutable = 1, Defs = [CPSR] in
-def tADDrr : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
- "add $dst, $lhs, $rhs",
- [(set tGPR:$dst, (add tGPR:$lhs, tGPR:$rhs))]>;
+let isCommutable = 1 in
+def tADDrr : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
+ "add", " $dst, $lhs, $rhs",
+ [(set tGPR:$dst, (add tGPR:$lhs, tGPR:$rhs))]>;
let neverHasSideEffects = 1 in
-def tADDhirr : T1It<(outs tGPR:$dst), (ins GPR:$lhs, GPR:$rhs),
- "add $dst, $rhs @ addhirr", []>;
+def tADDhirr : T1pIt<(outs tGPR:$dst), (ins GPR:$lhs, GPR:$rhs),
+ "add", " $dst, $rhs @ addhirr", []>;
// And register
-let isCommutable = 1, Defs = [CPSR] in
-def tAND : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
- "and $dst, $rhs",
- [(set tGPR:$dst, (and tGPR:$lhs, tGPR:$rhs))]>;
+let isCommutable = 1 in
+def tAND : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
+ "and", " $dst, $rhs",
+ [(set tGPR:$dst, (and tGPR:$lhs, tGPR:$rhs))]>;
// ASR immediate
-let Defs = [CPSR] in
-def tASRri : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
- "asr $dst, $lhs, $rhs",
- [(set tGPR:$dst, (sra tGPR:$lhs, (i32 imm:$rhs)))]>;
+def tASRri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
+ "asr", " $dst, $lhs, $rhs",
+ [(set tGPR:$dst, (sra tGPR:$lhs, (i32 imm:$rhs)))]>;
// ASR register
-let Defs = [CPSR] in
-def tASRrr : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
- "asr $dst, $rhs",
- [(set tGPR:$dst, (sra tGPR:$lhs, tGPR:$rhs))]>;
+def tASRrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
+ "asr", " $dst, $rhs",
+ [(set tGPR:$dst, (sra tGPR:$lhs, tGPR:$rhs))]>;
// BIC register
-let Defs = [CPSR] in
-def tBIC : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
- "bic $dst, $rhs",
- [(set tGPR:$dst, (and tGPR:$lhs, (not tGPR:$rhs)))]>;
+def tBIC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
+ "bic", " $dst, $rhs",
+ [(set tGPR:$dst, (and tGPR:$lhs, (not tGPR:$rhs)))]>;
// CMN register
let Defs = [CPSR] in {
-def tCMN : T1I<(outs), (ins tGPR:$lhs, tGPR:$rhs),
- "cmn $lhs, $rhs",
- [(ARMcmp tGPR:$lhs, (ineg tGPR:$rhs))]>;
-def tCMNZ : T1I<(outs), (ins tGPR:$lhs, tGPR:$rhs),
- "cmn $lhs, $rhs",
- [(ARMcmpZ tGPR:$lhs, (ineg tGPR:$rhs))]>;
+def tCMN : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs),
+ "cmn", " $lhs, $rhs",
+ [(ARMcmp tGPR:$lhs, (ineg tGPR:$rhs))]>;
+def tCMNZ : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs),
+ "cmn", " $lhs, $rhs",
+ [(ARMcmpZ tGPR:$lhs, (ineg tGPR:$rhs))]>;
}
// CMP immediate
let Defs = [CPSR] in {
-def tCMPi8 : T1I<(outs), (ins tGPR:$lhs, i32imm:$rhs),
- "cmp $lhs, $rhs",
- [(ARMcmp tGPR:$lhs, imm0_255:$rhs)]>;
-def tCMPZi8 : T1I<(outs), (ins tGPR:$lhs, i32imm:$rhs),
- "cmp $lhs, $rhs",
- [(ARMcmpZ tGPR:$lhs, imm0_255:$rhs)]>;
+def tCMPi8 : T1pI<(outs), (ins tGPR:$lhs, i32imm:$rhs),
+ "cmp", " $lhs, $rhs",
+ [(ARMcmp tGPR:$lhs, imm0_255:$rhs)]>;
+def tCMPZi8 : T1pI<(outs), (ins tGPR:$lhs, i32imm:$rhs),
+ "cmp", " $lhs, $rhs",
+ [(ARMcmpZ tGPR:$lhs, imm0_255:$rhs)]>;
}
// CMP register
let Defs = [CPSR] in {
-def tCMPr : T1I<(outs), (ins tGPR:$lhs, tGPR:$rhs),
- "cmp $lhs, $rhs",
- [(ARMcmp tGPR:$lhs, tGPR:$rhs)]>;
-def tCMPZr : T1I<(outs), (ins tGPR:$lhs, tGPR:$rhs),
- "cmp $lhs, $rhs",
- [(ARMcmpZ tGPR:$lhs, tGPR:$rhs)]>;
+def tCMPr : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs),
+ "cmp", " $lhs, $rhs",
+ [(ARMcmp tGPR:$lhs, tGPR:$rhs)]>;
+def tCMPZr : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs),
+ "cmp", " $lhs, $rhs",
+ [(ARMcmpZ tGPR:$lhs, tGPR:$rhs)]>;
+
+// TODO: Make use of the followings cmp hi regs
+def tCMPhir : T1pI<(outs), (ins GPR:$lhs, GPR:$rhs),
+ "cmp", " $lhs, $rhs", []>;
+def tCMPZhir : T1pI<(outs), (ins GPR:$lhs, GPR:$rhs),
+ "cmp", " $lhs, $rhs", []>;
}
-// TODO: A7-37: CMP(3) - cmp hi regs
// XOR register
-let isCommutable = 1, Defs = [CPSR] in
-def tEOR : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
- "eor $dst, $rhs",
- [(set tGPR:$dst, (xor tGPR:$lhs, tGPR:$rhs))]>;
+let isCommutable = 1 in
+def tEOR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
+ "eor", " $dst, $rhs",
+ [(set tGPR:$dst, (xor tGPR:$lhs, tGPR:$rhs))]>;
// LSL immediate
-let Defs = [CPSR] in
-def tLSLri : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
- "lsl $dst, $lhs, $rhs",
- [(set tGPR:$dst, (shl tGPR:$lhs, (i32 imm:$rhs)))]>;
+def tLSLri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
+ "lsl", " $dst, $lhs, $rhs",
+ [(set tGPR:$dst, (shl tGPR:$lhs, (i32 imm:$rhs)))]>;
// LSL register
-let Defs = [CPSR] in
-def tLSLrr : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
- "lsl $dst, $rhs",
- [(set tGPR:$dst, (shl tGPR:$lhs, tGPR:$rhs))]>;
+def tLSLrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
+ "lsl", " $dst, $rhs",
+ [(set tGPR:$dst, (shl tGPR:$lhs, tGPR:$rhs))]>;
// LSR immediate
-let Defs = [CPSR] in
-def tLSRri : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
- "lsr $dst, $lhs, $rhs",
- [(set tGPR:$dst, (srl tGPR:$lhs, (i32 imm:$rhs)))]>;
+def tLSRri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
+ "lsr", " $dst, $lhs, $rhs",
+ [(set tGPR:$dst, (srl tGPR:$lhs, (i32 imm:$rhs)))]>;
// LSR register
-let Defs = [CPSR] in
-def tLSRrr : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
- "lsr $dst, $rhs",
- [(set tGPR:$dst, (srl tGPR:$lhs, tGPR:$rhs))]>;
+def tLSRrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
+ "lsr", " $dst, $rhs",
+ [(set tGPR:$dst, (srl tGPR:$lhs, tGPR:$rhs))]>;
// move register
-let Defs = [CPSR] in
-def tMOVi8 : T1I<(outs tGPR:$dst), (ins i32imm:$src),
- "mov $dst, $src",
- [(set tGPR:$dst, imm0_255:$src)]>;
+def tMOVi8 : T1sI<(outs tGPR:$dst), (ins i32imm:$src),
+ "mov", " $dst, $src",
+ [(set tGPR:$dst, imm0_255:$src)]>;
// TODO: A7-73: MOV(2) - mov setting flag.
-// Note: MOV(2) of two low regs updates the flags, so we emit this as 'cpy',
-// which is MOV(3). This also supports high registers.
let neverHasSideEffects = 1 in {
+// FIXME: Make this predicable.
def tMOVr : T1I<(outs tGPR:$dst), (ins tGPR:$src),
- "cpy $dst, $src", []>;
+ "mov $dst, $src", []>;
+let Defs = [CPSR] in
+def tMOVSr : T1I<(outs tGPR:$dst), (ins tGPR:$src),
+ "movs $dst, $src", []>;
+
+// FIXME: Make these predicable.
def tMOVhir2lor : T1I<(outs tGPR:$dst), (ins GPR:$src),
- "cpy $dst, $src\t@ hir2lor", []>;
+ "mov $dst, $src\t@ hir2lor", []>;
def tMOVlor2hir : T1I<(outs GPR:$dst), (ins tGPR:$src),
- "cpy $dst, $src\t@ lor2hir", []>;
+ "mov $dst, $src\t@ lor2hir", []>;
def tMOVhir2hir : T1I<(outs GPR:$dst), (ins GPR:$src),
- "cpy $dst, $src\t@ hir2hir", []>;
+ "mov $dst, $src\t@ hir2hir", []>;
} // neverHasSideEffects
// multiply register
-let isCommutable = 1, Defs = [CPSR] in
-def tMUL : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
- "mul $dst, $rhs",
- [(set tGPR:$dst, (mul tGPR:$lhs, tGPR:$rhs))]>;
+let isCommutable = 1 in
+def tMUL : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
+ "mul", " $dst, $rhs",
+ [(set tGPR:$dst, (mul tGPR:$lhs, tGPR:$rhs))]>;
// move inverse register
-let Defs = [CPSR] in
-def tMVN : T1I<(outs tGPR:$dst), (ins tGPR:$src),
- "mvn $dst, $src",
- [(set tGPR:$dst, (not tGPR:$src))]>;
-
-// negate register
-let Defs = [CPSR] in
-def tNEG : T1I<(outs tGPR:$dst), (ins tGPR:$src),
- "neg $dst, $src",
- [(set tGPR:$dst, (ineg tGPR:$src))]>;
+def tMVN : T1sI<(outs tGPR:$dst), (ins tGPR:$src),
+ "mvn", " $dst, $src",
+ [(set tGPR:$dst, (not tGPR:$src))]>;
// bitwise or register
-let isCommutable = 1, Defs = [CPSR] in
-def tORR : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
- "orr $dst, $rhs",
- [(set tGPR:$dst, (or tGPR:$lhs, tGPR:$rhs))]>;
+let isCommutable = 1 in
+def tORR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
+ "orr", " $dst, $rhs",
+ [(set tGPR:$dst, (or tGPR:$lhs, tGPR:$rhs))]>;
// swaps
-def tREV : T1I<(outs tGPR:$dst), (ins tGPR:$src),
- "rev $dst, $src",
- [(set tGPR:$dst, (bswap tGPR:$src))]>,
- Requires<[IsThumb1Only, HasV6]>;
-
-def tREV16 : T1I<(outs tGPR:$dst), (ins tGPR:$src),
- "rev16 $dst, $src",
- [(set tGPR:$dst,
- (or (and (srl tGPR:$src, (i32 8)), 0xFF),
- (or (and (shl tGPR:$src, (i32 8)), 0xFF00),
- (or (and (srl tGPR:$src, (i32 8)), 0xFF0000),
- (and (shl tGPR:$src, (i32 8)), 0xFF000000)))))]>,
+def tREV : T1pI<(outs tGPR:$dst), (ins tGPR:$src),
+ "rev", " $dst, $src",
+ [(set tGPR:$dst, (bswap tGPR:$src))]>,
Requires<[IsThumb1Only, HasV6]>;
-def tREVSH : T1I<(outs tGPR:$dst), (ins tGPR:$src),
- "revsh $dst, $src",
- [(set tGPR:$dst,
- (sext_inreg
- (or (srl (and tGPR:$src, 0xFFFF), (i32 8)),
- (shl tGPR:$src, (i32 8))), i16))]>,
+def tREV16 : T1pI<(outs tGPR:$dst), (ins tGPR:$src),
+ "rev16", " $dst, $src",
+ [(set tGPR:$dst,
+ (or (and (srl tGPR:$src, (i32 8)), 0xFF),
+ (or (and (shl tGPR:$src, (i32 8)), 0xFF00),
+ (or (and (srl tGPR:$src, (i32 8)), 0xFF0000),
+ (and (shl tGPR:$src, (i32 8)), 0xFF000000)))))]>,
Requires<[IsThumb1Only, HasV6]>;
+def tREVSH : T1pI<(outs tGPR:$dst), (ins tGPR:$src),
+ "revsh", " $dst, $src",
+ [(set tGPR:$dst,
+ (sext_inreg
+ (or (srl (and tGPR:$src, 0xFFFF), (i32 8)),
+ (shl tGPR:$src, (i32 8))), i16))]>,
+ Requires<[IsThumb1Only, HasV6]>;
+
// rotate right register
-let Defs = [CPSR] in
-def tROR : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
- "ror $dst, $rhs",
- [(set tGPR:$dst, (rotr tGPR:$lhs, tGPR:$rhs))]>;
+def tROR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
+ "ror", " $dst, $rhs",
+ [(set tGPR:$dst, (rotr tGPR:$lhs, tGPR:$rhs))]>;
+
+// negate register
+def tRSB : T1sI<(outs tGPR:$dst), (ins tGPR:$src),
+ "rsb", " $dst, $src, #0",
+ [(set tGPR:$dst, (ineg tGPR:$src))]>;
// Subtract with carry register
-let Defs = [CPSR], Uses = [CPSR] in
-def tSBCS : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
- "sbc $dst, $rhs",
- [(set tGPR:$dst, (sube tGPR:$lhs, tGPR:$rhs))]>;
+let Uses = [CPSR] in
+def tSBC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
+ "sbc", " $dst, $rhs",
+ [(set tGPR:$dst, (sube tGPR:$lhs, tGPR:$rhs))]>;
// Subtract immediate
-let Defs = [CPSR] in
-def tSUBi3 : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
- "sub $dst, $lhs, $rhs",
- [(set tGPR:$dst, (add tGPR:$lhs, imm0_7_neg:$rhs))]>;
+def tSUBi3 : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
+ "sub", " $dst, $lhs, $rhs",
+ [(set tGPR:$dst, (add tGPR:$lhs, imm0_7_neg:$rhs))]>;
-let Defs = [CPSR] in
-def tSUBi8 : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
- "sub $dst, $rhs",
- [(set tGPR:$dst, (add tGPR:$lhs, imm8_255_neg:$rhs))]>;
+def tSUBi8 : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
+ "sub", " $dst, $rhs",
+ [(set tGPR:$dst, (add tGPR:$lhs, imm8_255_neg:$rhs))]>;
// subtract register
-let Defs = [CPSR] in
-def tSUBrr : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
- "sub $dst, $lhs, $rhs",
- [(set tGPR:$dst, (sub tGPR:$lhs, tGPR:$rhs))]>;
+def tSUBrr : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
+ "sub", " $dst, $lhs, $rhs",
+ [(set tGPR:$dst, (sub tGPR:$lhs, tGPR:$rhs))]>;
// TODO: A7-96: STMIA - store multiple.
@@ -513,38 +507,39 @@ def tSUBspi : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
"sub $dst, $rhs * 4", []>;
// sign-extend byte
-def tSXTB : T1I<(outs tGPR:$dst), (ins tGPR:$src),
- "sxtb $dst, $src",
- [(set tGPR:$dst, (sext_inreg tGPR:$src, i8))]>,
- Requires<[IsThumb1Only, HasV6]>;
+def tSXTB : T1pI<(outs tGPR:$dst), (ins tGPR:$src),
+ "sxtb", " $dst, $src",
+ [(set tGPR:$dst, (sext_inreg tGPR:$src, i8))]>,
+ Requires<[IsThumb1Only, HasV6]>;
// sign-extend short
-def tSXTH : T1I<(outs tGPR:$dst), (ins tGPR:$src),
- "sxth $dst, $src",
- [(set tGPR:$dst, (sext_inreg tGPR:$src, i16))]>,
- Requires<[IsThumb1Only, HasV6]>;
+def tSXTH : T1pI<(outs tGPR:$dst), (ins tGPR:$src),
+ "sxth", " $dst, $src",
+ [(set tGPR:$dst, (sext_inreg tGPR:$src, i16))]>,
+ Requires<[IsThumb1Only, HasV6]>;
// test
let isCommutable = 1, Defs = [CPSR] in
-def tTST : T1I<(outs), (ins tGPR:$lhs, tGPR:$rhs),
- "tst $lhs, $rhs",
- [(ARMcmpZ (and tGPR:$lhs, tGPR:$rhs), 0)]>;
+def tTST : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs),
+ "tst", " $lhs, $rhs",
+ [(ARMcmpZ (and tGPR:$lhs, tGPR:$rhs), 0)]>;
// zero-extend byte
-def tUXTB : T1I<(outs tGPR:$dst), (ins tGPR:$src),
- "uxtb $dst, $src",
- [(set tGPR:$dst, (and tGPR:$src, 0xFF))]>,
- Requires<[IsThumb1Only, HasV6]>;
+def tUXTB : T1pI<(outs tGPR:$dst), (ins tGPR:$src),
+ "uxtb", " $dst, $src",
+ [(set tGPR:$dst, (and tGPR:$src, 0xFF))]>,
+ Requires<[IsThumb1Only, HasV6]>;
// zero-extend short
-def tUXTH : T1I<(outs tGPR:$dst), (ins tGPR:$src),
- "uxth $dst, $src",
- [(set tGPR:$dst, (and tGPR:$src, 0xFFFF))]>,
- Requires<[IsThumb1Only, HasV6]>;
+def tUXTH : T1pI<(outs tGPR:$dst), (ins tGPR:$src),
+ "uxth", " $dst, $src",
+ [(set tGPR:$dst, (and tGPR:$src, 0xFFFF))]>,
+ Requires<[IsThumb1Only, HasV6]>;
// Conditional move tMOVCCr - Used to implement the Thumb SELECT_CC DAG operation.
// Expanded by the scheduler into a branch sequence.
+// FIXME: Add actual movcc in IT blocks for Thumb2