ARMInstrThumb.td revision 198892
1193323Sed//===- ARMInstrThumb.td - Thumb support for ARM ---------------------------===//
2193323Sed//
3193323Sed//                     The LLVM Compiler Infrastructure
4193323Sed//
5193323Sed// This file is distributed under the University of Illinois Open Source
6193323Sed// License. See LICENSE.TXT for details.
7193323Sed//
8193323Sed//===----------------------------------------------------------------------===//
9193323Sed//
10193323Sed// This file describes the Thumb instruction set.
11193323Sed//
12193323Sed//===----------------------------------------------------------------------===//
13193323Sed
14193323Sed//===----------------------------------------------------------------------===//
15193323Sed// Thumb specific DAG Nodes.
16193323Sed//
17193323Sed
18193323Seddef ARMtcall : SDNode<"ARMISD::tCALL", SDT_ARMcall,
19193323Sed                      [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
20193323Sed
21193323Seddef imm_neg_XFORM : SDNodeXForm<imm, [{
22193323Sed  return CurDAG->getTargetConstant(-(int)N->getZExtValue(), MVT::i32);
23193323Sed}]>;
24193323Seddef imm_comp_XFORM : SDNodeXForm<imm, [{
25193323Sed  return CurDAG->getTargetConstant(~((uint32_t)N->getZExtValue()), MVT::i32);
26193323Sed}]>;
27193323Sed
28193323Sed
29193323Sed/// imm0_7 predicate - True if the 32-bit immediate is in the range [0,7].
30193323Seddef imm0_7 : PatLeaf<(i32 imm), [{
31193323Sed  return (uint32_t)N->getZExtValue() < 8;
32193323Sed}]>;
33193323Seddef imm0_7_neg : PatLeaf<(i32 imm), [{
34193323Sed  return (uint32_t)-N->getZExtValue() < 8;
35193323Sed}], imm_neg_XFORM>;
36193323Sed
37193323Seddef imm0_255 : PatLeaf<(i32 imm), [{
38193323Sed  return (uint32_t)N->getZExtValue() < 256;
39193323Sed}]>;
40193323Seddef imm0_255_comp : PatLeaf<(i32 imm), [{
41193323Sed  return ~((uint32_t)N->getZExtValue()) < 256;
42193323Sed}]>;
43193323Sed
44193323Seddef imm8_255 : PatLeaf<(i32 imm), [{
45193323Sed  return (uint32_t)N->getZExtValue() >= 8 && (uint32_t)N->getZExtValue() < 256;
46193323Sed}]>;
47193323Seddef imm8_255_neg : PatLeaf<(i32 imm), [{
48193323Sed  unsigned Val = -N->getZExtValue();
49193323Sed  return Val >= 8 && Val < 256;
50193323Sed}], imm_neg_XFORM>;
51193323Sed
52193323Sed// Break imm's up into two pieces: an immediate + a left shift.
53193323Sed// This uses thumb_immshifted to match and thumb_immshifted_val and
54193323Sed// thumb_immshifted_shamt to get the val/shift pieces.
55193323Seddef thumb_immshifted : PatLeaf<(imm), [{
56193323Sed  return ARM_AM::isThumbImmShiftedVal((unsigned)N->getZExtValue());
57193323Sed}]>;
58193323Sed
59193323Seddef thumb_immshifted_val : SDNodeXForm<imm, [{
60193323Sed  unsigned V = ARM_AM::getThumbImmNonShiftedVal((unsigned)N->getZExtValue());
61193323Sed  return CurDAG->getTargetConstant(V, MVT::i32);
62193323Sed}]>;
63193323Sed
64193323Seddef thumb_immshifted_shamt : SDNodeXForm<imm, [{
65193323Sed  unsigned V = ARM_AM::getThumbImmValShift((unsigned)N->getZExtValue());
66193323Sed  return CurDAG->getTargetConstant(V, MVT::i32);
67193323Sed}]>;
68193323Sed
69193323Sed// Define Thumb specific addressing modes.
70193323Sed
71193323Sed// t_addrmode_rr := reg + reg
72193323Sed//
73193323Seddef t_addrmode_rr : Operand<i32>,
74193323Sed                    ComplexPattern<i32, 2, "SelectThumbAddrModeRR", []> {
75193323Sed  let PrintMethod = "printThumbAddrModeRROperand";
76193323Sed  let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg);
77193323Sed}
78193323Sed
79193323Sed// t_addrmode_s4 := reg + reg
80193323Sed//                  reg + imm5 * 4
81193323Sed//
82193323Seddef t_addrmode_s4 : Operand<i32>,
83193323Sed                    ComplexPattern<i32, 3, "SelectThumbAddrModeS4", []> {
84193323Sed  let PrintMethod = "printThumbAddrModeS4Operand";
85193323Sed  let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg);
86193323Sed}
87193323Sed
88193323Sed// t_addrmode_s2 := reg + reg
89193323Sed//                  reg + imm5 * 2
90193323Sed//
91193323Seddef t_addrmode_s2 : Operand<i32>,
92193323Sed                    ComplexPattern<i32, 3, "SelectThumbAddrModeS2", []> {
93193323Sed  let PrintMethod = "printThumbAddrModeS2Operand";
94193323Sed  let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg);
95193323Sed}
96193323Sed
97193323Sed// t_addrmode_s1 := reg + reg
98193323Sed//                  reg + imm5
99193323Sed//
100193323Seddef t_addrmode_s1 : Operand<i32>,
101193323Sed                    ComplexPattern<i32, 3, "SelectThumbAddrModeS1", []> {
102193323Sed  let PrintMethod = "printThumbAddrModeS1Operand";
103193323Sed  let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg);
104193323Sed}
105193323Sed
106193323Sed// t_addrmode_sp := sp + imm8 * 4
107193323Sed//
108193323Seddef t_addrmode_sp : Operand<i32>,
109193323Sed                    ComplexPattern<i32, 2, "SelectThumbAddrModeSP", []> {
110193323Sed  let PrintMethod = "printThumbAddrModeSPOperand";
111193323Sed  let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm);
112193323Sed}
113193323Sed
114193323Sed//===----------------------------------------------------------------------===//
115193323Sed//  Miscellaneous Instructions.
116193323Sed//
117193323Sed
118193323Sedlet Defs = [SP], Uses = [SP] in {
119193323Seddef tADJCALLSTACKUP :
120198090SrdivackyPseudoInst<(outs), (ins i32imm:$amt1, i32imm:$amt2), NoItinerary,
121193323Sed           "@ tADJCALLSTACKUP $amt1",
122198090Srdivacky           [(ARMcallseq_end imm:$amt1, imm:$amt2)]>, Requires<[IsThumb1Only]>;
123193323Sed
124193323Seddef tADJCALLSTACKDOWN :
125198090SrdivackyPseudoInst<(outs), (ins i32imm:$amt), NoItinerary,
126193323Sed           "@ tADJCALLSTACKDOWN $amt",
127198090Srdivacky           [(ARMcallseq_start imm:$amt)]>, Requires<[IsThumb1Only]>;
128193323Sed}
129193323Sed
130198090Srdivacky// For both thumb1 and thumb2.
131193323Sedlet isNotDuplicable = 1 in
132198090Srdivackydef tPICADD : TIt<(outs GPR:$dst), (ins GPR:$lhs, pclabel:$cp), IIC_iALUr,
133198892Srdivacky                 "\n$cp:\n\tadd\t$dst, pc",
134198090Srdivacky                 [(set GPR:$dst, (ARMpic_add GPR:$lhs, imm:$cp))]>;
135193323Sed
136195098Sed// PC relative add.
137198090Srdivackydef tADDrPCi : T1I<(outs tGPR:$dst), (ins i32imm:$rhs), IIC_iALUi,
138198892Srdivacky                  "add\t$dst, pc, $rhs * 4", []>;
139195098Sed
140195098Sed// ADD rd, sp, #imm8
141198090Srdivackydef tADDrSPi : T1I<(outs tGPR:$dst), (ins GPR:$sp, i32imm:$rhs), IIC_iALUi,
142198892Srdivacky                  "add\t$dst, $sp, $rhs * 4", []>;
143195098Sed
144195098Sed// ADD sp, sp, #imm7
145198090Srdivackydef tADDspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs), IIC_iALUi,
146198892Srdivacky                  "add\t$dst, $rhs * 4", []>;
147195098Sed
148198090Srdivacky// SUB sp, sp, #imm7
149198090Srdivackydef tSUBspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs), IIC_iALUi,
150198892Srdivacky                  "sub\t$dst, $rhs * 4", []>;
151198090Srdivacky
152198090Srdivacky// ADD rm, sp
153198090Srdivackydef tADDrSP : TIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr,
154198892Srdivacky                  "add\t$dst, $rhs", []>;
155198090Srdivacky
156195098Sed// ADD sp, rm
157198090Srdivackydef tADDspr : TIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr,
158198892Srdivacky                  "add\t$dst, $rhs", []>;
159195098Sed
160198090Srdivacky// Pseudo instruction that will expand into a tSUBspi + a copy.
161198892Srdivackylet usesCustomInserter = 1 in { // Expanded after instruction selection.
162198090Srdivackydef tSUBspi_ : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs),
163198892Srdivacky               NoItinerary, "@ sub\t$dst, $rhs * 4", []>;
164198090Srdivacky
165198090Srdivackydef tADDspr_ : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs),
166198892Srdivacky               NoItinerary, "@ add\t$dst, $rhs", []>;
167198090Srdivacky
168198090Srdivackylet Defs = [CPSR] in
169198090Srdivackydef tANDsp : PseudoInst<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
170198892Srdivacky             NoItinerary, "@ and\t$dst, $rhs", []>;
171198892Srdivacky} // usesCustomInserter
172198090Srdivacky
173193323Sed//===----------------------------------------------------------------------===//
174193323Sed//  Control Flow Instructions.
175193323Sed//
176193323Sed
177198090Srdivackylet isReturn = 1, isTerminator = 1, isBarrier = 1 in {
178198892Srdivacky  def tBX_RET : TI<(outs), (ins), IIC_Br, "bx\tlr", [(ARMretflag)]>;
179193323Sed  // Alternative return instruction used by vararg functions.
180198892Srdivacky  def tBX_RET_vararg : TI<(outs), (ins tGPR:$target), IIC_Br, "bx\t$target", []>;
181193323Sed}
182193323Sed
183198892Srdivacky// Indirect branches
184198892Srdivackylet isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
185198892Srdivacky  def tBRIND : TI<(outs), (ins GPR:$dst), IIC_Br, "mov\tpc, $dst",
186198892Srdivacky                  [(brind GPR:$dst)]>;
187198892Srdivacky}
188198892Srdivacky
189193323Sed// FIXME: remove when we have a way to marking a MI with these properties.
190198090Srdivackylet isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1,
191198090Srdivacky    hasExtraDefRegAllocReq = 1 in
192198090Srdivackydef tPOP_RET : T1I<(outs), (ins pred:$p, reglist:$wb, variable_ops), IIC_Br,
193198892Srdivacky                   "pop${p}\t$wb", []>;
194193323Sed
195193323Sedlet isCall = 1,
196198090Srdivacky  Defs = [R0,  R1,  R2,  R3,  R12, LR,
197198090Srdivacky          D0,  D1,  D2,  D3,  D4,  D5,  D6,  D7,
198198090Srdivacky          D16, D17, D18, D19, D20, D21, D22, D23,
199198090Srdivacky          D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR] in {
200198090Srdivacky  // Also used for Thumb2
201198090Srdivacky  def tBL  : TIx2<(outs), (ins i32imm:$func, variable_ops), IIC_Br, 
202198892Srdivacky                   "bl\t${func:call}",
203198090Srdivacky                   [(ARMtcall tglobaladdr:$func)]>,
204198090Srdivacky             Requires<[IsThumb, IsNotDarwin]>;
205198090Srdivacky
206198090Srdivacky  // ARMv5T and above, also used for Thumb2
207198090Srdivacky  def tBLXi : TIx2<(outs), (ins i32imm:$func, variable_ops), IIC_Br, 
208198892Srdivacky                    "blx\t${func:call}",
209198090Srdivacky                    [(ARMcall tglobaladdr:$func)]>,
210198090Srdivacky              Requires<[IsThumb, HasV5T, IsNotDarwin]>;
211198090Srdivacky
212198090Srdivacky  // Also used for Thumb2
213198090Srdivacky  def tBLXr : TI<(outs), (ins GPR:$func, variable_ops), IIC_Br, 
214198892Srdivacky                  "blx\t$func",
215198090Srdivacky                  [(ARMtcall GPR:$func)]>,
216198090Srdivacky              Requires<[IsThumb, HasV5T, IsNotDarwin]>;
217198090Srdivacky
218193323Sed  // ARMv4T
219198090Srdivacky  def tBX : TIx2<(outs), (ins tGPR:$func, variable_ops), IIC_Br, 
220198892Srdivacky                  "mov\tlr, pc\n\tbx\t$func",
221198090Srdivacky                  [(ARMcall_nolink tGPR:$func)]>,
222198090Srdivacky            Requires<[IsThumb1Only, IsNotDarwin]>;
223193323Sed}
224193323Sed
225198090Srdivacky// On Darwin R9 is call-clobbered.
226198090Srdivackylet isCall = 1,
227198090Srdivacky  Defs = [R0,  R1,  R2,  R3,  R9,  R12, LR,
228198090Srdivacky          D0,  D1,  D2,  D3,  D4,  D5,  D6,  D7,
229198090Srdivacky          D16, D17, D18, D19, D20, D21, D22, D23,
230198090Srdivacky          D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR] in {
231198090Srdivacky  // Also used for Thumb2
232198090Srdivacky  def tBLr9 : TIx2<(outs), (ins i32imm:$func, variable_ops), IIC_Br, 
233198892Srdivacky                   "bl\t${func:call}",
234198090Srdivacky                   [(ARMtcall tglobaladdr:$func)]>,
235198090Srdivacky              Requires<[IsThumb, IsDarwin]>;
236198090Srdivacky
237198090Srdivacky  // ARMv5T and above, also used for Thumb2
238198090Srdivacky  def tBLXi_r9 : TIx2<(outs), (ins i32imm:$func, variable_ops), IIC_Br, 
239198892Srdivacky                      "blx\t${func:call}",
240198090Srdivacky                      [(ARMcall tglobaladdr:$func)]>,
241198090Srdivacky                 Requires<[IsThumb, HasV5T, IsDarwin]>;
242198090Srdivacky
243198090Srdivacky  // Also used for Thumb2
244198090Srdivacky  def tBLXr_r9 : TI<(outs), (ins GPR:$func, variable_ops), IIC_Br, 
245198892Srdivacky                  "blx\t$func",
246198090Srdivacky                  [(ARMtcall GPR:$func)]>,
247198090Srdivacky                 Requires<[IsThumb, HasV5T, IsDarwin]>;
248198090Srdivacky
249198090Srdivacky  // ARMv4T
250198090Srdivacky  def tBXr9 : TIx2<(outs), (ins tGPR:$func, variable_ops), IIC_Br, 
251198892Srdivacky                  "mov\tlr, pc\n\tbx\t$func",
252198090Srdivacky                  [(ARMcall_nolink tGPR:$func)]>,
253198090Srdivacky              Requires<[IsThumb1Only, IsDarwin]>;
254198090Srdivacky}
255198090Srdivacky
256193323Sedlet isBranch = 1, isTerminator = 1 in {
257193323Sed  let isBarrier = 1 in {
258193323Sed    let isPredicable = 1 in
259198090Srdivacky    def tB   : T1I<(outs), (ins brtarget:$target), IIC_Br,
260198892Srdivacky                   "b\t$target", [(br bb:$target)]>;
261193323Sed
262193323Sed  // Far jump
263198090Srdivacky  let Defs = [LR] in
264198090Srdivacky  def tBfar : TIx2<(outs), (ins brtarget:$target), IIC_Br, 
265198892Srdivacky                    "bl\t$target\t@ far jump",[]>;
266193323Sed
267195340Sed  def tBR_JTr : T1JTI<(outs),
268195340Sed                      (ins tGPR:$target, jtblock_operand:$jt, i32imm:$id),
269198892Srdivacky                      IIC_Br, "mov\tpc, $target\n\t.align\t2\n$jt",
270195340Sed                      [(ARMbrjt tGPR:$target, tjumptable:$jt, imm:$id)]>;
271193323Sed  }
272193323Sed}
273193323Sed
274193323Sed// FIXME: should be able to write a pattern for ARMBrcond, but can't use
275193323Sed// a two-value operand where a dag node expects two operands. :(
276193323Sedlet isBranch = 1, isTerminator = 1 in
277198090Srdivacky  def tBcc : T1I<(outs), (ins brtarget:$target, pred:$cc), IIC_Br,
278198892Srdivacky                 "b$cc\t$target",
279193323Sed                 [/*(ARMbrcond bb:$target, imm:$cc)*/]>;
280193323Sed
281198892Srdivacky// Compare and branch on zero / non-zero
282198892Srdivackylet isBranch = 1, isTerminator = 1 in {
283198892Srdivacky  def tCBZ  : T1I<(outs), (ins tGPR:$cmp, brtarget:$target), IIC_Br,
284198892Srdivacky                  "cbz\t$cmp, $target", []>;
285198892Srdivacky
286198892Srdivacky  def tCBNZ : T1I<(outs), (ins tGPR:$cmp, brtarget:$target), IIC_Br,
287198892Srdivacky                  "cbnz\t$cmp, $target", []>;
288198892Srdivacky}
289198892Srdivacky
290193323Sed//===----------------------------------------------------------------------===//
291193323Sed//  Load Store Instructions.
292193323Sed//
293193323Sed
294193323Sedlet canFoldAsLoad = 1 in
295198090Srdivackydef tLDR : T1pI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr), IIC_iLoadr, 
296198892Srdivacky               "ldr", "\t$dst, $addr",
297193323Sed               [(set tGPR:$dst, (load t_addrmode_s4:$addr))]>;
298193323Sed
299198090Srdivackydef tLDRB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr), IIC_iLoadr,
300198892Srdivacky                "ldrb", "\t$dst, $addr",
301193323Sed                [(set tGPR:$dst, (zextloadi8 t_addrmode_s1:$addr))]>;
302193323Sed
303198090Srdivackydef tLDRH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr), IIC_iLoadr,
304198892Srdivacky                "ldrh", "\t$dst, $addr",
305193323Sed                [(set tGPR:$dst, (zextloadi16 t_addrmode_s2:$addr))]>;
306193323Sed
307198090Srdivackylet AddedComplexity = 10 in
308198090Srdivackydef tLDRSB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), IIC_iLoadr,
309198892Srdivacky                 "ldrsb", "\t$dst, $addr",
310193323Sed                 [(set tGPR:$dst, (sextloadi8 t_addrmode_rr:$addr))]>;
311193323Sed
312198090Srdivackylet AddedComplexity = 10 in
313198090Srdivackydef tLDRSH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), IIC_iLoadr,
314198892Srdivacky                 "ldrsh", "\t$dst, $addr",
315193323Sed                 [(set tGPR:$dst, (sextloadi16 t_addrmode_rr:$addr))]>;
316193323Sed
317193323Sedlet canFoldAsLoad = 1 in
318198090Srdivackydef tLDRspi : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), IIC_iLoadi,
319198892Srdivacky                  "ldr", "\t$dst, $addr",
320193323Sed                  [(set tGPR:$dst, (load t_addrmode_sp:$addr))]>;
321193323Sed
322193323Sed// Special instruction for restore. It cannot clobber condition register
323193323Sed// when it's expanded by eliminateCallFramePseudoInstr().
324193323Sedlet canFoldAsLoad = 1, mayLoad = 1 in
325198090Srdivackydef tRestore : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), IIC_iLoadi,
326198892Srdivacky                    "ldr", "\t$dst, $addr", []>;
327193323Sed
328193323Sed// Load tconstpool
329198892Srdivacky// FIXME: Use ldr.n to work around a Darwin assembler bug.
330193323Sedlet canFoldAsLoad = 1 in
331198090Srdivackydef tLDRpci : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr), IIC_iLoadi,
332198892Srdivacky                  "ldr", ".n\t$dst, $addr",
333193323Sed                  [(set tGPR:$dst, (load (ARMWrapper tconstpool:$addr)))]>;
334193323Sed
335193323Sed// Special LDR for loads from non-pc-relative constpools.
336193323Sedlet canFoldAsLoad = 1, mayLoad = 1, isReMaterializable = 1 in
337198090Srdivackydef tLDRcp  : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr), IIC_iLoadi,
338198892Srdivacky                  "ldr", "\t$dst, $addr", []>;
339193323Sed
340198090Srdivackydef tSTR : T1pI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr), IIC_iStorer,
341198892Srdivacky               "str", "\t$src, $addr",
342193323Sed               [(store tGPR:$src, t_addrmode_s4:$addr)]>;
343193323Sed
344198090Srdivackydef tSTRB : T1pI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr), IIC_iStorer,
345198892Srdivacky                 "strb", "\t$src, $addr",
346193323Sed                 [(truncstorei8 tGPR:$src, t_addrmode_s1:$addr)]>;
347193323Sed
348198090Srdivackydef tSTRH : T1pI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr), IIC_iStorer,
349198892Srdivacky                 "strh", "\t$src, $addr",
350193323Sed                 [(truncstorei16 tGPR:$src, t_addrmode_s2:$addr)]>;
351193323Sed
352198090Srdivackydef tSTRspi : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStorei,
353198892Srdivacky                   "str", "\t$src, $addr",
354193323Sed                   [(store tGPR:$src, t_addrmode_sp:$addr)]>;
355193323Sed
356193323Sedlet mayStore = 1 in {
357193323Sed// Special instruction for spill. It cannot clobber condition register
358193323Sed// when it's expanded by eliminateCallFramePseudoInstr().
359198090Srdivackydef tSpill : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStorei,
360198892Srdivacky                  "str", "\t$src, $addr", []>;
361193323Sed}
362193323Sed
363193323Sed//===----------------------------------------------------------------------===//
364193323Sed//  Load / store multiple Instructions.
365193323Sed//
366193323Sed
367198090Srdivacky// These requires base address to be written back or one of the loaded regs.
368198090Srdivackylet mayLoad = 1, hasExtraDefRegAllocReq = 1 in
369198090Srdivackydef tLDM : T1I<(outs),
370198090Srdivacky               (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops),
371198090Srdivacky               IIC_iLoadm,
372198892Srdivacky               "ldm${addr:submode}${p}\t$addr, $wb", []>;
373193323Sed
374198090Srdivackylet mayStore = 1, hasExtraSrcRegAllocReq = 1 in
375198090Srdivackydef tSTM : T1I<(outs),
376198090Srdivacky               (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops),
377198090Srdivacky               IIC_iStorem,
378198892Srdivacky               "stm${addr:submode}${p}\t$addr, $wb", []>;
379193323Sed
380198090Srdivackylet mayLoad = 1, Uses = [SP], Defs = [SP], hasExtraDefRegAllocReq = 1 in
381198090Srdivackydef tPOP : T1I<(outs), (ins pred:$p, reglist:$wb, variable_ops), IIC_Br,
382198892Srdivacky               "pop${p}\t$wb", []>;
383193323Sed
384198090Srdivackylet mayStore = 1, Uses = [SP], Defs = [SP], hasExtraSrcRegAllocReq = 1 in
385198090Srdivackydef tPUSH : T1I<(outs), (ins pred:$p, reglist:$wb, variable_ops), IIC_Br,
386198892Srdivacky                "push${p}\t$wb", []>;
387198090Srdivacky
388193323Sed//===----------------------------------------------------------------------===//
389193323Sed//  Arithmetic Instructions.
390193323Sed//
391193323Sed
392195098Sed// Add with carry register
393198090Srdivackylet isCommutable = 1, Uses = [CPSR] in
394198090Srdivackydef tADC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr,
395198892Srdivacky                 "adc", "\t$dst, $rhs",
396198090Srdivacky                 [(set tGPR:$dst, (adde tGPR:$lhs, tGPR:$rhs))]>;
397193323Sed
398195098Sed// Add immediate
399198090Srdivackydef tADDi3 : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi,
400198892Srdivacky                   "add", "\t$dst, $lhs, $rhs",
401198090Srdivacky                   [(set tGPR:$dst, (add tGPR:$lhs, imm0_7:$rhs))]>;
402193323Sed
403198090Srdivackydef tADDi8 : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi,
404198892Srdivacky                   "add", "\t$dst, $rhs",
405198090Srdivacky                   [(set tGPR:$dst, (add tGPR:$lhs, imm8_255:$rhs))]>;
406193323Sed
407195098Sed// Add register
408198090Srdivackylet isCommutable = 1 in
409198090Srdivackydef tADDrr : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr,
410198892Srdivacky                   "add", "\t$dst, $lhs, $rhs",
411198090Srdivacky                   [(set tGPR:$dst, (add tGPR:$lhs, tGPR:$rhs))]>;
412193323Sed
413194178Sedlet neverHasSideEffects = 1 in
414198090Srdivackydef tADDhirr : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr,
415198892Srdivacky                     "add", "\t$dst, $rhs", []>;
416193323Sed
417195098Sed// And register
418198090Srdivackylet isCommutable = 1 in
419198090Srdivackydef tAND : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr,
420198892Srdivacky                 "and", "\t$dst, $rhs",
421198090Srdivacky                 [(set tGPR:$dst, (and tGPR:$lhs, tGPR:$rhs))]>;
422193323Sed
423195098Sed// ASR immediate
424198090Srdivackydef tASRri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iMOVsi,
425198892Srdivacky                  "asr", "\t$dst, $lhs, $rhs",
426198090Srdivacky                  [(set tGPR:$dst, (sra tGPR:$lhs, (i32 imm:$rhs)))]>;
427193323Sed
428195098Sed// ASR register
429198090Srdivackydef tASRrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr,
430198892Srdivacky                   "asr", "\t$dst, $rhs",
431198090Srdivacky                   [(set tGPR:$dst, (sra tGPR:$lhs, tGPR:$rhs))]>;
432193323Sed
433195098Sed// BIC register
434198090Srdivackydef tBIC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr,
435198892Srdivacky                 "bic", "\t$dst, $rhs",
436198090Srdivacky                 [(set tGPR:$dst, (and tGPR:$lhs, (not tGPR:$rhs)))]>;
437193323Sed
438195098Sed// CMN register
439195098Sedlet Defs = [CPSR] in {
440198090Srdivackydef tCMN : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr,
441198892Srdivacky                "cmn", "\t$lhs, $rhs",
442198090Srdivacky                [(ARMcmp tGPR:$lhs, (ineg tGPR:$rhs))]>;
443198090Srdivackydef tCMNZ : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr,
444198892Srdivacky                 "cmn", "\t$lhs, $rhs",
445198090Srdivacky                 [(ARMcmpZ tGPR:$lhs, (ineg tGPR:$rhs))]>;
446195098Sed}
447193323Sed
448195098Sed// CMP immediate
449195098Sedlet Defs = [CPSR] in {
450198090Srdivackydef tCMPi8 : T1pI<(outs), (ins tGPR:$lhs, i32imm:$rhs), IIC_iCMPi,
451198892Srdivacky                  "cmp", "\t$lhs, $rhs",
452198090Srdivacky                  [(ARMcmp tGPR:$lhs, imm0_255:$rhs)]>;
453198090Srdivackydef tCMPzi8 : T1pI<(outs), (ins tGPR:$lhs, i32imm:$rhs), IIC_iCMPi,
454198892Srdivacky                  "cmp", "\t$lhs, $rhs",
455198090Srdivacky                  [(ARMcmpZ tGPR:$lhs, imm0_255:$rhs)]>;
456193323Sed
457195098Sed}
458195098Sed
459195098Sed// CMP register
460195098Sedlet Defs = [CPSR] in {
461198090Srdivackydef tCMPr : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr,
462198892Srdivacky                 "cmp", "\t$lhs, $rhs",
463198090Srdivacky                 [(ARMcmp tGPR:$lhs, tGPR:$rhs)]>;
464198090Srdivackydef tCMPzr : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr,
465198892Srdivacky                  "cmp", "\t$lhs, $rhs",
466198090Srdivacky                  [(ARMcmpZ tGPR:$lhs, tGPR:$rhs)]>;
467198090Srdivacky
468198090Srdivackydef tCMPhir : T1pI<(outs), (ins GPR:$lhs, GPR:$rhs), IIC_iCMPr,
469198892Srdivacky                   "cmp", "\t$lhs, $rhs", []>;
470198090Srdivackydef tCMPzhir : T1pI<(outs), (ins GPR:$lhs, GPR:$rhs), IIC_iCMPr,
471198892Srdivacky                    "cmp", "\t$lhs, $rhs", []>;
472195098Sed}
473193323Sed
474193323Sed
475195098Sed// XOR register
476198090Srdivackylet isCommutable = 1 in
477198090Srdivackydef tEOR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr,
478198892Srdivacky                 "eor", "\t$dst, $rhs",
479198090Srdivacky                 [(set tGPR:$dst, (xor tGPR:$lhs, tGPR:$rhs))]>;
480193323Sed
481195098Sed// LSL immediate
482198090Srdivackydef tLSLri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iMOVsi,
483198892Srdivacky                  "lsl", "\t$dst, $lhs, $rhs",
484198090Srdivacky                  [(set tGPR:$dst, (shl tGPR:$lhs, (i32 imm:$rhs)))]>;
485193323Sed
486195098Sed// LSL register
487198090Srdivackydef tLSLrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr,
488198892Srdivacky                   "lsl", "\t$dst, $rhs",
489198090Srdivacky                   [(set tGPR:$dst, (shl tGPR:$lhs, tGPR:$rhs))]>;
490193323Sed
491195098Sed// LSR immediate
492198090Srdivackydef tLSRri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iMOVsi,
493198892Srdivacky                  "lsr", "\t$dst, $lhs, $rhs",
494198090Srdivacky                  [(set tGPR:$dst, (srl tGPR:$lhs, (i32 imm:$rhs)))]>;
495193323Sed
496195098Sed// LSR register
497198090Srdivackydef tLSRrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr,
498198892Srdivacky                   "lsr", "\t$dst, $rhs",
499198090Srdivacky                   [(set tGPR:$dst, (srl tGPR:$lhs, tGPR:$rhs))]>;
500193323Sed
501195098Sed// move register
502198090Srdivackydef tMOVi8 : T1sI<(outs tGPR:$dst), (ins i32imm:$src), IIC_iMOVi,
503198892Srdivacky                  "mov", "\t$dst, $src",
504198090Srdivacky                  [(set tGPR:$dst, imm0_255:$src)]>;
505193323Sed
506193323Sed// TODO: A7-73: MOV(2) - mov setting flag.
507193323Sed
508193323Sed
509194178Sedlet neverHasSideEffects = 1 in {
510198090Srdivacky// FIXME: Make this predicable.
511198090Srdivackydef tMOVr       : T1I<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr,
512198892Srdivacky                      "mov\t$dst, $src", []>;
513198090Srdivackylet Defs = [CPSR] in
514198090Srdivackydef tMOVSr      : T1I<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr,
515198892Srdivacky                       "movs\t$dst, $src", []>;
516198090Srdivacky
517198090Srdivacky// FIXME: Make these predicable.
518198090Srdivackydef tMOVgpr2tgpr : T1I<(outs tGPR:$dst), (ins GPR:$src), IIC_iMOVr,
519198892Srdivacky                       "mov\t$dst, $src", []>;
520198090Srdivackydef tMOVtgpr2gpr : T1I<(outs GPR:$dst), (ins tGPR:$src), IIC_iMOVr,
521198892Srdivacky                       "mov\t$dst, $src", []>;
522198090Srdivackydef tMOVgpr2gpr  : T1I<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVr,
523198892Srdivacky                       "mov\t$dst, $src", []>;
524194178Sed} // neverHasSideEffects
525193323Sed
526195098Sed// multiply register
527198090Srdivackylet isCommutable = 1 in
528198090Srdivackydef tMUL : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMUL32,
529198892Srdivacky                 "mul", "\t$dst, $rhs",
530198090Srdivacky                 [(set tGPR:$dst, (mul tGPR:$lhs, tGPR:$rhs))]>;
531193323Sed
532195098Sed// move inverse register
533198090Srdivackydef tMVN : T1sI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr,
534198892Srdivacky                "mvn", "\t$dst, $src",
535198090Srdivacky                [(set tGPR:$dst, (not tGPR:$src))]>;
536193323Sed
537195098Sed// bitwise or register
538198090Srdivackylet isCommutable = 1 in
539198090Srdivackydef tORR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),  IIC_iALUr,
540198892Srdivacky                 "orr", "\t$dst, $rhs",
541198090Srdivacky                 [(set tGPR:$dst, (or tGPR:$lhs, tGPR:$rhs))]>;
542193323Sed
543195098Sed// swaps
544198090Srdivackydef tREV : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr,
545198892Srdivacky                "rev", "\t$dst, $src",
546198090Srdivacky                [(set tGPR:$dst, (bswap tGPR:$src))]>,
547198090Srdivacky                Requires<[IsThumb1Only, HasV6]>;
548193323Sed
549198090Srdivackydef tREV16 : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr,
550198892Srdivacky                  "rev16", "\t$dst, $src",
551198090Srdivacky             [(set tGPR:$dst,
552198090Srdivacky                   (or (and (srl tGPR:$src, (i32 8)), 0xFF),
553198090Srdivacky                       (or (and (shl tGPR:$src, (i32 8)), 0xFF00),
554198090Srdivacky                           (or (and (srl tGPR:$src, (i32 8)), 0xFF0000),
555198090Srdivacky                               (and (shl tGPR:$src, (i32 8)), 0xFF000000)))))]>,
556198090Srdivacky                Requires<[IsThumb1Only, HasV6]>;
557193323Sed
558198090Srdivackydef tREVSH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr,
559198892Srdivacky                  "revsh", "\t$dst, $src",
560198090Srdivacky                  [(set tGPR:$dst,
561198090Srdivacky                        (sext_inreg
562198090Srdivacky                          (or (srl (and tGPR:$src, 0xFF00), (i32 8)),
563198090Srdivacky                              (shl tGPR:$src, (i32 8))), i16))]>,
564198090Srdivacky                  Requires<[IsThumb1Only, HasV6]>;
565193323Sed
566195098Sed// rotate right register
567198090Srdivackydef tROR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr,
568198892Srdivacky                 "ror", "\t$dst, $rhs",
569198090Srdivacky                 [(set tGPR:$dst, (rotr tGPR:$lhs, tGPR:$rhs))]>;
570193323Sed
571198090Srdivacky// negate register
572198090Srdivackydef tRSB : T1sI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iALUi,
573198892Srdivacky                "rsb", "\t$dst, $src, #0",
574198090Srdivacky                [(set tGPR:$dst, (ineg tGPR:$src))]>;
575198090Srdivacky
576195098Sed// Subtract with carry register
577198090Srdivackylet Uses = [CPSR] in
578198090Srdivackydef tSBC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr,
579198892Srdivacky                 "sbc", "\t$dst, $rhs",
580198090Srdivacky                 [(set tGPR:$dst, (sube tGPR:$lhs, tGPR:$rhs))]>;
581193323Sed
582195098Sed// Subtract immediate
583198090Srdivackydef tSUBi3 : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi,
584198892Srdivacky                  "sub", "\t$dst, $lhs, $rhs",
585198090Srdivacky                  [(set tGPR:$dst, (add tGPR:$lhs, imm0_7_neg:$rhs))]>;
586193323Sed
587198090Srdivackydef tSUBi8 : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi,
588198892Srdivacky                   "sub", "\t$dst, $rhs",
589198090Srdivacky                   [(set tGPR:$dst, (add tGPR:$lhs, imm8_255_neg:$rhs))]>;
590193323Sed
591195098Sed// subtract register
592198090Srdivackydef tSUBrr : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr,
593198892Srdivacky                  "sub", "\t$dst, $lhs, $rhs",
594198090Srdivacky                  [(set tGPR:$dst, (sub tGPR:$lhs, tGPR:$rhs))]>;
595193323Sed
596195098Sed// TODO: A7-96: STMIA - store multiple.
597195098Sed
598195098Sed// sign-extend byte
599198090Srdivackydef tSXTB  : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr,
600198892Srdivacky                  "sxtb", "\t$dst, $src",
601198090Srdivacky                  [(set tGPR:$dst, (sext_inreg tGPR:$src, i8))]>,
602198090Srdivacky                  Requires<[IsThumb1Only, HasV6]>;
603195098Sed
604195098Sed// sign-extend short
605198090Srdivackydef tSXTH  : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr,
606198892Srdivacky                  "sxth", "\t$dst, $src",
607198090Srdivacky                  [(set tGPR:$dst, (sext_inreg tGPR:$src, i16))]>,
608198090Srdivacky                  Requires<[IsThumb1Only, HasV6]>;
609193323Sed
610195098Sed// test
611195098Sedlet isCommutable = 1, Defs = [CPSR] in
612198090Srdivackydef tTST  : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr,
613198892Srdivacky                 "tst", "\t$lhs, $rhs",
614198090Srdivacky                 [(ARMcmpZ (and tGPR:$lhs, tGPR:$rhs), 0)]>;
615193323Sed
616195098Sed// zero-extend byte
617198090Srdivackydef tUXTB  : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr,
618198892Srdivacky                  "uxtb", "\t$dst, $src",
619198090Srdivacky                  [(set tGPR:$dst, (and tGPR:$src, 0xFF))]>,
620198090Srdivacky                  Requires<[IsThumb1Only, HasV6]>;
621195098Sed
622195098Sed// zero-extend short
623198090Srdivackydef tUXTH  : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr,
624198892Srdivacky                  "uxth", "\t$dst, $src",
625198090Srdivacky                  [(set tGPR:$dst, (and tGPR:$src, 0xFFFF))]>,
626198090Srdivacky                  Requires<[IsThumb1Only, HasV6]>;
627193323Sed
628193323Sed
629193323Sed// Conditional move tMOVCCr - Used to implement the Thumb SELECT_CC DAG operation.
630198892Srdivacky// Expanded after instruction selection into a branch sequence.
631198892Srdivackylet usesCustomInserter = 1 in  // Expanded after instruction selection.
632198090Srdivacky  def tMOVCCr_pseudo :
633193323Sed  PseudoInst<(outs tGPR:$dst), (ins tGPR:$false, tGPR:$true, pred:$cc),
634198090Srdivacky              NoItinerary, "@ tMOVCCr $cc",
635198090Srdivacky             [/*(set tGPR:$dst, (ARMcmov tGPR:$false, tGPR:$true, imm:$cc))*/]>;
636193323Sed
637198090Srdivacky
638198090Srdivacky// 16-bit movcc in IT blocks for Thumb2.
639198090Srdivackydef tMOVCCr : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iCMOVr,
640198892Srdivacky                    "mov", "\t$dst, $rhs", []>;
641198090Srdivacky
642198090Srdivackydef tMOVCCi : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs), IIC_iCMOVi,
643198892Srdivacky                    "mov", "\t$dst, $rhs", []>;
644198090Srdivacky
645193323Sed// tLEApcrel - Load a pc-relative address into a register without offending the
646193323Sed// assembler.
647198090Srdivackydef tLEApcrel : T1I<(outs tGPR:$dst), (ins i32imm:$label, pred:$p), IIC_iALUi,
648198892Srdivacky                    "adr$p\t$dst, #$label", []>;
649193323Sed
650198090Srdivackydef tLEApcrelJT : T1I<(outs tGPR:$dst),
651198090Srdivacky                      (ins i32imm:$label, nohash_imm:$id, pred:$p),
652198892Srdivacky                      IIC_iALUi, "adr$p\t$dst, #${label}_${id}", []>;
653193323Sed
654193323Sed//===----------------------------------------------------------------------===//
655193323Sed// TLS Instructions
656193323Sed//
657193323Sed
658193323Sed// __aeabi_read_tp preserves the registers r1-r3.
659193323Sedlet isCall = 1,
660193323Sed  Defs = [R0, LR] in {
661198090Srdivacky  def tTPsoft  : TIx2<(outs), (ins), IIC_Br,
662198892Srdivacky               "bl\t__aeabi_read_tp",
663193323Sed               [(set R0, ARMthread_pointer)]>;
664193323Sed}
665193323Sed
666193323Sed//===----------------------------------------------------------------------===//
667193323Sed// Non-Instruction Patterns
668193323Sed//
669193323Sed
670198090Srdivacky// Add with carry
671198090Srdivackydef : T1Pat<(addc   tGPR:$lhs, imm0_7:$rhs),
672198090Srdivacky            (tADDi3 tGPR:$lhs, imm0_7:$rhs)>;
673198090Srdivackydef : T1Pat<(addc   tGPR:$lhs, imm8_255:$rhs),
674198090Srdivacky            (tADDi8 tGPR:$lhs, imm8_255:$rhs)>;
675198090Srdivackydef : T1Pat<(addc   tGPR:$lhs, tGPR:$rhs),
676198090Srdivacky            (tADDrr tGPR:$lhs, tGPR:$rhs)>;
677198090Srdivacky
678198090Srdivacky// Subtract with carry
679198090Srdivackydef : T1Pat<(addc   tGPR:$lhs, imm0_7_neg:$rhs),
680198090Srdivacky            (tSUBi3 tGPR:$lhs, imm0_7_neg:$rhs)>;
681198090Srdivackydef : T1Pat<(addc   tGPR:$lhs, imm8_255_neg:$rhs),
682198090Srdivacky            (tSUBi8 tGPR:$lhs, imm8_255_neg:$rhs)>;
683198090Srdivackydef : T1Pat<(subc   tGPR:$lhs, tGPR:$rhs),
684198090Srdivacky            (tSUBrr tGPR:$lhs, tGPR:$rhs)>;
685198090Srdivacky
686193323Sed// ConstantPool, GlobalAddress
687198090Srdivackydef : T1Pat<(ARMWrapper  tglobaladdr :$dst), (tLEApcrel tglobaladdr :$dst)>;
688198090Srdivackydef : T1Pat<(ARMWrapper  tconstpool  :$dst), (tLEApcrel tconstpool  :$dst)>;
689193323Sed
690193323Sed// JumpTable
691198090Srdivackydef : T1Pat<(ARMWrapperJT tjumptable:$dst, imm:$id),
692198090Srdivacky            (tLEApcrelJT tjumptable:$dst, imm:$id)>;
693193323Sed
694193323Sed// Direct calls
695198090Srdivackydef : T1Pat<(ARMtcall texternalsym:$func), (tBL texternalsym:$func)>,
696198090Srdivacky      Requires<[IsThumb, IsNotDarwin]>;
697198090Srdivackydef : T1Pat<(ARMtcall texternalsym:$func), (tBLr9 texternalsym:$func)>,
698198090Srdivacky      Requires<[IsThumb, IsDarwin]>;
699193323Sed
700198090Srdivackydef : Tv5Pat<(ARMcall texternalsym:$func), (tBLXi texternalsym:$func)>,
701198090Srdivacky      Requires<[IsThumb, HasV5T, IsNotDarwin]>;
702198090Srdivackydef : Tv5Pat<(ARMcall texternalsym:$func), (tBLXi_r9 texternalsym:$func)>,
703198090Srdivacky      Requires<[IsThumb, HasV5T, IsDarwin]>;
704198090Srdivacky
705193323Sed// Indirect calls to ARM routines
706198090Srdivackydef : Tv5Pat<(ARMcall GPR:$dst), (tBLXr GPR:$dst)>,
707198090Srdivacky      Requires<[IsThumb, HasV5T, IsNotDarwin]>;
708198090Srdivackydef : Tv5Pat<(ARMcall GPR:$dst), (tBLXr_r9 GPR:$dst)>,
709198090Srdivacky      Requires<[IsThumb, HasV5T, IsDarwin]>;
710193323Sed
711193323Sed// zextload i1 -> zextload i8
712195340Seddef : T1Pat<(zextloadi1 t_addrmode_s1:$addr),
713195340Sed            (tLDRB t_addrmode_s1:$addr)>;
714193323Sed
715193323Sed// extload -> zextload
716195340Seddef : T1Pat<(extloadi1  t_addrmode_s1:$addr),  (tLDRB t_addrmode_s1:$addr)>;
717195340Seddef : T1Pat<(extloadi8  t_addrmode_s1:$addr),  (tLDRB t_addrmode_s1:$addr)>;
718195340Seddef : T1Pat<(extloadi16 t_addrmode_s2:$addr),  (tLDRH t_addrmode_s2:$addr)>;
719193323Sed
720198090Srdivacky// If it's impossible to use [r,r] address mode for sextload, select to
721198090Srdivacky// ldr{b|h} + sxt{b|h} instead.
722198090Srdivackydef : T1Pat<(sextloadi8 t_addrmode_s1:$addr),
723198090Srdivacky            (tSXTB (tLDRB t_addrmode_s1:$addr))>,
724198090Srdivacky      Requires<[IsThumb1Only, HasV6]>;
725198090Srdivackydef : T1Pat<(sextloadi16 t_addrmode_s2:$addr),
726198090Srdivacky            (tSXTH (tLDRH t_addrmode_s2:$addr))>,
727198090Srdivacky      Requires<[IsThumb1Only, HasV6]>;
728198090Srdivacky
729198090Srdivackydef : T1Pat<(sextloadi8 t_addrmode_s1:$addr),
730198090Srdivacky            (tASRri (tLSLri (tLDRB t_addrmode_s1:$addr), 24), 24)>;
731198090Srdivackydef : T1Pat<(sextloadi16 t_addrmode_s1:$addr),
732198090Srdivacky            (tASRri (tLSLri (tLDRH t_addrmode_s1:$addr), 16), 16)>;
733198090Srdivacky
734193323Sed// Large immediate handling.
735193323Sed
736193323Sed// Two piece imms.
737195098Seddef : T1Pat<(i32 thumb_immshifted:$src),
738195098Sed            (tLSLri (tMOVi8 (thumb_immshifted_val imm:$src)),
739195098Sed                    (thumb_immshifted_shamt imm:$src))>;
740193323Sed
741195098Seddef : T1Pat<(i32 imm0_255_comp:$src),
742195098Sed            (tMVN (tMOVi8 (imm_comp_XFORM imm:$src)))>;
743