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 bits
53 // [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 /// imm1_31 predicate - True if the 32-bit immediate is in the range [1,31].
92 def imm1_31 : PatLeaf<(i32 imm), [{
93 return (int32_t)N->getZExtValue() >= 1 && (int32_t)N->getZExtValue() < 32;
96 /// imm0_4095 predicate - True if the 32-bit immediate is in the range [0.4095].
97 def imm0_4095 : Operand<i32>,
99 return (uint32_t)N->getZExtValue() < 4096;
102 def imm0_4095_neg : PatLeaf<(i32 imm), [{
103 return (uint32_t)(-N->getZExtValue()) < 4096;
106 def imm0_255_neg : PatLeaf<(i32 imm), [{
107 return (uint32_t)(-N->getZExtValue()) < 255;
110 // Define Thumb2 specific addressing modes.
112 // t2addrmode_imm12 := reg + imm12
113 def t2addrmode_imm12 : Operand<i32>,
114 ComplexPattern<i32, 2, "SelectT2AddrModeImm12", []> {
115 let PrintMethod = "printT2AddrModeImm12Operand";
116 let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
119 // t2addrmode_imm8 := reg - imm8
120 def t2addrmode_imm8 : Operand<i32>,
121 ComplexPattern<i32, 2, "SelectT2AddrModeImm8", []> {
122 let PrintMethod = "printT2AddrModeImm8Operand";
123 let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
126 def t2am_imm8_offset : Operand<i32>,
127 ComplexPattern<i32, 1, "SelectT2AddrModeImm8Offset", []>{
128 let PrintMethod = "printT2AddrModeImm8OffsetOperand";
131 // t2addrmode_imm8s4 := reg +/- (imm8 << 2)
132 def t2addrmode_imm8s4 : Operand<i32>,
133 ComplexPattern<i32, 2, "SelectT2AddrModeImm8s4", []> {
134 let PrintMethod = "printT2AddrModeImm8s4Operand";
135 let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
138 // t2addrmode_so_reg := reg + (reg << imm2)
139 def t2addrmode_so_reg : Operand<i32>,
140 ComplexPattern<i32, 3, "SelectT2AddrModeSoReg", []> {
141 let PrintMethod = "printT2AddrModeSoRegOperand";
142 let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);
146 //===----------------------------------------------------------------------===//
147 // Multiclass helpers...
150 /// T2I_un_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a
151 /// unary operation that produces a value. These are predicable and can be
152 /// changed to modify CPSR.
153 multiclass T2I_un_irs<string opc, PatFrag opnode, bit Cheap = 0, bit ReMat = 0>{
155 def i : T2sI<(outs GPR:$dst), (ins t2_so_imm:$src), IIC_iMOVi,
157 [(set GPR:$dst, (opnode t2_so_imm:$src))]> {
158 let isAsCheapAsAMove = Cheap;
159 let isReMaterializable = ReMat;
162 def r : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVr,
163 opc, ".w\t$dst, $src",
164 [(set GPR:$dst, (opnode GPR:$src))]>;
166 def s : T2I<(outs GPR:$dst), (ins t2_so_reg:$src), IIC_iMOVsi,
167 opc, ".w\t$dst, $src",
168 [(set GPR:$dst, (opnode t2_so_reg:$src))]>;
171 /// T2I_bin_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a
172 // binary operation that produces a value. These are predicable and can be
173 /// changed to modify CPSR.
174 multiclass T2I_bin_irs<string opc, PatFrag opnode,
175 bit Commutable = 0, string wide =""> {
177 def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi,
178 opc, "\t$dst, $lhs, $rhs",
179 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>;
181 def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr,
182 opc, !strconcat(wide, "\t$dst, $lhs, $rhs"),
183 [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]> {
184 let isCommutable = Commutable;
187 def rs : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi,
188 opc, !strconcat(wide, "\t$dst, $lhs, $rhs"),
189 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>;
192 /// T2I_bin_w_irs - Same as T2I_bin_irs except these operations need
193 // the ".w" prefix to indicate that they are wide.
194 multiclass T2I_bin_w_irs<string opc, PatFrag opnode, bit Commutable = 0> :
195 T2I_bin_irs<opc, opnode, Commutable, ".w">;
197 /// T2I_rbin_is - Same as T2I_bin_irs except the order of operands are
198 /// reversed. It doesn't define the 'rr' form since it's handled by its
199 /// T2I_bin_irs counterpart.
200 multiclass T2I_rbin_is<string opc, PatFrag opnode> {
202 def ri : T2I<(outs GPR:$dst), (ins GPR:$rhs, t2_so_imm:$lhs), IIC_iALUi,
203 opc, ".w\t$dst, $rhs, $lhs",
204 [(set GPR:$dst, (opnode t2_so_imm:$lhs, GPR:$rhs))]>;
206 def rs : T2I<(outs GPR:$dst), (ins GPR:$rhs, t2_so_reg:$lhs), IIC_iALUsi,
207 opc, "\t$dst, $rhs, $lhs",
208 [(set GPR:$dst, (opnode t2_so_reg:$lhs, GPR:$rhs))]>;
211 /// T2I_bin_s_irs - Similar to T2I_bin_irs except it sets the 's' bit so the
212 /// instruction modifies the CPSR register.
213 let Defs = [CPSR] in {
214 multiclass T2I_bin_s_irs<string opc, PatFrag opnode, bit Commutable = 0> {
216 def ri : T2I<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi,
217 !strconcat(opc, "s"), ".w\t$dst, $lhs, $rhs",
218 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>;
220 def rr : T2I<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr,
221 !strconcat(opc, "s"), ".w\t$dst, $lhs, $rhs",
222 [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]> {
223 let isCommutable = Commutable;
226 def rs : T2I<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi,
227 !strconcat(opc, "s"), ".w\t$dst, $lhs, $rhs",
228 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>;
232 /// T2I_bin_ii12rs - Defines a set of (op reg, {so_imm|imm0_4095|r|so_reg})
233 /// patterns for a binary operation that produces a value.
234 multiclass T2I_bin_ii12rs<string opc, PatFrag opnode, bit Commutable = 0> {
236 def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi,
237 opc, ".w\t$dst, $lhs, $rhs",
238 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>;
240 def ri12 : T2sI<(outs GPR:$dst), (ins GPR:$lhs, imm0_4095:$rhs), IIC_iALUi,
241 !strconcat(opc, "w"), "\t$dst, $lhs, $rhs",
242 [(set GPR:$dst, (opnode GPR:$lhs, imm0_4095:$rhs))]>;
244 def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr,
245 opc, ".w\t$dst, $lhs, $rhs",
246 [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]> {
247 let isCommutable = Commutable;
250 def rs : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi,
251 opc, ".w\t$dst, $lhs, $rhs",
252 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>;
255 /// T2I_adde_sube_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a
256 /// binary operation that produces a value and use and define the carry bit.
257 /// It's not predicable.
258 let Uses = [CPSR] in {
259 multiclass T2I_adde_sube_irs<string opc, PatFrag opnode, bit Commutable = 0> {
261 def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi,
262 opc, "\t$dst, $lhs, $rhs",
263 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>,
264 Requires<[IsThumb2, CarryDefIsUnused]>;
266 def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr,
267 opc, ".w\t$dst, $lhs, $rhs",
268 [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>,
269 Requires<[IsThumb2, CarryDefIsUnused]> {
270 let isCommutable = Commutable;
273 def rs : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi,
274 opc, ".w\t$dst, $lhs, $rhs",
275 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>,
276 Requires<[IsThumb2, CarryDefIsUnused]>;
277 // Carry setting variants
279 def Sri : T2XI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi,
280 !strconcat(opc, "s\t$dst, $lhs, $rhs"),
281 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>,
282 Requires<[IsThumb2, CarryDefIsUsed]> {
286 def Srr : T2XI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr,
287 !strconcat(opc, "s.w\t$dst, $lhs, $rhs"),
288 [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>,
289 Requires<[IsThumb2, CarryDefIsUsed]> {
291 let isCommutable = Commutable;
294 def Srs : T2XI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi,
295 !strconcat(opc, "s.w\t$dst, $lhs, $rhs"),
296 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>,
297 Requires<[IsThumb2, CarryDefIsUsed]> {
303 /// T2I_rbin_s_is - Same as T2I_rbin_is except sets 's' bit.
304 let Defs = [CPSR] in {
305 multiclass T2I_rbin_s_is<string opc, PatFrag opnode> {
307 def ri : T2XI<(outs GPR:$dst), (ins GPR:$rhs, t2_so_imm:$lhs, cc_out:$s),
309 !strconcat(opc, "${s}.w\t$dst, $rhs, $lhs"),
310 [(set GPR:$dst, (opnode t2_so_imm:$lhs, GPR:$rhs))]>;
312 def rs : T2XI<(outs GPR:$dst), (ins GPR:$rhs, t2_so_reg:$lhs, cc_out:$s),
314 !strconcat(opc, "${s}\t$dst, $rhs, $lhs"),
315 [(set GPR:$dst, (opnode t2_so_reg:$lhs, GPR:$rhs))]>;
319 /// T2I_sh_ir - Defines a set of (op reg, {so_imm|r}) patterns for a shift /
320 // rotate operation that produces a value.
321 multiclass T2I_sh_ir<string opc, PatFrag opnode> {
323 def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs), IIC_iMOVsi,
324 opc, ".w\t$dst, $lhs, $rhs",
325 [(set GPR:$dst, (opnode GPR:$lhs, imm1_31:$rhs))]>;
327 def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iMOVsr,
328 opc, ".w\t$dst, $lhs, $rhs",
329 [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>;
332 /// T2I_cmp_is - Defines a set of (op r, {so_imm|r|so_reg}) cmp / test
333 /// patterns. Similar to T2I_bin_irs except the instruction does not produce
334 /// a explicit result, only implicitly set CPSR.
335 let Defs = [CPSR] in {
336 multiclass T2I_cmp_is<string opc, PatFrag opnode> {
338 def ri : T2I<(outs), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iCMPi,
339 opc, ".w\t$lhs, $rhs",
340 [(opnode GPR:$lhs, t2_so_imm:$rhs)]>;
342 def rr : T2I<(outs), (ins GPR:$lhs, GPR:$rhs), IIC_iCMPr,
343 opc, ".w\t$lhs, $rhs",
344 [(opnode GPR:$lhs, GPR:$rhs)]>;
346 def rs : T2I<(outs), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iCMPsi,
347 opc, ".w\t$lhs, $rhs",
348 [(opnode GPR:$lhs, t2_so_reg:$rhs)]>;
352 /// T2I_ld - Defines a set of (op r, {imm12|imm8|so_reg}) load patterns.
353 multiclass T2I_ld<string opc, PatFrag opnode> {
354 def i12 : T2Ii12<(outs GPR:$dst), (ins t2addrmode_imm12:$addr), IIC_iLoadi,
355 opc, ".w\t$dst, $addr",
356 [(set GPR:$dst, (opnode t2addrmode_imm12:$addr))]>;
357 def i8 : T2Ii8 <(outs GPR:$dst), (ins t2addrmode_imm8:$addr), IIC_iLoadi,
358 opc, "\t$dst, $addr",
359 [(set GPR:$dst, (opnode t2addrmode_imm8:$addr))]>;
360 def s : T2Iso <(outs GPR:$dst), (ins t2addrmode_so_reg:$addr), IIC_iLoadr,
361 opc, ".w\t$dst, $addr",
362 [(set GPR:$dst, (opnode t2addrmode_so_reg:$addr))]>;
363 def pci : T2Ipc <(outs GPR:$dst), (ins i32imm:$addr), IIC_iLoadi,
364 opc, ".w\t$dst, $addr",
365 [(set GPR:$dst, (opnode (ARMWrapper tconstpool:$addr)))]> {
366 let isReMaterializable = 1;
370 /// T2I_st - Defines a set of (op r, {imm12|imm8|so_reg}) store patterns.
371 multiclass T2I_st<string opc, PatFrag opnode> {
372 def i12 : T2Ii12<(outs), (ins GPR:$src, t2addrmode_imm12:$addr), IIC_iStorei,
373 opc, ".w\t$src, $addr",
374 [(opnode GPR:$src, t2addrmode_imm12:$addr)]>;
375 def i8 : T2Ii8 <(outs), (ins GPR:$src, t2addrmode_imm8:$addr), IIC_iStorei,
376 opc, "\t$src, $addr",
377 [(opnode GPR:$src, t2addrmode_imm8:$addr)]>;
378 def s : T2Iso <(outs), (ins GPR:$src, t2addrmode_so_reg:$addr), IIC_iStorer,
379 opc, ".w\t$src, $addr",
380 [(opnode GPR:$src, t2addrmode_so_reg:$addr)]>;
383 /// T2I_picld - Defines the PIC load pattern.
384 class T2I_picld<string opc, PatFrag opnode> :
385 T2I<(outs GPR:$dst), (ins addrmodepc:$addr), IIC_iLoadi,
386 !strconcat("\n${addr:label}:\n\t", opc), "\t$dst, $addr",
387 [(set GPR:$dst, (opnode addrmodepc:$addr))]>;
389 /// T2I_picst - Defines the PIC store pattern.
390 class T2I_picst<string opc, PatFrag opnode> :
391 T2I<(outs), (ins GPR:$src, addrmodepc:$addr), IIC_iStorer,
392 !strconcat("\n${addr:label}:\n\t", opc), "\t$src, $addr",
393 [(opnode GPR:$src, addrmodepc:$addr)]>;
396 /// T2I_unary_rrot - A unary operation with two forms: one whose operand is a
397 /// register and one whose operand is a register rotated by 8/16/24.
398 multiclass T2I_unary_rrot<string opc, PatFrag opnode> {
399 def r : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
400 opc, ".w\t$dst, $src",
401 [(set GPR:$dst, (opnode GPR:$src))]>;
402 def r_rot : T2I<(outs GPR:$dst), (ins GPR:$src, i32imm:$rot), IIC_iUNAsi,
403 opc, ".w\t$dst, $src, ror $rot",
404 [(set GPR:$dst, (opnode (rotr GPR:$src, rot_imm:$rot)))]>;
407 /// T2I_bin_rrot - A binary operation with two forms: one whose operand is a
408 /// register and one whose operand is a register rotated by 8/16/24.
409 multiclass T2I_bin_rrot<string opc, PatFrag opnode> {
410 def rr : T2I<(outs GPR:$dst), (ins GPR:$LHS, GPR:$RHS), IIC_iALUr,
411 opc, "\t$dst, $LHS, $RHS",
412 [(set GPR:$dst, (opnode GPR:$LHS, GPR:$RHS))]>;
413 def rr_rot : T2I<(outs GPR:$dst), (ins GPR:$LHS, GPR:$RHS, i32imm:$rot),
414 IIC_iALUsr, opc, "\t$dst, $LHS, $RHS, ror $rot",
415 [(set GPR:$dst, (opnode GPR:$LHS,
416 (rotr GPR:$RHS, rot_imm:$rot)))]>;
419 //===----------------------------------------------------------------------===//
421 //===----------------------------------------------------------------------===//
423 //===----------------------------------------------------------------------===//
424 // Miscellaneous Instructions.
427 // LEApcrel - Load a pc-relative address into a register without offending the
429 def t2LEApcrel : T2XI<(outs GPR:$dst), (ins i32imm:$label, pred:$p), IIC_iALUi,
430 "adr$p.w\t$dst, #$label", []>;
432 def t2LEApcrelJT : T2XI<(outs GPR:$dst),
433 (ins i32imm:$label, nohash_imm:$id, pred:$p), IIC_iALUi,
434 "adr$p.w\t$dst, #${label}_${id}", []>;
436 // ADD r, sp, {so_imm|i12}
437 def t2ADDrSPi : T2sI<(outs GPR:$dst), (ins GPR:$sp, t2_so_imm:$imm),
438 IIC_iALUi, "add", ".w\t$dst, $sp, $imm", []>;
439 def t2ADDrSPi12 : T2I<(outs GPR:$dst), (ins GPR:$sp, imm0_4095:$imm),
440 IIC_iALUi, "addw", "\t$dst, $sp, $imm", []>;
443 def t2ADDrSPs : T2sI<(outs GPR:$dst), (ins GPR:$sp, t2_so_reg:$rhs),
444 IIC_iALUsi, "add", ".w\t$dst, $sp, $rhs", []>;
446 // SUB r, sp, {so_imm|i12}
447 def t2SUBrSPi : T2sI<(outs GPR:$dst), (ins GPR:$sp, t2_so_imm:$imm),
448 IIC_iALUi, "sub", ".w\t$dst, $sp, $imm", []>;
449 def t2SUBrSPi12 : T2I<(outs GPR:$dst), (ins GPR:$sp, imm0_4095:$imm),
450 IIC_iALUi, "subw", "\t$dst, $sp, $imm", []>;
453 def t2SUBrSPs : T2sI<(outs GPR:$dst), (ins GPR:$sp, t2_so_reg:$rhs),
455 "sub", "\t$dst, $sp, $rhs", []>;
458 // Pseudo instruction that will expand into a t2SUBrSPi + a copy.
459 let usesCustomInserter = 1 in { // Expanded after instruction selection.
460 def t2SUBrSPi_ : PseudoInst<(outs GPR:$dst), (ins GPR:$sp, t2_so_imm:$imm),
461 NoItinerary, "@ sub.w\t$dst, $sp, $imm", []>;
462 def t2SUBrSPi12_ : PseudoInst<(outs GPR:$dst), (ins GPR:$sp, imm0_4095:$imm),
463 NoItinerary, "@ subw\t$dst, $sp, $imm", []>;
464 def t2SUBrSPs_ : PseudoInst<(outs GPR:$dst), (ins GPR:$sp, t2_so_reg:$rhs),
465 NoItinerary, "@ sub\t$dst, $sp, $rhs", []>;
466 } // usesCustomInserter
469 //===----------------------------------------------------------------------===//
470 // Load / store Instructions.
474 let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in
475 defm t2LDR : T2I_ld<"ldr", UnOpFrag<(load node:$Src)>>;
477 // Loads with zero extension
478 defm t2LDRH : T2I_ld<"ldrh", UnOpFrag<(zextloadi16 node:$Src)>>;
479 defm t2LDRB : T2I_ld<"ldrb", UnOpFrag<(zextloadi8 node:$Src)>>;
481 // Loads with sign extension
482 defm t2LDRSH : T2I_ld<"ldrsh", UnOpFrag<(sextloadi16 node:$Src)>>;
483 defm t2LDRSB : T2I_ld<"ldrsb", UnOpFrag<(sextloadi8 node:$Src)>>;
485 let mayLoad = 1, hasExtraDefRegAllocReq = 1 in {
487 def t2LDRDi8 : T2Ii8s4<(outs GPR:$dst1, GPR:$dst2),
488 (ins t2addrmode_imm8s4:$addr),
489 IIC_iLoadi, "ldrd", "\t$dst1, $addr", []>;
490 def t2LDRDpci : T2Ii8s4<(outs GPR:$dst1, GPR:$dst2),
491 (ins i32imm:$addr), IIC_iLoadi,
492 "ldrd", "\t$dst1, $addr", []>;
495 // zextload i1 -> zextload i8
496 def : T2Pat<(zextloadi1 t2addrmode_imm12:$addr),
497 (t2LDRBi12 t2addrmode_imm12:$addr)>;
498 def : T2Pat<(zextloadi1 t2addrmode_imm8:$addr),
499 (t2LDRBi8 t2addrmode_imm8:$addr)>;
500 def : T2Pat<(zextloadi1 t2addrmode_so_reg:$addr),
501 (t2LDRBs t2addrmode_so_reg:$addr)>;
502 def : T2Pat<(zextloadi1 (ARMWrapper tconstpool:$addr)),
503 (t2LDRBpci tconstpool:$addr)>;
505 // extload -> zextload
506 // FIXME: Reduce the number of patterns by legalizing extload to zextload
508 def : T2Pat<(extloadi1 t2addrmode_imm12:$addr),
509 (t2LDRBi12 t2addrmode_imm12:$addr)>;
510 def : T2Pat<(extloadi1 t2addrmode_imm8:$addr),
511 (t2LDRBi8 t2addrmode_imm8:$addr)>;
512 def : T2Pat<(extloadi1 t2addrmode_so_reg:$addr),
513 (t2LDRBs t2addrmode_so_reg:$addr)>;
514 def : T2Pat<(extloadi1 (ARMWrapper tconstpool:$addr)),
515 (t2LDRBpci tconstpool:$addr)>;
517 def : T2Pat<(extloadi8 t2addrmode_imm12:$addr),
518 (t2LDRBi12 t2addrmode_imm12:$addr)>;
519 def : T2Pat<(extloadi8 t2addrmode_imm8:$addr),
520 (t2LDRBi8 t2addrmode_imm8:$addr)>;
521 def : T2Pat<(extloadi8 t2addrmode_so_reg:$addr),
522 (t2LDRBs t2addrmode_so_reg:$addr)>;
523 def : T2Pat<(extloadi8 (ARMWrapper tconstpool:$addr)),
524 (t2LDRBpci tconstpool:$addr)>;
526 def : T2Pat<(extloadi16 t2addrmode_imm12:$addr),
527 (t2LDRHi12 t2addrmode_imm12:$addr)>;
528 def : T2Pat<(extloadi16 t2addrmode_imm8:$addr),
529 (t2LDRHi8 t2addrmode_imm8:$addr)>;
530 def : T2Pat<(extloadi16 t2addrmode_so_reg:$addr),
531 (t2LDRHs t2addrmode_so_reg:$addr)>;
532 def : T2Pat<(extloadi16 (ARMWrapper tconstpool:$addr)),
533 (t2LDRHpci tconstpool:$addr)>;
537 def t2LDR_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
538 (ins t2addrmode_imm8:$addr),
539 AddrModeT2_i8, IndexModePre, IIC_iLoadiu,
540 "ldr", "\t$dst, $addr!", "$addr.base = $base_wb",
543 def t2LDR_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
544 (ins GPR:$base, t2am_imm8_offset:$offset),
545 AddrModeT2_i8, IndexModePost, IIC_iLoadiu,
546 "ldr", "\t$dst, [$base], $offset", "$base = $base_wb",
549 def t2LDRB_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
550 (ins t2addrmode_imm8:$addr),
551 AddrModeT2_i8, IndexModePre, IIC_iLoadiu,
552 "ldrb", "\t$dst, $addr!", "$addr.base = $base_wb",
554 def t2LDRB_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
555 (ins GPR:$base, t2am_imm8_offset:$offset),
556 AddrModeT2_i8, IndexModePost, IIC_iLoadiu,
557 "ldrb", "\t$dst, [$base], $offset", "$base = $base_wb",
560 def t2LDRH_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
561 (ins t2addrmode_imm8:$addr),
562 AddrModeT2_i8, IndexModePre, IIC_iLoadiu,
563 "ldrh", "\t$dst, $addr!", "$addr.base = $base_wb",
565 def t2LDRH_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
566 (ins GPR:$base, t2am_imm8_offset:$offset),
567 AddrModeT2_i8, IndexModePost, IIC_iLoadiu,
568 "ldrh", "\t$dst, [$base], $offset", "$base = $base_wb",
571 def t2LDRSB_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
572 (ins t2addrmode_imm8:$addr),
573 AddrModeT2_i8, IndexModePre, IIC_iLoadiu,
574 "ldrsb", "\t$dst, $addr!", "$addr.base = $base_wb",
576 def t2LDRSB_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
577 (ins GPR:$base, t2am_imm8_offset:$offset),
578 AddrModeT2_i8, IndexModePost, IIC_iLoadiu,
579 "ldrsb", "\t$dst, [$base], $offset", "$base = $base_wb",
582 def t2LDRSH_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
583 (ins t2addrmode_imm8:$addr),
584 AddrModeT2_i8, IndexModePre, IIC_iLoadiu,
585 "ldrsh", "\t$dst, $addr!", "$addr.base = $base_wb",
587 def t2LDRSH_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
588 (ins GPR:$base, t2am_imm8_offset:$offset),
589 AddrModeT2_i8, IndexModePost, IIC_iLoadiu,
590 "ldrsh", "\t$dst, [$base], $offset", "$base = $base_wb",
595 defm t2STR : T2I_st<"str", BinOpFrag<(store node:$LHS, node:$RHS)>>;
596 defm t2STRB : T2I_st<"strb", BinOpFrag<(truncstorei8 node:$LHS, node:$RHS)>>;
597 defm t2STRH : T2I_st<"strh", BinOpFrag<(truncstorei16 node:$LHS, node:$RHS)>>;
600 let mayLoad = 1, hasExtraSrcRegAllocReq = 1 in
601 def t2STRDi8 : T2Ii8s4<(outs),
602 (ins GPR:$src1, GPR:$src2, t2addrmode_imm8s4:$addr),
603 IIC_iStorer, "strd", "\t$src1, $addr", []>;
606 def t2STR_PRE : T2Iidxldst<(outs GPR:$base_wb),
607 (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset),
608 AddrModeT2_i8, IndexModePre, IIC_iStoreiu,
609 "str", "\t$src, [$base, $offset]!", "$base = $base_wb",
611 (pre_store GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>;
613 def t2STR_POST : T2Iidxldst<(outs GPR:$base_wb),
614 (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset),
615 AddrModeT2_i8, IndexModePost, IIC_iStoreiu,
616 "str", "\t$src, [$base], $offset", "$base = $base_wb",
618 (post_store GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>;
620 def t2STRH_PRE : T2Iidxldst<(outs GPR:$base_wb),
621 (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset),
622 AddrModeT2_i8, IndexModePre, IIC_iStoreiu,
623 "strh", "\t$src, [$base, $offset]!", "$base = $base_wb",
625 (pre_truncsti16 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>;
627 def t2STRH_POST : T2Iidxldst<(outs GPR:$base_wb),
628 (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset),
629 AddrModeT2_i8, IndexModePost, IIC_iStoreiu,
630 "strh", "\t$src, [$base], $offset", "$base = $base_wb",
632 (post_truncsti16 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>;
634 def t2STRB_PRE : T2Iidxldst<(outs GPR:$base_wb),
635 (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset),
636 AddrModeT2_i8, IndexModePre, IIC_iStoreiu,
637 "strb", "\t$src, [$base, $offset]!", "$base = $base_wb",
639 (pre_truncsti8 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>;
641 def t2STRB_POST : T2Iidxldst<(outs GPR:$base_wb),
642 (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset),
643 AddrModeT2_i8, IndexModePost, IIC_iStoreiu,
644 "strb", "\t$src, [$base], $offset", "$base = $base_wb",
646 (post_truncsti8 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>;
649 // FIXME: ldrd / strd pre / post variants
651 //===----------------------------------------------------------------------===//
652 // Load / store multiple Instructions.
655 let mayLoad = 1, hasExtraDefRegAllocReq = 1 in
656 def t2LDM : T2XI<(outs),
657 (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops),
658 IIC_iLoadm, "ldm${addr:submode}${p}${addr:wide}\t$addr, $wb", []>;
660 let mayStore = 1, hasExtraSrcRegAllocReq = 1 in
661 def t2STM : T2XI<(outs),
662 (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops),
663 IIC_iStorem, "stm${addr:submode}${p}${addr:wide}\t$addr, $wb", []>;
665 //===----------------------------------------------------------------------===//
666 // Move Instructions.
669 let neverHasSideEffects = 1 in
670 def t2MOVr : T2sI<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVr,
671 "mov", ".w\t$dst, $src", []>;
673 // AddedComplexity to ensure isel tries t2MOVi before t2MOVi16.
674 let isReMaterializable = 1, isAsCheapAsAMove = 1, AddedComplexity = 1 in
675 def t2MOVi : T2sI<(outs GPR:$dst), (ins t2_so_imm:$src), IIC_iMOVi,
676 "mov", ".w\t$dst, $src",
677 [(set GPR:$dst, t2_so_imm:$src)]>;
679 let isReMaterializable = 1, isAsCheapAsAMove = 1 in
680 def t2MOVi16 : T2I<(outs GPR:$dst), (ins i32imm:$src), IIC_iMOVi,
681 "movw", "\t$dst, $src",
682 [(set GPR:$dst, imm0_65535:$src)]>;
684 let Constraints = "$src = $dst" in
685 def t2MOVTi16 : T2I<(outs GPR:$dst), (ins GPR:$src, i32imm:$imm), IIC_iMOVi,
686 "movt", "\t$dst, $imm",
688 (or (and GPR:$src, 0xffff), lo16AllZero:$imm))]>;
690 def : T2Pat<(or GPR:$src, 0xffff0000), (t2MOVTi16 GPR:$src, 0xffff)>;
692 //===----------------------------------------------------------------------===//
693 // Extend Instructions.
698 defm t2SXTB : T2I_unary_rrot<"sxtb", UnOpFrag<(sext_inreg node:$Src, i8)>>;
699 defm t2SXTH : T2I_unary_rrot<"sxth", UnOpFrag<(sext_inreg node:$Src, i16)>>;
701 defm t2SXTAB : T2I_bin_rrot<"sxtab",
702 BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS, i8))>>;
703 defm t2SXTAH : T2I_bin_rrot<"sxtah",
704 BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS,i16))>>;
706 // TODO: SXT(A){B|H}16
710 let AddedComplexity = 16 in {
711 defm t2UXTB : T2I_unary_rrot<"uxtb" , UnOpFrag<(and node:$Src, 0x000000FF)>>;
712 defm t2UXTH : T2I_unary_rrot<"uxth" , UnOpFrag<(and node:$Src, 0x0000FFFF)>>;
713 defm t2UXTB16 : T2I_unary_rrot<"uxtb16", UnOpFrag<(and node:$Src, 0x00FF00FF)>>;
715 def : T2Pat<(and (shl GPR:$Src, (i32 8)), 0xFF00FF),
716 (t2UXTB16r_rot GPR:$Src, 24)>;
717 def : T2Pat<(and (srl GPR:$Src, (i32 8)), 0xFF00FF),
718 (t2UXTB16r_rot GPR:$Src, 8)>;
720 defm t2UXTAB : T2I_bin_rrot<"uxtab",
721 BinOpFrag<(add node:$LHS, (and node:$RHS, 0x00FF))>>;
722 defm t2UXTAH : T2I_bin_rrot<"uxtah",
723 BinOpFrag<(add node:$LHS, (and node:$RHS, 0xFFFF))>>;
726 //===----------------------------------------------------------------------===//
727 // Arithmetic Instructions.
730 defm t2ADD : T2I_bin_ii12rs<"add", BinOpFrag<(add node:$LHS, node:$RHS)>, 1>;
731 defm t2SUB : T2I_bin_ii12rs<"sub", BinOpFrag<(sub node:$LHS, node:$RHS)>>;
733 // ADD and SUB with 's' bit set. No 12-bit immediate (T4) variants.
734 defm t2ADDS : T2I_bin_s_irs <"add", BinOpFrag<(addc node:$LHS, node:$RHS)>, 1>;
735 defm t2SUBS : T2I_bin_s_irs <"sub", BinOpFrag<(subc node:$LHS, node:$RHS)>>;
737 defm t2ADC : T2I_adde_sube_irs<"adc",BinOpFrag<(adde node:$LHS, node:$RHS)>,1>;
738 defm t2SBC : T2I_adde_sube_irs<"sbc",BinOpFrag<(sube node:$LHS, node:$RHS)>>;
741 defm t2RSB : T2I_rbin_is <"rsb", BinOpFrag<(sub node:$LHS, node:$RHS)>>;
742 defm t2RSBS : T2I_rbin_s_is <"rsb", BinOpFrag<(subc node:$LHS, node:$RHS)>>;
744 // (sub X, imm) gets canonicalized to (add X, -imm). Match this form.
745 let AddedComplexity = 1 in
746 def : T2Pat<(add GPR:$src, imm0_255_neg:$imm),
747 (t2SUBri GPR:$src, imm0_255_neg:$imm)>;
748 def : T2Pat<(add GPR:$src, t2_so_imm_neg:$imm),
749 (t2SUBri GPR:$src, t2_so_imm_neg:$imm)>;
750 def : T2Pat<(add GPR:$src, imm0_4095_neg:$imm),
751 (t2SUBri12 GPR:$src, imm0_4095_neg:$imm)>;
754 //===----------------------------------------------------------------------===//
755 // Shift and rotate Instructions.
758 defm t2LSL : T2I_sh_ir<"lsl", BinOpFrag<(shl node:$LHS, node:$RHS)>>;
759 defm t2LSR : T2I_sh_ir<"lsr", BinOpFrag<(srl node:$LHS, node:$RHS)>>;
760 defm t2ASR : T2I_sh_ir<"asr", BinOpFrag<(sra node:$LHS, node:$RHS)>>;
761 defm t2ROR : T2I_sh_ir<"ror", BinOpFrag<(rotr node:$LHS, node:$RHS)>>;
763 let Uses = [CPSR] in {
764 def t2MOVrx : T2sI<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVsi,
765 "rrx", "\t$dst, $src",
766 [(set GPR:$dst, (ARMrrx GPR:$src))]>;
769 let Defs = [CPSR] in {
770 def t2MOVsrl_flag : T2XI<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVsi,
771 "lsrs.w\t$dst, $src, #1",
772 [(set GPR:$dst, (ARMsrl_flag GPR:$src))]>;
773 def t2MOVsra_flag : T2XI<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVsi,
774 "asrs.w\t$dst, $src, #1",
775 [(set GPR:$dst, (ARMsra_flag GPR:$src))]>;
778 //===----------------------------------------------------------------------===//
779 // Bitwise Instructions.
782 defm t2AND : T2I_bin_w_irs<"and", BinOpFrag<(and node:$LHS, node:$RHS)>, 1>;
783 defm t2ORR : T2I_bin_w_irs<"orr", BinOpFrag<(or node:$LHS, node:$RHS)>, 1>;
784 defm t2EOR : T2I_bin_w_irs<"eor", BinOpFrag<(xor node:$LHS, node:$RHS)>, 1>;
786 defm t2BIC : T2I_bin_w_irs<"bic", BinOpFrag<(and node:$LHS, (not node:$RHS))>>;
788 let Constraints = "$src = $dst" in
789 def t2BFC : T2I<(outs GPR:$dst), (ins GPR:$src, bf_inv_mask_imm:$imm),
790 IIC_iUNAsi, "bfc", "\t$dst, $imm",
791 [(set GPR:$dst, (and GPR:$src, bf_inv_mask_imm:$imm))]>;
793 def t2SBFX : T2I<(outs GPR:$dst), (ins GPR:$src, imm0_31:$lsb, imm0_31:$width),
794 IIC_iALUi, "sbfx", "\t$dst, $src, $lsb, $width", []>;
796 def t2UBFX : T2I<(outs GPR:$dst), (ins GPR:$src, imm0_31:$lsb, imm0_31:$width),
797 IIC_iALUi, "ubfx", "\t$dst, $src, $lsb, $width", []>;
799 // FIXME: A8.6.18 BFI - Bitfield insert (Encoding T1)
801 defm t2ORN : T2I_bin_irs<"orn", BinOpFrag<(or node:$LHS, (not node:$RHS))>>;
803 // Prefer over of t2EORri ra, rb, -1 because mvn has 16-bit version
804 let AddedComplexity = 1 in
805 defm t2MVN : T2I_un_irs <"mvn", UnOpFrag<(not node:$Src)>, 1, 1>;
808 def : T2Pat<(and GPR:$src, t2_so_imm_not:$imm),
809 (t2BICri GPR:$src, t2_so_imm_not:$imm)>;
811 // FIXME: Disable this pattern on Darwin to workaround an assembler bug.
812 def : T2Pat<(or GPR:$src, t2_so_imm_not:$imm),
813 (t2ORNri GPR:$src, t2_so_imm_not:$imm)>,
814 Requires<[IsThumb2]>;
816 def : T2Pat<(t2_so_imm_not:$src),
817 (t2MVNi t2_so_imm_not:$src)>;
819 //===----------------------------------------------------------------------===//
820 // Multiply Instructions.
822 let isCommutable = 1 in
823 def t2MUL: T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32,
824 "mul", "\t$dst, $a, $b",
825 [(set GPR:$dst, (mul GPR:$a, GPR:$b))]>;
827 def t2MLA: T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), IIC_iMAC32,
828 "mla", "\t$dst, $a, $b, $c",
829 [(set GPR:$dst, (add (mul GPR:$a, GPR:$b), GPR:$c))]>;
831 def t2MLS: T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), IIC_iMAC32,
832 "mls", "\t$dst, $a, $b, $c",
833 [(set GPR:$dst, (sub GPR:$c, (mul GPR:$a, GPR:$b)))]>;
835 // Extra precision multiplies with low / high results
836 let neverHasSideEffects = 1 in {
837 let isCommutable = 1 in {
838 def t2SMULL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), IIC_iMUL64,
839 "smull", "\t$ldst, $hdst, $a, $b", []>;
841 def t2UMULL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), IIC_iMUL64,
842 "umull", "\t$ldst, $hdst, $a, $b", []>;
845 // Multiply + accumulate
846 def t2SMLAL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), IIC_iMAC64,
847 "smlal", "\t$ldst, $hdst, $a, $b", []>;
849 def t2UMLAL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), IIC_iMAC64,
850 "umlal", "\t$ldst, $hdst, $a, $b", []>;
852 def t2UMAAL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), IIC_iMAC64,
853 "umaal", "\t$ldst, $hdst, $a, $b", []>;
854 } // neverHasSideEffects
856 // Most significant word multiply
857 def t2SMMUL : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32,
858 "smmul", "\t$dst, $a, $b",
859 [(set GPR:$dst, (mulhs GPR:$a, GPR:$b))]>;
861 def t2SMMLA : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), IIC_iMAC32,
862 "smmla", "\t$dst, $a, $b, $c",
863 [(set GPR:$dst, (add (mulhs GPR:$a, GPR:$b), GPR:$c))]>;
866 def t2SMMLS : T2I <(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), IIC_iMAC32,
867 "smmls", "\t$dst, $a, $b, $c",
868 [(set GPR:$dst, (sub GPR:$c, (mulhs GPR:$a, GPR:$b)))]>;
870 multiclass T2I_smul<string opc, PatFrag opnode> {
871 def BB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32,
872 !strconcat(opc, "bb"), "\t$dst, $a, $b",
873 [(set GPR:$dst, (opnode (sext_inreg GPR:$a, i16),
874 (sext_inreg GPR:$b, i16)))]>;
876 def BT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32,
877 !strconcat(opc, "bt"), "\t$dst, $a, $b",
878 [(set GPR:$dst, (opnode (sext_inreg GPR:$a, i16),
879 (sra GPR:$b, (i32 16))))]>;
881 def TB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32,
882 !strconcat(opc, "tb"), "\t$dst, $a, $b",
883 [(set GPR:$dst, (opnode (sra GPR:$a, (i32 16)),
884 (sext_inreg GPR:$b, i16)))]>;
886 def TT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32,
887 !strconcat(opc, "tt"), "\t$dst, $a, $b",
888 [(set GPR:$dst, (opnode (sra GPR:$a, (i32 16)),
889 (sra GPR:$b, (i32 16))))]>;
891 def WB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL16,
892 !strconcat(opc, "wb"), "\t$dst, $a, $b",
893 [(set GPR:$dst, (sra (opnode GPR:$a,
894 (sext_inreg GPR:$b, i16)), (i32 16)))]>;
896 def WT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL16,
897 !strconcat(opc, "wt"), "\t$dst, $a, $b",
898 [(set GPR:$dst, (sra (opnode GPR:$a,
899 (sra GPR:$b, (i32 16))), (i32 16)))]>;
903 multiclass T2I_smla<string opc, PatFrag opnode> {
904 def BB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16,
905 !strconcat(opc, "bb"), "\t$dst, $a, $b, $acc",
906 [(set GPR:$dst, (add GPR:$acc,
907 (opnode (sext_inreg GPR:$a, i16),
908 (sext_inreg GPR:$b, i16))))]>;
910 def BT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16,
911 !strconcat(opc, "bt"), "\t$dst, $a, $b, $acc",
912 [(set GPR:$dst, (add GPR:$acc, (opnode (sext_inreg GPR:$a, i16),
913 (sra GPR:$b, (i32 16)))))]>;
915 def TB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16,
916 !strconcat(opc, "tb"), "\t$dst, $a, $b, $acc",
917 [(set GPR:$dst, (add GPR:$acc, (opnode (sra GPR:$a, (i32 16)),
918 (sext_inreg GPR:$b, i16))))]>;
920 def TT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16,
921 !strconcat(opc, "tt"), "\t$dst, $a, $b, $acc",
922 [(set GPR:$dst, (add GPR:$acc, (opnode (sra GPR:$a, (i32 16)),
923 (sra GPR:$b, (i32 16)))))]>;
925 def WB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16,
926 !strconcat(opc, "wb"), "\t$dst, $a, $b, $acc",
927 [(set GPR:$dst, (add GPR:$acc, (sra (opnode GPR:$a,
928 (sext_inreg GPR:$b, i16)), (i32 16))))]>;
930 def WT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16,
931 !strconcat(opc, "wt"), "\t$dst, $a, $b, $acc",
932 [(set GPR:$dst, (add GPR:$acc, (sra (opnode GPR:$a,
933 (sra GPR:$b, (i32 16))), (i32 16))))]>;
936 defm t2SMUL : T2I_smul<"smul", BinOpFrag<(mul node:$LHS, node:$RHS)>>;
937 defm t2SMLA : T2I_smla<"smla", BinOpFrag<(mul node:$LHS, node:$RHS)>>;
939 // TODO: Halfword multiple accumulate long: SMLAL<x><y>
940 // TODO: Dual halfword multiple: SMUAD, SMUSD, SMLAD, SMLSD, SMLALD, SMLSLD
943 //===----------------------------------------------------------------------===//
944 // Misc. Arithmetic Instructions.
947 def t2CLZ : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
948 "clz", "\t$dst, $src",
949 [(set GPR:$dst, (ctlz GPR:$src))]>;
951 def t2REV : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
952 "rev", ".w\t$dst, $src",
953 [(set GPR:$dst, (bswap GPR:$src))]>;
955 def t2REV16 : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
956 "rev16", ".w\t$dst, $src",
958 (or (and (srl GPR:$src, (i32 8)), 0xFF),
959 (or (and (shl GPR:$src, (i32 8)), 0xFF00),
960 (or (and (srl GPR:$src, (i32 8)), 0xFF0000),
961 (and (shl GPR:$src, (i32 8)), 0xFF000000)))))]>;
963 def t2REVSH : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
964 "revsh", ".w\t$dst, $src",
967 (or (srl (and GPR:$src, 0xFF00), (i32 8)),
968 (shl GPR:$src, (i32 8))), i16))]>;
970 def t2PKHBT : T2I<(outs GPR:$dst), (ins GPR:$src1, GPR:$src2, i32imm:$shamt),
971 IIC_iALUsi, "pkhbt", "\t$dst, $src1, $src2, LSL $shamt",
972 [(set GPR:$dst, (or (and GPR:$src1, 0xFFFF),
973 (and (shl GPR:$src2, (i32 imm:$shamt)),
976 // Alternate cases for PKHBT where identities eliminate some nodes.
977 def : T2Pat<(or (and GPR:$src1, 0xFFFF), (and GPR:$src2, 0xFFFF0000)),
978 (t2PKHBT GPR:$src1, GPR:$src2, 0)>;
979 def : T2Pat<(or (and GPR:$src1, 0xFFFF), (shl GPR:$src2, imm16_31:$shamt)),
980 (t2PKHBT GPR:$src1, GPR:$src2, imm16_31:$shamt)>;
982 def t2PKHTB : T2I<(outs GPR:$dst), (ins GPR:$src1, GPR:$src2, i32imm:$shamt),
983 IIC_iALUsi, "pkhtb", "\t$dst, $src1, $src2, ASR $shamt",
984 [(set GPR:$dst, (or (and GPR:$src1, 0xFFFF0000),
985 (and (sra GPR:$src2, imm16_31:$shamt),
988 // Alternate cases for PKHTB where identities eliminate some nodes. Note that
989 // a shift amount of 0 is *not legal* here, it is PKHBT instead.
990 def : T2Pat<(or (and GPR:$src1, 0xFFFF0000), (srl GPR:$src2, (i32 16))),
991 (t2PKHTB GPR:$src1, GPR:$src2, 16)>;
992 def : T2Pat<(or (and GPR:$src1, 0xFFFF0000),
993 (and (srl GPR:$src2, imm1_15:$shamt), 0xFFFF)),
994 (t2PKHTB GPR:$src1, GPR:$src2, imm1_15:$shamt)>;
996 //===----------------------------------------------------------------------===//
997 // Comparison Instructions...
1000 defm t2CMP : T2I_cmp_is<"cmp",
1001 BinOpFrag<(ARMcmp node:$LHS, node:$RHS)>>;
1002 defm t2CMPz : T2I_cmp_is<"cmp",
1003 BinOpFrag<(ARMcmpZ node:$LHS, node:$RHS)>>;
1005 defm t2CMN : T2I_cmp_is<"cmn",
1006 BinOpFrag<(ARMcmp node:$LHS,(ineg node:$RHS))>>;
1007 defm t2CMNz : T2I_cmp_is<"cmn",
1008 BinOpFrag<(ARMcmpZ node:$LHS,(ineg node:$RHS))>>;
1010 def : T2Pat<(ARMcmp GPR:$src, t2_so_imm_neg:$imm),
1011 (t2CMNri GPR:$src, t2_so_imm_neg:$imm)>;
1013 def : T2Pat<(ARMcmpZ GPR:$src, t2_so_imm_neg:$imm),
1014 (t2CMNri GPR:$src, t2_so_imm_neg:$imm)>;
1016 defm t2TST : T2I_cmp_is<"tst",
1017 BinOpFrag<(ARMcmpZ (and node:$LHS, node:$RHS), 0)>>;
1018 defm t2TEQ : T2I_cmp_is<"teq",
1019 BinOpFrag<(ARMcmpZ (xor node:$LHS, node:$RHS), 0)>>;
1021 // A8.6.27 CBNZ, CBZ - Compare and branch on (non)zero.
1022 // Short range conditional branch. Looks awesome for loops. Need to figure
1023 // out how to use this one.
1026 // Conditional moves
1027 // FIXME: should be able to write a pattern for ARMcmov, but can't use
1028 // a two-value operand where a dag node expects two operands. :(
1029 def t2MOVCCr : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true), IIC_iCMOVr,
1030 "mov", ".w\t$dst, $true",
1031 [/*(set GPR:$dst, (ARMcmov GPR:$false, GPR:$true, imm:$cc, CCR:$ccr))*/]>,
1032 RegConstraint<"$false = $dst">;
1034 def t2MOVCCi : T2I<(outs GPR:$dst), (ins GPR:$false, t2_so_imm:$true),
1035 IIC_iCMOVi, "mov", ".w\t$dst, $true",
1036 [/*(set GPR:$dst, (ARMcmov GPR:$false, t2_so_imm:$true, imm:$cc, CCR:$ccr))*/]>,
1037 RegConstraint<"$false = $dst">;
1039 def t2MOVCClsl : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true, i32imm:$rhs),
1040 IIC_iCMOVsi, "lsl", ".w\t$dst, $true, $rhs", []>,
1041 RegConstraint<"$false = $dst">;
1042 def t2MOVCClsr : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true, i32imm:$rhs),
1043 IIC_iCMOVsi, "lsr", ".w\t$dst, $true, $rhs", []>,
1044 RegConstraint<"$false = $dst">;
1045 def t2MOVCCasr : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true, i32imm:$rhs),
1046 IIC_iCMOVsi, "asr", ".w\t$dst, $true, $rhs", []>,
1047 RegConstraint<"$false = $dst">;
1048 def t2MOVCCror : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true, i32imm:$rhs),
1049 IIC_iCMOVsi, "ror", ".w\t$dst, $true, $rhs", []>,
1050 RegConstraint<"$false = $dst">;
1052 //===----------------------------------------------------------------------===//
1056 // __aeabi_read_tp preserves the registers r1-r3.
1058 Defs = [R0, R12, LR, CPSR] in {
1059 def t2TPsoft : T2XI<(outs), (ins), IIC_Br,
1060 "bl\t__aeabi_read_tp",
1061 [(set R0, ARMthread_pointer)]>;
1064 //===----------------------------------------------------------------------===//
1065 // SJLJ Exception handling intrinsics
1066 // eh_sjlj_setjmp() is an instruction sequence to store the return
1067 // address and save #0 in R0 for the non-longjmp case.
1068 // Since by its nature we may be coming from some other function to get
1069 // here, and we're using the stack frame for the containing function to
1070 // save/restore registers, we can't keep anything live in regs across
1071 // the eh_sjlj_setjmp(), else it will almost certainly have been tromped upon
1072 // when we get here from a longjmp(). We force everthing out of registers
1073 // except for our own input by listing the relevant registers in Defs. By
1074 // doing so, we also cause the prologue/epilogue code to actively preserve
1075 // all of the callee-saved resgisters, which is exactly what we want.
1077 [ R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, LR, D0,
1078 D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15,
1079 D16, D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30,
1081 def t2Int_eh_sjlj_setjmp : Thumb2XI<(outs), (ins GPR:$src),
1082 AddrModeNone, SizeSpecial, NoItinerary,
1083 "str.w\tsp, [$src, #+8] @ eh_setjmp begin\n"
1085 "\torr.w\tr12, r12, #1\n"
1086 "\tstr.w\tr12, [$src, #+4]\n"
1089 "0:\tmovs\tr0, #1 @ eh_setjmp end\n"
1091 [(set R0, (ARMeh_sjlj_setjmp GPR:$src))]>;
1096 //===----------------------------------------------------------------------===//
1097 // Control-Flow Instructions
1100 // FIXME: remove when we have a way to marking a MI with these properties.
1101 // FIXME: $dst1 should be a def. But the extra ops must be in the end of the
1103 // FIXME: Should pc be an implicit operand like PICADD, etc?
1104 let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1,
1105 hasExtraDefRegAllocReq = 1 in
1106 def t2LDM_RET : T2XI<(outs),
1107 (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops),
1108 IIC_Br, "ldm${addr:submode}${p}${addr:wide}\t$addr, $wb",
1111 let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
1112 let isPredicable = 1 in
1113 def t2B : T2XI<(outs), (ins brtarget:$target), IIC_Br,
1117 let isNotDuplicable = 1, isIndirectBranch = 1 in {
1120 (ins GPR:$target, GPR:$index, jt2block_operand:$jt, i32imm:$id),
1121 IIC_Br, "mov\tpc, $target\n$jt",
1122 [(ARMbr2jt GPR:$target, GPR:$index, tjumptable:$jt, imm:$id)]>;
1124 // FIXME: Add a non-pc based case that can be predicated.
1127 (ins tb_addrmode:$index, jt2block_operand:$jt, i32imm:$id),
1128 IIC_Br, "tbb\t$index\n$jt", []>;
1132 (ins tb_addrmode:$index, jt2block_operand:$jt, i32imm:$id),
1133 IIC_Br, "tbh\t$index\n$jt", []>;
1134 } // isNotDuplicable, isIndirectBranch
1136 } // isBranch, isTerminator, isBarrier
1138 // FIXME: should be able to write a pattern for ARMBrcond, but can't use
1139 // a two-value operand where a dag node expects two operands. :(
1140 let isBranch = 1, isTerminator = 1 in
1141 def t2Bcc : T2I<(outs), (ins brtarget:$target), IIC_Br,
1143 [/*(ARMbrcond bb:$target, imm:$cc)*/]>;
1147 def t2IT : Thumb2XI<(outs), (ins it_pred:$cc, it_mask:$mask),
1148 AddrModeNone, Size2Bytes, IIC_iALUx,
1149 "it$mask\t$cc", "", []>;
1151 //===----------------------------------------------------------------------===//
1152 // Non-Instruction Patterns
1155 // Two piece so_imms.
1156 def : T2Pat<(or GPR:$LHS, t2_so_imm2part:$RHS),
1157 (t2ORRri (t2ORRri GPR:$LHS, (t2_so_imm2part_1 imm:$RHS)),
1158 (t2_so_imm2part_2 imm:$RHS))>;
1159 def : T2Pat<(xor GPR:$LHS, t2_so_imm2part:$RHS),
1160 (t2EORri (t2EORri GPR:$LHS, (t2_so_imm2part_1 imm:$RHS)),
1161 (t2_so_imm2part_2 imm:$RHS))>;
1162 def : T2Pat<(add GPR:$LHS, t2_so_imm2part:$RHS),
1163 (t2ADDri (t2ADDri GPR:$LHS, (t2_so_imm2part_1 imm:$RHS)),
1164 (t2_so_imm2part_2 imm:$RHS))>;
1165 def : T2Pat<(sub GPR:$LHS, t2_so_imm2part:$RHS),
1166 (t2SUBri (t2SUBri GPR:$LHS, (t2_so_imm2part_1 imm:$RHS)),
1167 (t2_so_imm2part_2 imm:$RHS))>;
1169 // ConstantPool, GlobalAddress, and JumpTable
1170 def : T2Pat<(ARMWrapper tglobaladdr :$dst), (t2LEApcrel tglobaladdr :$dst)>;
1171 def : T2Pat<(ARMWrapper tconstpool :$dst), (t2LEApcrel tconstpool :$dst)>;
1172 def : T2Pat<(ARMWrapperJT tjumptable:$dst, imm:$id),
1173 (t2LEApcrelJT tjumptable:$dst, imm:$id)>;
1175 // 32-bit immediate using movw + movt.
1176 // This is a single pseudo instruction to make it re-materializable. Remove
1177 // when we can do generalized remat.
1178 let isReMaterializable = 1 in
1179 def t2MOVi32imm : T2Ix2<(outs GPR:$dst), (ins i32imm:$src), IIC_iMOVi,
1180 "movw", "\t$dst, ${src:lo16}\n\tmovt${p}\t$dst, ${src:hi16}",
1181 [(set GPR:$dst, (i32 imm:$src))]>;
1183 // Pseudo instruction that combines ldr from constpool and add pc. This should
1184 // be expanded into two instructions late to allow if-conversion and
1186 let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in
1187 def t2LDRpci_pic : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr, pclabel:$cp),
1188 NoItinerary, "@ ldr.w\t$dst, $addr\n$cp:\n\tadd\t$dst, pc",
1189 [(set GPR:$dst, (ARMpic_add (load (ARMWrapper tconstpool:$addr)),
1191 Requires<[IsThumb2]>;