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 /// imm1_31 predicate - True if the 32-bit immediate is in the range [1,31].
73 def imm1_31 : PatLeaf<(i32 imm), [{
74 return (int32_t)N->getZExtValue() >= 1 && (int32_t)N->getZExtValue() < 32;
77 /// imm0_4095 predicate - True if the 32-bit immediate is in the range [0.4095].
78 def imm0_4095 : Operand<i32>,
80 return (uint32_t)N->getZExtValue() < 4096;
83 def imm0_4095_neg : PatLeaf<(i32 imm), [{
84 return (uint32_t)(-N->getZExtValue()) < 4096;
87 def imm0_255_neg : PatLeaf<(i32 imm), [{
88 return (uint32_t)(-N->getZExtValue()) < 255;
91 // Define Thumb2 specific addressing modes.
93 // t2addrmode_imm12 := reg + imm12
94 def t2addrmode_imm12 : Operand<i32>,
95 ComplexPattern<i32, 2, "SelectT2AddrModeImm12", []> {
96 let PrintMethod = "printT2AddrModeImm12Operand";
97 let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
100 // t2addrmode_imm8 := reg - imm8
101 def t2addrmode_imm8 : Operand<i32>,
102 ComplexPattern<i32, 2, "SelectT2AddrModeImm8", []> {
103 let PrintMethod = "printT2AddrModeImm8Operand";
104 let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
107 def t2am_imm8_offset : Operand<i32>,
108 ComplexPattern<i32, 1, "SelectT2AddrModeImm8Offset", []>{
109 let PrintMethod = "printT2AddrModeImm8OffsetOperand";
112 // t2addrmode_imm8s4 := reg +/- (imm8 << 2)
113 def t2addrmode_imm8s4 : Operand<i32>,
114 ComplexPattern<i32, 2, "SelectT2AddrModeImm8s4", []> {
115 let PrintMethod = "printT2AddrModeImm8s4Operand";
116 let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
119 // t2addrmode_so_reg := reg + (reg << imm2)
120 def t2addrmode_so_reg : Operand<i32>,
121 ComplexPattern<i32, 3, "SelectT2AddrModeSoReg", []> {
122 let PrintMethod = "printT2AddrModeSoRegOperand";
123 let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);
127 //===----------------------------------------------------------------------===//
128 // Multiclass helpers...
131 /// T2I_un_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a
132 /// unary operation that produces a value. These are predicable and can be
133 /// changed to modify CPSR.
134 multiclass T2I_un_irs<string opc, PatFrag opnode, bit Cheap = 0, bit ReMat = 0>{
136 def i : T2sI<(outs GPR:$dst), (ins t2_so_imm:$src), IIC_iMOVi,
138 [(set GPR:$dst, (opnode t2_so_imm:$src))]> {
139 let isAsCheapAsAMove = Cheap;
140 let isReMaterializable = ReMat;
143 def r : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVr,
144 opc, ".w $dst, $src",
145 [(set GPR:$dst, (opnode GPR:$src))]>;
147 def s : T2I<(outs GPR:$dst), (ins t2_so_reg:$src), IIC_iMOVsi,
148 opc, ".w $dst, $src",
149 [(set GPR:$dst, (opnode t2_so_reg:$src))]>;
152 /// T2I_bin_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a
153 // binary operation that produces a value. These are predicable and can be
154 /// changed to modify CPSR.
155 multiclass T2I_bin_irs<string opc, PatFrag opnode,
156 bit Commutable = 0, string wide =""> {
158 def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi,
159 opc, " $dst, $lhs, $rhs",
160 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>;
162 def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr,
163 opc, !strconcat(wide, " $dst, $lhs, $rhs"),
164 [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]> {
165 let isCommutable = Commutable;
168 def rs : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi,
169 opc, !strconcat(wide, " $dst, $lhs, $rhs"),
170 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>;
173 /// T2I_bin_w_irs - Same as T2I_bin_irs except these operations need
174 // the ".w" prefix to indicate that they are wide.
175 multiclass T2I_bin_w_irs<string opc, PatFrag opnode, bit Commutable = 0> :
176 T2I_bin_irs<opc, opnode, Commutable, ".w">;
178 /// T2I_rbin_is - Same as T2I_bin_irs except the order of operands are
179 /// reversed. It doesn't define the 'rr' form since it's handled by its
180 /// T2I_bin_irs counterpart.
181 multiclass T2I_rbin_is<string opc, PatFrag opnode> {
183 def ri : T2I<(outs GPR:$dst), (ins GPR:$rhs, t2_so_imm:$lhs), IIC_iALUi,
184 opc, ".w $dst, $rhs, $lhs",
185 [(set GPR:$dst, (opnode t2_so_imm:$lhs, GPR:$rhs))]>;
187 def rs : T2I<(outs GPR:$dst), (ins GPR:$rhs, t2_so_reg:$lhs), IIC_iALUsi,
188 opc, " $dst, $rhs, $lhs",
189 [(set GPR:$dst, (opnode t2_so_reg:$lhs, GPR:$rhs))]>;
192 /// T2I_bin_s_irs - Similar to T2I_bin_irs except it sets the 's' bit so the
193 /// instruction modifies the CPSR register.
194 let Defs = [CPSR] in {
195 multiclass T2I_bin_s_irs<string opc, PatFrag opnode, bit Commutable = 0> {
197 def ri : T2I<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi,
198 !strconcat(opc, "s"), ".w $dst, $lhs, $rhs",
199 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>;
201 def rr : T2I<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr,
202 !strconcat(opc, "s"), ".w $dst, $lhs, $rhs",
203 [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]> {
204 let isCommutable = Commutable;
207 def rs : T2I<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi,
208 !strconcat(opc, "s"), ".w $dst, $lhs, $rhs",
209 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>;
213 /// T2I_bin_ii12rs - Defines a set of (op reg, {so_imm|imm0_4095|r|so_reg})
214 /// patterns for a binary operation that produces a value.
215 multiclass T2I_bin_ii12rs<string opc, PatFrag opnode, bit Commutable = 0> {
217 def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi,
218 opc, ".w $dst, $lhs, $rhs",
219 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>;
221 def ri12 : T2sI<(outs GPR:$dst), (ins GPR:$lhs, imm0_4095:$rhs), IIC_iALUi,
222 !strconcat(opc, "w"), " $dst, $lhs, $rhs",
223 [(set GPR:$dst, (opnode GPR:$lhs, imm0_4095:$rhs))]>;
225 def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr,
226 opc, ".w $dst, $lhs, $rhs",
227 [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]> {
228 let isCommutable = Commutable;
231 def rs : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi,
232 opc, ".w $dst, $lhs, $rhs",
233 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>;
236 /// T2I_adde_sube_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a
237 /// binary operation that produces a value and use and define the carry bit.
238 /// It's not predicable.
239 let Uses = [CPSR] in {
240 multiclass T2I_adde_sube_irs<string opc, PatFrag opnode, bit Commutable = 0> {
242 def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi,
243 opc, " $dst, $lhs, $rhs",
244 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>,
245 Requires<[IsThumb2, CarryDefIsUnused]>;
247 def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr,
248 opc, ".w $dst, $lhs, $rhs",
249 [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>,
250 Requires<[IsThumb2, CarryDefIsUnused]> {
251 let isCommutable = Commutable;
254 def rs : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi,
255 opc, ".w $dst, $lhs, $rhs",
256 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>,
257 Requires<[IsThumb2, CarryDefIsUnused]>;
258 // Carry setting variants
260 def Sri : T2XI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi,
261 !strconcat(opc, "s $dst, $lhs, $rhs"),
262 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>,
263 Requires<[IsThumb2, CarryDefIsUsed]> {
267 def Srr : T2XI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr,
268 !strconcat(opc, "s.w $dst, $lhs, $rhs"),
269 [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>,
270 Requires<[IsThumb2, CarryDefIsUsed]> {
272 let isCommutable = Commutable;
275 def Srs : T2XI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi,
276 !strconcat(opc, "s.w $dst, $lhs, $rhs"),
277 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>,
278 Requires<[IsThumb2, CarryDefIsUsed]> {
284 /// T2I_rbin_s_is - Same as T2I_rbin_is except sets 's' bit.
285 let Defs = [CPSR] in {
286 multiclass T2I_rbin_s_is<string opc, PatFrag opnode> {
288 def ri : T2XI<(outs GPR:$dst), (ins GPR:$rhs, t2_so_imm:$lhs, cc_out:$s),
290 !strconcat(opc, "${s}.w $dst, $rhs, $lhs"),
291 [(set GPR:$dst, (opnode t2_so_imm:$lhs, GPR:$rhs))]>;
293 def rs : T2XI<(outs GPR:$dst), (ins GPR:$rhs, t2_so_reg:$lhs, cc_out:$s),
295 !strconcat(opc, "${s} $dst, $rhs, $lhs"),
296 [(set GPR:$dst, (opnode t2_so_reg:$lhs, GPR:$rhs))]>;
300 /// T2I_sh_ir - Defines a set of (op reg, {so_imm|r}) patterns for a shift /
301 // rotate operation that produces a value.
302 multiclass T2I_sh_ir<string opc, PatFrag opnode> {
304 def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs), IIC_iMOVsi,
305 opc, ".w $dst, $lhs, $rhs",
306 [(set GPR:$dst, (opnode GPR:$lhs, imm1_31:$rhs))]>;
308 def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iMOVsr,
309 opc, ".w $dst, $lhs, $rhs",
310 [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>;
313 /// T2I_cmp_is - Defines a set of (op r, {so_imm|r|so_reg}) cmp / test
314 /// patterns. Similar to T2I_bin_irs except the instruction does not produce
315 /// a explicit result, only implicitly set CPSR.
316 let Defs = [CPSR] in {
317 multiclass T2I_cmp_is<string opc, PatFrag opnode> {
319 def ri : T2I<(outs), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iCMPi,
320 opc, ".w $lhs, $rhs",
321 [(opnode GPR:$lhs, t2_so_imm:$rhs)]>;
323 def rr : T2I<(outs), (ins GPR:$lhs, GPR:$rhs), IIC_iCMPr,
324 opc, ".w $lhs, $rhs",
325 [(opnode GPR:$lhs, GPR:$rhs)]>;
327 def rs : T2I<(outs), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iCMPsi,
328 opc, ".w $lhs, $rhs",
329 [(opnode GPR:$lhs, t2_so_reg:$rhs)]>;
333 /// T2I_ld - Defines a set of (op r, {imm12|imm8|so_reg}) load patterns.
334 multiclass T2I_ld<string opc, PatFrag opnode> {
335 def i12 : T2Ii12<(outs GPR:$dst), (ins t2addrmode_imm12:$addr), IIC_iLoadi,
336 opc, ".w $dst, $addr",
337 [(set GPR:$dst, (opnode t2addrmode_imm12:$addr))]>;
338 def i8 : T2Ii8 <(outs GPR:$dst), (ins t2addrmode_imm8:$addr), IIC_iLoadi,
340 [(set GPR:$dst, (opnode t2addrmode_imm8:$addr))]>;
341 def s : T2Iso <(outs GPR:$dst), (ins t2addrmode_so_reg:$addr), IIC_iLoadr,
342 opc, ".w $dst, $addr",
343 [(set GPR:$dst, (opnode t2addrmode_so_reg:$addr))]>;
344 def pci : T2Ipc <(outs GPR:$dst), (ins i32imm:$addr), IIC_iLoadi,
345 opc, ".w $dst, $addr",
346 [(set GPR:$dst, (opnode (ARMWrapper tconstpool:$addr)))]>;
349 /// T2I_st - Defines a set of (op r, {imm12|imm8|so_reg}) store patterns.
350 multiclass T2I_st<string opc, PatFrag opnode> {
351 def i12 : T2Ii12<(outs), (ins GPR:$src, t2addrmode_imm12:$addr), IIC_iStorei,
352 opc, ".w $src, $addr",
353 [(opnode GPR:$src, t2addrmode_imm12:$addr)]>;
354 def i8 : T2Ii8 <(outs), (ins GPR:$src, t2addrmode_imm8:$addr), IIC_iStorei,
356 [(opnode GPR:$src, t2addrmode_imm8:$addr)]>;
357 def s : T2Iso <(outs), (ins GPR:$src, t2addrmode_so_reg:$addr), IIC_iStorer,
358 opc, ".w $src, $addr",
359 [(opnode GPR:$src, t2addrmode_so_reg:$addr)]>;
362 /// T2I_picld - Defines the PIC load pattern.
363 class T2I_picld<string opc, PatFrag opnode> :
364 T2I<(outs GPR:$dst), (ins addrmodepc:$addr), IIC_iLoadi,
365 !strconcat("\n${addr:label}:\n\t", opc), " $dst, $addr",
366 [(set GPR:$dst, (opnode addrmodepc:$addr))]>;
368 /// T2I_picst - Defines the PIC store pattern.
369 class T2I_picst<string opc, PatFrag opnode> :
370 T2I<(outs), (ins GPR:$src, addrmodepc:$addr), IIC_iStorer,
371 !strconcat("\n${addr:label}:\n\t", opc), " $src, $addr",
372 [(opnode GPR:$src, addrmodepc:$addr)]>;
375 /// T2I_unary_rrot - A unary operation with two forms: one whose operand is a
376 /// register and one whose operand is a register rotated by 8/16/24.
377 multiclass T2I_unary_rrot<string opc, PatFrag opnode> {
378 def r : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
379 opc, ".w $dst, $src",
380 [(set GPR:$dst, (opnode GPR:$src))]>;
381 def r_rot : T2I<(outs GPR:$dst), (ins GPR:$src, i32imm:$rot), IIC_iUNAsi,
382 opc, ".w $dst, $src, ror $rot",
383 [(set GPR:$dst, (opnode (rotr GPR:$src, rot_imm:$rot)))]>;
386 /// T2I_bin_rrot - A binary operation with two forms: one whose operand is a
387 /// register and one whose operand is a register rotated by 8/16/24.
388 multiclass T2I_bin_rrot<string opc, PatFrag opnode> {
389 def rr : T2I<(outs GPR:$dst), (ins GPR:$LHS, GPR:$RHS), IIC_iALUr,
390 opc, " $dst, $LHS, $RHS",
391 [(set GPR:$dst, (opnode GPR:$LHS, GPR:$RHS))]>;
392 def rr_rot : T2I<(outs GPR:$dst), (ins GPR:$LHS, GPR:$RHS, i32imm:$rot),
393 IIC_iALUsr, opc, " $dst, $LHS, $RHS, ror $rot",
394 [(set GPR:$dst, (opnode GPR:$LHS,
395 (rotr GPR:$RHS, rot_imm:$rot)))]>;
398 //===----------------------------------------------------------------------===//
400 //===----------------------------------------------------------------------===//
402 //===----------------------------------------------------------------------===//
403 // Miscellaneous Instructions.
406 // LEApcrel - Load a pc-relative address into a register without offending the
408 def t2LEApcrel : T2XI<(outs GPR:$dst), (ins i32imm:$label, pred:$p), IIC_iALUi,
409 "adr$p.w $dst, #$label", []>;
411 def t2LEApcrelJT : T2XI<(outs GPR:$dst),
412 (ins i32imm:$label, nohash_imm:$id, pred:$p), IIC_iALUi,
413 "adr$p.w $dst, #${label}_${id}", []>;
415 // ADD r, sp, {so_imm|i12}
416 def t2ADDrSPi : T2sI<(outs GPR:$dst), (ins GPR:$sp, t2_so_imm:$imm),
417 IIC_iALUi, "add", ".w $dst, $sp, $imm", []>;
418 def t2ADDrSPi12 : T2I<(outs GPR:$dst), (ins GPR:$sp, imm0_4095:$imm),
419 IIC_iALUi, "addw", " $dst, $sp, $imm", []>;
422 def t2ADDrSPs : T2sI<(outs GPR:$dst), (ins GPR:$sp, t2_so_reg:$rhs),
423 IIC_iALUsi, "add", ".w $dst, $sp, $rhs", []>;
425 // SUB r, sp, {so_imm|i12}
426 def t2SUBrSPi : T2sI<(outs GPR:$dst), (ins GPR:$sp, t2_so_imm:$imm),
427 IIC_iALUi, "sub", ".w $dst, $sp, $imm", []>;
428 def t2SUBrSPi12 : T2I<(outs GPR:$dst), (ins GPR:$sp, imm0_4095:$imm),
429 IIC_iALUi, "subw", " $dst, $sp, $imm", []>;
432 def t2SUBrSPs : T2sI<(outs GPR:$dst), (ins GPR:$sp, t2_so_reg:$rhs),
434 "sub", " $dst, $sp, $rhs", []>;
437 // Pseudo instruction that will expand into a t2SUBrSPi + a copy.
438 let usesCustomDAGSchedInserter = 1 in { // Expanded by the scheduler.
439 def t2SUBrSPi_ : PseudoInst<(outs GPR:$dst), (ins GPR:$sp, t2_so_imm:$imm),
440 NoItinerary, "@ sub.w $dst, $sp, $imm", []>;
441 def t2SUBrSPi12_ : PseudoInst<(outs GPR:$dst), (ins GPR:$sp, imm0_4095:$imm),
442 NoItinerary, "@ subw $dst, $sp, $imm", []>;
443 def t2SUBrSPs_ : PseudoInst<(outs GPR:$dst), (ins GPR:$sp, t2_so_reg:$rhs),
444 NoItinerary, "@ sub $dst, $sp, $rhs", []>;
445 } // usesCustomDAGSchedInserter
448 //===----------------------------------------------------------------------===//
449 // Load / store Instructions.
453 let canFoldAsLoad = 1 in
454 defm t2LDR : T2I_ld<"ldr", UnOpFrag<(load node:$Src)>>;
456 // Loads with zero extension
457 defm t2LDRH : T2I_ld<"ldrh", UnOpFrag<(zextloadi16 node:$Src)>>;
458 defm t2LDRB : T2I_ld<"ldrb", UnOpFrag<(zextloadi8 node:$Src)>>;
460 // Loads with sign extension
461 defm t2LDRSH : T2I_ld<"ldrsh", UnOpFrag<(sextloadi16 node:$Src)>>;
462 defm t2LDRSB : T2I_ld<"ldrsb", UnOpFrag<(sextloadi8 node:$Src)>>;
464 let mayLoad = 1, hasExtraDefRegAllocReq = 1 in {
466 def t2LDRDi8 : T2Ii8s4<(outs GPR:$dst1, GPR:$dst2),
467 (ins t2addrmode_imm8s4:$addr),
468 IIC_iLoadi, "ldrd", " $dst1, $addr", []>;
469 def t2LDRDpci : T2Ii8s4<(outs GPR:$dst1, GPR:$dst2),
470 (ins i32imm:$addr), IIC_iLoadi,
471 "ldrd", " $dst1, $addr", []>;
474 // zextload i1 -> zextload i8
475 def : T2Pat<(zextloadi1 t2addrmode_imm12:$addr),
476 (t2LDRBi12 t2addrmode_imm12:$addr)>;
477 def : T2Pat<(zextloadi1 t2addrmode_imm8:$addr),
478 (t2LDRBi8 t2addrmode_imm8:$addr)>;
479 def : T2Pat<(zextloadi1 t2addrmode_so_reg:$addr),
480 (t2LDRBs t2addrmode_so_reg:$addr)>;
481 def : T2Pat<(zextloadi1 (ARMWrapper tconstpool:$addr)),
482 (t2LDRBpci tconstpool:$addr)>;
484 // extload -> zextload
485 // FIXME: Reduce the number of patterns by legalizing extload to zextload
487 def : T2Pat<(extloadi1 t2addrmode_imm12:$addr),
488 (t2LDRBi12 t2addrmode_imm12:$addr)>;
489 def : T2Pat<(extloadi1 t2addrmode_imm8:$addr),
490 (t2LDRBi8 t2addrmode_imm8:$addr)>;
491 def : T2Pat<(extloadi1 t2addrmode_so_reg:$addr),
492 (t2LDRBs t2addrmode_so_reg:$addr)>;
493 def : T2Pat<(extloadi1 (ARMWrapper tconstpool:$addr)),
494 (t2LDRBpci tconstpool:$addr)>;
496 def : T2Pat<(extloadi8 t2addrmode_imm12:$addr),
497 (t2LDRBi12 t2addrmode_imm12:$addr)>;
498 def : T2Pat<(extloadi8 t2addrmode_imm8:$addr),
499 (t2LDRBi8 t2addrmode_imm8:$addr)>;
500 def : T2Pat<(extloadi8 t2addrmode_so_reg:$addr),
501 (t2LDRBs t2addrmode_so_reg:$addr)>;
502 def : T2Pat<(extloadi8 (ARMWrapper tconstpool:$addr)),
503 (t2LDRBpci tconstpool:$addr)>;
505 def : T2Pat<(extloadi16 t2addrmode_imm12:$addr),
506 (t2LDRHi12 t2addrmode_imm12:$addr)>;
507 def : T2Pat<(extloadi16 t2addrmode_imm8:$addr),
508 (t2LDRHi8 t2addrmode_imm8:$addr)>;
509 def : T2Pat<(extloadi16 t2addrmode_so_reg:$addr),
510 (t2LDRHs t2addrmode_so_reg:$addr)>;
511 def : T2Pat<(extloadi16 (ARMWrapper tconstpool:$addr)),
512 (t2LDRHpci tconstpool:$addr)>;
516 def t2LDR_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
517 (ins t2addrmode_imm8:$addr),
518 AddrModeT2_i8, IndexModePre, IIC_iLoadiu,
519 "ldr", " $dst, $addr!", "$addr.base = $base_wb",
522 def t2LDR_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
523 (ins GPR:$base, t2am_imm8_offset:$offset),
524 AddrModeT2_i8, IndexModePost, IIC_iLoadiu,
525 "ldr", " $dst, [$base], $offset", "$base = $base_wb",
528 def t2LDRB_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
529 (ins t2addrmode_imm8:$addr),
530 AddrModeT2_i8, IndexModePre, IIC_iLoadiu,
531 "ldrb", " $dst, $addr!", "$addr.base = $base_wb",
533 def t2LDRB_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
534 (ins GPR:$base, t2am_imm8_offset:$offset),
535 AddrModeT2_i8, IndexModePost, IIC_iLoadiu,
536 "ldrb", " $dst, [$base], $offset", "$base = $base_wb",
539 def t2LDRH_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
540 (ins t2addrmode_imm8:$addr),
541 AddrModeT2_i8, IndexModePre, IIC_iLoadiu,
542 "ldrh", " $dst, $addr!", "$addr.base = $base_wb",
544 def t2LDRH_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
545 (ins GPR:$base, t2am_imm8_offset:$offset),
546 AddrModeT2_i8, IndexModePost, IIC_iLoadiu,
547 "ldrh", " $dst, [$base], $offset", "$base = $base_wb",
550 def t2LDRSB_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
551 (ins t2addrmode_imm8:$addr),
552 AddrModeT2_i8, IndexModePre, IIC_iLoadiu,
553 "ldrsb", " $dst, $addr!", "$addr.base = $base_wb",
555 def t2LDRSB_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
556 (ins GPR:$base, t2am_imm8_offset:$offset),
557 AddrModeT2_i8, IndexModePost, IIC_iLoadiu,
558 "ldrsb", " $dst, [$base], $offset", "$base = $base_wb",
561 def t2LDRSH_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
562 (ins t2addrmode_imm8:$addr),
563 AddrModeT2_i8, IndexModePre, IIC_iLoadiu,
564 "ldrsh", " $dst, $addr!", "$addr.base = $base_wb",
566 def t2LDRSH_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
567 (ins GPR:$base, t2am_imm8_offset:$offset),
568 AddrModeT2_i8, IndexModePost, IIC_iLoadiu,
569 "ldrsh", " $dst, [$base], $offset", "$base = $base_wb",
574 defm t2STR : T2I_st<"str", BinOpFrag<(store node:$LHS, node:$RHS)>>;
575 defm t2STRB : T2I_st<"strb", BinOpFrag<(truncstorei8 node:$LHS, node:$RHS)>>;
576 defm t2STRH : T2I_st<"strh", BinOpFrag<(truncstorei16 node:$LHS, node:$RHS)>>;
579 let mayLoad = 1, hasExtraSrcRegAllocReq = 1 in
580 def t2STRDi8 : T2Ii8s4<(outs),
581 (ins GPR:$src1, GPR:$src2, t2addrmode_imm8s4:$addr),
582 IIC_iStorer, "strd", " $src1, $addr", []>;
585 def t2STR_PRE : T2Iidxldst<(outs GPR:$base_wb),
586 (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset),
587 AddrModeT2_i8, IndexModePre, IIC_iStoreiu,
588 "str", " $src, [$base, $offset]!", "$base = $base_wb",
590 (pre_store GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>;
592 def t2STR_POST : T2Iidxldst<(outs GPR:$base_wb),
593 (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset),
594 AddrModeT2_i8, IndexModePost, IIC_iStoreiu,
595 "str", " $src, [$base], $offset", "$base = $base_wb",
597 (post_store GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>;
599 def t2STRH_PRE : T2Iidxldst<(outs GPR:$base_wb),
600 (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset),
601 AddrModeT2_i8, IndexModePre, IIC_iStoreiu,
602 "strh", " $src, [$base, $offset]!", "$base = $base_wb",
604 (pre_truncsti16 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>;
606 def t2STRH_POST : T2Iidxldst<(outs GPR:$base_wb),
607 (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset),
608 AddrModeT2_i8, IndexModePost, IIC_iStoreiu,
609 "strh", " $src, [$base], $offset", "$base = $base_wb",
611 (post_truncsti16 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>;
613 def t2STRB_PRE : T2Iidxldst<(outs GPR:$base_wb),
614 (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset),
615 AddrModeT2_i8, IndexModePre, IIC_iStoreiu,
616 "strb", " $src, [$base, $offset]!", "$base = $base_wb",
618 (pre_truncsti8 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>;
620 def t2STRB_POST : T2Iidxldst<(outs GPR:$base_wb),
621 (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset),
622 AddrModeT2_i8, IndexModePost, IIC_iStoreiu,
623 "strb", " $src, [$base], $offset", "$base = $base_wb",
625 (post_truncsti8 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>;
628 // FIXME: ldrd / strd pre / post variants
630 //===----------------------------------------------------------------------===//
631 // Load / store multiple Instructions.
634 let mayLoad = 1, hasExtraDefRegAllocReq = 1 in
635 def t2LDM : T2XI<(outs),
636 (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops),
637 IIC_iLoadm, "ldm${addr:submode}${p}${addr:wide} $addr, $wb", []>;
639 let mayStore = 1, hasExtraSrcRegAllocReq = 1 in
640 def t2STM : T2XI<(outs),
641 (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops),
642 IIC_iStorem, "stm${addr:submode}${p}${addr:wide} $addr, $wb", []>;
644 //===----------------------------------------------------------------------===//
645 // Move Instructions.
648 let neverHasSideEffects = 1 in
649 def t2MOVr : T2sI<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVr,
650 "mov", ".w $dst, $src", []>;
652 // AddedComplexity to ensure isel tries t2MOVi before t2MOVi16.
653 let isReMaterializable = 1, isAsCheapAsAMove = 1, AddedComplexity = 1 in
654 def t2MOVi : T2sI<(outs GPR:$dst), (ins t2_so_imm:$src), IIC_iMOVi,
655 "mov", ".w $dst, $src",
656 [(set GPR:$dst, t2_so_imm:$src)]>;
658 let isReMaterializable = 1, isAsCheapAsAMove = 1 in
659 def t2MOVi16 : T2I<(outs GPR:$dst), (ins i32imm:$src), IIC_iMOVi,
660 "movw", " $dst, $src",
661 [(set GPR:$dst, imm0_65535:$src)]>;
663 let Constraints = "$src = $dst" in
664 def t2MOVTi16 : T2I<(outs GPR:$dst), (ins GPR:$src, i32imm:$imm), IIC_iMOVi,
665 "movt", " $dst, $imm",
667 (or (and GPR:$src, 0xffff), lo16AllZero:$imm))]>;
669 //===----------------------------------------------------------------------===//
670 // Extend Instructions.
675 defm t2SXTB : T2I_unary_rrot<"sxtb", UnOpFrag<(sext_inreg node:$Src, i8)>>;
676 defm t2SXTH : T2I_unary_rrot<"sxth", UnOpFrag<(sext_inreg node:$Src, i16)>>;
678 defm t2SXTAB : T2I_bin_rrot<"sxtab",
679 BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS, i8))>>;
680 defm t2SXTAH : T2I_bin_rrot<"sxtah",
681 BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS,i16))>>;
683 // TODO: SXT(A){B|H}16
687 let AddedComplexity = 16 in {
688 defm t2UXTB : T2I_unary_rrot<"uxtb" , UnOpFrag<(and node:$Src, 0x000000FF)>>;
689 defm t2UXTH : T2I_unary_rrot<"uxth" , UnOpFrag<(and node:$Src, 0x0000FFFF)>>;
690 defm t2UXTB16 : T2I_unary_rrot<"uxtb16", UnOpFrag<(and node:$Src, 0x00FF00FF)>>;
692 def : T2Pat<(and (shl GPR:$Src, (i32 8)), 0xFF00FF),
693 (t2UXTB16r_rot GPR:$Src, 24)>;
694 def : T2Pat<(and (srl GPR:$Src, (i32 8)), 0xFF00FF),
695 (t2UXTB16r_rot GPR:$Src, 8)>;
697 defm t2UXTAB : T2I_bin_rrot<"uxtab",
698 BinOpFrag<(add node:$LHS, (and node:$RHS, 0x00FF))>>;
699 defm t2UXTAH : T2I_bin_rrot<"uxtah",
700 BinOpFrag<(add node:$LHS, (and node:$RHS, 0xFFFF))>>;
703 //===----------------------------------------------------------------------===//
704 // Arithmetic Instructions.
707 defm t2ADD : T2I_bin_ii12rs<"add", BinOpFrag<(add node:$LHS, node:$RHS)>, 1>;
708 defm t2SUB : T2I_bin_ii12rs<"sub", BinOpFrag<(sub node:$LHS, node:$RHS)>>;
710 // ADD and SUB with 's' bit set. No 12-bit immediate (T4) variants.
711 defm t2ADDS : T2I_bin_s_irs <"add", BinOpFrag<(addc node:$LHS, node:$RHS)>, 1>;
712 defm t2SUBS : T2I_bin_s_irs <"sub", BinOpFrag<(subc node:$LHS, node:$RHS)>>;
714 defm t2ADC : T2I_adde_sube_irs<"adc",BinOpFrag<(adde node:$LHS, node:$RHS)>,1>;
715 defm t2SBC : T2I_adde_sube_irs<"sbc",BinOpFrag<(sube node:$LHS, node:$RHS)>>;
718 defm t2RSB : T2I_rbin_is <"rsb", BinOpFrag<(sub node:$LHS, node:$RHS)>>;
719 defm t2RSBS : T2I_rbin_s_is <"rsb", BinOpFrag<(subc node:$LHS, node:$RHS)>>;
721 // (sub X, imm) gets canonicalized to (add X, -imm). Match this form.
722 let AddedComplexity = 1 in
723 def : T2Pat<(add GPR:$src, imm0_255_neg:$imm),
724 (t2SUBri GPR:$src, imm0_255_neg:$imm)>;
725 def : T2Pat<(add GPR:$src, t2_so_imm_neg:$imm),
726 (t2SUBri GPR:$src, t2_so_imm_neg:$imm)>;
727 def : T2Pat<(add GPR:$src, imm0_4095_neg:$imm),
728 (t2SUBri12 GPR:$src, imm0_4095_neg:$imm)>;
731 //===----------------------------------------------------------------------===//
732 // Shift and rotate Instructions.
735 defm t2LSL : T2I_sh_ir<"lsl", BinOpFrag<(shl node:$LHS, node:$RHS)>>;
736 defm t2LSR : T2I_sh_ir<"lsr", BinOpFrag<(srl node:$LHS, node:$RHS)>>;
737 defm t2ASR : T2I_sh_ir<"asr", BinOpFrag<(sra node:$LHS, node:$RHS)>>;
738 defm t2ROR : T2I_sh_ir<"ror", BinOpFrag<(rotr node:$LHS, node:$RHS)>>;
740 let Uses = [CPSR] in {
741 def t2MOVrx : T2sI<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVsi,
742 "rrx", " $dst, $src",
743 [(set GPR:$dst, (ARMrrx GPR:$src))]>;
746 let Defs = [CPSR] in {
747 def t2MOVsrl_flag : T2XI<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVsi,
748 "lsrs.w $dst, $src, #1",
749 [(set GPR:$dst, (ARMsrl_flag GPR:$src))]>;
750 def t2MOVsra_flag : T2XI<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVsi,
751 "asrs.w $dst, $src, #1",
752 [(set GPR:$dst, (ARMsra_flag GPR:$src))]>;
755 //===----------------------------------------------------------------------===//
756 // Bitwise Instructions.
759 defm t2AND : T2I_bin_w_irs<"and", BinOpFrag<(and node:$LHS, node:$RHS)>, 1>;
760 defm t2ORR : T2I_bin_w_irs<"orr", BinOpFrag<(or node:$LHS, node:$RHS)>, 1>;
761 defm t2EOR : T2I_bin_w_irs<"eor", BinOpFrag<(xor node:$LHS, node:$RHS)>, 1>;
763 defm t2BIC : T2I_bin_w_irs<"bic", BinOpFrag<(and node:$LHS, (not node:$RHS))>>;
765 let Constraints = "$src = $dst" in
766 def t2BFC : T2I<(outs GPR:$dst), (ins GPR:$src, bf_inv_mask_imm:$imm),
767 IIC_iALUi, "bfc", " $dst, $imm",
768 [(set GPR:$dst, (and GPR:$src, bf_inv_mask_imm:$imm))]>;
770 def t2SBFX : T2I<(outs GPR:$dst), (ins GPR:$src, imm0_31:$lsb, imm0_31:$width),
771 IIC_iALUi, "sbfx", " $dst, $src, $lsb, $width", []>;
773 def t2UBFX : T2I<(outs GPR:$dst), (ins GPR:$src, imm0_31:$lsb, imm0_31:$width),
774 IIC_iALUi, "ubfx", " $dst, $src, $lsb, $width", []>;
776 // FIXME: A8.6.18 BFI - Bitfield insert (Encoding T1)
778 defm t2ORN : T2I_bin_irs<"orn", BinOpFrag<(or node:$LHS, (not node:$RHS))>>;
780 // Prefer over of t2EORri ra, rb, -1 because mvn has 16-bit version
781 let AddedComplexity = 1 in
782 defm t2MVN : T2I_un_irs <"mvn", UnOpFrag<(not node:$Src)>, 1, 1>;
785 def : T2Pat<(and GPR:$src, t2_so_imm_not:$imm),
786 (t2BICri GPR:$src, t2_so_imm_not:$imm)>;
788 // FIXME: Disable this pattern on Darwin to workaround an assembler bug.
789 def : T2Pat<(or GPR:$src, t2_so_imm_not:$imm),
790 (t2ORNri GPR:$src, t2_so_imm_not:$imm)>,
791 Requires<[IsThumb2]>;
793 def : T2Pat<(t2_so_imm_not:$src),
794 (t2MVNi t2_so_imm_not:$src)>;
796 //===----------------------------------------------------------------------===//
797 // Multiply Instructions.
799 let isCommutable = 1 in
800 def t2MUL: T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32,
801 "mul", " $dst, $a, $b",
802 [(set GPR:$dst, (mul GPR:$a, GPR:$b))]>;
804 def t2MLA: T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), IIC_iMAC32,
805 "mla", " $dst, $a, $b, $c",
806 [(set GPR:$dst, (add (mul GPR:$a, GPR:$b), GPR:$c))]>;
808 def t2MLS: T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), IIC_iMAC32,
809 "mls", " $dst, $a, $b, $c",
810 [(set GPR:$dst, (sub GPR:$c, (mul GPR:$a, GPR:$b)))]>;
812 // Extra precision multiplies with low / high results
813 let neverHasSideEffects = 1 in {
814 let isCommutable = 1 in {
815 def t2SMULL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), IIC_iMUL64,
816 "smull", " $ldst, $hdst, $a, $b", []>;
818 def t2UMULL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), IIC_iMUL64,
819 "umull", " $ldst, $hdst, $a, $b", []>;
822 // Multiply + accumulate
823 def t2SMLAL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), IIC_iMAC64,
824 "smlal", " $ldst, $hdst, $a, $b", []>;
826 def t2UMLAL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), IIC_iMAC64,
827 "umlal", " $ldst, $hdst, $a, $b", []>;
829 def t2UMAAL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), IIC_iMAC64,
830 "umaal", " $ldst, $hdst, $a, $b", []>;
831 } // neverHasSideEffects
833 // Most significant word multiply
834 def t2SMMUL : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32,
835 "smmul", " $dst, $a, $b",
836 [(set GPR:$dst, (mulhs GPR:$a, GPR:$b))]>;
838 def t2SMMLA : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), IIC_iMAC32,
839 "smmla", " $dst, $a, $b, $c",
840 [(set GPR:$dst, (add (mulhs GPR:$a, GPR:$b), GPR:$c))]>;
843 def t2SMMLS : T2I <(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), IIC_iMAC32,
844 "smmls", " $dst, $a, $b, $c",
845 [(set GPR:$dst, (sub GPR:$c, (mulhs GPR:$a, GPR:$b)))]>;
847 multiclass T2I_smul<string opc, PatFrag opnode> {
848 def BB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32,
849 !strconcat(opc, "bb"), " $dst, $a, $b",
850 [(set GPR:$dst, (opnode (sext_inreg GPR:$a, i16),
851 (sext_inreg GPR:$b, i16)))]>;
853 def BT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32,
854 !strconcat(opc, "bt"), " $dst, $a, $b",
855 [(set GPR:$dst, (opnode (sext_inreg GPR:$a, i16),
856 (sra GPR:$b, (i32 16))))]>;
858 def TB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32,
859 !strconcat(opc, "tb"), " $dst, $a, $b",
860 [(set GPR:$dst, (opnode (sra GPR:$a, (i32 16)),
861 (sext_inreg GPR:$b, i16)))]>;
863 def TT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32,
864 !strconcat(opc, "tt"), " $dst, $a, $b",
865 [(set GPR:$dst, (opnode (sra GPR:$a, (i32 16)),
866 (sra GPR:$b, (i32 16))))]>;
868 def WB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL16,
869 !strconcat(opc, "wb"), " $dst, $a, $b",
870 [(set GPR:$dst, (sra (opnode GPR:$a,
871 (sext_inreg GPR:$b, i16)), (i32 16)))]>;
873 def WT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL16,
874 !strconcat(opc, "wt"), " $dst, $a, $b",
875 [(set GPR:$dst, (sra (opnode GPR:$a,
876 (sra GPR:$b, (i32 16))), (i32 16)))]>;
880 multiclass T2I_smla<string opc, PatFrag opnode> {
881 def BB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16,
882 !strconcat(opc, "bb"), " $dst, $a, $b, $acc",
883 [(set GPR:$dst, (add GPR:$acc,
884 (opnode (sext_inreg GPR:$a, i16),
885 (sext_inreg GPR:$b, i16))))]>;
887 def BT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16,
888 !strconcat(opc, "bt"), " $dst, $a, $b, $acc",
889 [(set GPR:$dst, (add GPR:$acc, (opnode (sext_inreg GPR:$a, i16),
890 (sra GPR:$b, (i32 16)))))]>;
892 def TB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16,
893 !strconcat(opc, "tb"), " $dst, $a, $b, $acc",
894 [(set GPR:$dst, (add GPR:$acc, (opnode (sra GPR:$a, (i32 16)),
895 (sext_inreg GPR:$b, i16))))]>;
897 def TT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16,
898 !strconcat(opc, "tt"), " $dst, $a, $b, $acc",
899 [(set GPR:$dst, (add GPR:$acc, (opnode (sra GPR:$a, (i32 16)),
900 (sra GPR:$b, (i32 16)))))]>;
902 def WB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16,
903 !strconcat(opc, "wb"), " $dst, $a, $b, $acc",
904 [(set GPR:$dst, (add GPR:$acc, (sra (opnode GPR:$a,
905 (sext_inreg GPR:$b, i16)), (i32 16))))]>;
907 def WT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16,
908 !strconcat(opc, "wt"), " $dst, $a, $b, $acc",
909 [(set GPR:$dst, (add GPR:$acc, (sra (opnode GPR:$a,
910 (sra GPR:$b, (i32 16))), (i32 16))))]>;
913 defm t2SMUL : T2I_smul<"smul", BinOpFrag<(mul node:$LHS, node:$RHS)>>;
914 defm t2SMLA : T2I_smla<"smla", BinOpFrag<(mul node:$LHS, node:$RHS)>>;
916 // TODO: Halfword multiple accumulate long: SMLAL<x><y>
917 // TODO: Dual halfword multiple: SMUAD, SMUSD, SMLAD, SMLSD, SMLALD, SMLSLD
920 //===----------------------------------------------------------------------===//
921 // Misc. Arithmetic Instructions.
924 def t2CLZ : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
925 "clz", " $dst, $src",
926 [(set GPR:$dst, (ctlz GPR:$src))]>;
928 def t2REV : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
929 "rev", ".w $dst, $src",
930 [(set GPR:$dst, (bswap GPR:$src))]>;
932 def t2REV16 : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
933 "rev16", ".w $dst, $src",
935 (or (and (srl GPR:$src, (i32 8)), 0xFF),
936 (or (and (shl GPR:$src, (i32 8)), 0xFF00),
937 (or (and (srl GPR:$src, (i32 8)), 0xFF0000),
938 (and (shl GPR:$src, (i32 8)), 0xFF000000)))))]>;
940 def t2REVSH : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
941 "revsh", ".w $dst, $src",
944 (or (srl (and GPR:$src, 0xFF00), (i32 8)),
945 (shl GPR:$src, (i32 8))), i16))]>;
947 def t2PKHBT : T2I<(outs GPR:$dst), (ins GPR:$src1, GPR:$src2, i32imm:$shamt),
948 IIC_iALUsi, "pkhbt", " $dst, $src1, $src2, LSL $shamt",
949 [(set GPR:$dst, (or (and GPR:$src1, 0xFFFF),
950 (and (shl GPR:$src2, (i32 imm:$shamt)),
953 // Alternate cases for PKHBT where identities eliminate some nodes.
954 def : T2Pat<(or (and GPR:$src1, 0xFFFF), (and GPR:$src2, 0xFFFF0000)),
955 (t2PKHBT GPR:$src1, GPR:$src2, 0)>;
956 def : T2Pat<(or (and GPR:$src1, 0xFFFF), (shl GPR:$src2, imm16_31:$shamt)),
957 (t2PKHBT GPR:$src1, GPR:$src2, imm16_31:$shamt)>;
959 def t2PKHTB : T2I<(outs GPR:$dst), (ins GPR:$src1, GPR:$src2, i32imm:$shamt),
960 IIC_iALUsi, "pkhtb", " $dst, $src1, $src2, ASR $shamt",
961 [(set GPR:$dst, (or (and GPR:$src1, 0xFFFF0000),
962 (and (sra GPR:$src2, imm16_31:$shamt),
965 // Alternate cases for PKHTB where identities eliminate some nodes. Note that
966 // a shift amount of 0 is *not legal* here, it is PKHBT instead.
967 def : T2Pat<(or (and GPR:$src1, 0xFFFF0000), (srl GPR:$src2, (i32 16))),
968 (t2PKHTB GPR:$src1, GPR:$src2, 16)>;
969 def : T2Pat<(or (and GPR:$src1, 0xFFFF0000),
970 (and (srl GPR:$src2, imm1_15:$shamt), 0xFFFF)),
971 (t2PKHTB GPR:$src1, GPR:$src2, imm1_15:$shamt)>;
973 //===----------------------------------------------------------------------===//
974 // Comparison Instructions...
977 defm t2CMP : T2I_cmp_is<"cmp",
978 BinOpFrag<(ARMcmp node:$LHS, node:$RHS)>>;
979 defm t2CMPz : T2I_cmp_is<"cmp",
980 BinOpFrag<(ARMcmpZ node:$LHS, node:$RHS)>>;
982 defm t2CMN : T2I_cmp_is<"cmn",
983 BinOpFrag<(ARMcmp node:$LHS,(ineg node:$RHS))>>;
984 defm t2CMNz : T2I_cmp_is<"cmn",
985 BinOpFrag<(ARMcmpZ node:$LHS,(ineg node:$RHS))>>;
987 def : T2Pat<(ARMcmp GPR:$src, t2_so_imm_neg:$imm),
988 (t2CMNri GPR:$src, t2_so_imm_neg:$imm)>;
990 def : T2Pat<(ARMcmpZ GPR:$src, t2_so_imm_neg:$imm),
991 (t2CMNri GPR:$src, t2_so_imm_neg:$imm)>;
993 defm t2TST : T2I_cmp_is<"tst",
994 BinOpFrag<(ARMcmpZ (and node:$LHS, node:$RHS), 0)>>;
995 defm t2TEQ : T2I_cmp_is<"teq",
996 BinOpFrag<(ARMcmpZ (xor node:$LHS, node:$RHS), 0)>>;
998 // A8.6.27 CBNZ, CBZ - Compare and branch on (non)zero.
999 // Short range conditional branch. Looks awesome for loops. Need to figure
1000 // out how to use this one.
1003 // Conditional moves
1004 // FIXME: should be able to write a pattern for ARMcmov, but can't use
1005 // a two-value operand where a dag node expects two operands. :(
1006 def t2MOVCCr : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true), IIC_iCMOVr,
1007 "mov", ".w $dst, $true",
1008 [/*(set GPR:$dst, (ARMcmov GPR:$false, GPR:$true, imm:$cc, CCR:$ccr))*/]>,
1009 RegConstraint<"$false = $dst">;
1011 def t2MOVCCi : T2I<(outs GPR:$dst), (ins GPR:$false, t2_so_imm:$true),
1012 IIC_iCMOVi, "mov", ".w $dst, $true",
1013 [/*(set GPR:$dst, (ARMcmov GPR:$false, t2_so_imm:$true, imm:$cc, CCR:$ccr))*/]>,
1014 RegConstraint<"$false = $dst">;
1016 def t2MOVCClsl : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true, i32imm:$rhs),
1017 IIC_iCMOVsi, "lsl", ".w $dst, $true, $rhs", []>,
1018 RegConstraint<"$false = $dst">;
1019 def t2MOVCClsr : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true, i32imm:$rhs),
1020 IIC_iCMOVsi, "lsr", ".w $dst, $true, $rhs", []>,
1021 RegConstraint<"$false = $dst">;
1022 def t2MOVCCasr : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true, i32imm:$rhs),
1023 IIC_iCMOVsi, "asr", ".w $dst, $true, $rhs", []>,
1024 RegConstraint<"$false = $dst">;
1025 def t2MOVCCror : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true, i32imm:$rhs),
1026 IIC_iCMOVsi, "ror", ".w $dst, $true, $rhs", []>,
1027 RegConstraint<"$false = $dst">;
1029 //===----------------------------------------------------------------------===//
1033 // __aeabi_read_tp preserves the registers r1-r3.
1035 Defs = [R0, R12, LR, CPSR] in {
1036 def t2TPsoft : T2XI<(outs), (ins), IIC_Br,
1037 "bl __aeabi_read_tp",
1038 [(set R0, ARMthread_pointer)]>;
1041 //===----------------------------------------------------------------------===//
1042 // SJLJ Exception handling intrinsics
1043 // eh_sjlj_setjmp() is an instruction sequence to store the return
1044 // address and save #0 in R0 for the non-longjmp case.
1045 // Since by its nature we may be coming from some other function to get
1046 // here, and we're using the stack frame for the containing function to
1047 // save/restore registers, we can't keep anything live in regs across
1048 // the eh_sjlj_setjmp(), else it will almost certainly have been tromped upon
1049 // when we get here from a longjmp(). We force everthing out of registers
1050 // except for our own input by listing the relevant registers in Defs. By
1051 // doing so, we also cause the prologue/epilogue code to actively preserve
1052 // all of the callee-saved resgisters, which is exactly what we want.
1054 [ R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, LR, D0,
1055 D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15,
1056 D16, D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30,
1058 def t2Int_eh_sjlj_setjmp : Thumb2XI<(outs), (ins GPR:$src),
1059 AddrModeNone, SizeSpecial, NoItinerary,
1060 "str.w sp, [$src, #+8] @ eh_setjmp begin\n"
1063 "\tstr.w r12, [$src, #+4]\n"
1066 "0:\tmovs r0, #1 @ eh_setjmp end\n"
1068 [(set R0, (ARMeh_sjlj_setjmp GPR:$src))]>;
1073 //===----------------------------------------------------------------------===//
1074 // Control-Flow Instructions
1077 // FIXME: remove when we have a way to marking a MI with these properties.
1078 // FIXME: $dst1 should be a def. But the extra ops must be in the end of the
1080 // FIXME: Should pc be an implicit operand like PICADD, etc?
1081 let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1,
1082 hasExtraDefRegAllocReq = 1 in
1083 def t2LDM_RET : T2XI<(outs),
1084 (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops),
1085 IIC_Br, "ldm${addr:submode}${p}${addr:wide} $addr, $wb",
1088 let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
1089 let isPredicable = 1 in
1090 def t2B : T2XI<(outs), (ins brtarget:$target), IIC_Br,
1094 let isNotDuplicable = 1, isIndirectBranch = 1 in {
1097 (ins GPR:$target, GPR:$index, jt2block_operand:$jt, i32imm:$id),
1098 IIC_Br, "mov pc, $target\n$jt",
1099 [(ARMbr2jt GPR:$target, GPR:$index, tjumptable:$jt, imm:$id)]>;
1101 // FIXME: Add a non-pc based case that can be predicated.
1104 (ins tb_addrmode:$index, jt2block_operand:$jt, i32imm:$id),
1105 IIC_Br, "tbb $index\n$jt", []>;
1109 (ins tb_addrmode:$index, jt2block_operand:$jt, i32imm:$id),
1110 IIC_Br, "tbh $index\n$jt", []>;
1111 } // isNotDuplicable, isIndirectBranch
1113 } // isBranch, isTerminator, isBarrier
1115 // FIXME: should be able to write a pattern for ARMBrcond, but can't use
1116 // a two-value operand where a dag node expects two operands. :(
1117 let isBranch = 1, isTerminator = 1 in
1118 def t2Bcc : T2I<(outs), (ins brtarget:$target), IIC_Br,
1120 [/*(ARMbrcond bb:$target, imm:$cc)*/]>;
1124 def t2IT : Thumb2XI<(outs), (ins it_pred:$cc, it_mask:$mask),
1125 AddrModeNone, Size2Bytes, IIC_iALUx,
1126 "it$mask $cc", "", []>;
1128 //===----------------------------------------------------------------------===//
1129 // Non-Instruction Patterns
1132 // ConstantPool, GlobalAddress, and JumpTable
1133 def : T2Pat<(ARMWrapper tglobaladdr :$dst), (t2LEApcrel tglobaladdr :$dst)>;
1134 def : T2Pat<(ARMWrapper tconstpool :$dst), (t2LEApcrel tconstpool :$dst)>;
1135 def : T2Pat<(ARMWrapperJT tjumptable:$dst, imm:$id),
1136 (t2LEApcrelJT tjumptable:$dst, imm:$id)>;
1138 // 32-bit immediate using movw + movt.
1139 // This is a single pseudo instruction to make it re-materializable. Remove
1140 // when we can do generalized remat.
1141 let isReMaterializable = 1 in
1142 def t2MOVi32imm : T2Ix2<(outs GPR:$dst), (ins i32imm:$src), IIC_iMOVi,
1143 "movw", " $dst, ${src:lo16}\n\tmovt${p} $dst, ${src:hi16}",
1144 [(set GPR:$dst, (i32 imm:$src))]>;