1 //===- ARMInstrThumb2.td - Thumb2 support for ARM -------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file describes the Thumb2 instruction set.
12 //===----------------------------------------------------------------------===//
14 // IT block predicate field
15 def it_pred : Operand<i32> {
16 let PrintMethod = "printPredicateOperand";
19 // IT block condition mask
20 def it_mask : Operand<i32> {
21 let PrintMethod = "printThumbITMask";
24 // Table branch address
25 def tb_addrmode : Operand<i32> {
26 let PrintMethod = "printTBAddrMode";
29 // Shifted operands. No register controlled shifts for Thumb2.
30 // Note: We do not support rrx shifted operands yet.
31 def t2_so_reg : Operand<i32>, // reg imm
32 ComplexPattern<i32, 2, "SelectT2ShifterOperandReg",
34 let PrintMethod = "printT2SOOperand";
35 let MIOperandInfo = (ops GPR, i32imm);
38 // t2_so_imm_not_XFORM - Return the complement of a t2_so_imm value
39 def t2_so_imm_not_XFORM : SDNodeXForm<imm, [{
40 return CurDAG->getTargetConstant(~((uint32_t)N->getZExtValue()), MVT::i32);
43 // t2_so_imm_neg_XFORM - Return the negation of a t2_so_imm value
44 def t2_so_imm_neg_XFORM : SDNodeXForm<imm, [{
45 return CurDAG->getTargetConstant(-((int)N->getZExtValue()), MVT::i32);
48 // t2_so_imm - Match a 32-bit immediate operand, which is an
49 // 8-bit immediate rotated by an arbitrary number of bits, or an 8-bit
50 // immediate splatted into multiple bytes of the word. t2_so_imm values are
51 // represented in the imm field in the same 12-bit form that they are encoded
52 // into t2_so_imm instructions: the 8-bit immediate is the least significant
53 // bits [bits 0-7], the 4-bit shift/splat amount is the next 4 bits [bits 8-11].
54 def t2_so_imm : Operand<i32>,
56 return ARM_AM::getT2SOImmVal((uint32_t)N->getZExtValue()) != -1;
59 // t2_so_imm_not - Match an immediate that is a complement
61 def t2_so_imm_not : Operand<i32>,
63 return ARM_AM::getT2SOImmVal(~((uint32_t)N->getZExtValue())) != -1;
64 }], t2_so_imm_not_XFORM>;
66 // t2_so_imm_neg - Match an immediate that is a negation of a t2_so_imm.
67 def t2_so_imm_neg : Operand<i32>,
69 return ARM_AM::getT2SOImmVal(-((int)N->getZExtValue())) != -1;
70 }], t2_so_imm_neg_XFORM>;
72 // Break t2_so_imm's up into two pieces. This handles immediates with up to 16
73 // bits set in them. This uses t2_so_imm2part to match and t2_so_imm2part_[12]
74 // to get the first/second pieces.
75 def t2_so_imm2part : Operand<i32>,
77 return ARM_AM::isT2SOImmTwoPartVal((unsigned)N->getZExtValue());
81 def t2_so_imm2part_1 : SDNodeXForm<imm, [{
82 unsigned V = ARM_AM::getT2SOImmTwoPartFirst((unsigned)N->getZExtValue());
83 return CurDAG->getTargetConstant(V, MVT::i32);
86 def t2_so_imm2part_2 : SDNodeXForm<imm, [{
87 unsigned V = ARM_AM::getT2SOImmTwoPartSecond((unsigned)N->getZExtValue());
88 return CurDAG->getTargetConstant(V, MVT::i32);
91 def t2_so_neg_imm2part : Operand<i32>, PatLeaf<(imm), [{
92 return ARM_AM::isT2SOImmTwoPartVal(-(int)N->getZExtValue());
96 def t2_so_neg_imm2part_1 : SDNodeXForm<imm, [{
97 unsigned V = ARM_AM::getT2SOImmTwoPartFirst(-(int)N->getZExtValue());
98 return CurDAG->getTargetConstant(V, MVT::i32);
101 def t2_so_neg_imm2part_2 : SDNodeXForm<imm, [{
102 unsigned V = ARM_AM::getT2SOImmTwoPartSecond(-(int)N->getZExtValue());
103 return CurDAG->getTargetConstant(V, MVT::i32);
106 /// imm1_31 predicate - True if the 32-bit immediate is in the range [1,31].
107 def imm1_31 : PatLeaf<(i32 imm), [{
108 return (int32_t)N->getZExtValue() >= 1 && (int32_t)N->getZExtValue() < 32;
111 /// imm0_4095 predicate - True if the 32-bit immediate is in the range [0.4095].
112 def imm0_4095 : Operand<i32>,
113 PatLeaf<(i32 imm), [{
114 return (uint32_t)N->getZExtValue() < 4096;
117 def imm0_4095_neg : PatLeaf<(i32 imm), [{
118 return (uint32_t)(-N->getZExtValue()) < 4096;
121 def imm0_255_neg : PatLeaf<(i32 imm), [{
122 return (uint32_t)(-N->getZExtValue()) < 255;
125 // Define Thumb2 specific addressing modes.
127 // t2addrmode_imm12 := reg + imm12
128 def t2addrmode_imm12 : Operand<i32>,
129 ComplexPattern<i32, 2, "SelectT2AddrModeImm12", []> {
130 let PrintMethod = "printT2AddrModeImm12Operand";
131 let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
134 // t2addrmode_imm8 := reg - imm8
135 def t2addrmode_imm8 : Operand<i32>,
136 ComplexPattern<i32, 2, "SelectT2AddrModeImm8", []> {
137 let PrintMethod = "printT2AddrModeImm8Operand";
138 let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
141 def t2am_imm8_offset : Operand<i32>,
142 ComplexPattern<i32, 1, "SelectT2AddrModeImm8Offset", []>{
143 let PrintMethod = "printT2AddrModeImm8OffsetOperand";
146 // t2addrmode_imm8s4 := reg +/- (imm8 << 2)
147 def t2addrmode_imm8s4 : Operand<i32>,
148 ComplexPattern<i32, 2, "SelectT2AddrModeImm8s4", []> {
149 let PrintMethod = "printT2AddrModeImm8s4Operand";
150 let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
153 // t2addrmode_so_reg := reg + (reg << imm2)
154 def t2addrmode_so_reg : Operand<i32>,
155 ComplexPattern<i32, 3, "SelectT2AddrModeSoReg", []> {
156 let PrintMethod = "printT2AddrModeSoRegOperand";
157 let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);
161 //===----------------------------------------------------------------------===//
162 // Multiclass helpers...
165 /// T2I_un_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a
166 /// unary operation that produces a value. These are predicable and can be
167 /// changed to modify CPSR.
168 multiclass T2I_un_irs<string opc, PatFrag opnode, bit Cheap = 0, bit ReMat = 0>{
170 def i : T2sI<(outs GPR:$dst), (ins t2_so_imm:$src), IIC_iMOVi,
172 [(set GPR:$dst, (opnode t2_so_imm:$src))]> {
173 let isAsCheapAsAMove = Cheap;
174 let isReMaterializable = ReMat;
177 def r : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVr,
178 opc, ".w\t$dst, $src",
179 [(set GPR:$dst, (opnode GPR:$src))]>;
181 def s : T2I<(outs GPR:$dst), (ins t2_so_reg:$src), IIC_iMOVsi,
182 opc, ".w\t$dst, $src",
183 [(set GPR:$dst, (opnode t2_so_reg:$src))]>;
186 /// T2I_bin_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a
187 // binary operation that produces a value. These are predicable and can be
188 /// changed to modify CPSR.
189 multiclass T2I_bin_irs<string opc, PatFrag opnode,
190 bit Commutable = 0, string wide =""> {
192 def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi,
193 opc, "\t$dst, $lhs, $rhs",
194 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>;
196 def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr,
197 opc, !strconcat(wide, "\t$dst, $lhs, $rhs"),
198 [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]> {
199 let isCommutable = Commutable;
202 def rs : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi,
203 opc, !strconcat(wide, "\t$dst, $lhs, $rhs"),
204 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>;
207 /// T2I_bin_w_irs - Same as T2I_bin_irs except these operations need
208 // the ".w" prefix to indicate that they are wide.
209 multiclass T2I_bin_w_irs<string opc, PatFrag opnode, bit Commutable = 0> :
210 T2I_bin_irs<opc, opnode, Commutable, ".w">;
212 /// T2I_rbin_is - Same as T2I_bin_irs except the order of operands are
213 /// reversed. It doesn't define the 'rr' form since it's handled by its
214 /// T2I_bin_irs counterpart.
215 multiclass T2I_rbin_is<string opc, PatFrag opnode> {
217 def ri : T2I<(outs GPR:$dst), (ins GPR:$rhs, t2_so_imm:$lhs), IIC_iALUi,
218 opc, ".w\t$dst, $rhs, $lhs",
219 [(set GPR:$dst, (opnode t2_so_imm:$lhs, GPR:$rhs))]>;
221 def rs : T2I<(outs GPR:$dst), (ins GPR:$rhs, t2_so_reg:$lhs), IIC_iALUsi,
222 opc, "\t$dst, $rhs, $lhs",
223 [(set GPR:$dst, (opnode t2_so_reg:$lhs, GPR:$rhs))]>;
226 /// T2I_bin_s_irs - Similar to T2I_bin_irs except it sets the 's' bit so the
227 /// instruction modifies the CPSR register.
228 let Defs = [CPSR] in {
229 multiclass T2I_bin_s_irs<string opc, PatFrag opnode, bit Commutable = 0> {
231 def ri : T2I<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi,
232 !strconcat(opc, "s"), ".w\t$dst, $lhs, $rhs",
233 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>;
235 def rr : T2I<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr,
236 !strconcat(opc, "s"), ".w\t$dst, $lhs, $rhs",
237 [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]> {
238 let isCommutable = Commutable;
241 def rs : T2I<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi,
242 !strconcat(opc, "s"), ".w\t$dst, $lhs, $rhs",
243 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>;
247 /// T2I_bin_ii12rs - Defines a set of (op reg, {so_imm|imm0_4095|r|so_reg})
248 /// patterns for a binary operation that produces a value.
249 multiclass T2I_bin_ii12rs<string opc, PatFrag opnode, bit Commutable = 0> {
251 def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi,
252 opc, ".w\t$dst, $lhs, $rhs",
253 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>;
255 def ri12 : T2sI<(outs GPR:$dst), (ins GPR:$lhs, imm0_4095:$rhs), IIC_iALUi,
256 !strconcat(opc, "w"), "\t$dst, $lhs, $rhs",
257 [(set GPR:$dst, (opnode GPR:$lhs, imm0_4095:$rhs))]>;
259 def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr,
260 opc, ".w\t$dst, $lhs, $rhs",
261 [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]> {
262 let isCommutable = Commutable;
265 def rs : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi,
266 opc, ".w\t$dst, $lhs, $rhs",
267 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>;
270 /// T2I_adde_sube_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns
271 /// for a binary operation that produces a value and use and define the carry
272 /// bit. It's not predicable.
273 let Uses = [CPSR] in {
274 multiclass T2I_adde_sube_irs<string opc, PatFrag opnode, bit Commutable = 0> {
276 def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi,
277 opc, "\t$dst, $lhs, $rhs",
278 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>,
279 Requires<[IsThumb2, CarryDefIsUnused]>;
281 def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr,
282 opc, ".w\t$dst, $lhs, $rhs",
283 [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>,
284 Requires<[IsThumb2, CarryDefIsUnused]> {
285 let isCommutable = Commutable;
288 def rs : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi,
289 opc, ".w\t$dst, $lhs, $rhs",
290 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>,
291 Requires<[IsThumb2, CarryDefIsUnused]>;
292 // Carry setting variants
294 def Sri : T2XI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi,
295 !strconcat(opc, "s\t$dst, $lhs, $rhs"),
296 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>,
297 Requires<[IsThumb2, CarryDefIsUsed]> {
301 def Srr : T2XI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr,
302 !strconcat(opc, "s.w\t$dst, $lhs, $rhs"),
303 [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>,
304 Requires<[IsThumb2, CarryDefIsUsed]> {
306 let isCommutable = Commutable;
309 def Srs : T2XI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi,
310 !strconcat(opc, "s.w\t$dst, $lhs, $rhs"),
311 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>,
312 Requires<[IsThumb2, CarryDefIsUsed]> {
318 /// T2I_rbin_s_is - Same as T2I_rbin_is except sets 's' bit.
319 let Defs = [CPSR] in {
320 multiclass T2I_rbin_s_is<string opc, PatFrag opnode> {
322 def ri : T2XI<(outs GPR:$dst), (ins GPR:$rhs, t2_so_imm:$lhs, cc_out:$s),
324 !strconcat(opc, "${s}.w\t$dst, $rhs, $lhs"),
325 [(set GPR:$dst, (opnode t2_so_imm:$lhs, GPR:$rhs))]>;
327 def rs : T2XI<(outs GPR:$dst), (ins GPR:$rhs, t2_so_reg:$lhs, cc_out:$s),
329 !strconcat(opc, "${s}\t$dst, $rhs, $lhs"),
330 [(set GPR:$dst, (opnode t2_so_reg:$lhs, GPR:$rhs))]>;
334 /// T2I_sh_ir - Defines a set of (op reg, {so_imm|r}) patterns for a shift /
335 // rotate operation that produces a value.
336 multiclass T2I_sh_ir<string opc, PatFrag opnode> {
338 def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs), IIC_iMOVsi,
339 opc, ".w\t$dst, $lhs, $rhs",
340 [(set GPR:$dst, (opnode GPR:$lhs, imm1_31:$rhs))]>;
342 def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iMOVsr,
343 opc, ".w\t$dst, $lhs, $rhs",
344 [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>;
347 /// T2I_cmp_is - Defines a set of (op r, {so_imm|r|so_reg}) cmp / test
348 /// patterns. Similar to T2I_bin_irs except the instruction does not produce
349 /// a explicit result, only implicitly set CPSR.
350 let Defs = [CPSR] in {
351 multiclass T2I_cmp_is<string opc, PatFrag opnode> {
353 def ri : T2I<(outs), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iCMPi,
354 opc, ".w\t$lhs, $rhs",
355 [(opnode GPR:$lhs, t2_so_imm:$rhs)]>;
357 def rr : T2I<(outs), (ins GPR:$lhs, GPR:$rhs), IIC_iCMPr,
358 opc, ".w\t$lhs, $rhs",
359 [(opnode GPR:$lhs, GPR:$rhs)]>;
361 def rs : T2I<(outs), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iCMPsi,
362 opc, ".w\t$lhs, $rhs",
363 [(opnode GPR:$lhs, t2_so_reg:$rhs)]>;
367 /// T2I_ld - Defines a set of (op r, {imm12|imm8|so_reg}) load patterns.
368 multiclass T2I_ld<string opc, PatFrag opnode> {
369 def i12 : T2Ii12<(outs GPR:$dst), (ins t2addrmode_imm12:$addr), IIC_iLoadi,
370 opc, ".w\t$dst, $addr",
371 [(set GPR:$dst, (opnode t2addrmode_imm12:$addr))]>;
372 def i8 : T2Ii8 <(outs GPR:$dst), (ins t2addrmode_imm8:$addr), IIC_iLoadi,
373 opc, "\t$dst, $addr",
374 [(set GPR:$dst, (opnode t2addrmode_imm8:$addr))]>;
375 def s : T2Iso <(outs GPR:$dst), (ins t2addrmode_so_reg:$addr), IIC_iLoadr,
376 opc, ".w\t$dst, $addr",
377 [(set GPR:$dst, (opnode t2addrmode_so_reg:$addr))]>;
378 def pci : T2Ipc <(outs GPR:$dst), (ins i32imm:$addr), IIC_iLoadi,
379 opc, ".w\t$dst, $addr",
380 [(set GPR:$dst, (opnode (ARMWrapper tconstpool:$addr)))]> {
381 let isReMaterializable = 1;
385 /// T2I_st - Defines a set of (op r, {imm12|imm8|so_reg}) store patterns.
386 multiclass T2I_st<string opc, PatFrag opnode> {
387 def i12 : T2Ii12<(outs), (ins GPR:$src, t2addrmode_imm12:$addr), IIC_iStorei,
388 opc, ".w\t$src, $addr",
389 [(opnode GPR:$src, t2addrmode_imm12:$addr)]>;
390 def i8 : T2Ii8 <(outs), (ins GPR:$src, t2addrmode_imm8:$addr), IIC_iStorei,
391 opc, "\t$src, $addr",
392 [(opnode GPR:$src, t2addrmode_imm8:$addr)]>;
393 def s : T2Iso <(outs), (ins GPR:$src, t2addrmode_so_reg:$addr), IIC_iStorer,
394 opc, ".w\t$src, $addr",
395 [(opnode GPR:$src, t2addrmode_so_reg:$addr)]>;
398 /// T2I_picld - Defines the PIC load pattern.
399 class T2I_picld<string opc, PatFrag opnode> :
400 T2I<(outs GPR:$dst), (ins addrmodepc:$addr), IIC_iLoadi,
401 !strconcat("\n${addr:label}:\n\t", opc), "\t$dst, $addr",
402 [(set GPR:$dst, (opnode addrmodepc:$addr))]>;
404 /// T2I_picst - Defines the PIC store pattern.
405 class T2I_picst<string opc, PatFrag opnode> :
406 T2I<(outs), (ins GPR:$src, addrmodepc:$addr), IIC_iStorer,
407 !strconcat("\n${addr:label}:\n\t", opc), "\t$src, $addr",
408 [(opnode GPR:$src, addrmodepc:$addr)]>;
411 /// T2I_unary_rrot - A unary operation with two forms: one whose operand is a
412 /// register and one whose operand is a register rotated by 8/16/24.
413 multiclass T2I_unary_rrot<string opc, PatFrag opnode> {
414 def r : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
415 opc, ".w\t$dst, $src",
416 [(set GPR:$dst, (opnode GPR:$src))]>;
417 def r_rot : T2I<(outs GPR:$dst), (ins GPR:$src, i32imm:$rot), IIC_iUNAsi,
418 opc, ".w\t$dst, $src, ror $rot",
419 [(set GPR:$dst, (opnode (rotr GPR:$src, rot_imm:$rot)))]>;
422 /// T2I_bin_rrot - A binary operation with two forms: one whose operand is a
423 /// register and one whose operand is a register rotated by 8/16/24.
424 multiclass T2I_bin_rrot<string opc, PatFrag opnode> {
425 def rr : T2I<(outs GPR:$dst), (ins GPR:$LHS, GPR:$RHS), IIC_iALUr,
426 opc, "\t$dst, $LHS, $RHS",
427 [(set GPR:$dst, (opnode GPR:$LHS, GPR:$RHS))]>;
428 def rr_rot : T2I<(outs GPR:$dst), (ins GPR:$LHS, GPR:$RHS, i32imm:$rot),
429 IIC_iALUsr, opc, "\t$dst, $LHS, $RHS, ror $rot",
430 [(set GPR:$dst, (opnode GPR:$LHS,
431 (rotr GPR:$RHS, rot_imm:$rot)))]>;
434 //===----------------------------------------------------------------------===//
436 //===----------------------------------------------------------------------===//
438 //===----------------------------------------------------------------------===//
439 // Miscellaneous Instructions.
442 // LEApcrel - Load a pc-relative address into a register without offending the
444 def t2LEApcrel : T2XI<(outs GPR:$dst), (ins i32imm:$label, pred:$p), IIC_iALUi,
445 "adr$p.w\t$dst, #$label", []>;
447 def t2LEApcrelJT : T2XI<(outs GPR:$dst),
448 (ins i32imm:$label, nohash_imm:$id, pred:$p), IIC_iALUi,
449 "adr$p.w\t$dst, #${label}_${id}", []>;
451 // ADD r, sp, {so_imm|i12}
452 def t2ADDrSPi : T2sI<(outs GPR:$dst), (ins GPR:$sp, t2_so_imm:$imm),
453 IIC_iALUi, "add", ".w\t$dst, $sp, $imm", []>;
454 def t2ADDrSPi12 : T2I<(outs GPR:$dst), (ins GPR:$sp, imm0_4095:$imm),
455 IIC_iALUi, "addw", "\t$dst, $sp, $imm", []>;
458 def t2ADDrSPs : T2sI<(outs GPR:$dst), (ins GPR:$sp, t2_so_reg:$rhs),
459 IIC_iALUsi, "add", ".w\t$dst, $sp, $rhs", []>;
461 // SUB r, sp, {so_imm|i12}
462 def t2SUBrSPi : T2sI<(outs GPR:$dst), (ins GPR:$sp, t2_so_imm:$imm),
463 IIC_iALUi, "sub", ".w\t$dst, $sp, $imm", []>;
464 def t2SUBrSPi12 : T2I<(outs GPR:$dst), (ins GPR:$sp, imm0_4095:$imm),
465 IIC_iALUi, "subw", "\t$dst, $sp, $imm", []>;
468 def t2SUBrSPs : T2sI<(outs GPR:$dst), (ins GPR:$sp, t2_so_reg:$rhs),
470 "sub", "\t$dst, $sp, $rhs", []>;
473 // Pseudo instruction that will expand into a t2SUBrSPi + a copy.
474 let usesCustomInserter = 1 in { // Expanded after instruction selection.
475 def t2SUBrSPi_ : PseudoInst<(outs GPR:$dst), (ins GPR:$sp, t2_so_imm:$imm),
476 NoItinerary, "@ sub.w\t$dst, $sp, $imm", []>;
477 def t2SUBrSPi12_ : PseudoInst<(outs GPR:$dst), (ins GPR:$sp, imm0_4095:$imm),
478 NoItinerary, "@ subw\t$dst, $sp, $imm", []>;
479 def t2SUBrSPs_ : PseudoInst<(outs GPR:$dst), (ins GPR:$sp, t2_so_reg:$rhs),
480 NoItinerary, "@ sub\t$dst, $sp, $rhs", []>;
481 } // usesCustomInserter
484 //===----------------------------------------------------------------------===//
485 // Load / store Instructions.
489 let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in
490 defm t2LDR : T2I_ld<"ldr", UnOpFrag<(load node:$Src)>>;
492 // Loads with zero extension
493 defm t2LDRH : T2I_ld<"ldrh", UnOpFrag<(zextloadi16 node:$Src)>>;
494 defm t2LDRB : T2I_ld<"ldrb", UnOpFrag<(zextloadi8 node:$Src)>>;
496 // Loads with sign extension
497 defm t2LDRSH : T2I_ld<"ldrsh", UnOpFrag<(sextloadi16 node:$Src)>>;
498 defm t2LDRSB : T2I_ld<"ldrsb", UnOpFrag<(sextloadi8 node:$Src)>>;
500 let mayLoad = 1, hasExtraDefRegAllocReq = 1 in {
502 def t2LDRDi8 : T2Ii8s4<(outs GPR:$dst1, GPR:$dst2),
503 (ins t2addrmode_imm8s4:$addr),
504 IIC_iLoadi, "ldrd", "\t$dst1, $addr", []>;
505 def t2LDRDpci : T2Ii8s4<(outs GPR:$dst1, GPR:$dst2),
506 (ins i32imm:$addr), IIC_iLoadi,
507 "ldrd", "\t$dst1, $addr", []>;
510 // zextload i1 -> zextload i8
511 def : T2Pat<(zextloadi1 t2addrmode_imm12:$addr),
512 (t2LDRBi12 t2addrmode_imm12:$addr)>;
513 def : T2Pat<(zextloadi1 t2addrmode_imm8:$addr),
514 (t2LDRBi8 t2addrmode_imm8:$addr)>;
515 def : T2Pat<(zextloadi1 t2addrmode_so_reg:$addr),
516 (t2LDRBs t2addrmode_so_reg:$addr)>;
517 def : T2Pat<(zextloadi1 (ARMWrapper tconstpool:$addr)),
518 (t2LDRBpci tconstpool:$addr)>;
520 // extload -> zextload
521 // FIXME: Reduce the number of patterns by legalizing extload to zextload
523 def : T2Pat<(extloadi1 t2addrmode_imm12:$addr),
524 (t2LDRBi12 t2addrmode_imm12:$addr)>;
525 def : T2Pat<(extloadi1 t2addrmode_imm8:$addr),
526 (t2LDRBi8 t2addrmode_imm8:$addr)>;
527 def : T2Pat<(extloadi1 t2addrmode_so_reg:$addr),
528 (t2LDRBs t2addrmode_so_reg:$addr)>;
529 def : T2Pat<(extloadi1 (ARMWrapper tconstpool:$addr)),
530 (t2LDRBpci tconstpool:$addr)>;
532 def : T2Pat<(extloadi8 t2addrmode_imm12:$addr),
533 (t2LDRBi12 t2addrmode_imm12:$addr)>;
534 def : T2Pat<(extloadi8 t2addrmode_imm8:$addr),
535 (t2LDRBi8 t2addrmode_imm8:$addr)>;
536 def : T2Pat<(extloadi8 t2addrmode_so_reg:$addr),
537 (t2LDRBs t2addrmode_so_reg:$addr)>;
538 def : T2Pat<(extloadi8 (ARMWrapper tconstpool:$addr)),
539 (t2LDRBpci tconstpool:$addr)>;
541 def : T2Pat<(extloadi16 t2addrmode_imm12:$addr),
542 (t2LDRHi12 t2addrmode_imm12:$addr)>;
543 def : T2Pat<(extloadi16 t2addrmode_imm8:$addr),
544 (t2LDRHi8 t2addrmode_imm8:$addr)>;
545 def : T2Pat<(extloadi16 t2addrmode_so_reg:$addr),
546 (t2LDRHs t2addrmode_so_reg:$addr)>;
547 def : T2Pat<(extloadi16 (ARMWrapper tconstpool:$addr)),
548 (t2LDRHpci tconstpool:$addr)>;
552 def t2LDR_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
553 (ins t2addrmode_imm8:$addr),
554 AddrModeT2_i8, IndexModePre, IIC_iLoadiu,
555 "ldr", "\t$dst, $addr!", "$addr.base = $base_wb",
558 def t2LDR_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
559 (ins GPR:$base, t2am_imm8_offset:$offset),
560 AddrModeT2_i8, IndexModePost, IIC_iLoadiu,
561 "ldr", "\t$dst, [$base], $offset", "$base = $base_wb",
564 def t2LDRB_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
565 (ins t2addrmode_imm8:$addr),
566 AddrModeT2_i8, IndexModePre, IIC_iLoadiu,
567 "ldrb", "\t$dst, $addr!", "$addr.base = $base_wb",
569 def t2LDRB_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
570 (ins GPR:$base, t2am_imm8_offset:$offset),
571 AddrModeT2_i8, IndexModePost, IIC_iLoadiu,
572 "ldrb", "\t$dst, [$base], $offset", "$base = $base_wb",
575 def t2LDRH_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
576 (ins t2addrmode_imm8:$addr),
577 AddrModeT2_i8, IndexModePre, IIC_iLoadiu,
578 "ldrh", "\t$dst, $addr!", "$addr.base = $base_wb",
580 def t2LDRH_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
581 (ins GPR:$base, t2am_imm8_offset:$offset),
582 AddrModeT2_i8, IndexModePost, IIC_iLoadiu,
583 "ldrh", "\t$dst, [$base], $offset", "$base = $base_wb",
586 def t2LDRSB_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
587 (ins t2addrmode_imm8:$addr),
588 AddrModeT2_i8, IndexModePre, IIC_iLoadiu,
589 "ldrsb", "\t$dst, $addr!", "$addr.base = $base_wb",
591 def t2LDRSB_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
592 (ins GPR:$base, t2am_imm8_offset:$offset),
593 AddrModeT2_i8, IndexModePost, IIC_iLoadiu,
594 "ldrsb", "\t$dst, [$base], $offset", "$base = $base_wb",
597 def t2LDRSH_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
598 (ins t2addrmode_imm8:$addr),
599 AddrModeT2_i8, IndexModePre, IIC_iLoadiu,
600 "ldrsh", "\t$dst, $addr!", "$addr.base = $base_wb",
602 def t2LDRSH_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
603 (ins GPR:$base, t2am_imm8_offset:$offset),
604 AddrModeT2_i8, IndexModePost, IIC_iLoadiu,
605 "ldrsh", "\t$dst, [$base], $offset", "$base = $base_wb",
610 defm t2STR : T2I_st<"str", BinOpFrag<(store node:$LHS, node:$RHS)>>;
611 defm t2STRB : T2I_st<"strb", BinOpFrag<(truncstorei8 node:$LHS, node:$RHS)>>;
612 defm t2STRH : T2I_st<"strh", BinOpFrag<(truncstorei16 node:$LHS, node:$RHS)>>;
615 let mayLoad = 1, hasExtraSrcRegAllocReq = 1 in
616 def t2STRDi8 : T2Ii8s4<(outs),
617 (ins GPR:$src1, GPR:$src2, t2addrmode_imm8s4:$addr),
618 IIC_iStorer, "strd", "\t$src1, $addr", []>;
621 def t2STR_PRE : T2Iidxldst<(outs GPR:$base_wb),
622 (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset),
623 AddrModeT2_i8, IndexModePre, IIC_iStoreiu,
624 "str", "\t$src, [$base, $offset]!", "$base = $base_wb",
626 (pre_store GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>;
628 def t2STR_POST : T2Iidxldst<(outs GPR:$base_wb),
629 (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset),
630 AddrModeT2_i8, IndexModePost, IIC_iStoreiu,
631 "str", "\t$src, [$base], $offset", "$base = $base_wb",
633 (post_store GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>;
635 def t2STRH_PRE : T2Iidxldst<(outs GPR:$base_wb),
636 (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset),
637 AddrModeT2_i8, IndexModePre, IIC_iStoreiu,
638 "strh", "\t$src, [$base, $offset]!", "$base = $base_wb",
640 (pre_truncsti16 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>;
642 def t2STRH_POST : T2Iidxldst<(outs GPR:$base_wb),
643 (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset),
644 AddrModeT2_i8, IndexModePost, IIC_iStoreiu,
645 "strh", "\t$src, [$base], $offset", "$base = $base_wb",
647 (post_truncsti16 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>;
649 def t2STRB_PRE : T2Iidxldst<(outs GPR:$base_wb),
650 (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset),
651 AddrModeT2_i8, IndexModePre, IIC_iStoreiu,
652 "strb", "\t$src, [$base, $offset]!", "$base = $base_wb",
654 (pre_truncsti8 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>;
656 def t2STRB_POST : T2Iidxldst<(outs GPR:$base_wb),
657 (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset),
658 AddrModeT2_i8, IndexModePost, IIC_iStoreiu,
659 "strb", "\t$src, [$base], $offset", "$base = $base_wb",
661 (post_truncsti8 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>;
664 // FIXME: ldrd / strd pre / post variants
666 //===----------------------------------------------------------------------===//
667 // Load / store multiple Instructions.
670 let mayLoad = 1, hasExtraDefRegAllocReq = 1 in
671 def t2LDM : T2XI<(outs),
672 (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops),
673 IIC_iLoadm, "ldm${addr:submode}${p}${addr:wide}\t$addr, $wb", []>;
675 let mayStore = 1, hasExtraSrcRegAllocReq = 1 in
676 def t2STM : T2XI<(outs),
677 (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops),
678 IIC_iStorem, "stm${addr:submode}${p}${addr:wide}\t$addr, $wb", []>;
680 //===----------------------------------------------------------------------===//
681 // Move Instructions.
684 let neverHasSideEffects = 1 in
685 def t2MOVr : T2sI<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVr,
686 "mov", ".w\t$dst, $src", []>;
688 // AddedComplexity to ensure isel tries t2MOVi before t2MOVi16.
689 let isReMaterializable = 1, isAsCheapAsAMove = 1, AddedComplexity = 1 in
690 def t2MOVi : T2sI<(outs GPR:$dst), (ins t2_so_imm:$src), IIC_iMOVi,
691 "mov", ".w\t$dst, $src",
692 [(set GPR:$dst, t2_so_imm:$src)]>;
694 let isReMaterializable = 1, isAsCheapAsAMove = 1 in
695 def t2MOVi16 : T2I<(outs GPR:$dst), (ins i32imm:$src), IIC_iMOVi,
696 "movw", "\t$dst, $src",
697 [(set GPR:$dst, imm0_65535:$src)]>;
699 let Constraints = "$src = $dst" in
700 def t2MOVTi16 : T2I<(outs GPR:$dst), (ins GPR:$src, i32imm:$imm), IIC_iMOVi,
701 "movt", "\t$dst, $imm",
703 (or (and GPR:$src, 0xffff), lo16AllZero:$imm))]>;
705 def : T2Pat<(or GPR:$src, 0xffff0000), (t2MOVTi16 GPR:$src, 0xffff)>;
707 //===----------------------------------------------------------------------===//
708 // Extend Instructions.
713 defm t2SXTB : T2I_unary_rrot<"sxtb", UnOpFrag<(sext_inreg node:$Src, i8)>>;
714 defm t2SXTH : T2I_unary_rrot<"sxth", UnOpFrag<(sext_inreg node:$Src, i16)>>;
716 defm t2SXTAB : T2I_bin_rrot<"sxtab",
717 BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS, i8))>>;
718 defm t2SXTAH : T2I_bin_rrot<"sxtah",
719 BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS,i16))>>;
721 // TODO: SXT(A){B|H}16
725 let AddedComplexity = 16 in {
726 defm t2UXTB : T2I_unary_rrot<"uxtb" , UnOpFrag<(and node:$Src, 0x000000FF)>>;
727 defm t2UXTH : T2I_unary_rrot<"uxth" , UnOpFrag<(and node:$Src, 0x0000FFFF)>>;
728 defm t2UXTB16 : T2I_unary_rrot<"uxtb16", UnOpFrag<(and node:$Src, 0x00FF00FF)>>;
730 def : T2Pat<(and (shl GPR:$Src, (i32 8)), 0xFF00FF),
731 (t2UXTB16r_rot GPR:$Src, 24)>;
732 def : T2Pat<(and (srl GPR:$Src, (i32 8)), 0xFF00FF),
733 (t2UXTB16r_rot GPR:$Src, 8)>;
735 defm t2UXTAB : T2I_bin_rrot<"uxtab",
736 BinOpFrag<(add node:$LHS, (and node:$RHS, 0x00FF))>>;
737 defm t2UXTAH : T2I_bin_rrot<"uxtah",
738 BinOpFrag<(add node:$LHS, (and node:$RHS, 0xFFFF))>>;
741 //===----------------------------------------------------------------------===//
742 // Arithmetic Instructions.
745 defm t2ADD : T2I_bin_ii12rs<"add", BinOpFrag<(add node:$LHS, node:$RHS)>, 1>;
746 defm t2SUB : T2I_bin_ii12rs<"sub", BinOpFrag<(sub node:$LHS, node:$RHS)>>;
748 // ADD and SUB with 's' bit set. No 12-bit immediate (T4) variants.
749 defm t2ADDS : T2I_bin_s_irs <"add", BinOpFrag<(addc node:$LHS, node:$RHS)>, 1>;
750 defm t2SUBS : T2I_bin_s_irs <"sub", BinOpFrag<(subc node:$LHS, node:$RHS)>>;
752 defm t2ADC : T2I_adde_sube_irs<"adc",BinOpFrag<(adde node:$LHS, node:$RHS)>,1>;
753 defm t2SBC : T2I_adde_sube_irs<"sbc",BinOpFrag<(sube node:$LHS, node:$RHS)>>;
756 defm t2RSB : T2I_rbin_is <"rsb", BinOpFrag<(sub node:$LHS, node:$RHS)>>;
757 defm t2RSBS : T2I_rbin_s_is <"rsb", BinOpFrag<(subc node:$LHS, node:$RHS)>>;
759 // (sub X, imm) gets canonicalized to (add X, -imm). Match this form.
760 let AddedComplexity = 1 in
761 def : T2Pat<(add GPR:$src, imm0_255_neg:$imm),
762 (t2SUBri GPR:$src, imm0_255_neg:$imm)>;
763 def : T2Pat<(add GPR:$src, t2_so_imm_neg:$imm),
764 (t2SUBri GPR:$src, t2_so_imm_neg:$imm)>;
765 def : T2Pat<(add GPR:$src, imm0_4095_neg:$imm),
766 (t2SUBri12 GPR:$src, imm0_4095_neg:$imm)>;
769 //===----------------------------------------------------------------------===//
770 // Shift and rotate Instructions.
773 defm t2LSL : T2I_sh_ir<"lsl", BinOpFrag<(shl node:$LHS, node:$RHS)>>;
774 defm t2LSR : T2I_sh_ir<"lsr", BinOpFrag<(srl node:$LHS, node:$RHS)>>;
775 defm t2ASR : T2I_sh_ir<"asr", BinOpFrag<(sra node:$LHS, node:$RHS)>>;
776 defm t2ROR : T2I_sh_ir<"ror", BinOpFrag<(rotr node:$LHS, node:$RHS)>>;
778 let Uses = [CPSR] in {
779 def t2MOVrx : T2sI<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVsi,
780 "rrx", "\t$dst, $src",
781 [(set GPR:$dst, (ARMrrx GPR:$src))]>;
784 let Defs = [CPSR] in {
785 def t2MOVsrl_flag : T2XI<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVsi,
786 "lsrs.w\t$dst, $src, #1",
787 [(set GPR:$dst, (ARMsrl_flag GPR:$src))]>;
788 def t2MOVsra_flag : T2XI<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVsi,
789 "asrs.w\t$dst, $src, #1",
790 [(set GPR:$dst, (ARMsra_flag GPR:$src))]>;
793 //===----------------------------------------------------------------------===//
794 // Bitwise Instructions.
797 defm t2AND : T2I_bin_w_irs<"and", BinOpFrag<(and node:$LHS, node:$RHS)>, 1>;
798 defm t2ORR : T2I_bin_w_irs<"orr", BinOpFrag<(or node:$LHS, node:$RHS)>, 1>;
799 defm t2EOR : T2I_bin_w_irs<"eor", BinOpFrag<(xor node:$LHS, node:$RHS)>, 1>;
801 defm t2BIC : T2I_bin_w_irs<"bic", BinOpFrag<(and node:$LHS, (not node:$RHS))>>;
803 let Constraints = "$src = $dst" in
804 def t2BFC : T2I<(outs GPR:$dst), (ins GPR:$src, bf_inv_mask_imm:$imm),
805 IIC_iUNAsi, "bfc", "\t$dst, $imm",
806 [(set GPR:$dst, (and GPR:$src, bf_inv_mask_imm:$imm))]>;
808 def t2SBFX : T2I<(outs GPR:$dst), (ins GPR:$src, imm0_31:$lsb, imm0_31:$width),
809 IIC_iALUi, "sbfx", "\t$dst, $src, $lsb, $width", []>;
811 def t2UBFX : T2I<(outs GPR:$dst), (ins GPR:$src, imm0_31:$lsb, imm0_31:$width),
812 IIC_iALUi, "ubfx", "\t$dst, $src, $lsb, $width", []>;
814 // FIXME: A8.6.18 BFI - Bitfield insert (Encoding T1)
816 defm t2ORN : T2I_bin_irs<"orn", BinOpFrag<(or node:$LHS, (not node:$RHS))>>;
818 // Prefer over of t2EORri ra, rb, -1 because mvn has 16-bit version
819 let AddedComplexity = 1 in
820 defm t2MVN : T2I_un_irs <"mvn", UnOpFrag<(not node:$Src)>, 1, 1>;
823 def : T2Pat<(and GPR:$src, t2_so_imm_not:$imm),
824 (t2BICri GPR:$src, t2_so_imm_not:$imm)>;
826 // FIXME: Disable this pattern on Darwin to workaround an assembler bug.
827 def : T2Pat<(or GPR:$src, t2_so_imm_not:$imm),
828 (t2ORNri GPR:$src, t2_so_imm_not:$imm)>,
829 Requires<[IsThumb2]>;
831 def : T2Pat<(t2_so_imm_not:$src),
832 (t2MVNi t2_so_imm_not:$src)>;
834 //===----------------------------------------------------------------------===//
835 // Multiply Instructions.
837 let isCommutable = 1 in
838 def t2MUL: T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32,
839 "mul", "\t$dst, $a, $b",
840 [(set GPR:$dst, (mul GPR:$a, GPR:$b))]>;
842 def t2MLA: T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), IIC_iMAC32,
843 "mla", "\t$dst, $a, $b, $c",
844 [(set GPR:$dst, (add (mul GPR:$a, GPR:$b), GPR:$c))]>;
846 def t2MLS: T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), IIC_iMAC32,
847 "mls", "\t$dst, $a, $b, $c",
848 [(set GPR:$dst, (sub GPR:$c, (mul GPR:$a, GPR:$b)))]>;
850 // Extra precision multiplies with low / high results
851 let neverHasSideEffects = 1 in {
852 let isCommutable = 1 in {
853 def t2SMULL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), IIC_iMUL64,
854 "smull", "\t$ldst, $hdst, $a, $b", []>;
856 def t2UMULL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), IIC_iMUL64,
857 "umull", "\t$ldst, $hdst, $a, $b", []>;
860 // Multiply + accumulate
861 def t2SMLAL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), IIC_iMAC64,
862 "smlal", "\t$ldst, $hdst, $a, $b", []>;
864 def t2UMLAL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), IIC_iMAC64,
865 "umlal", "\t$ldst, $hdst, $a, $b", []>;
867 def t2UMAAL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), IIC_iMAC64,
868 "umaal", "\t$ldst, $hdst, $a, $b", []>;
869 } // neverHasSideEffects
871 // Most significant word multiply
872 def t2SMMUL : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32,
873 "smmul", "\t$dst, $a, $b",
874 [(set GPR:$dst, (mulhs GPR:$a, GPR:$b))]>;
876 def t2SMMLA : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), IIC_iMAC32,
877 "smmla", "\t$dst, $a, $b, $c",
878 [(set GPR:$dst, (add (mulhs GPR:$a, GPR:$b), GPR:$c))]>;
881 def t2SMMLS : T2I <(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), IIC_iMAC32,
882 "smmls", "\t$dst, $a, $b, $c",
883 [(set GPR:$dst, (sub GPR:$c, (mulhs GPR:$a, GPR:$b)))]>;
885 multiclass T2I_smul<string opc, PatFrag opnode> {
886 def BB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32,
887 !strconcat(opc, "bb"), "\t$dst, $a, $b",
888 [(set GPR:$dst, (opnode (sext_inreg GPR:$a, i16),
889 (sext_inreg GPR:$b, i16)))]>;
891 def BT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32,
892 !strconcat(opc, "bt"), "\t$dst, $a, $b",
893 [(set GPR:$dst, (opnode (sext_inreg GPR:$a, i16),
894 (sra GPR:$b, (i32 16))))]>;
896 def TB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32,
897 !strconcat(opc, "tb"), "\t$dst, $a, $b",
898 [(set GPR:$dst, (opnode (sra GPR:$a, (i32 16)),
899 (sext_inreg GPR:$b, i16)))]>;
901 def TT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32,
902 !strconcat(opc, "tt"), "\t$dst, $a, $b",
903 [(set GPR:$dst, (opnode (sra GPR:$a, (i32 16)),
904 (sra GPR:$b, (i32 16))))]>;
906 def WB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL16,
907 !strconcat(opc, "wb"), "\t$dst, $a, $b",
908 [(set GPR:$dst, (sra (opnode GPR:$a,
909 (sext_inreg GPR:$b, i16)), (i32 16)))]>;
911 def WT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL16,
912 !strconcat(opc, "wt"), "\t$dst, $a, $b",
913 [(set GPR:$dst, (sra (opnode GPR:$a,
914 (sra GPR:$b, (i32 16))), (i32 16)))]>;
918 multiclass T2I_smla<string opc, PatFrag opnode> {
919 def BB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16,
920 !strconcat(opc, "bb"), "\t$dst, $a, $b, $acc",
921 [(set GPR:$dst, (add GPR:$acc,
922 (opnode (sext_inreg GPR:$a, i16),
923 (sext_inreg GPR:$b, i16))))]>;
925 def BT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16,
926 !strconcat(opc, "bt"), "\t$dst, $a, $b, $acc",
927 [(set GPR:$dst, (add GPR:$acc, (opnode (sext_inreg GPR:$a, i16),
928 (sra GPR:$b, (i32 16)))))]>;
930 def TB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16,
931 !strconcat(opc, "tb"), "\t$dst, $a, $b, $acc",
932 [(set GPR:$dst, (add GPR:$acc, (opnode (sra GPR:$a, (i32 16)),
933 (sext_inreg GPR:$b, i16))))]>;
935 def TT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16,
936 !strconcat(opc, "tt"), "\t$dst, $a, $b, $acc",
937 [(set GPR:$dst, (add GPR:$acc, (opnode (sra GPR:$a, (i32 16)),
938 (sra GPR:$b, (i32 16)))))]>;
940 def WB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16,
941 !strconcat(opc, "wb"), "\t$dst, $a, $b, $acc",
942 [(set GPR:$dst, (add GPR:$acc, (sra (opnode GPR:$a,
943 (sext_inreg GPR:$b, i16)), (i32 16))))]>;
945 def WT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16,
946 !strconcat(opc, "wt"), "\t$dst, $a, $b, $acc",
947 [(set GPR:$dst, (add GPR:$acc, (sra (opnode GPR:$a,
948 (sra GPR:$b, (i32 16))), (i32 16))))]>;
951 defm t2SMUL : T2I_smul<"smul", BinOpFrag<(mul node:$LHS, node:$RHS)>>;
952 defm t2SMLA : T2I_smla<"smla", BinOpFrag<(mul node:$LHS, node:$RHS)>>;
954 // TODO: Halfword multiple accumulate long: SMLAL<x><y>
955 // TODO: Dual halfword multiple: SMUAD, SMUSD, SMLAD, SMLSD, SMLALD, SMLSLD
958 //===----------------------------------------------------------------------===//
959 // Misc. Arithmetic Instructions.
962 def t2CLZ : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
963 "clz", "\t$dst, $src",
964 [(set GPR:$dst, (ctlz GPR:$src))]>;
966 def t2REV : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
967 "rev", ".w\t$dst, $src",
968 [(set GPR:$dst, (bswap GPR:$src))]>;
970 def t2REV16 : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
971 "rev16", ".w\t$dst, $src",
973 (or (and (srl GPR:$src, (i32 8)), 0xFF),
974 (or (and (shl GPR:$src, (i32 8)), 0xFF00),
975 (or (and (srl GPR:$src, (i32 8)), 0xFF0000),
976 (and (shl GPR:$src, (i32 8)), 0xFF000000)))))]>;
978 def t2REVSH : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
979 "revsh", ".w\t$dst, $src",
982 (or (srl (and GPR:$src, 0xFF00), (i32 8)),
983 (shl GPR:$src, (i32 8))), i16))]>;
985 def t2PKHBT : T2I<(outs GPR:$dst), (ins GPR:$src1, GPR:$src2, i32imm:$shamt),
986 IIC_iALUsi, "pkhbt", "\t$dst, $src1, $src2, LSL $shamt",
987 [(set GPR:$dst, (or (and GPR:$src1, 0xFFFF),
988 (and (shl GPR:$src2, (i32 imm:$shamt)),
991 // Alternate cases for PKHBT where identities eliminate some nodes.
992 def : T2Pat<(or (and GPR:$src1, 0xFFFF), (and GPR:$src2, 0xFFFF0000)),
993 (t2PKHBT GPR:$src1, GPR:$src2, 0)>;
994 def : T2Pat<(or (and GPR:$src1, 0xFFFF), (shl GPR:$src2, imm16_31:$shamt)),
995 (t2PKHBT GPR:$src1, GPR:$src2, imm16_31:$shamt)>;
997 def t2PKHTB : T2I<(outs GPR:$dst), (ins GPR:$src1, GPR:$src2, i32imm:$shamt),
998 IIC_iALUsi, "pkhtb", "\t$dst, $src1, $src2, ASR $shamt",
999 [(set GPR:$dst, (or (and GPR:$src1, 0xFFFF0000),
1000 (and (sra GPR:$src2, imm16_31:$shamt),
1003 // Alternate cases for PKHTB where identities eliminate some nodes. Note that
1004 // a shift amount of 0 is *not legal* here, it is PKHBT instead.
1005 def : T2Pat<(or (and GPR:$src1, 0xFFFF0000), (srl GPR:$src2, (i32 16))),
1006 (t2PKHTB GPR:$src1, GPR:$src2, 16)>;
1007 def : T2Pat<(or (and GPR:$src1, 0xFFFF0000),
1008 (and (srl GPR:$src2, imm1_15:$shamt), 0xFFFF)),
1009 (t2PKHTB GPR:$src1, GPR:$src2, imm1_15:$shamt)>;
1011 //===----------------------------------------------------------------------===//
1012 // Comparison Instructions...
1015 defm t2CMP : T2I_cmp_is<"cmp",
1016 BinOpFrag<(ARMcmp node:$LHS, node:$RHS)>>;
1017 defm t2CMPz : T2I_cmp_is<"cmp",
1018 BinOpFrag<(ARMcmpZ node:$LHS, node:$RHS)>>;
1020 defm t2CMN : T2I_cmp_is<"cmn",
1021 BinOpFrag<(ARMcmp node:$LHS,(ineg node:$RHS))>>;
1022 defm t2CMNz : T2I_cmp_is<"cmn",
1023 BinOpFrag<(ARMcmpZ node:$LHS,(ineg node:$RHS))>>;
1025 def : T2Pat<(ARMcmp GPR:$src, t2_so_imm_neg:$imm),
1026 (t2CMNri GPR:$src, t2_so_imm_neg:$imm)>;
1028 def : T2Pat<(ARMcmpZ GPR:$src, t2_so_imm_neg:$imm),
1029 (t2CMNri GPR:$src, t2_so_imm_neg:$imm)>;
1031 defm t2TST : T2I_cmp_is<"tst",
1032 BinOpFrag<(ARMcmpZ (and node:$LHS, node:$RHS), 0)>>;
1033 defm t2TEQ : T2I_cmp_is<"teq",
1034 BinOpFrag<(ARMcmpZ (xor node:$LHS, node:$RHS), 0)>>;
1036 // A8.6.27 CBNZ, CBZ - Compare and branch on (non)zero.
1037 // Short range conditional branch. Looks awesome for loops. Need to figure
1038 // out how to use this one.
1041 // Conditional moves
1042 // FIXME: should be able to write a pattern for ARMcmov, but can't use
1043 // a two-value operand where a dag node expects two operands. :(
1044 def t2MOVCCr : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true), IIC_iCMOVr,
1045 "mov", ".w\t$dst, $true",
1046 [/*(set GPR:$dst, (ARMcmov GPR:$false, GPR:$true, imm:$cc, CCR:$ccr))*/]>,
1047 RegConstraint<"$false = $dst">;
1049 def t2MOVCCi : T2I<(outs GPR:$dst), (ins GPR:$false, t2_so_imm:$true),
1050 IIC_iCMOVi, "mov", ".w\t$dst, $true",
1051 [/*(set GPR:$dst, (ARMcmov GPR:$false, t2_so_imm:$true, imm:$cc, CCR:$ccr))*/]>,
1052 RegConstraint<"$false = $dst">;
1054 def t2MOVCClsl : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true, i32imm:$rhs),
1055 IIC_iCMOVsi, "lsl", ".w\t$dst, $true, $rhs", []>,
1056 RegConstraint<"$false = $dst">;
1057 def t2MOVCClsr : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true, i32imm:$rhs),
1058 IIC_iCMOVsi, "lsr", ".w\t$dst, $true, $rhs", []>,
1059 RegConstraint<"$false = $dst">;
1060 def t2MOVCCasr : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true, i32imm:$rhs),
1061 IIC_iCMOVsi, "asr", ".w\t$dst, $true, $rhs", []>,
1062 RegConstraint<"$false = $dst">;
1063 def t2MOVCCror : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true, i32imm:$rhs),
1064 IIC_iCMOVsi, "ror", ".w\t$dst, $true, $rhs", []>,
1065 RegConstraint<"$false = $dst">;
1067 //===----------------------------------------------------------------------===//
1068 // Atomic operations intrinsics
1071 // memory barriers protect the atomic sequences
1072 let hasSideEffects = 1 in {
1073 def t2Int_MemBarrierV7 : AInoP<(outs), (ins),
1074 Pseudo, NoItinerary,
1076 [(ARMMemBarrierV7)]>,
1077 Requires<[IsThumb2]> {
1078 // FIXME: add support for options other than a full system DMB
1081 def t2Int_SyncBarrierV7 : AInoP<(outs), (ins),
1082 Pseudo, NoItinerary,
1084 [(ARMSyncBarrierV7)]>,
1085 Requires<[IsThumb2]> {
1086 // FIXME: add support for options other than a full system DSB
1090 let mayLoad = 1 in {
1091 def t2LDREXB : Thumb2I<(outs GPR:$dest), (ins GPR:$ptr), AddrModeNone,
1092 Size4Bytes, NoItinerary,
1093 "ldrexb", "\t$dest, [$ptr]", "",
1095 def t2LDREXH : Thumb2I<(outs GPR:$dest), (ins GPR:$ptr), AddrModeNone,
1096 Size4Bytes, NoItinerary,
1097 "ldrexh", "\t$dest, [$ptr]", "",
1099 def t2LDREX : Thumb2I<(outs GPR:$dest), (ins GPR:$ptr), AddrModeNone,
1100 Size4Bytes, NoItinerary,
1101 "ldrex", "\t$dest, [$ptr]", "",
1103 def t2LDREXD : Thumb2I<(outs GPR:$dest, GPR:$dest2), (ins GPR:$ptr),
1104 AddrModeNone, Size4Bytes, NoItinerary,
1105 "ldrexd", "\t$dest, $dest2, [$ptr]", "",
1109 let mayStore = 1 in {
1110 def t2STREXB : Thumb2I<(outs GPR:$success), (ins GPR:$src, GPR:$ptr),
1111 AddrModeNone, Size4Bytes, NoItinerary,
1112 "strexb", "\t$success, $src, [$ptr]", "",
1114 def t2STREXH : Thumb2I<(outs GPR:$success), (ins GPR:$src, GPR:$ptr),
1115 AddrModeNone, Size4Bytes, NoItinerary,
1116 "strexh", "\t$success, $src, [$ptr]", "",
1118 def t2STREX : Thumb2I<(outs GPR:$success), (ins GPR:$src, GPR:$ptr),
1119 AddrModeNone, Size4Bytes, NoItinerary,
1120 "strex", "\t$success, $src, [$ptr]", "",
1122 def t2STREXD : Thumb2I<(outs GPR:$success),
1123 (ins GPR:$src, GPR:$src2, GPR:$ptr),
1124 AddrModeNone, Size4Bytes, NoItinerary,
1125 "strexd", "\t$success, $src, $src2, [$ptr]", "",
1129 //===----------------------------------------------------------------------===//
1133 // __aeabi_read_tp preserves the registers r1-r3.
1135 Defs = [R0, R12, LR, CPSR] in {
1136 def t2TPsoft : T2XI<(outs), (ins), IIC_Br,
1137 "bl\t__aeabi_read_tp",
1138 [(set R0, ARMthread_pointer)]>;
1141 //===----------------------------------------------------------------------===//
1142 // SJLJ Exception handling intrinsics
1143 // eh_sjlj_setjmp() is an instruction sequence to store the return
1144 // address and save #0 in R0 for the non-longjmp case.
1145 // Since by its nature we may be coming from some other function to get
1146 // here, and we're using the stack frame for the containing function to
1147 // save/restore registers, we can't keep anything live in regs across
1148 // the eh_sjlj_setjmp(), else it will almost certainly have been tromped upon
1149 // when we get here from a longjmp(). We force everthing out of registers
1150 // except for our own input by listing the relevant registers in Defs. By
1151 // doing so, we also cause the prologue/epilogue code to actively preserve
1152 // all of the callee-saved resgisters, which is exactly what we want.
1154 [ R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, LR, D0,
1155 D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15,
1156 D16, D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30,
1158 def t2Int_eh_sjlj_setjmp : Thumb2XI<(outs), (ins GPR:$src),
1159 AddrModeNone, SizeSpecial, NoItinerary,
1160 "str.w\tsp, [$src, #+8] @ eh_setjmp begin\n"
1162 "\torr.w\tr12, r12, #1\n"
1163 "\tstr.w\tr12, [$src, #+4]\n"
1166 "0:\tmovs\tr0, #1 @ eh_setjmp end\n"
1168 [(set R0, (ARMeh_sjlj_setjmp GPR:$src))]>;
1173 //===----------------------------------------------------------------------===//
1174 // Control-Flow Instructions
1177 // FIXME: remove when we have a way to marking a MI with these properties.
1178 // FIXME: $dst1 should be a def. But the extra ops must be in the end of the
1180 // FIXME: Should pc be an implicit operand like PICADD, etc?
1181 let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1,
1182 hasExtraDefRegAllocReq = 1 in
1183 def t2LDM_RET : T2XI<(outs),
1184 (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops),
1185 IIC_Br, "ldm${addr:submode}${p}${addr:wide}\t$addr, $wb",
1188 let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
1189 let isPredicable = 1 in
1190 def t2B : T2XI<(outs), (ins brtarget:$target), IIC_Br,
1194 let isNotDuplicable = 1, isIndirectBranch = 1 in {
1197 (ins GPR:$target, GPR:$index, jt2block_operand:$jt, i32imm:$id),
1198 IIC_Br, "mov\tpc, $target\n$jt",
1199 [(ARMbr2jt GPR:$target, GPR:$index, tjumptable:$jt, imm:$id)]>;
1201 // FIXME: Add a non-pc based case that can be predicated.
1204 (ins tb_addrmode:$index, jt2block_operand:$jt, i32imm:$id),
1205 IIC_Br, "tbb\t$index\n$jt", []>;
1209 (ins tb_addrmode:$index, jt2block_operand:$jt, i32imm:$id),
1210 IIC_Br, "tbh\t$index\n$jt", []>;
1211 } // isNotDuplicable, isIndirectBranch
1213 } // isBranch, isTerminator, isBarrier
1215 // FIXME: should be able to write a pattern for ARMBrcond, but can't use
1216 // a two-value operand where a dag node expects two operands. :(
1217 let isBranch = 1, isTerminator = 1 in
1218 def t2Bcc : T2I<(outs), (ins brtarget:$target), IIC_Br,
1220 [/*(ARMbrcond bb:$target, imm:$cc)*/]>;
1224 def t2IT : Thumb2XI<(outs), (ins it_pred:$cc, it_mask:$mask),
1225 AddrModeNone, Size2Bytes, IIC_iALUx,
1226 "it$mask\t$cc", "", []>;
1228 //===----------------------------------------------------------------------===//
1229 // Non-Instruction Patterns
1232 // Two piece so_imms.
1233 def : T2Pat<(or GPR:$LHS, t2_so_imm2part:$RHS),
1234 (t2ORRri (t2ORRri GPR:$LHS, (t2_so_imm2part_1 imm:$RHS)),
1235 (t2_so_imm2part_2 imm:$RHS))>;
1236 def : T2Pat<(xor GPR:$LHS, t2_so_imm2part:$RHS),
1237 (t2EORri (t2EORri GPR:$LHS, (t2_so_imm2part_1 imm:$RHS)),
1238 (t2_so_imm2part_2 imm:$RHS))>;
1239 def : T2Pat<(add GPR:$LHS, t2_so_imm2part:$RHS),
1240 (t2ADDri (t2ADDri GPR:$LHS, (t2_so_imm2part_1 imm:$RHS)),
1241 (t2_so_imm2part_2 imm:$RHS))>;
1242 def : T2Pat<(add GPR:$LHS, t2_so_neg_imm2part:$RHS),
1243 (t2SUBri (t2SUBri GPR:$LHS, (t2_so_neg_imm2part_1 imm:$RHS)),
1244 (t2_so_neg_imm2part_2 imm:$RHS))>;
1246 // 32-bit immediate using movw + movt.
1247 // This is a single pseudo instruction to make it re-materializable. Remove
1248 // when we can do generalized remat.
1249 let isReMaterializable = 1 in
1250 def t2MOVi32imm : T2Ix2<(outs GPR:$dst), (ins i32imm:$src), IIC_iMOVi,
1251 "movw", "\t$dst, ${src:lo16}\n\tmovt${p}\t$dst, ${src:hi16}",
1252 [(set GPR:$dst, (i32 imm:$src))]>;
1254 // ConstantPool, GlobalAddress, and JumpTable
1255 def : T2Pat<(ARMWrapper tglobaladdr :$dst), (t2LEApcrel tglobaladdr :$dst)>,
1256 Requires<[IsThumb2, DontUseMovt]>;
1257 def : T2Pat<(ARMWrapper tconstpool :$dst), (t2LEApcrel tconstpool :$dst)>;
1258 def : T2Pat<(ARMWrapper tglobaladdr :$dst), (t2MOVi32imm tglobaladdr :$dst)>,
1259 Requires<[IsThumb2, UseMovt]>;
1261 def : T2Pat<(ARMWrapperJT tjumptable:$dst, imm:$id),
1262 (t2LEApcrelJT tjumptable:$dst, imm:$id)>;
1264 // Pseudo instruction that combines ldr from constpool and add pc. This should
1265 // be expanded into two instructions late to allow if-conversion and
1267 let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in
1268 def t2LDRpci_pic : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr, pclabel:$cp),
1269 NoItinerary, "@ ldr.w\t$dst, $addr\n$cp:\n\tadd\t$dst, pc",
1270 [(set GPR:$dst, (ARMpic_add (load (ARMWrapper tconstpool:$addr)),
1272 Requires<[IsThumb2]>;