1234353Sdim//===-- ARMInstrThumb2.td - Thumb2 support for ARM ---------*- tablegen -*-===//
2193323Sed//
3193323Sed//                     The LLVM Compiler Infrastructure
4193323Sed//
5193323Sed// This file is distributed under the University of Illinois Open Source
6193323Sed// License. See LICENSE.TXT for details.
7193323Sed//
8193323Sed//===----------------------------------------------------------------------===//
9193323Sed//
10193323Sed// This file describes the Thumb2 instruction set.
11193323Sed//
12193323Sed//===----------------------------------------------------------------------===//
13194612Sed
14198090Srdivacky// IT block predicate field
15226633Sdimdef it_pred_asmoperand : AsmOperandClass {
16226633Sdim  let Name = "ITCondCode";
17226633Sdim  let ParserMethod = "parseITCondCode";
18226633Sdim}
19198090Srdivackydef it_pred : Operand<i32> {
20204642Srdivacky  let PrintMethod = "printMandatoryPredicateOperand";
21226633Sdim  let ParserMatchClass = it_pred_asmoperand;
22198090Srdivacky}
23198090Srdivacky
24198090Srdivacky// IT block condition mask
25226633Sdimdef it_mask_asmoperand : AsmOperandClass { let Name = "ITMask"; }
26198090Srdivackydef it_mask : Operand<i32> {
27198090Srdivacky  let PrintMethod = "printThumbITMask";
28226633Sdim  let ParserMatchClass = it_mask_asmoperand;
29198090Srdivacky}
30198090Srdivacky
31226633Sdim// t2_shift_imm: An integer that encodes a shift amount and the type of shift
32226633Sdim// (asr or lsl). The 6-bit immediate encodes as:
33226633Sdim//    {5}     0 ==> lsl
34226633Sdim//            1     asr
35226633Sdim//    {4-0}   imm5 shift amount.
36226633Sdim//            asr #32 not allowed
37226633Sdimdef t2_shift_imm : Operand<i32> {
38226633Sdim  let PrintMethod = "printShiftImmOperand";
39226633Sdim  let ParserMatchClass = ShifterImmAsmOperand;
40226633Sdim  let DecoderMethod = "DecodeT2ShifterImmOperand";
41226633Sdim}
42226633Sdim
43194612Sed// Shifted operands. No register controlled shifts for Thumb2.
44194612Sed// Note: We do not support rrx shifted operands yet.
45194612Seddef t2_so_reg : Operand<i32>,    // reg imm
46195098Sed                ComplexPattern<i32, 2, "SelectT2ShifterOperandReg",
47194612Sed                               [shl,srl,sra,rotr]> {
48218893Sdim  let EncoderMethod = "getT2SORegOpValue";
49195098Sed  let PrintMethod = "printT2SOOperand";
50226633Sdim  let DecoderMethod = "DecodeSORegImmOperand";
51226633Sdim  let ParserMatchClass = ShiftedImmAsmOperand;
52212904Sdim  let MIOperandInfo = (ops rGPR, i32imm);
53194612Sed}
54194612Sed
55194754Sed// t2_so_imm_not_XFORM - Return the complement of a t2_so_imm value
56194754Seddef t2_so_imm_not_XFORM : SDNodeXForm<imm, [{
57198090Srdivacky  return CurDAG->getTargetConstant(~((uint32_t)N->getZExtValue()), MVT::i32);
58194612Sed}]>;
59194612Sed
60194754Sed// t2_so_imm_neg_XFORM - Return the negation of a t2_so_imm value
61194754Seddef t2_so_imm_neg_XFORM : SDNodeXForm<imm, [{
62198090Srdivacky  return CurDAG->getTargetConstant(-((int)N->getZExtValue()), MVT::i32);
63194754Sed}]>;
64194612Sed
65239462Sdim// so_imm_notSext_XFORM - Return a so_imm value packed into the format
66239462Sdim// described for so_imm_notSext def below, with sign extension from 16
67239462Sdim// bits.
68239462Sdimdef t2_so_imm_notSext16_XFORM : SDNodeXForm<imm, [{
69239462Sdim  APInt apIntN = N->getAPIntValue();
70239462Sdim  unsigned N16bitSignExt = apIntN.trunc(16).sext(32).getZExtValue();
71239462Sdim  return CurDAG->getTargetConstant(~N16bitSignExt, MVT::i32);
72239462Sdim}]>;
73239462Sdim
74194754Sed// t2_so_imm - Match a 32-bit immediate operand, which is an
75194754Sed// 8-bit immediate rotated by an arbitrary number of bits, or an 8-bit
76218893Sdim// immediate splatted into multiple bytes of the word.
77234353Sdimdef t2_so_imm_asmoperand : ImmAsmOperand { let Name = "T2SOImm"; }
78221345Sdimdef t2_so_imm : Operand<i32>, ImmLeaf<i32, [{
79221345Sdim    return ARM_AM::getT2SOImmVal(Imm) != -1;
80221345Sdim  }]> {
81224145Sdim  let ParserMatchClass = t2_so_imm_asmoperand;
82218893Sdim  let EncoderMethod = "getT2SOImmOpValue";
83226633Sdim  let DecoderMethod = "DecodeT2SOImm";
84218893Sdim}
85194612Sed
86204642Srdivacky// t2_so_imm_not - Match an immediate that is a complement
87194754Sed// of a t2_so_imm.
88234353Sdim// Note: this pattern doesn't require an encoder method and such, as it's
89234353Sdim// only used on aliases (Pat<> and InstAlias<>). The actual encoding
90234353Sdim// is handled by the destination instructions, which use t2_so_imm.
91234353Sdimdef t2_so_imm_not_asmoperand : AsmOperandClass { let Name = "T2SOImmNot"; }
92234353Sdimdef t2_so_imm_not : Operand<i32>, PatLeaf<(imm), [{
93198090Srdivacky  return ARM_AM::getT2SOImmVal(~((uint32_t)N->getZExtValue())) != -1;
94234353Sdim}], t2_so_imm_not_XFORM> {
95234353Sdim  let ParserMatchClass = t2_so_imm_not_asmoperand;
96234353Sdim}
97194612Sed
98239462Sdim// t2_so_imm_notSext - match an immediate that is a complement of a t2_so_imm
99239462Sdim// if the upper 16 bits are zero.
100239462Sdimdef t2_so_imm_notSext : Operand<i32>, PatLeaf<(imm), [{
101239462Sdim    APInt apIntN = N->getAPIntValue();
102239462Sdim    if (!apIntN.isIntN(16)) return false;
103239462Sdim    unsigned N16bitSignExt = apIntN.trunc(16).sext(32).getZExtValue();
104239462Sdim    return ARM_AM::getT2SOImmVal(~N16bitSignExt) != -1;
105239462Sdim  }], t2_so_imm_notSext16_XFORM> {
106239462Sdim  let ParserMatchClass = t2_so_imm_not_asmoperand;
107239462Sdim}
108239462Sdim
109194754Sed// t2_so_imm_neg - Match an immediate that is a negation of a t2_so_imm.
110234353Sdimdef t2_so_imm_neg_asmoperand : AsmOperandClass { let Name = "T2SOImmNeg"; }
111234353Sdimdef t2_so_imm_neg : Operand<i32>, PatLeaf<(imm), [{
112234353Sdim  int64_t Value = -(int)N->getZExtValue();
113234353Sdim  return Value && ARM_AM::getT2SOImmVal(Value) != -1;
114234353Sdim}], t2_so_imm_neg_XFORM> {
115234353Sdim  let ParserMatchClass = t2_so_imm_neg_asmoperand;
116234353Sdim}
117194754Sed
118194754Sed/// imm0_4095 predicate - True if the 32-bit immediate is in the range [0.4095].
119234353Sdimdef imm0_4095_asmoperand: ImmAsmOperand { let Name = "Imm0_4095"; }
120234353Sdimdef imm0_4095 : Operand<i32>, ImmLeaf<i32, [{
121221345Sdim  return Imm >= 0 && Imm < 4096;
122234353Sdim}]> {
123234353Sdim  let ParserMatchClass = imm0_4095_asmoperand;
124234353Sdim}
125194754Sed
126234353Sdimdef imm0_4095_neg_asmoperand: AsmOperandClass { let Name = "Imm0_4095Neg"; }
127234353Sdimdef imm0_4095_neg : Operand<i32>, PatLeaf<(i32 imm), [{
128204642Srdivacky return (uint32_t)(-N->getZExtValue()) < 4096;
129234353Sdim}], imm_neg_XFORM> {
130234353Sdim  let ParserMatchClass = imm0_4095_neg_asmoperand;
131234353Sdim}
132194612Sed
133249423Sdimdef imm1_255_neg : PatLeaf<(i32 imm), [{
134249423Sdim  uint32_t Val = -N->getZExtValue();
135249423Sdim  return (Val > 0 && Val < 255);
136204642Srdivacky}], imm_neg_XFORM>;
137194612Sed
138210299Seddef imm0_255_not : PatLeaf<(i32 imm), [{
139210299Sed  return (uint32_t)(~N->getZExtValue()) < 255;
140210299Sed}], imm_comp_XFORM>;
141210299Sed
142221345Sdimdef lo5AllOne : PatLeaf<(i32 imm), [{
143221345Sdim  // Returns true if all low 5-bits are 1.
144221345Sdim  return (((uint32_t)N->getZExtValue()) & 0x1FUL) == 0x1FUL;
145221345Sdim}]>;
146221345Sdim
147195340Sed// Define Thumb2 specific addressing modes.
148195340Sed
149195340Sed// t2addrmode_imm12  := reg + imm12
150226633Sdimdef t2addrmode_imm12_asmoperand : AsmOperandClass {let Name="MemUImm12Offset";}
151195340Seddef t2addrmode_imm12 : Operand<i32>,
152195340Sed                       ComplexPattern<i32, 2, "SelectT2AddrModeImm12", []> {
153251662Sdim  let PrintMethod = "printAddrModeImm12Operand<false>";
154218893Sdim  let EncoderMethod = "getAddrModeImm12OpValue";
155226633Sdim  let DecoderMethod = "DecodeT2AddrModeImm12";
156226633Sdim  let ParserMatchClass = t2addrmode_imm12_asmoperand;
157195340Sed  let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
158195340Sed}
159195340Sed
160221345Sdim// t2ldrlabel  := imm12
161221345Sdimdef t2ldrlabel : Operand<i32> {
162221345Sdim  let EncoderMethod = "getAddrModeImm12OpValue";
163243830Sdim  let PrintMethod = "printThumbLdrLabelOperand";
164221345Sdim}
165221345Sdim
166234353Sdimdef t2ldr_pcrel_imm12_asmoperand : AsmOperandClass {let Name = "MemPCRelImm12";}
167234353Sdimdef t2ldr_pcrel_imm12 : Operand<i32> {
168234353Sdim  let ParserMatchClass = t2ldr_pcrel_imm12_asmoperand;
169234353Sdim  // used for assembler pseudo instruction and maps to t2ldrlabel, so
170234353Sdim  // doesn't need encoder or print methods of its own.
171234353Sdim}
172221345Sdim
173218893Sdim// ADR instruction labels.
174218893Sdimdef t2adrlabel : Operand<i32> {
175218893Sdim  let EncoderMethod = "getT2AdrLabelOpValue";
176263508Sdim  let PrintMethod = "printAdrLabelOperand<0>";
177218893Sdim}
178218893Sdim
179226633Sdim// t2addrmode_posimm8  := reg + imm8
180226633Sdimdef MemPosImm8OffsetAsmOperand : AsmOperandClass {let Name="MemPosImm8Offset";}
181226633Sdimdef t2addrmode_posimm8 : Operand<i32> {
182263508Sdim  let PrintMethod = "printT2AddrModeImm8Operand<false>";
183226633Sdim  let EncoderMethod = "getT2AddrModeImm8OpValue";
184226633Sdim  let DecoderMethod = "DecodeT2AddrModeImm8";
185226633Sdim  let ParserMatchClass = MemPosImm8OffsetAsmOperand;
186226633Sdim  let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
187226633Sdim}
188226633Sdim
189226633Sdim// t2addrmode_negimm8  := reg - imm8
190226633Sdimdef MemNegImm8OffsetAsmOperand : AsmOperandClass {let Name="MemNegImm8Offset";}
191226633Sdimdef t2addrmode_negimm8 : Operand<i32>,
192226633Sdim                      ComplexPattern<i32, 2, "SelectT2AddrModeImm8", []> {
193263508Sdim  let PrintMethod = "printT2AddrModeImm8Operand<false>";
194226633Sdim  let EncoderMethod = "getT2AddrModeImm8OpValue";
195226633Sdim  let DecoderMethod = "DecodeT2AddrModeImm8";
196226633Sdim  let ParserMatchClass = MemNegImm8OffsetAsmOperand;
197226633Sdim  let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
198226633Sdim}
199226633Sdim
200204792Srdivacky// t2addrmode_imm8  := reg +/- imm8
201226633Sdimdef MemImm8OffsetAsmOperand : AsmOperandClass { let Name = "MemImm8Offset"; }
202263508Sdimclass T2AddrMode_Imm8 : Operand<i32>,
203263508Sdim                        ComplexPattern<i32, 2, "SelectT2AddrModeImm8", []> {
204218893Sdim  let EncoderMethod = "getT2AddrModeImm8OpValue";
205226633Sdim  let DecoderMethod = "DecodeT2AddrModeImm8";
206226633Sdim  let ParserMatchClass = MemImm8OffsetAsmOperand;
207195340Sed  let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
208195340Sed}
209195340Sed
210263508Sdimdef t2addrmode_imm8 : T2AddrMode_Imm8 {
211263508Sdim  let PrintMethod = "printT2AddrModeImm8Operand<false>";
212263508Sdim}
213263508Sdim
214263508Sdimdef t2addrmode_imm8_pre : T2AddrMode_Imm8 {
215263508Sdim  let PrintMethod = "printT2AddrModeImm8Operand<true>";
216263508Sdim}
217263508Sdim
218195340Seddef t2am_imm8_offset : Operand<i32>,
219218893Sdim                       ComplexPattern<i32, 1, "SelectT2AddrModeImm8Offset",
220218893Sdim                                      [], [SDNPWantRoot]> {
221195340Sed  let PrintMethod = "printT2AddrModeImm8OffsetOperand";
222218893Sdim  let EncoderMethod = "getT2AddrModeImm8OffsetOpValue";
223226633Sdim  let DecoderMethod = "DecodeT2Imm8";
224195340Sed}
225195340Sed
226198090Srdivacky// t2addrmode_imm8s4  := reg +/- (imm8 << 2)
227226633Sdimdef MemImm8s4OffsetAsmOperand : AsmOperandClass {let Name = "MemImm8s4Offset";}
228263508Sdimclass T2AddrMode_Imm8s4 : Operand<i32> {
229218893Sdim  let EncoderMethod = "getT2AddrModeImm8s4OpValue";
230226633Sdim  let DecoderMethod = "DecodeT2AddrModeImm8s4";
231226633Sdim  let ParserMatchClass = MemImm8s4OffsetAsmOperand;
232195340Sed  let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
233195340Sed}
234195340Sed
235263508Sdimdef t2addrmode_imm8s4 : T2AddrMode_Imm8s4 {
236263508Sdim  let PrintMethod = "printT2AddrModeImm8s4Operand<false>";
237263508Sdim}
238263508Sdim
239263508Sdimdef t2addrmode_imm8s4_pre : T2AddrMode_Imm8s4 {
240263508Sdim  let PrintMethod = "printT2AddrModeImm8s4Operand<true>";
241263508Sdim}
242263508Sdim
243226633Sdimdef t2am_imm8s4_offset_asmoperand : AsmOperandClass { let Name = "Imm8s4"; }
244205218Srdivackydef t2am_imm8s4_offset : Operand<i32> {
245205218Srdivacky  let PrintMethod = "printT2AddrModeImm8s4OffsetOperand";
246226633Sdim  let EncoderMethod = "getT2Imm8s4OpValue";
247226633Sdim  let DecoderMethod = "DecodeT2Imm8S4";
248205218Srdivacky}
249205218Srdivacky
250226633Sdim// t2addrmode_imm0_1020s4  := reg + (imm8 << 2)
251226633Sdimdef MemImm0_1020s4OffsetAsmOperand : AsmOperandClass {
252226633Sdim  let Name = "MemImm0_1020s4Offset";
253226633Sdim}
254263508Sdimdef t2addrmode_imm0_1020s4 : Operand<i32>,
255263508Sdim                         ComplexPattern<i32, 2, "SelectT2AddrModeExclusive"> {
256226633Sdim  let PrintMethod = "printT2AddrModeImm0_1020s4Operand";
257226633Sdim  let EncoderMethod = "getT2AddrModeImm0_1020s4OpValue";
258226633Sdim  let DecoderMethod = "DecodeT2AddrModeImm0_1020s4";
259226633Sdim  let ParserMatchClass = MemImm0_1020s4OffsetAsmOperand;
260226633Sdim  let MIOperandInfo = (ops GPRnopc:$base, i32imm:$offsimm);
261226633Sdim}
262226633Sdim
263198090Srdivacky// t2addrmode_so_reg  := reg + (reg << imm2)
264226633Sdimdef t2addrmode_so_reg_asmoperand : AsmOperandClass {let Name="T2MemRegOffset";}
265195340Seddef t2addrmode_so_reg : Operand<i32>,
266195340Sed                        ComplexPattern<i32, 3, "SelectT2AddrModeSoReg", []> {
267195340Sed  let PrintMethod = "printT2AddrModeSoRegOperand";
268218893Sdim  let EncoderMethod = "getT2AddrModeSORegOpValue";
269226633Sdim  let DecoderMethod = "DecodeT2AddrModeSOReg";
270226633Sdim  let ParserMatchClass = t2addrmode_so_reg_asmoperand;
271212904Sdim  let MIOperandInfo = (ops GPR:$base, rGPR:$offsreg, i32imm:$offsimm);
272195340Sed}
273195340Sed
274226633Sdim// Addresses for the TBB/TBH instructions.
275226633Sdimdef addrmode_tbb_asmoperand : AsmOperandClass { let Name = "MemTBB"; }
276226633Sdimdef addrmode_tbb : Operand<i32> {
277226633Sdim  let PrintMethod = "printAddrModeTBB";
278226633Sdim  let ParserMatchClass = addrmode_tbb_asmoperand;
279226633Sdim  let MIOperandInfo = (ops GPR:$Rn, rGPR:$Rm);
280221345Sdim}
281226633Sdimdef addrmode_tbh_asmoperand : AsmOperandClass { let Name = "MemTBH"; }
282226633Sdimdef addrmode_tbh : Operand<i32> {
283226633Sdim  let PrintMethod = "printAddrModeTBH";
284226633Sdim  let ParserMatchClass = addrmode_tbh_asmoperand;
285226633Sdim  let MIOperandInfo = (ops GPR:$Rn, rGPR:$Rm);
286226633Sdim}
287195340Sed
288194612Sed//===----------------------------------------------------------------------===//
289195098Sed// Multiclass helpers...
290194612Sed//
291194612Sed
292218893Sdim
293218893Sdimclass T2OneRegImm<dag oops, dag iops, InstrItinClass itin,
294218893Sdim           string opc, string asm, list<dag> pattern>
295218893Sdim  : T2I<oops, iops, itin, opc, asm, pattern> {
296218893Sdim  bits<4> Rd;
297218893Sdim  bits<12> imm;
298218893Sdim
299218893Sdim  let Inst{11-8}  = Rd;
300218893Sdim  let Inst{26}    = imm{11};
301218893Sdim  let Inst{14-12} = imm{10-8};
302218893Sdim  let Inst{7-0}   = imm{7-0};
303218893Sdim}
304218893Sdim
305218893Sdim
306218893Sdimclass T2sOneRegImm<dag oops, dag iops, InstrItinClass itin,
307218893Sdim           string opc, string asm, list<dag> pattern>
308218893Sdim  : T2sI<oops, iops, itin, opc, asm, pattern> {
309218893Sdim  bits<4> Rd;
310218893Sdim  bits<4> Rn;
311218893Sdim  bits<12> imm;
312218893Sdim
313218893Sdim  let Inst{11-8}  = Rd;
314218893Sdim  let Inst{26}    = imm{11};
315218893Sdim  let Inst{14-12} = imm{10-8};
316218893Sdim  let Inst{7-0}   = imm{7-0};
317218893Sdim}
318218893Sdim
319218893Sdimclass T2OneRegCmpImm<dag oops, dag iops, InstrItinClass itin,
320218893Sdim           string opc, string asm, list<dag> pattern>
321218893Sdim  : T2I<oops, iops, itin, opc, asm, pattern> {
322218893Sdim  bits<4> Rn;
323218893Sdim  bits<12> imm;
324218893Sdim
325218893Sdim  let Inst{19-16}  = Rn;
326218893Sdim  let Inst{26}    = imm{11};
327218893Sdim  let Inst{14-12} = imm{10-8};
328218893Sdim  let Inst{7-0}   = imm{7-0};
329218893Sdim}
330218893Sdim
331218893Sdim
332218893Sdimclass T2OneRegShiftedReg<dag oops, dag iops, InstrItinClass itin,
333218893Sdim           string opc, string asm, list<dag> pattern>
334218893Sdim  : T2I<oops, iops, itin, opc, asm, pattern> {
335218893Sdim  bits<4> Rd;
336218893Sdim  bits<12> ShiftedRm;
337218893Sdim
338218893Sdim  let Inst{11-8}  = Rd;
339218893Sdim  let Inst{3-0}   = ShiftedRm{3-0};
340218893Sdim  let Inst{5-4}   = ShiftedRm{6-5};
341218893Sdim  let Inst{14-12} = ShiftedRm{11-9};
342218893Sdim  let Inst{7-6}   = ShiftedRm{8-7};
343218893Sdim}
344218893Sdim
345218893Sdimclass T2sOneRegShiftedReg<dag oops, dag iops, InstrItinClass itin,
346218893Sdim           string opc, string asm, list<dag> pattern>
347218893Sdim  : T2sI<oops, iops, itin, opc, asm, pattern> {
348218893Sdim  bits<4> Rd;
349218893Sdim  bits<12> ShiftedRm;
350218893Sdim
351218893Sdim  let Inst{11-8}  = Rd;
352218893Sdim  let Inst{3-0}   = ShiftedRm{3-0};
353218893Sdim  let Inst{5-4}   = ShiftedRm{6-5};
354218893Sdim  let Inst{14-12} = ShiftedRm{11-9};
355218893Sdim  let Inst{7-6}   = ShiftedRm{8-7};
356218893Sdim}
357218893Sdim
358218893Sdimclass T2OneRegCmpShiftedReg<dag oops, dag iops, InstrItinClass itin,
359218893Sdim           string opc, string asm, list<dag> pattern>
360218893Sdim  : T2I<oops, iops, itin, opc, asm, pattern> {
361218893Sdim  bits<4> Rn;
362218893Sdim  bits<12> ShiftedRm;
363218893Sdim
364218893Sdim  let Inst{19-16} = Rn;
365218893Sdim  let Inst{3-0}   = ShiftedRm{3-0};
366218893Sdim  let Inst{5-4}   = ShiftedRm{6-5};
367218893Sdim  let Inst{14-12} = ShiftedRm{11-9};
368218893Sdim  let Inst{7-6}   = ShiftedRm{8-7};
369218893Sdim}
370218893Sdim
371218893Sdimclass T2TwoReg<dag oops, dag iops, InstrItinClass itin,
372218893Sdim           string opc, string asm, list<dag> pattern>
373218893Sdim  : T2I<oops, iops, itin, opc, asm, pattern> {
374218893Sdim  bits<4> Rd;
375218893Sdim  bits<4> Rm;
376218893Sdim
377218893Sdim  let Inst{11-8}  = Rd;
378218893Sdim  let Inst{3-0}   = Rm;
379218893Sdim}
380218893Sdim
381218893Sdimclass T2sTwoReg<dag oops, dag iops, InstrItinClass itin,
382218893Sdim           string opc, string asm, list<dag> pattern>
383218893Sdim  : T2sI<oops, iops, itin, opc, asm, pattern> {
384218893Sdim  bits<4> Rd;
385218893Sdim  bits<4> Rm;
386218893Sdim
387218893Sdim  let Inst{11-8}  = Rd;
388218893Sdim  let Inst{3-0}   = Rm;
389218893Sdim}
390218893Sdim
391218893Sdimclass T2TwoRegCmp<dag oops, dag iops, InstrItinClass itin,
392218893Sdim           string opc, string asm, list<dag> pattern>
393218893Sdim  : T2I<oops, iops, itin, opc, asm, pattern> {
394218893Sdim  bits<4> Rn;
395218893Sdim  bits<4> Rm;
396218893Sdim
397218893Sdim  let Inst{19-16} = Rn;
398218893Sdim  let Inst{3-0}   = Rm;
399218893Sdim}
400218893Sdim
401218893Sdim
402218893Sdimclass T2TwoRegImm<dag oops, dag iops, InstrItinClass itin,
403218893Sdim           string opc, string asm, list<dag> pattern>
404218893Sdim  : T2I<oops, iops, itin, opc, asm, pattern> {
405218893Sdim  bits<4> Rd;
406218893Sdim  bits<4> Rn;
407218893Sdim  bits<12> imm;
408218893Sdim
409218893Sdim  let Inst{11-8}  = Rd;
410218893Sdim  let Inst{19-16} = Rn;
411218893Sdim  let Inst{26}    = imm{11};
412218893Sdim  let Inst{14-12} = imm{10-8};
413218893Sdim  let Inst{7-0}   = imm{7-0};
414218893Sdim}
415218893Sdim
416218893Sdimclass T2sTwoRegImm<dag oops, dag iops, InstrItinClass itin,
417218893Sdim           string opc, string asm, list<dag> pattern>
418218893Sdim  : T2sI<oops, iops, itin, opc, asm, pattern> {
419218893Sdim  bits<4> Rd;
420218893Sdim  bits<4> Rn;
421218893Sdim  bits<12> imm;
422218893Sdim
423218893Sdim  let Inst{11-8}  = Rd;
424218893Sdim  let Inst{19-16} = Rn;
425218893Sdim  let Inst{26}    = imm{11};
426218893Sdim  let Inst{14-12} = imm{10-8};
427218893Sdim  let Inst{7-0}   = imm{7-0};
428218893Sdim}
429218893Sdim
430218893Sdimclass T2TwoRegShiftImm<dag oops, dag iops, InstrItinClass itin,
431218893Sdim           string opc, string asm, list<dag> pattern>
432218893Sdim  : T2I<oops, iops, itin, opc, asm, pattern> {
433218893Sdim  bits<4> Rd;
434218893Sdim  bits<4> Rm;
435218893Sdim  bits<5> imm;
436218893Sdim
437218893Sdim  let Inst{11-8}  = Rd;
438218893Sdim  let Inst{3-0}   = Rm;
439218893Sdim  let Inst{14-12} = imm{4-2};
440218893Sdim  let Inst{7-6}   = imm{1-0};
441218893Sdim}
442218893Sdim
443218893Sdimclass T2sTwoRegShiftImm<dag oops, dag iops, InstrItinClass itin,
444218893Sdim           string opc, string asm, list<dag> pattern>
445218893Sdim  : T2sI<oops, iops, itin, opc, asm, pattern> {
446218893Sdim  bits<4> Rd;
447218893Sdim  bits<4> Rm;
448218893Sdim  bits<5> imm;
449218893Sdim
450218893Sdim  let Inst{11-8}  = Rd;
451218893Sdim  let Inst{3-0}   = Rm;
452218893Sdim  let Inst{14-12} = imm{4-2};
453218893Sdim  let Inst{7-6}   = imm{1-0};
454218893Sdim}
455218893Sdim
456218893Sdimclass T2ThreeReg<dag oops, dag iops, InstrItinClass itin,
457218893Sdim           string opc, string asm, list<dag> pattern>
458218893Sdim  : T2I<oops, iops, itin, opc, asm, pattern> {
459218893Sdim  bits<4> Rd;
460218893Sdim  bits<4> Rn;
461218893Sdim  bits<4> Rm;
462218893Sdim
463218893Sdim  let Inst{11-8}  = Rd;
464218893Sdim  let Inst{19-16} = Rn;
465218893Sdim  let Inst{3-0}   = Rm;
466218893Sdim}
467218893Sdim
468263508Sdimclass T2ThreeRegNoP<dag oops, dag iops, InstrItinClass itin,
469263508Sdim           string asm, list<dag> pattern>
470263508Sdim  : T2XI<oops, iops, itin, asm, pattern> {
471263508Sdim  bits<4> Rd;
472263508Sdim  bits<4> Rn;
473263508Sdim  bits<4> Rm;
474263508Sdim
475263508Sdim  let Inst{11-8}  = Rd;
476263508Sdim  let Inst{19-16} = Rn;
477263508Sdim  let Inst{3-0}   = Rm;
478263508Sdim}
479263508Sdim
480218893Sdimclass T2sThreeReg<dag oops, dag iops, InstrItinClass itin,
481218893Sdim           string opc, string asm, list<dag> pattern>
482218893Sdim  : T2sI<oops, iops, itin, opc, asm, pattern> {
483218893Sdim  bits<4> Rd;
484218893Sdim  bits<4> Rn;
485218893Sdim  bits<4> Rm;
486218893Sdim
487218893Sdim  let Inst{11-8}  = Rd;
488218893Sdim  let Inst{19-16} = Rn;
489218893Sdim  let Inst{3-0}   = Rm;
490218893Sdim}
491218893Sdim
492218893Sdimclass T2TwoRegShiftedReg<dag oops, dag iops, InstrItinClass itin,
493218893Sdim           string opc, string asm, list<dag> pattern>
494218893Sdim  : T2I<oops, iops, itin, opc, asm, pattern> {
495218893Sdim  bits<4> Rd;
496218893Sdim  bits<4> Rn;
497218893Sdim  bits<12> ShiftedRm;
498218893Sdim
499218893Sdim  let Inst{11-8}  = Rd;
500218893Sdim  let Inst{19-16} = Rn;
501218893Sdim  let Inst{3-0}   = ShiftedRm{3-0};
502218893Sdim  let Inst{5-4}   = ShiftedRm{6-5};
503218893Sdim  let Inst{14-12} = ShiftedRm{11-9};
504218893Sdim  let Inst{7-6}   = ShiftedRm{8-7};
505218893Sdim}
506218893Sdim
507218893Sdimclass T2sTwoRegShiftedReg<dag oops, dag iops, InstrItinClass itin,
508218893Sdim           string opc, string asm, list<dag> pattern>
509218893Sdim  : T2sI<oops, iops, itin, opc, asm, pattern> {
510218893Sdim  bits<4> Rd;
511218893Sdim  bits<4> Rn;
512218893Sdim  bits<12> ShiftedRm;
513218893Sdim
514218893Sdim  let Inst{11-8}  = Rd;
515218893Sdim  let Inst{19-16} = Rn;
516218893Sdim  let Inst{3-0}   = ShiftedRm{3-0};
517218893Sdim  let Inst{5-4}   = ShiftedRm{6-5};
518218893Sdim  let Inst{14-12} = ShiftedRm{11-9};
519218893Sdim  let Inst{7-6}   = ShiftedRm{8-7};
520218893Sdim}
521218893Sdim
522218893Sdimclass T2FourReg<dag oops, dag iops, InstrItinClass itin,
523218893Sdim           string opc, string asm, list<dag> pattern>
524218893Sdim  : T2I<oops, iops, itin, opc, asm, pattern> {
525218893Sdim  bits<4> Rd;
526218893Sdim  bits<4> Rn;
527218893Sdim  bits<4> Rm;
528218893Sdim  bits<4> Ra;
529218893Sdim
530218893Sdim  let Inst{19-16} = Rn;
531218893Sdim  let Inst{15-12} = Ra;
532218893Sdim  let Inst{11-8}  = Rd;
533218893Sdim  let Inst{3-0}   = Rm;
534218893Sdim}
535218893Sdim
536218893Sdimclass T2MulLong<bits<3> opc22_20, bits<4> opc7_4,
537218893Sdim                dag oops, dag iops, InstrItinClass itin,
538218893Sdim                string opc, string asm, list<dag> pattern>
539218893Sdim  : T2I<oops, iops, itin, opc, asm, pattern> {
540218893Sdim  bits<4> RdLo;
541218893Sdim  bits<4> RdHi;
542218893Sdim  bits<4> Rn;
543218893Sdim  bits<4> Rm;
544218893Sdim
545218893Sdim  let Inst{31-23} = 0b111110111;
546218893Sdim  let Inst{22-20} = opc22_20;
547218893Sdim  let Inst{19-16} = Rn;
548218893Sdim  let Inst{15-12} = RdLo;
549218893Sdim  let Inst{11-8}  = RdHi;
550218893Sdim  let Inst{7-4}   = opc7_4;
551218893Sdim  let Inst{3-0}   = Rm;
552218893Sdim}
553243830Sdimclass T2MlaLong<bits<3> opc22_20, bits<4> opc7_4,
554243830Sdim                dag oops, dag iops, InstrItinClass itin,
555243830Sdim                string opc, string asm, list<dag> pattern>
556243830Sdim  : T2I<oops, iops, itin, opc, asm, pattern> {
557243830Sdim  bits<4> RdLo;
558243830Sdim  bits<4> RdHi;
559243830Sdim  bits<4> Rn;
560243830Sdim  bits<4> Rm;
561218893Sdim
562243830Sdim  let Inst{31-23} = 0b111110111;
563243830Sdim  let Inst{22-20} = opc22_20;
564243830Sdim  let Inst{19-16} = Rn;
565243830Sdim  let Inst{15-12} = RdLo;
566243830Sdim  let Inst{11-8}  = RdHi;
567243830Sdim  let Inst{7-4}   = opc7_4;
568243830Sdim  let Inst{3-0}   = Rm;
569243830Sdim}
570218893Sdim
571243830Sdim
572195098Sed/// T2I_bin_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a
573208599Srdivacky/// binary operation that produces a value. These are predicable and can be
574195098Sed/// changed to modify CPSR.
575218893Sdimmulticlass T2I_bin_irs<bits<4> opcod, string opc,
576218893Sdim                     InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
577239462Sdim                       PatFrag opnode, bit Commutable = 0,
578224145Sdim                       string wide = ""> {
579195098Sed   // shifted imm
580218893Sdim   def ri : T2sTwoRegImm<
581218893Sdim                (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_imm:$imm), iii,
582218893Sdim                 opc, "\t$Rd, $Rn, $imm",
583263508Sdim                 [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_imm:$imm))]>,
584263508Sdim                 Sched<[WriteALU, ReadALU]> {
585201360Srdivacky     let Inst{31-27} = 0b11110;
586201360Srdivacky     let Inst{25} = 0;
587201360Srdivacky     let Inst{24-21} = opcod;
588201360Srdivacky     let Inst{15} = 0;
589201360Srdivacky   }
590195098Sed   // register
591218893Sdim   def rr : T2sThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), iir,
592218893Sdim                 opc, !strconcat(wide, "\t$Rd, $Rn, $Rm"),
593263508Sdim                 [(set rGPR:$Rd, (opnode rGPR:$Rn, rGPR:$Rm))]>,
594263508Sdim                 Sched<[WriteALU, ReadALU, ReadALU]> {
595195098Sed     let isCommutable = Commutable;
596201360Srdivacky     let Inst{31-27} = 0b11101;
597201360Srdivacky     let Inst{26-25} = 0b01;
598201360Srdivacky     let Inst{24-21} = opcod;
599201360Srdivacky     let Inst{14-12} = 0b000; // imm3
600201360Srdivacky     let Inst{7-6} = 0b00; // imm2
601201360Srdivacky     let Inst{5-4} = 0b00; // type
602195098Sed   }
603195098Sed   // shifted register
604218893Sdim   def rs : T2sTwoRegShiftedReg<
605218893Sdim                 (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_reg:$ShiftedRm), iis,
606218893Sdim                 opc, !strconcat(wide, "\t$Rd, $Rn, $ShiftedRm"),
607263508Sdim                 [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_reg:$ShiftedRm))]>,
608263508Sdim                 Sched<[WriteALUsi, ReadALU]>  {
609201360Srdivacky     let Inst{31-27} = 0b11101;
610201360Srdivacky     let Inst{26-25} = 0b01;
611201360Srdivacky     let Inst{24-21} = opcod;
612201360Srdivacky   }
613224145Sdim  // Assembly aliases for optional destination operand when it's the same
614224145Sdim  // as the source operand.
615226633Sdim  def : t2InstAlias<!strconcat(opc, "${s}${p} $Rdn, $imm"),
616239462Sdim     (!cast<Instruction>(NAME#"ri") rGPR:$Rdn, rGPR:$Rdn,
617224145Sdim                                                    t2_so_imm:$imm, pred:$p,
618226633Sdim                                                    cc_out:$s)>;
619226633Sdim  def : t2InstAlias<!strconcat(opc, "${s}${p}", wide, " $Rdn, $Rm"),
620239462Sdim     (!cast<Instruction>(NAME#"rr") rGPR:$Rdn, rGPR:$Rdn,
621224145Sdim                                                    rGPR:$Rm, pred:$p,
622226633Sdim                                                    cc_out:$s)>;
623226633Sdim  def : t2InstAlias<!strconcat(opc, "${s}${p}", wide, " $Rdn, $shift"),
624239462Sdim     (!cast<Instruction>(NAME#"rs") rGPR:$Rdn, rGPR:$Rdn,
625224145Sdim                                                    t2_so_reg:$shift, pred:$p,
626226633Sdim                                                    cc_out:$s)>;
627195098Sed}
628195098Sed
629198090Srdivacky/// T2I_bin_w_irs - Same as T2I_bin_irs except these operations need
630224145Sdim//  the ".w" suffix to indicate that they are wide.
631218893Sdimmulticlass T2I_bin_w_irs<bits<4> opcod, string opc,
632218893Sdim                     InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
633239462Sdim                         PatFrag opnode, bit Commutable = 0> :
634239462Sdim    T2I_bin_irs<opcod, opc, iii, iir, iis, opnode, Commutable, ".w"> {
635234353Sdim  // Assembler aliases w/ the ".w" suffix.
636234353Sdim  def : t2InstAlias<!strconcat(opc, "${s}${p}.w", " $Rd, $Rn, $imm"),
637239462Sdim     (!cast<Instruction>(NAME#"ri") rGPR:$Rd, rGPR:$Rn, t2_so_imm:$imm, pred:$p,
638239462Sdim                                    cc_out:$s)>;
639226633Sdim  // Assembler aliases w/o the ".w" suffix.
640226633Sdim  def : t2InstAlias<!strconcat(opc, "${s}${p}", " $Rd, $Rn, $Rm"),
641239462Sdim     (!cast<Instruction>(NAME#"rr") rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, pred:$p,
642239462Sdim                                    cc_out:$s)>;
643226633Sdim  def : t2InstAlias<!strconcat(opc, "${s}${p}", " $Rd, $Rn, $shift"),
644239462Sdim     (!cast<Instruction>(NAME#"rs") rGPR:$Rd, rGPR:$Rn, t2_so_reg:$shift,
645239462Sdim                                    pred:$p, cc_out:$s)>;
646198090Srdivacky
647226633Sdim  // and with the optional destination operand, too.
648234353Sdim  def : t2InstAlias<!strconcat(opc, "${s}${p}.w", " $Rdn, $imm"),
649239462Sdim     (!cast<Instruction>(NAME#"ri") rGPR:$Rdn, rGPR:$Rdn, t2_so_imm:$imm,
650239462Sdim                                    pred:$p, cc_out:$s)>;
651226633Sdim  def : t2InstAlias<!strconcat(opc, "${s}${p}", " $Rdn, $Rm"),
652239462Sdim     (!cast<Instruction>(NAME#"rr") rGPR:$Rdn, rGPR:$Rdn, rGPR:$Rm, pred:$p,
653239462Sdim                                    cc_out:$s)>;
654226633Sdim  def : t2InstAlias<!strconcat(opc, "${s}${p}", " $Rdn, $shift"),
655239462Sdim     (!cast<Instruction>(NAME#"rs") rGPR:$Rdn, rGPR:$Rdn, t2_so_reg:$shift,
656239462Sdim                                    pred:$p, cc_out:$s)>;
657226633Sdim}
658226633Sdim
659195098Sed/// T2I_rbin_is - Same as T2I_bin_irs except the order of operands are
660212904Sdim/// reversed.  The 'rr' form is only defined for the disassembler; for codegen
661212904Sdim/// it is equivalent to the T2I_bin_irs counterpart.
662212904Sdimmulticlass T2I_rbin_irs<bits<4> opcod, string opc, PatFrag opnode> {
663194754Sed   // shifted imm
664218893Sdim   def ri : T2sTwoRegImm<
665218893Sdim                 (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_imm:$imm), IIC_iALUi,
666218893Sdim                 opc, ".w\t$Rd, $Rn, $imm",
667263508Sdim                 [(set rGPR:$Rd, (opnode t2_so_imm:$imm, rGPR:$Rn))]>,
668263508Sdim                 Sched<[WriteALU, ReadALU]> {
669201360Srdivacky     let Inst{31-27} = 0b11110;
670201360Srdivacky     let Inst{25} = 0;
671201360Srdivacky     let Inst{24-21} = opcod;
672201360Srdivacky     let Inst{15} = 0;
673201360Srdivacky   }
674212904Sdim   // register
675218893Sdim   def rr : T2sThreeReg<
676218893Sdim                 (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iALUr,
677218893Sdim                 opc, "\t$Rd, $Rn, $Rm",
678263508Sdim                 [/* For disassembly only; pattern left blank */]>,
679263508Sdim                 Sched<[WriteALU, ReadALU, ReadALU]> {
680212904Sdim     let Inst{31-27} = 0b11101;
681212904Sdim     let Inst{26-25} = 0b01;
682212904Sdim     let Inst{24-21} = opcod;
683212904Sdim     let Inst{14-12} = 0b000; // imm3
684212904Sdim     let Inst{7-6} = 0b00; // imm2
685212904Sdim     let Inst{5-4} = 0b00; // type
686212904Sdim   }
687194754Sed   // shifted register
688218893Sdim   def rs : T2sTwoRegShiftedReg<
689218893Sdim                 (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_reg:$ShiftedRm),
690218893Sdim                 IIC_iALUsir, opc, "\t$Rd, $Rn, $ShiftedRm",
691263508Sdim                 [(set rGPR:$Rd, (opnode t2_so_reg:$ShiftedRm, rGPR:$Rn))]>,
692263508Sdim                 Sched<[WriteALUsi, ReadALU]> {
693201360Srdivacky     let Inst{31-27} = 0b11101;
694201360Srdivacky     let Inst{26-25} = 0b01;
695201360Srdivacky     let Inst{24-21} = opcod;
696201360Srdivacky   }
697194754Sed}
698194754Sed
699195098Sed/// T2I_bin_s_irs - Similar to T2I_bin_irs except it sets the 's' bit so the
700194612Sed/// instruction modifies the CPSR register.
701226633Sdim///
702226633Sdim/// These opcodes will be converted to the real non-S opcodes by
703226633Sdim/// AdjustInstrPostInstrSelection after giving then an optional CPSR operand.
704234353Sdimlet hasPostISelHook = 1, Defs = [CPSR] in {
705234353Sdimmulticlass T2I_bin_s_irs<InstrItinClass iii, InstrItinClass iir,
706234353Sdim                         InstrItinClass iis, PatFrag opnode,
707234353Sdim                         bit Commutable = 0> {
708194612Sed   // shifted imm
709234353Sdim   def ri : t2PseudoInst<(outs rGPR:$Rd),
710234353Sdim                         (ins GPRnopc:$Rn, t2_so_imm:$imm, pred:$p),
711234353Sdim                         4, iii,
712234353Sdim                         [(set rGPR:$Rd, CPSR, (opnode GPRnopc:$Rn,
713263508Sdim                                                t2_so_imm:$imm))]>,
714263508Sdim            Sched<[WriteALU, ReadALU]>;
715195098Sed   // register
716234353Sdim   def rr : t2PseudoInst<(outs rGPR:$Rd), (ins GPRnopc:$Rn, rGPR:$Rm, pred:$p),
717234353Sdim                         4, iir,
718234353Sdim                         [(set rGPR:$Rd, CPSR, (opnode GPRnopc:$Rn,
719263508Sdim                                                rGPR:$Rm))]>,
720263508Sdim            Sched<[WriteALU, ReadALU, ReadALU]> {
721234353Sdim     let isCommutable = Commutable;
722234353Sdim   }
723194754Sed   // shifted register
724234353Sdim   def rs : t2PseudoInst<(outs rGPR:$Rd),
725234353Sdim                         (ins GPRnopc:$Rn, t2_so_reg:$ShiftedRm, pred:$p),
726234353Sdim                         4, iis,
727234353Sdim                         [(set rGPR:$Rd, CPSR, (opnode GPRnopc:$Rn,
728263508Sdim                                                t2_so_reg:$ShiftedRm))]>,
729263508Sdim            Sched<[WriteALUsi, ReadALUsr]>;
730194754Sed}
731194754Sed}
732194612Sed
733234353Sdim/// T2I_rbin_s_is -  Same as T2I_bin_s_irs, except selection DAG
734234353Sdim/// operands are reversed.
735234353Sdimlet hasPostISelHook = 1, Defs = [CPSR] in {
736234353Sdimmulticlass T2I_rbin_s_is<PatFrag opnode> {
737234353Sdim   // shifted imm
738234353Sdim   def ri : t2PseudoInst<(outs rGPR:$Rd),
739239462Sdim                         (ins rGPR:$Rn, t2_so_imm:$imm, pred:$p),
740234353Sdim                         4, IIC_iALUi,
741234353Sdim                         [(set rGPR:$Rd, CPSR, (opnode t2_so_imm:$imm,
742263508Sdim                                                rGPR:$Rn))]>,
743263508Sdim            Sched<[WriteALU, ReadALU]>;
744234353Sdim   // shifted register
745234353Sdim   def rs : t2PseudoInst<(outs rGPR:$Rd),
746239462Sdim                         (ins rGPR:$Rn, t2_so_reg:$ShiftedRm, pred:$p),
747234353Sdim                         4, IIC_iALUsi,
748234353Sdim                         [(set rGPR:$Rd, CPSR, (opnode t2_so_reg:$ShiftedRm,
749263508Sdim                                                rGPR:$Rn))]>,
750263508Sdim            Sched<[WriteALUsi, ReadALU]>;
751234353Sdim}
752234353Sdim}
753234353Sdim
754195098Sed/// T2I_bin_ii12rs - Defines a set of (op reg, {so_imm|imm0_4095|r|so_reg})
755195098Sed/// patterns for a binary operation that produces a value.
756201360Srdivackymulticlass T2I_bin_ii12rs<bits<3> op23_21, string opc, PatFrag opnode,
757201360Srdivacky                          bit Commutable = 0> {
758194754Sed   // shifted imm
759212904Sdim   // The register-immediate version is re-materializable. This is useful
760212904Sdim   // in particular for taking the address of a local.
761212904Sdim   let isReMaterializable = 1 in {
762218893Sdim   def ri : T2sTwoRegImm<
763226633Sdim               (outs GPRnopc:$Rd), (ins GPRnopc:$Rn, t2_so_imm:$imm), IIC_iALUi,
764226633Sdim               opc, ".w\t$Rd, $Rn, $imm",
765263508Sdim               [(set GPRnopc:$Rd, (opnode GPRnopc:$Rn, t2_so_imm:$imm))]>,
766263508Sdim               Sched<[WriteALU, ReadALU]> {
767201360Srdivacky     let Inst{31-27} = 0b11110;
768201360Srdivacky     let Inst{25} = 0;
769201360Srdivacky     let Inst{24} = 1;
770201360Srdivacky     let Inst{23-21} = op23_21;
771201360Srdivacky     let Inst{15} = 0;
772201360Srdivacky   }
773212904Sdim   }
774195098Sed   // 12-bit imm
775218893Sdim   def ri12 : T2I<
776226633Sdim                  (outs GPRnopc:$Rd), (ins GPR:$Rn, imm0_4095:$imm), IIC_iALUi,
777218893Sdim                  !strconcat(opc, "w"), "\t$Rd, $Rn, $imm",
778263508Sdim                  [(set GPRnopc:$Rd, (opnode GPR:$Rn, imm0_4095:$imm))]>,
779263508Sdim                  Sched<[WriteALU, ReadALU]> {
780218893Sdim     bits<4> Rd;
781218893Sdim     bits<4> Rn;
782218893Sdim     bits<12> imm;
783201360Srdivacky     let Inst{31-27} = 0b11110;
784218893Sdim     let Inst{26} = imm{11};
785218893Sdim     let Inst{25-24} = 0b10;
786201360Srdivacky     let Inst{23-21} = op23_21;
787201360Srdivacky     let Inst{20} = 0; // The S bit.
788218893Sdim     let Inst{19-16} = Rn;
789201360Srdivacky     let Inst{15} = 0;
790218893Sdim     let Inst{14-12} = imm{10-8};
791218893Sdim     let Inst{11-8} = Rd;
792218893Sdim     let Inst{7-0} = imm{7-0};
793201360Srdivacky   }
794195098Sed   // register
795226633Sdim   def rr : T2sThreeReg<(outs GPRnopc:$Rd), (ins GPRnopc:$Rn, rGPR:$Rm),
796226633Sdim                 IIC_iALUr, opc, ".w\t$Rd, $Rn, $Rm",
797263508Sdim                 [(set GPRnopc:$Rd, (opnode GPRnopc:$Rn, rGPR:$Rm))]>,
798263508Sdim                 Sched<[WriteALU, ReadALU, ReadALU]> {
799195098Sed     let isCommutable = Commutable;
800201360Srdivacky     let Inst{31-27} = 0b11101;
801201360Srdivacky     let Inst{26-25} = 0b01;
802201360Srdivacky     let Inst{24} = 1;
803201360Srdivacky     let Inst{23-21} = op23_21;
804201360Srdivacky     let Inst{14-12} = 0b000; // imm3
805201360Srdivacky     let Inst{7-6} = 0b00; // imm2
806201360Srdivacky     let Inst{5-4} = 0b00; // type
807195098Sed   }
808194612Sed   // shifted register
809218893Sdim   def rs : T2sTwoRegShiftedReg<
810226633Sdim                 (outs GPRnopc:$Rd), (ins GPRnopc:$Rn, t2_so_reg:$ShiftedRm),
811218893Sdim                 IIC_iALUsi, opc, ".w\t$Rd, $Rn, $ShiftedRm",
812263508Sdim              [(set GPRnopc:$Rd, (opnode GPRnopc:$Rn, t2_so_reg:$ShiftedRm))]>,
813263508Sdim              Sched<[WriteALUsi, ReadALU]> {
814201360Srdivacky     let Inst{31-27} = 0b11101;
815202375Srdivacky     let Inst{26-25} = 0b01;
816201360Srdivacky     let Inst{24} = 1;
817201360Srdivacky     let Inst{23-21} = op23_21;
818201360Srdivacky   }
819194612Sed}
820194612Sed
821199989Srdivacky/// T2I_adde_sube_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns
822204642Srdivacky/// for a binary operation that produces a value and use the carry
823199989Srdivacky/// bit. It's not predicable.
824226633Sdimlet Defs = [CPSR], Uses = [CPSR] in {
825204642Srdivackymulticlass T2I_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode,
826204642Srdivacky                             bit Commutable = 0> {
827194754Sed   // shifted imm
828218893Sdim   def ri : T2sTwoRegImm<(outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_imm:$imm),
829218893Sdim                 IIC_iALUi, opc, "\t$Rd, $Rn, $imm",
830226633Sdim               [(set rGPR:$Rd, CPSR, (opnode rGPR:$Rn, t2_so_imm:$imm, CPSR))]>,
831263508Sdim                 Requires<[IsThumb2]>, Sched<[WriteALU, ReadALU]> {
832201360Srdivacky     let Inst{31-27} = 0b11110;
833201360Srdivacky     let Inst{25} = 0;
834201360Srdivacky     let Inst{24-21} = opcod;
835201360Srdivacky     let Inst{15} = 0;
836201360Srdivacky   }
837195098Sed   // register
838218893Sdim   def rr : T2sThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iALUr,
839218893Sdim                 opc, ".w\t$Rd, $Rn, $Rm",
840226633Sdim                 [(set rGPR:$Rd, CPSR, (opnode rGPR:$Rn, rGPR:$Rm, CPSR))]>,
841263508Sdim                 Requires<[IsThumb2]>, Sched<[WriteALU, ReadALU, ReadALU]> {
842195098Sed     let isCommutable = Commutable;
843201360Srdivacky     let Inst{31-27} = 0b11101;
844201360Srdivacky     let Inst{26-25} = 0b01;
845201360Srdivacky     let Inst{24-21} = opcod;
846201360Srdivacky     let Inst{14-12} = 0b000; // imm3
847201360Srdivacky     let Inst{7-6} = 0b00; // imm2
848201360Srdivacky     let Inst{5-4} = 0b00; // type
849195098Sed   }
850194754Sed   // shifted register
851218893Sdim   def rs : T2sTwoRegShiftedReg<
852218893Sdim                 (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_reg:$ShiftedRm),
853218893Sdim                 IIC_iALUsi, opc, ".w\t$Rd, $Rn, $ShiftedRm",
854226633Sdim         [(set rGPR:$Rd, CPSR, (opnode rGPR:$Rn, t2_so_reg:$ShiftedRm, CPSR))]>,
855263508Sdim                 Requires<[IsThumb2]>, Sched<[WriteALUsi, ReadALU]> {
856201360Srdivacky     let Inst{31-27} = 0b11101;
857201360Srdivacky     let Inst{26-25} = 0b01;
858201360Srdivacky     let Inst{24-21} = opcod;
859201360Srdivacky   }
860204642Srdivacky}
861221345Sdim}
862204642Srdivacky
863195098Sed/// T2I_sh_ir - Defines a set of (op reg, {so_imm|r}) patterns for a shift /
864195098Sed//  rotate operation that produces a value.
865239462Sdimmulticlass T2I_sh_ir<bits<2> opcod, string opc, Operand ty, PatFrag opnode> {
866195098Sed   // 5-bit imm
867218893Sdim   def ri : T2sTwoRegShiftImm<
868226633Sdim                 (outs rGPR:$Rd), (ins rGPR:$Rm, ty:$imm), IIC_iMOVsi,
869218893Sdim                 opc, ".w\t$Rd, $Rm, $imm",
870263508Sdim                 [(set rGPR:$Rd, (opnode rGPR:$Rm, (i32 ty:$imm)))]>,
871263508Sdim                 Sched<[WriteALU]> {
872201360Srdivacky     let Inst{31-27} = 0b11101;
873201360Srdivacky     let Inst{26-21} = 0b010010;
874201360Srdivacky     let Inst{19-16} = 0b1111; // Rn
875201360Srdivacky     let Inst{5-4} = opcod;
876201360Srdivacky   }
877195098Sed   // register
878218893Sdim   def rr : T2sThreeReg<
879218893Sdim                 (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMOVsr,
880218893Sdim                 opc, ".w\t$Rd, $Rn, $Rm",
881263508Sdim                 [(set rGPR:$Rd, (opnode rGPR:$Rn, rGPR:$Rm))]>,
882263508Sdim                 Sched<[WriteALU]> {
883201360Srdivacky     let Inst{31-27} = 0b11111;
884201360Srdivacky     let Inst{26-23} = 0b0100;
885201360Srdivacky     let Inst{22-21} = opcod;
886201360Srdivacky     let Inst{15-12} = 0b1111;
887201360Srdivacky     let Inst{7-4} = 0b0000;
888201360Srdivacky   }
889226633Sdim
890226633Sdim  // Optional destination register
891226633Sdim  def : t2InstAlias<!strconcat(opc, "${s}${p}", ".w $Rdn, $imm"),
892239462Sdim     (!cast<Instruction>(NAME#"ri") rGPR:$Rdn, rGPR:$Rdn, ty:$imm, pred:$p,
893239462Sdim                                    cc_out:$s)>;
894226633Sdim  def : t2InstAlias<!strconcat(opc, "${s}${p}", ".w $Rdn, $Rm"),
895239462Sdim     (!cast<Instruction>(NAME#"rr") rGPR:$Rdn, rGPR:$Rdn, rGPR:$Rm, pred:$p,
896239462Sdim                                    cc_out:$s)>;
897226633Sdim
898226633Sdim  // Assembler aliases w/o the ".w" suffix.
899226633Sdim  def : t2InstAlias<!strconcat(opc, "${s}${p}", " $Rd, $Rn, $imm"),
900239462Sdim     (!cast<Instruction>(NAME#"ri") rGPR:$Rd, rGPR:$Rn, ty:$imm, pred:$p,
901239462Sdim                                    cc_out:$s)>;
902226633Sdim  def : t2InstAlias<!strconcat(opc, "${s}${p}", " $Rd, $Rn, $Rm"),
903239462Sdim     (!cast<Instruction>(NAME#"rr") rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, pred:$p,
904239462Sdim                                    cc_out:$s)>;
905226633Sdim
906226633Sdim  // and with the optional destination operand, too.
907226633Sdim  def : t2InstAlias<!strconcat(opc, "${s}${p}", " $Rdn, $imm"),
908239462Sdim     (!cast<Instruction>(NAME#"ri") rGPR:$Rdn, rGPR:$Rdn, ty:$imm, pred:$p,
909239462Sdim                                    cc_out:$s)>;
910226633Sdim  def : t2InstAlias<!strconcat(opc, "${s}${p}", " $Rdn, $Rm"),
911239462Sdim     (!cast<Instruction>(NAME#"rr") rGPR:$Rdn, rGPR:$Rdn, rGPR:$Rm, pred:$p,
912239462Sdim                                    cc_out:$s)>;
913195098Sed}
914194754Sed
915201360Srdivacky/// T2I_cmp_irs - Defines a set of (op r, {so_imm|r|so_reg}) cmp / test
916195098Sed/// patterns. Similar to T2I_bin_irs except the instruction does not produce
917194754Sed/// a explicit result, only implicitly set CPSR.
918218893Sdimmulticlass T2I_cmp_irs<bits<4> opcod, string opc,
919218893Sdim                     InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
920239462Sdim                       PatFrag opnode> {
921226633Sdimlet isCompare = 1, Defs = [CPSR] in {
922194754Sed   // shifted imm
923218893Sdim   def ri : T2OneRegCmpImm<
924226633Sdim                (outs), (ins GPRnopc:$Rn, t2_so_imm:$imm), iii,
925218893Sdim                opc, ".w\t$Rn, $imm",
926263508Sdim                [(opnode GPRnopc:$Rn, t2_so_imm:$imm)]>, Sched<[WriteCMP]> {
927201360Srdivacky     let Inst{31-27} = 0b11110;
928201360Srdivacky     let Inst{25} = 0;
929201360Srdivacky     let Inst{24-21} = opcod;
930201360Srdivacky     let Inst{20} = 1; // The S bit.
931201360Srdivacky     let Inst{15} = 0;
932201360Srdivacky     let Inst{11-8} = 0b1111; // Rd
933201360Srdivacky   }
934195098Sed   // register
935218893Sdim   def rr : T2TwoRegCmp<
936226633Sdim                (outs), (ins GPRnopc:$Rn, rGPR:$Rm), iir,
937226633Sdim                opc, ".w\t$Rn, $Rm",
938263508Sdim                [(opnode GPRnopc:$Rn, rGPR:$Rm)]>, Sched<[WriteCMP]> {
939201360Srdivacky     let Inst{31-27} = 0b11101;
940201360Srdivacky     let Inst{26-25} = 0b01;
941201360Srdivacky     let Inst{24-21} = opcod;
942201360Srdivacky     let Inst{20} = 1; // The S bit.
943201360Srdivacky     let Inst{14-12} = 0b000; // imm3
944201360Srdivacky     let Inst{11-8} = 0b1111; // Rd
945201360Srdivacky     let Inst{7-6} = 0b00; // imm2
946201360Srdivacky     let Inst{5-4} = 0b00; // type
947201360Srdivacky   }
948194754Sed   // shifted register
949218893Sdim   def rs : T2OneRegCmpShiftedReg<
950226633Sdim                (outs), (ins GPRnopc:$Rn, t2_so_reg:$ShiftedRm), iis,
951218893Sdim                opc, ".w\t$Rn, $ShiftedRm",
952263508Sdim                [(opnode GPRnopc:$Rn, t2_so_reg:$ShiftedRm)]>,
953263508Sdim                Sched<[WriteCMPsi]> {
954201360Srdivacky     let Inst{31-27} = 0b11101;
955201360Srdivacky     let Inst{26-25} = 0b01;
956201360Srdivacky     let Inst{24-21} = opcod;
957201360Srdivacky     let Inst{20} = 1; // The S bit.
958201360Srdivacky     let Inst{11-8} = 0b1111; // Rd
959201360Srdivacky   }
960194754Sed}
961226633Sdim
962226633Sdim  // Assembler aliases w/o the ".w" suffix.
963226633Sdim  // No alias here for 'rr' version as not all instantiations of this
964226633Sdim  // multiclass want one (CMP in particular, does not).
965226633Sdim  def : t2InstAlias<!strconcat(opc, "${p}", " $Rn, $imm"),
966239462Sdim     (!cast<Instruction>(NAME#"ri") GPRnopc:$Rn, t2_so_imm:$imm, pred:$p)>;
967226633Sdim  def : t2InstAlias<!strconcat(opc, "${p}", " $Rn, $shift"),
968239462Sdim     (!cast<Instruction>(NAME#"rs") GPRnopc:$Rn, t2_so_reg:$shift, pred:$p)>;
969194754Sed}
970194754Sed
971195340Sed/// T2I_ld - Defines a set of (op r, {imm12|imm8|so_reg}) load patterns.
972218893Sdimmulticlass T2I_ld<bit signed, bits<2> opcod, string opc,
973226633Sdim                  InstrItinClass iii, InstrItinClass iis, RegisterClass target,
974226633Sdim                  PatFrag opnode> {
975226633Sdim  def i12 : T2Ii12<(outs target:$Rt), (ins t2addrmode_imm12:$addr), iii,
976218893Sdim                   opc, ".w\t$Rt, $addr",
977226633Sdim                   [(set target:$Rt, (opnode t2addrmode_imm12:$addr))]> {
978226633Sdim    bits<4> Rt;
979226633Sdim    bits<17> addr;
980226633Sdim    let Inst{31-25} = 0b1111100;
981201360Srdivacky    let Inst{24} = signed;
982201360Srdivacky    let Inst{23} = 1;
983201360Srdivacky    let Inst{22-21} = opcod;
984201360Srdivacky    let Inst{20} = 1; // load
985226633Sdim    let Inst{19-16} = addr{16-13}; // Rn
986218893Sdim    let Inst{15-12} = Rt;
987218893Sdim    let Inst{11-0}  = addr{11-0};  // imm
988263508Sdim
989263508Sdim    let DecoderMethod = "DecodeT2LoadImm12";
990201360Srdivacky  }
991226633Sdim  def i8  : T2Ii8 <(outs target:$Rt), (ins t2addrmode_negimm8:$addr), iii,
992218893Sdim                   opc, "\t$Rt, $addr",
993226633Sdim                   [(set target:$Rt, (opnode t2addrmode_negimm8:$addr))]> {
994226633Sdim    bits<4> Rt;
995226633Sdim    bits<13> addr;
996201360Srdivacky    let Inst{31-27} = 0b11111;
997201360Srdivacky    let Inst{26-25} = 0b00;
998201360Srdivacky    let Inst{24} = signed;
999201360Srdivacky    let Inst{23} = 0;
1000201360Srdivacky    let Inst{22-21} = opcod;
1001201360Srdivacky    let Inst{20} = 1; // load
1002226633Sdim    let Inst{19-16} = addr{12-9}; // Rn
1003226633Sdim    let Inst{15-12} = Rt;
1004201360Srdivacky    let Inst{11} = 1;
1005201360Srdivacky    // Offset: index==TRUE, wback==FALSE
1006201360Srdivacky    let Inst{10} = 1; // The P bit.
1007226633Sdim    let Inst{9}     = addr{8};    // U
1008201360Srdivacky    let Inst{8} = 0; // The W bit.
1009218893Sdim    let Inst{7-0}   = addr{7-0};  // imm
1010263508Sdim
1011263508Sdim    let DecoderMethod = "DecodeT2LoadImm8";
1012201360Srdivacky  }
1013226633Sdim  def s   : T2Iso <(outs target:$Rt), (ins t2addrmode_so_reg:$addr), iis,
1014218893Sdim                   opc, ".w\t$Rt, $addr",
1015226633Sdim                   [(set target:$Rt, (opnode t2addrmode_so_reg:$addr))]> {
1016201360Srdivacky    let Inst{31-27} = 0b11111;
1017201360Srdivacky    let Inst{26-25} = 0b00;
1018201360Srdivacky    let Inst{24} = signed;
1019201360Srdivacky    let Inst{23} = 0;
1020201360Srdivacky    let Inst{22-21} = opcod;
1021201360Srdivacky    let Inst{20} = 1; // load
1022201360Srdivacky    let Inst{11-6} = 0b000000;
1023218893Sdim
1024218893Sdim    bits<4> Rt;
1025218893Sdim    let Inst{15-12} = Rt;
1026218893Sdim
1027218893Sdim    bits<10> addr;
1028218893Sdim    let Inst{19-16} = addr{9-6}; // Rn
1029218893Sdim    let Inst{3-0}   = addr{5-2}; // Rm
1030218893Sdim    let Inst{5-4}   = addr{1-0}; // imm
1031226633Sdim
1032226633Sdim    let DecoderMethod = "DecodeT2LoadShift";
1033201360Srdivacky  }
1034218893Sdim
1035234353Sdim  // pci variant is very similar to i12, but supports negative offsets
1036234353Sdim  // from the PC.
1037226633Sdim  def pci : T2Ipc <(outs target:$Rt), (ins t2ldrlabel:$addr), iii,
1038218893Sdim                   opc, ".w\t$Rt, $addr",
1039226633Sdim                   [(set target:$Rt, (opnode (ARMWrapper tconstpool:$addr)))]> {
1040198892Srdivacky    let isReMaterializable = 1;
1041201360Srdivacky    let Inst{31-27} = 0b11111;
1042201360Srdivacky    let Inst{26-25} = 0b00;
1043201360Srdivacky    let Inst{24} = signed;
1044201360Srdivacky    let Inst{22-21} = opcod;
1045201360Srdivacky    let Inst{20} = 1; // load
1046201360Srdivacky    let Inst{19-16} = 0b1111; // Rn
1047263508Sdim
1048218893Sdim    bits<4> Rt;
1049218893Sdim    let Inst{15-12} = Rt{3-0};
1050263508Sdim
1051263508Sdim    bits<13> addr;
1052263508Sdim    let Inst{23} = addr{12}; // add = (U == '1')
1053218893Sdim    let Inst{11-0}  = addr{11-0};
1054263508Sdim
1055263508Sdim    let DecoderMethod = "DecodeT2LoadLabel";
1056198892Srdivacky  }
1057195340Sed}
1058195340Sed
1059195340Sed/// T2I_st - Defines a set of (op r, {imm12|imm8|so_reg}) store patterns.
1060218893Sdimmulticlass T2I_st<bits<2> opcod, string opc,
1061226633Sdim                  InstrItinClass iii, InstrItinClass iis, RegisterClass target,
1062226633Sdim                  PatFrag opnode> {
1063226633Sdim  def i12 : T2Ii12<(outs), (ins target:$Rt, t2addrmode_imm12:$addr), iii,
1064218893Sdim                   opc, ".w\t$Rt, $addr",
1065226633Sdim                   [(opnode target:$Rt, t2addrmode_imm12:$addr)]> {
1066201360Srdivacky    let Inst{31-27} = 0b11111;
1067201360Srdivacky    let Inst{26-23} = 0b0001;
1068201360Srdivacky    let Inst{22-21} = opcod;
1069201360Srdivacky    let Inst{20} = 0; // !load
1070218893Sdim
1071218893Sdim    bits<4> Rt;
1072218893Sdim    let Inst{15-12} = Rt;
1073218893Sdim
1074218893Sdim    bits<17> addr;
1075221345Sdim    let addr{12}    = 1;           // add = TRUE
1076218893Sdim    let Inst{19-16} = addr{16-13}; // Rn
1077218893Sdim    let Inst{23}    = addr{12};    // U
1078218893Sdim    let Inst{11-0}  = addr{11-0};  // imm
1079201360Srdivacky  }
1080226633Sdim  def i8  : T2Ii8 <(outs), (ins target:$Rt, t2addrmode_negimm8:$addr), iii,
1081218893Sdim                   opc, "\t$Rt, $addr",
1082226633Sdim                   [(opnode target:$Rt, t2addrmode_negimm8:$addr)]> {
1083201360Srdivacky    let Inst{31-27} = 0b11111;
1084201360Srdivacky    let Inst{26-23} = 0b0000;
1085201360Srdivacky    let Inst{22-21} = opcod;
1086201360Srdivacky    let Inst{20} = 0; // !load
1087201360Srdivacky    let Inst{11} = 1;
1088201360Srdivacky    // Offset: index==TRUE, wback==FALSE
1089201360Srdivacky    let Inst{10} = 1; // The P bit.
1090201360Srdivacky    let Inst{8} = 0; // The W bit.
1091218893Sdim
1092218893Sdim    bits<4> Rt;
1093218893Sdim    let Inst{15-12} = Rt;
1094218893Sdim
1095218893Sdim    bits<13> addr;
1096218893Sdim    let Inst{19-16} = addr{12-9}; // Rn
1097218893Sdim    let Inst{9}     = addr{8};    // U
1098218893Sdim    let Inst{7-0}   = addr{7-0};  // imm
1099201360Srdivacky  }
1100226633Sdim  def s   : T2Iso <(outs), (ins target:$Rt, t2addrmode_so_reg:$addr), iis,
1101218893Sdim                   opc, ".w\t$Rt, $addr",
1102226633Sdim                   [(opnode target:$Rt, t2addrmode_so_reg:$addr)]> {
1103201360Srdivacky    let Inst{31-27} = 0b11111;
1104201360Srdivacky    let Inst{26-23} = 0b0000;
1105201360Srdivacky    let Inst{22-21} = opcod;
1106201360Srdivacky    let Inst{20} = 0; // !load
1107201360Srdivacky    let Inst{11-6} = 0b000000;
1108218893Sdim
1109218893Sdim    bits<4> Rt;
1110218893Sdim    let Inst{15-12} = Rt;
1111218893Sdim
1112218893Sdim    bits<10> addr;
1113218893Sdim    let Inst{19-16}   = addr{9-6}; // Rn
1114218893Sdim    let Inst{3-0} = addr{5-2}; // Rm
1115218893Sdim    let Inst{5-4}   = addr{1-0}; // imm
1116201360Srdivacky  }
1117195340Sed}
1118195340Sed
1119218893Sdim/// T2I_ext_rrot - A unary operation with two forms: one whose operand is a
1120195340Sed/// register and one whose operand is a register rotated by 8/16/24.
1121226633Sdimclass T2I_ext_rrot<bits<3> opcod, string opc, PatFrag opnode>
1122226633Sdim  : T2TwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm, rot_imm:$rot), IIC_iEXTr,
1123226633Sdim             opc, ".w\t$Rd, $Rm$rot",
1124226633Sdim             [(set rGPR:$Rd, (opnode (rotr rGPR:$Rm, rot_imm:$rot)))]>,
1125226633Sdim             Requires<[IsThumb2]> {
1126226633Sdim   let Inst{31-27} = 0b11111;
1127226633Sdim   let Inst{26-23} = 0b0100;
1128226633Sdim   let Inst{22-20} = opcod;
1129226633Sdim   let Inst{19-16} = 0b1111; // Rn
1130226633Sdim   let Inst{15-12} = 0b1111;
1131226633Sdim   let Inst{7} = 1;
1132218893Sdim
1133226633Sdim   bits<2> rot;
1134226633Sdim   let Inst{5-4} = rot{1-0}; // rotate
1135195340Sed}
1136195340Sed
1137210299Sed// UXTB16 - Requres T2ExtractPack, does not need the .w qualifier.
1138226633Sdimclass T2I_ext_rrot_uxtb16<bits<3> opcod, string opc, PatFrag opnode>
1139226633Sdim  : T2TwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm, rot_imm:$rot),
1140226633Sdim             IIC_iEXTr, opc, "\t$Rd, $Rm$rot",
1141226633Sdim            [(set rGPR:$Rd, (opnode (rotr rGPR:$Rm, rot_imm:$rot)))]>,
1142226633Sdim          Requires<[HasT2ExtractPack, IsThumb2]> {
1143226633Sdim  bits<2> rot;
1144226633Sdim  let Inst{31-27} = 0b11111;
1145226633Sdim  let Inst{26-23} = 0b0100;
1146226633Sdim  let Inst{22-20} = opcod;
1147226633Sdim  let Inst{19-16} = 0b1111; // Rn
1148226633Sdim  let Inst{15-12} = 0b1111;
1149226633Sdim  let Inst{7} = 1;
1150226633Sdim  let Inst{5-4} = rot;
1151204792Srdivacky}
1152204792Srdivacky
1153210299Sed// SXTB16 - Requres T2ExtractPack, does not need the .w qualifier, no pattern
1154210299Sed// supported yet.
1155226633Sdimclass T2I_ext_rrot_sxtb16<bits<3> opcod, string opc>
1156226633Sdim  : T2TwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm, rot_imm:$rot), IIC_iEXTr,
1157226633Sdim             opc, "\t$Rd, $Rm$rot", []>,
1158224145Sdim          Requires<[IsThumb2, HasT2ExtractPack]> {
1159226633Sdim  bits<2> rot;
1160226633Sdim  let Inst{31-27} = 0b11111;
1161226633Sdim  let Inst{26-23} = 0b0100;
1162226633Sdim  let Inst{22-20} = opcod;
1163226633Sdim  let Inst{19-16} = 0b1111; // Rn
1164226633Sdim  let Inst{15-12} = 0b1111;
1165226633Sdim  let Inst{7} = 1;
1166226633Sdim  let Inst{5-4} = rot;
1167204642Srdivacky}
1168204642Srdivacky
1169218893Sdim/// T2I_exta_rrot - A binary operation with two forms: one whose operand is a
1170195340Sed/// register and one whose operand is a register rotated by 8/16/24.
1171226633Sdimclass T2I_exta_rrot<bits<3> opcod, string opc, PatFrag opnode>
1172226633Sdim  : T2ThreeReg<(outs rGPR:$Rd),
1173226633Sdim               (ins rGPR:$Rn, rGPR:$Rm, rot_imm:$rot),
1174226633Sdim               IIC_iEXTAsr, opc, "\t$Rd, $Rn, $Rm$rot",
1175226633Sdim             [(set rGPR:$Rd, (opnode rGPR:$Rn, (rotr rGPR:$Rm,rot_imm:$rot)))]>,
1176226633Sdim           Requires<[HasT2ExtractPack, IsThumb2]> {
1177226633Sdim  bits<2> rot;
1178226633Sdim  let Inst{31-27} = 0b11111;
1179226633Sdim  let Inst{26-23} = 0b0100;
1180226633Sdim  let Inst{22-20} = opcod;
1181226633Sdim  let Inst{15-12} = 0b1111;
1182226633Sdim  let Inst{7} = 1;
1183226633Sdim  let Inst{5-4} = rot;
1184195340Sed}
1185195340Sed
1186226633Sdimclass T2I_exta_rrot_np<bits<3> opcod, string opc>
1187226633Sdim  : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm,rot_imm:$rot),
1188226633Sdim               IIC_iEXTAsr, opc, "\t$Rd, $Rn, $Rm$rot", []> {
1189226633Sdim  bits<2> rot;
1190226633Sdim  let Inst{31-27} = 0b11111;
1191226633Sdim  let Inst{26-23} = 0b0100;
1192226633Sdim  let Inst{22-20} = opcod;
1193226633Sdim  let Inst{15-12} = 0b1111;
1194226633Sdim  let Inst{7} = 1;
1195226633Sdim  let Inst{5-4} = rot;
1196204642Srdivacky}
1197204642Srdivacky
1198194612Sed//===----------------------------------------------------------------------===//
1199195098Sed// Instructions
1200195098Sed//===----------------------------------------------------------------------===//
1201195098Sed
1202195098Sed//===----------------------------------------------------------------------===//
1203195098Sed//  Miscellaneous Instructions.
1204194612Sed//
1205194612Sed
1206218893Sdimclass T2PCOneRegImm<dag oops, dag iops, InstrItinClass itin,
1207218893Sdim           string asm, list<dag> pattern>
1208218893Sdim  : T2XI<oops, iops, itin, asm, pattern> {
1209218893Sdim  bits<4> Rd;
1210218893Sdim  bits<12> label;
1211218893Sdim
1212218893Sdim  let Inst{11-8}  = Rd;
1213218893Sdim  let Inst{26}    = label{11};
1214218893Sdim  let Inst{14-12} = label{10-8};
1215218893Sdim  let Inst{7-0}   = label{7-0};
1216218893Sdim}
1217218893Sdim
1218195098Sed// LEApcrel - Load a pc-relative address into a register without offending the
1219195098Sed// assembler.
1220218893Sdimdef t2ADR : T2PCOneRegImm<(outs rGPR:$Rd),
1221218893Sdim              (ins t2adrlabel:$addr, pred:$p),
1222263508Sdim              IIC_iALUi, "adr{$p}.w\t$Rd, $addr", []>,
1223263508Sdim              Sched<[WriteALU, ReadALU]> {
1224201360Srdivacky  let Inst{31-27} = 0b11110;
1225201360Srdivacky  let Inst{25-24} = 0b10;
1226201360Srdivacky  // Inst{23:21} = '11' (add = FALSE) or '00' (add = TRUE)
1227201360Srdivacky  let Inst{22} = 0;
1228201360Srdivacky  let Inst{20} = 0;
1229201360Srdivacky  let Inst{19-16} = 0b1111; // Rn
1230201360Srdivacky  let Inst{15} = 0;
1231218893Sdim
1232218893Sdim  bits<4> Rd;
1233218893Sdim  bits<13> addr;
1234218893Sdim  let Inst{11-8} = Rd;
1235218893Sdim  let Inst{23}    = addr{12};
1236218893Sdim  let Inst{21}    = addr{12};
1237218893Sdim  let Inst{26}    = addr{11};
1238218893Sdim  let Inst{14-12} = addr{10-8};
1239218893Sdim  let Inst{7-0}   = addr{7-0};
1240226633Sdim
1241226633Sdim  let DecoderMethod = "DecodeT2Adr";
1242201360Srdivacky}
1243195098Sed
1244218893Sdimlet neverHasSideEffects = 1, isReMaterializable = 1 in
1245218893Sdimdef t2LEApcrel   : t2PseudoInst<(outs rGPR:$Rd), (ins i32imm:$label, pred:$p),
1246263508Sdim                                4, IIC_iALUi, []>, Sched<[WriteALU, ReadALU]>;
1247243830Sdimlet hasSideEffects = 1 in
1248218893Sdimdef t2LEApcrelJT : t2PseudoInst<(outs rGPR:$Rd),
1249218893Sdim                                (ins i32imm:$label, nohash_imm:$id, pred:$p),
1250224145Sdim                                4, IIC_iALUi,
1251263508Sdim                                []>, Sched<[WriteALU, ReadALU]>;
1252218893Sdim
1253218893Sdim
1254194612Sed//===----------------------------------------------------------------------===//
1255195098Sed//  Load / store Instructions.
1256195098Sed//
1257195098Sed
1258195340Sed// Load
1259204642Srdivackylet canFoldAsLoad = 1, isReMaterializable = 1  in
1260226633Sdimdefm t2LDR   : T2I_ld<0, 0b10, "ldr", IIC_iLoad_i, IIC_iLoad_si, GPR,
1261218893Sdim                      UnOpFrag<(load node:$Src)>>;
1262195340Sed
1263195340Sed// Loads with zero extension
1264218893Sdimdefm t2LDRH  : T2I_ld<0, 0b01, "ldrh", IIC_iLoad_bh_i, IIC_iLoad_bh_si,
1265263508Sdim                      GPR, UnOpFrag<(zextloadi16 node:$Src)>>;
1266218893Sdimdefm t2LDRB  : T2I_ld<0, 0b00, "ldrb", IIC_iLoad_bh_i, IIC_iLoad_bh_si,
1267263508Sdim                      GPR, UnOpFrag<(zextloadi8  node:$Src)>>;
1268195340Sed
1269195340Sed// Loads with sign extension
1270218893Sdimdefm t2LDRSH : T2I_ld<1, 0b01, "ldrsh", IIC_iLoad_bh_i, IIC_iLoad_bh_si,
1271263508Sdim                      GPR, UnOpFrag<(sextloadi16 node:$Src)>>;
1272218893Sdimdefm t2LDRSB : T2I_ld<1, 0b00, "ldrsb", IIC_iLoad_bh_i, IIC_iLoad_bh_si,
1273263508Sdim                      GPR, UnOpFrag<(sextloadi8  node:$Src)>>;
1274195340Sed
1275208599Srdivackylet mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1 in {
1276195340Sed// Load doubleword
1277218893Sdimdef t2LDRDi8  : T2Ii8s4<1, 0, 1, (outs rGPR:$Rt, rGPR:$Rt2),
1278198090Srdivacky                        (ins t2addrmode_imm8s4:$addr),
1279226633Sdim                        IIC_iLoad_d_i, "ldrd", "\t$Rt, $Rt2, $addr", "", []>;
1280208599Srdivacky} // mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1
1281195340Sed
1282195340Sed// zextload i1 -> zextload i8
1283195340Seddef : T2Pat<(zextloadi1 t2addrmode_imm12:$addr),
1284195340Sed            (t2LDRBi12  t2addrmode_imm12:$addr)>;
1285226633Sdimdef : T2Pat<(zextloadi1 t2addrmode_negimm8:$addr),
1286226633Sdim            (t2LDRBi8   t2addrmode_negimm8:$addr)>;
1287195340Seddef : T2Pat<(zextloadi1 t2addrmode_so_reg:$addr),
1288195340Sed            (t2LDRBs    t2addrmode_so_reg:$addr)>;
1289195340Seddef : T2Pat<(zextloadi1 (ARMWrapper tconstpool:$addr)),
1290195340Sed            (t2LDRBpci  tconstpool:$addr)>;
1291195340Sed
1292195340Sed// extload -> zextload
1293195340Sed// FIXME: Reduce the number of patterns by legalizing extload to zextload
1294195340Sed// earlier?
1295195340Seddef : T2Pat<(extloadi1  t2addrmode_imm12:$addr),
1296195340Sed            (t2LDRBi12  t2addrmode_imm12:$addr)>;
1297226633Sdimdef : T2Pat<(extloadi1  t2addrmode_negimm8:$addr),
1298226633Sdim            (t2LDRBi8   t2addrmode_negimm8:$addr)>;
1299195340Seddef : T2Pat<(extloadi1  t2addrmode_so_reg:$addr),
1300195340Sed            (t2LDRBs    t2addrmode_so_reg:$addr)>;
1301195340Seddef : T2Pat<(extloadi1  (ARMWrapper tconstpool:$addr)),
1302195340Sed            (t2LDRBpci  tconstpool:$addr)>;
1303195340Sed
1304195340Seddef : T2Pat<(extloadi8  t2addrmode_imm12:$addr),
1305195340Sed            (t2LDRBi12  t2addrmode_imm12:$addr)>;
1306226633Sdimdef : T2Pat<(extloadi8  t2addrmode_negimm8:$addr),
1307226633Sdim            (t2LDRBi8   t2addrmode_negimm8:$addr)>;
1308195340Seddef : T2Pat<(extloadi8  t2addrmode_so_reg:$addr),
1309195340Sed            (t2LDRBs    t2addrmode_so_reg:$addr)>;
1310195340Seddef : T2Pat<(extloadi8  (ARMWrapper tconstpool:$addr)),
1311195340Sed            (t2LDRBpci  tconstpool:$addr)>;
1312195340Sed
1313195340Seddef : T2Pat<(extloadi16 t2addrmode_imm12:$addr),
1314195340Sed            (t2LDRHi12  t2addrmode_imm12:$addr)>;
1315226633Sdimdef : T2Pat<(extloadi16 t2addrmode_negimm8:$addr),
1316226633Sdim            (t2LDRHi8   t2addrmode_negimm8:$addr)>;
1317195340Seddef : T2Pat<(extloadi16 t2addrmode_so_reg:$addr),
1318195340Sed            (t2LDRHs    t2addrmode_so_reg:$addr)>;
1319195340Seddef : T2Pat<(extloadi16 (ARMWrapper tconstpool:$addr)),
1320195340Sed            (t2LDRHpci  tconstpool:$addr)>;
1321195340Sed
1322212904Sdim// FIXME: The destination register of the loads and stores can't be PC, but
1323212904Sdim//        can be SP. We need another regclass (similar to rGPR) to represent
1324212904Sdim//        that. Not a pressing issue since these are selected manually,
1325212904Sdim//        not via pattern.
1326212904Sdim
1327195340Sed// Indexed loads
1328218893Sdim
1329208599Srdivackylet mayLoad = 1, neverHasSideEffects = 1 in {
1330226633Sdimdef t2LDR_PRE  : T2Ipreldst<0, 0b10, 1, 1, (outs GPR:$Rt, GPR:$Rn_wb),
1331263508Sdim                            (ins t2addrmode_imm8_pre:$addr),
1332218893Sdim                            AddrModeT2_i8, IndexModePre, IIC_iLoad_iu,
1333263508Sdim                            "ldr", "\t$Rt, $addr!", "$addr.base = $Rn_wb", []>;
1334195340Sed
1335226633Sdimdef t2LDR_POST : T2Ipostldst<0, 0b10, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
1336226633Sdim                          (ins addr_offset_none:$Rn, t2am_imm8_offset:$offset),
1337226633Sdim                          AddrModeT2_i8, IndexModePost, IIC_iLoad_iu,
1338226633Sdim                          "ldr", "\t$Rt, $Rn$offset", "$Rn = $Rn_wb", []>;
1339195340Sed
1340226633Sdimdef t2LDRB_PRE : T2Ipreldst<0, 0b00, 1, 1, (outs GPR:$Rt, GPR:$Rn_wb),
1341263508Sdim                            (ins t2addrmode_imm8_pre:$addr),
1342218893Sdim                            AddrModeT2_i8, IndexModePre, IIC_iLoad_bh_iu,
1343263508Sdim                            "ldrb", "\t$Rt, $addr!", "$addr.base = $Rn_wb", []>;
1344263508Sdim
1345226633Sdimdef t2LDRB_POST : T2Ipostldst<0, 0b00, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
1346226633Sdim                          (ins addr_offset_none:$Rn, t2am_imm8_offset:$offset),
1347226633Sdim                          AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu,
1348226633Sdim                          "ldrb", "\t$Rt, $Rn$offset", "$Rn = $Rn_wb", []>;
1349195340Sed
1350226633Sdimdef t2LDRH_PRE : T2Ipreldst<0, 0b01, 1, 1, (outs GPR:$Rt, GPR:$Rn_wb),
1351263508Sdim                            (ins t2addrmode_imm8_pre:$addr),
1352218893Sdim                            AddrModeT2_i8, IndexModePre, IIC_iLoad_bh_iu,
1353263508Sdim                            "ldrh", "\t$Rt, $addr!", "$addr.base = $Rn_wb", []>;
1354263508Sdim
1355226633Sdimdef t2LDRH_POST : T2Ipostldst<0, 0b01, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
1356226633Sdim                          (ins addr_offset_none:$Rn, t2am_imm8_offset:$offset),
1357226633Sdim                          AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu,
1358226633Sdim                          "ldrh", "\t$Rt, $Rn$offset", "$Rn = $Rn_wb", []>;
1359195340Sed
1360226633Sdimdef t2LDRSB_PRE : T2Ipreldst<1, 0b00, 1, 1, (outs GPR:$Rt, GPR:$Rn_wb),
1361263508Sdim                            (ins t2addrmode_imm8_pre:$addr),
1362218893Sdim                            AddrModeT2_i8, IndexModePre, IIC_iLoad_bh_iu,
1363226633Sdim                            "ldrsb", "\t$Rt, $addr!", "$addr.base = $Rn_wb",
1364263508Sdim                            []>;
1365263508Sdim
1366226633Sdimdef t2LDRSB_POST : T2Ipostldst<1, 0b00, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
1367226633Sdim                          (ins addr_offset_none:$Rn, t2am_imm8_offset:$offset),
1368226633Sdim                          AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu,
1369226633Sdim                          "ldrsb", "\t$Rt, $Rn$offset", "$Rn = $Rn_wb", []>;
1370195340Sed
1371226633Sdimdef t2LDRSH_PRE : T2Ipreldst<1, 0b01, 1, 1, (outs GPR:$Rt, GPR:$Rn_wb),
1372263508Sdim                            (ins t2addrmode_imm8_pre:$addr),
1373218893Sdim                            AddrModeT2_i8, IndexModePre, IIC_iLoad_bh_iu,
1374226633Sdim                            "ldrsh", "\t$Rt, $addr!", "$addr.base = $Rn_wb",
1375263508Sdim                            []>;
1376263508Sdim
1377226633Sdimdef t2LDRSH_POST : T2Ipostldst<1, 0b01, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
1378226633Sdim                          (ins addr_offset_none:$Rn, t2am_imm8_offset:$offset),
1379226633Sdim                          AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu,
1380226633Sdim                          "ldrsh", "\t$Rt, $Rn$offset", "$Rn = $Rn_wb", []>;
1381218893Sdim} // mayLoad = 1, neverHasSideEffects = 1
1382195340Sed
1383226633Sdim// LDRT, LDRBT, LDRHT, LDRSBT, LDRSHT all have offset mode (PUW=0b110).
1384204792Srdivacky// Ref: A8.6.57 LDR (immediate, Thumb) Encoding T4
1385218893Sdimclass T2IldT<bit signed, bits<2> type, string opc, InstrItinClass ii>
1386226633Sdim  : T2Ii8<(outs rGPR:$Rt), (ins t2addrmode_posimm8:$addr), ii, opc,
1387218893Sdim          "\t$Rt, $addr", []> {
1388226633Sdim  bits<4> Rt;
1389226633Sdim  bits<13> addr;
1390204792Srdivacky  let Inst{31-27} = 0b11111;
1391204792Srdivacky  let Inst{26-25} = 0b00;
1392204792Srdivacky  let Inst{24} = signed;
1393204792Srdivacky  let Inst{23} = 0;
1394204792Srdivacky  let Inst{22-21} = type;
1395204792Srdivacky  let Inst{20} = 1; // load
1396226633Sdim  let Inst{19-16} = addr{12-9};
1397226633Sdim  let Inst{15-12} = Rt;
1398204792Srdivacky  let Inst{11} = 1;
1399204792Srdivacky  let Inst{10-8} = 0b110; // PUW.
1400226633Sdim  let Inst{7-0} = addr{7-0};
1401263508Sdim
1402263508Sdim  let DecoderMethod = "DecodeT2LoadT";
1403204792Srdivacky}
1404204792Srdivacky
1405218893Sdimdef t2LDRT   : T2IldT<0, 0b10, "ldrt", IIC_iLoad_i>;
1406218893Sdimdef t2LDRBT  : T2IldT<0, 0b00, "ldrbt", IIC_iLoad_bh_i>;
1407218893Sdimdef t2LDRHT  : T2IldT<0, 0b01, "ldrht", IIC_iLoad_bh_i>;
1408218893Sdimdef t2LDRSBT : T2IldT<1, 0b00, "ldrsbt", IIC_iLoad_bh_i>;
1409218893Sdimdef t2LDRSHT : T2IldT<1, 0b01, "ldrsht", IIC_iLoad_bh_i>;
1410204792Srdivacky
1411263508Sdimclass T2Ildacq<bits<4> bits23_20, bits<2> bit54, dag oops, dag iops,
1412263508Sdim               string opc, string asm, list<dag> pattern>
1413263508Sdim  : Thumb2I<oops, iops, AddrModeNone, 4, NoItinerary,
1414263508Sdim            opc, asm, "", pattern>, Requires<[IsThumb, HasV8]> {
1415263508Sdim  bits<4> Rt;
1416263508Sdim  bits<4> addr;
1417263508Sdim
1418263508Sdim  let Inst{31-27} = 0b11101;
1419263508Sdim  let Inst{26-24} = 0b000;
1420263508Sdim  let Inst{23-20} = bits23_20;
1421263508Sdim  let Inst{11-6} = 0b111110;
1422263508Sdim  let Inst{5-4} = bit54;
1423263508Sdim  let Inst{3-0} = 0b1111;
1424263508Sdim
1425263508Sdim  // Encode instruction operands
1426263508Sdim  let Inst{19-16} = addr;
1427263508Sdim  let Inst{15-12} = Rt;
1428263508Sdim}
1429263508Sdim
1430263508Sdimdef t2LDA : T2Ildacq<0b1101, 0b10, (outs rGPR:$Rt),
1431263508Sdim                     (ins addr_offset_none:$addr), "lda", "\t$Rt, $addr", []>;
1432263508Sdimdef t2LDAB : T2Ildacq<0b1101, 0b00, (outs rGPR:$Rt),
1433263508Sdim                      (ins addr_offset_none:$addr), "ldab", "\t$Rt, $addr", []>;
1434263508Sdimdef t2LDAH : T2Ildacq<0b1101, 0b01, (outs rGPR:$Rt),
1435263508Sdim                      (ins addr_offset_none:$addr), "ldah", "\t$Rt, $addr", []>;
1436263508Sdim
1437195340Sed// Store
1438226633Sdimdefm t2STR :T2I_st<0b10,"str", IIC_iStore_i, IIC_iStore_si, GPR,
1439218893Sdim                   BinOpFrag<(store node:$LHS, node:$RHS)>>;
1440218893Sdimdefm t2STRB:T2I_st<0b00,"strb", IIC_iStore_bh_i, IIC_iStore_bh_si,
1441226633Sdim                   rGPR, BinOpFrag<(truncstorei8 node:$LHS, node:$RHS)>>;
1442218893Sdimdefm t2STRH:T2I_st<0b01,"strh", IIC_iStore_bh_i, IIC_iStore_bh_si,
1443226633Sdim                   rGPR, BinOpFrag<(truncstorei16 node:$LHS, node:$RHS)>>;
1444195340Sed
1445195340Sed// Store doubleword
1446234353Sdimlet mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in
1447201360Srdivackydef t2STRDi8 : T2Ii8s4<1, 0, 0, (outs),
1448218893Sdim                       (ins GPR:$Rt, GPR:$Rt2, t2addrmode_imm8s4:$addr),
1449226633Sdim               IIC_iStore_d_r, "strd", "\t$Rt, $Rt2, $addr", "", []>;
1450195340Sed
1451195340Sed// Indexed stores
1452234353Sdim
1453234353Sdimlet mayStore = 1, neverHasSideEffects = 1 in {
1454226633Sdimdef t2STR_PRE  : T2Ipreldst<0, 0b10, 0, 1, (outs GPRnopc:$Rn_wb),
1455263508Sdim                            (ins GPRnopc:$Rt, t2addrmode_imm8_pre:$addr),
1456218893Sdim                            AddrModeT2_i8, IndexModePre, IIC_iStore_iu,
1457226633Sdim                            "str", "\t$Rt, $addr!",
1458263508Sdim                            "$addr.base = $Rn_wb,@earlyclobber $Rn_wb", []>;
1459263508Sdim
1460226633Sdimdef t2STRH_PRE  : T2Ipreldst<0, 0b01, 0, 1, (outs GPRnopc:$Rn_wb),
1461263508Sdim                            (ins rGPR:$Rt, t2addrmode_imm8_pre:$addr),
1462226633Sdim                            AddrModeT2_i8, IndexModePre, IIC_iStore_iu,
1463226633Sdim                        "strh", "\t$Rt, $addr!",
1464263508Sdim                        "$addr.base = $Rn_wb,@earlyclobber $Rn_wb", []>;
1465195340Sed
1466226633Sdimdef t2STRB_PRE  : T2Ipreldst<0, 0b00, 0, 1, (outs GPRnopc:$Rn_wb),
1467263508Sdim                            (ins rGPR:$Rt, t2addrmode_imm8_pre:$addr),
1468226633Sdim                            AddrModeT2_i8, IndexModePre, IIC_iStore_bh_iu,
1469226633Sdim                        "strb", "\t$Rt, $addr!",
1470263508Sdim                        "$addr.base = $Rn_wb,@earlyclobber $Rn_wb", []>;
1471234353Sdim} // mayStore = 1, neverHasSideEffects = 1
1472226633Sdim
1473226633Sdimdef t2STR_POST : T2Ipostldst<0, 0b10, 0, 0, (outs GPRnopc:$Rn_wb),
1474234353Sdim                            (ins GPRnopc:$Rt, addr_offset_none:$Rn,
1475226633Sdim                                 t2am_imm8_offset:$offset),
1476218893Sdim                            AddrModeT2_i8, IndexModePost, IIC_iStore_iu,
1477226633Sdim                          "str", "\t$Rt, $Rn$offset",
1478226633Sdim                          "$Rn = $Rn_wb,@earlyclobber $Rn_wb",
1479226633Sdim             [(set GPRnopc:$Rn_wb,
1480234353Sdim                  (post_store GPRnopc:$Rt, addr_offset_none:$Rn,
1481226633Sdim                              t2am_imm8_offset:$offset))]>;
1482195340Sed
1483226633Sdimdef t2STRH_POST : T2Ipostldst<0, 0b01, 0, 0, (outs GPRnopc:$Rn_wb),
1484226633Sdim                            (ins rGPR:$Rt, addr_offset_none:$Rn,
1485226633Sdim                                 t2am_imm8_offset:$offset),
1486226633Sdim                            AddrModeT2_i8, IndexModePost, IIC_iStore_bh_iu,
1487226633Sdim                         "strh", "\t$Rt, $Rn$offset",
1488226633Sdim                         "$Rn = $Rn_wb,@earlyclobber $Rn_wb",
1489226633Sdim       [(set GPRnopc:$Rn_wb,
1490226633Sdim             (post_truncsti16 rGPR:$Rt, addr_offset_none:$Rn,
1491226633Sdim                              t2am_imm8_offset:$offset))]>;
1492195340Sed
1493226633Sdimdef t2STRB_POST : T2Ipostldst<0, 0b00, 0, 0, (outs GPRnopc:$Rn_wb),
1494226633Sdim                            (ins rGPR:$Rt, addr_offset_none:$Rn,
1495226633Sdim                                 t2am_imm8_offset:$offset),
1496218893Sdim                            AddrModeT2_i8, IndexModePost, IIC_iStore_bh_iu,
1497226633Sdim                         "strb", "\t$Rt, $Rn$offset",
1498226633Sdim                         "$Rn = $Rn_wb,@earlyclobber $Rn_wb",
1499226633Sdim        [(set GPRnopc:$Rn_wb,
1500226633Sdim              (post_truncsti8 rGPR:$Rt, addr_offset_none:$Rn,
1501226633Sdim                              t2am_imm8_offset:$offset))]>;
1502195340Sed
1503226633Sdim// Pseudo-instructions for pattern matching the pre-indexed stores. We can't
1504226633Sdim// put the patterns on the instruction definitions directly as ISel wants
1505226633Sdim// the address base and offset to be separate operands, not a single
1506226633Sdim// complex operand like we represent the instructions themselves. The
1507226633Sdim// pseudos map between the two.
1508226633Sdimlet usesCustomInserter = 1,
1509226633Sdim    Constraints = "$Rn = $Rn_wb,@earlyclobber $Rn_wb" in {
1510226633Sdimdef t2STR_preidx: t2PseudoInst<(outs GPRnopc:$Rn_wb),
1511226633Sdim               (ins rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$offset, pred:$p),
1512226633Sdim               4, IIC_iStore_ru,
1513226633Sdim      [(set GPRnopc:$Rn_wb,
1514226633Sdim            (pre_store rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$offset))]>;
1515226633Sdimdef t2STRB_preidx: t2PseudoInst<(outs GPRnopc:$Rn_wb),
1516226633Sdim               (ins rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$offset, pred:$p),
1517226633Sdim               4, IIC_iStore_ru,
1518226633Sdim      [(set GPRnopc:$Rn_wb,
1519226633Sdim            (pre_truncsti8 rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$offset))]>;
1520226633Sdimdef t2STRH_preidx: t2PseudoInst<(outs GPRnopc:$Rn_wb),
1521226633Sdim               (ins rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$offset, pred:$p),
1522226633Sdim               4, IIC_iStore_ru,
1523226633Sdim      [(set GPRnopc:$Rn_wb,
1524226633Sdim            (pre_truncsti16 rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$offset))]>;
1525226633Sdim}
1526195340Sed
1527204792Srdivacky// STRT, STRBT, STRHT all have offset mode (PUW=0b110) and are for disassembly
1528204792Srdivacky// only.
1529204792Srdivacky// Ref: A8.6.193 STR (immediate, Thumb) Encoding T4
1530218893Sdimclass T2IstT<bits<2> type, string opc, InstrItinClass ii>
1531221345Sdim  : T2Ii8<(outs rGPR:$Rt), (ins t2addrmode_imm8:$addr), ii, opc,
1532218893Sdim          "\t$Rt, $addr", []> {
1533204792Srdivacky  let Inst{31-27} = 0b11111;
1534204792Srdivacky  let Inst{26-25} = 0b00;
1535204792Srdivacky  let Inst{24} = 0; // not signed
1536204792Srdivacky  let Inst{23} = 0;
1537204792Srdivacky  let Inst{22-21} = type;
1538204792Srdivacky  let Inst{20} = 0; // store
1539204792Srdivacky  let Inst{11} = 1;
1540204792Srdivacky  let Inst{10-8} = 0b110; // PUW
1541218893Sdim
1542218893Sdim  bits<4> Rt;
1543218893Sdim  bits<13> addr;
1544218893Sdim  let Inst{15-12} = Rt;
1545218893Sdim  let Inst{19-16} = addr{12-9};
1546218893Sdim  let Inst{7-0}   = addr{7-0};
1547204792Srdivacky}
1548195340Sed
1549218893Sdimdef t2STRT   : T2IstT<0b10, "strt", IIC_iStore_i>;
1550218893Sdimdef t2STRBT  : T2IstT<0b00, "strbt", IIC_iStore_bh_i>;
1551218893Sdimdef t2STRHT  : T2IstT<0b01, "strht", IIC_iStore_bh_i>;
1552204792Srdivacky
1553205218Srdivacky// ldrd / strd pre / post variants
1554205218Srdivacky// For disassembly only.
1555195340Sed
1556226633Sdimdef t2LDRD_PRE  : T2Ii8s4<1, 1, 1, (outs rGPR:$Rt, rGPR:$Rt2, GPR:$wb),
1557263508Sdim                 (ins t2addrmode_imm8s4_pre:$addr), IIC_iLoad_d_ru,
1558226633Sdim                 "ldrd", "\t$Rt, $Rt2, $addr!", "$addr.base = $wb", []> {
1559226633Sdim  let DecoderMethod = "DecodeT2LDRDPreInstruction";
1560226633Sdim}
1561205218Srdivacky
1562226633Sdimdef t2LDRD_POST : T2Ii8s4post<0, 1, 1, (outs rGPR:$Rt, rGPR:$Rt2, GPR:$wb),
1563226633Sdim                 (ins addr_offset_none:$addr, t2am_imm8s4_offset:$imm),
1564226633Sdim                 IIC_iLoad_d_ru, "ldrd", "\t$Rt, $Rt2, $addr$imm",
1565226633Sdim                 "$addr.base = $wb", []>;
1566205218Srdivacky
1567226633Sdimdef t2STRD_PRE  : T2Ii8s4<1, 1, 0, (outs GPR:$wb),
1568263508Sdim                 (ins rGPR:$Rt, rGPR:$Rt2, t2addrmode_imm8s4_pre:$addr),
1569226633Sdim                 IIC_iStore_d_ru, "strd", "\t$Rt, $Rt2, $addr!",
1570226633Sdim                 "$addr.base = $wb", []> {
1571226633Sdim  let DecoderMethod = "DecodeT2STRDPreInstruction";
1572226633Sdim}
1573205218Srdivacky
1574226633Sdimdef t2STRD_POST : T2Ii8s4post<0, 1, 0, (outs GPR:$wb),
1575226633Sdim                 (ins rGPR:$Rt, rGPR:$Rt2, addr_offset_none:$addr,
1576226633Sdim                      t2am_imm8s4_offset:$imm),
1577226633Sdim                 IIC_iStore_d_ru, "strd", "\t$Rt, $Rt2, $addr$imm",
1578226633Sdim                 "$addr.base = $wb", []>;
1579205218Srdivacky
1580263508Sdimclass T2Istrrel<bits<2> bit54, dag oops, dag iops,
1581263508Sdim                string opc, string asm, list<dag> pattern>
1582263508Sdim  : Thumb2I<oops, iops, AddrModeNone, 4, NoItinerary, opc,
1583263508Sdim            asm, "", pattern>, Requires<[IsThumb, HasV8]> {
1584263508Sdim  bits<4> Rt;
1585263508Sdim  bits<4> addr;
1586263508Sdim
1587263508Sdim  let Inst{31-27} = 0b11101;
1588263508Sdim  let Inst{26-20} = 0b0001100;
1589263508Sdim  let Inst{11-6} = 0b111110;
1590263508Sdim  let Inst{5-4} = bit54;
1591263508Sdim  let Inst{3-0} = 0b1111;
1592263508Sdim
1593263508Sdim  // Encode instruction operands
1594263508Sdim  let Inst{19-16} = addr;
1595263508Sdim  let Inst{15-12} = Rt;
1596263508Sdim}
1597263508Sdim
1598263508Sdimdef t2STL  : T2Istrrel<0b10, (outs), (ins rGPR:$Rt, addr_offset_none:$addr),
1599263508Sdim                       "stl", "\t$Rt, $addr", []>;
1600263508Sdimdef t2STLB : T2Istrrel<0b00, (outs), (ins rGPR:$Rt, addr_offset_none:$addr),
1601263508Sdim                       "stlb", "\t$Rt, $addr", []>;
1602263508Sdimdef t2STLH : T2Istrrel<0b01, (outs), (ins rGPR:$Rt, addr_offset_none:$addr),
1603263508Sdim                       "stlh", "\t$Rt, $addr", []>;
1604263508Sdim
1605204792Srdivacky// T2Ipl (Preload Data/Instruction) signals the memory system of possible future
1606234353Sdim// data/instruction access.
1607218893Sdim// instr_write is inverted for Thumb mode: (prefetch 3) -> (preload 0),
1608218893Sdim// (prefetch 1) -> (preload 2),  (prefetch 2) -> (preload 1).
1609218893Sdimmulticlass T2Ipl<bits<1> write, bits<1> instr, string opc> {
1610204792Srdivacky
1611218893Sdim  def i12 : T2Ii12<(outs), (ins t2addrmode_imm12:$addr), IIC_Preload, opc,
1612218893Sdim                "\t$addr",
1613263508Sdim              [(ARMPreload t2addrmode_imm12:$addr, (i32 write), (i32 instr))]>,
1614263508Sdim              Sched<[WritePreLd]> {
1615204792Srdivacky    let Inst{31-25} = 0b1111100;
1616204792Srdivacky    let Inst{24} = instr;
1617263508Sdim    let Inst{23} = 1;
1618204792Srdivacky    let Inst{22} = 0;
1619204792Srdivacky    let Inst{21} = write;
1620204792Srdivacky    let Inst{20} = 1;
1621204792Srdivacky    let Inst{15-12} = 0b1111;
1622218893Sdim
1623218893Sdim    bits<17> addr;
1624218893Sdim    let Inst{19-16} = addr{16-13}; // Rn
1625218893Sdim    let Inst{11-0}  = addr{11-0};  // imm12
1626263508Sdim
1627263508Sdim    let DecoderMethod = "DecodeT2LoadImm12";
1628204792Srdivacky  }
1629204792Srdivacky
1630226633Sdim  def i8 : T2Ii8<(outs), (ins t2addrmode_negimm8:$addr), IIC_Preload, opc,
1631218893Sdim                "\t$addr",
1632263508Sdim            [(ARMPreload t2addrmode_negimm8:$addr, (i32 write), (i32 instr))]>,
1633263508Sdim            Sched<[WritePreLd]> {
1634204792Srdivacky    let Inst{31-25} = 0b1111100;
1635204792Srdivacky    let Inst{24} = instr;
1636204792Srdivacky    let Inst{23} = 0; // U = 0
1637204792Srdivacky    let Inst{22} = 0;
1638204792Srdivacky    let Inst{21} = write;
1639204792Srdivacky    let Inst{20} = 1;
1640204792Srdivacky    let Inst{15-12} = 0b1111;
1641204792Srdivacky    let Inst{11-8} = 0b1100;
1642204792Srdivacky
1643218893Sdim    bits<13> addr;
1644218893Sdim    let Inst{19-16} = addr{12-9}; // Rn
1645218893Sdim    let Inst{7-0}   = addr{7-0};  // imm8
1646263508Sdim
1647263508Sdim    let DecoderMethod = "DecodeT2LoadImm8";
1648204792Srdivacky  }
1649204792Srdivacky
1650218893Sdim  def s : T2Iso<(outs), (ins t2addrmode_so_reg:$addr), IIC_Preload, opc,
1651218893Sdim               "\t$addr",
1652263508Sdim             [(ARMPreload t2addrmode_so_reg:$addr, (i32 write), (i32 instr))]>,
1653263508Sdim             Sched<[WritePreLd]> {
1654204792Srdivacky    let Inst{31-25} = 0b1111100;
1655204792Srdivacky    let Inst{24} = instr;
1656204792Srdivacky    let Inst{23} = 0; // add = TRUE for T1
1657204792Srdivacky    let Inst{22} = 0;
1658204792Srdivacky    let Inst{21} = write;
1659204792Srdivacky    let Inst{20} = 1;
1660204792Srdivacky    let Inst{15-12} = 0b1111;
1661263508Sdim    let Inst{11-6} = 0b000000;
1662204792Srdivacky
1663218893Sdim    bits<10> addr;
1664218893Sdim    let Inst{19-16} = addr{9-6}; // Rn
1665218893Sdim    let Inst{3-0}   = addr{5-2}; // Rm
1666218893Sdim    let Inst{5-4}   = addr{1-0}; // imm2
1667226633Sdim
1668226633Sdim    let DecoderMethod = "DecodeT2LoadShift";
1669204792Srdivacky  }
1670204792Srdivacky}
1671204792Srdivacky
1672263508Sdimdefm t2PLD    : T2Ipl<0, 0, "pld">,  Requires<[IsThumb2]>;
1673263508Sdimdefm t2PLDW   : T2Ipl<1, 0, "pldw">, Requires<[IsThumb2,HasV7,HasMP]>;
1674263508Sdimdefm t2PLI    : T2Ipl<0, 1, "pli">,  Requires<[IsThumb2,HasV7]>;
1675204792Srdivacky
1676263508Sdim// pci variant is very similar to i12, but supports negative offsets
1677263508Sdim// from the PC. Only PLD and PLI have pci variants (not PLDW)
1678263508Sdimclass T2Iplpci<bits<1> inst, string opc> : T2Iso<(outs), (ins t2ldrlabel:$addr),
1679263508Sdim               IIC_Preload, opc, "\t$addr", 
1680263508Sdim               [(ARMPreload (ARMWrapper tconstpool:$addr),
1681263508Sdim                (i32 0), (i32 inst))]>, Sched<[WritePreLd]> {
1682263508Sdim  let Inst{31-25} = 0b1111100;
1683263508Sdim  let Inst{24} = inst;
1684263508Sdim  let Inst{22-20} = 0b001;
1685263508Sdim  let Inst{19-16} = 0b1111;
1686263508Sdim  let Inst{15-12} = 0b1111;
1687263508Sdim
1688263508Sdim  bits<13> addr;
1689263508Sdim  let Inst{23}   = addr{12};   // add = (U == '1')
1690263508Sdim  let Inst{11-0} = addr{11-0}; // imm12
1691263508Sdim
1692263508Sdim  let DecoderMethod = "DecodeT2LoadLabel";
1693263508Sdim}
1694263508Sdim
1695263508Sdimdef t2PLDpci : T2Iplpci<0, "pld">,  Requires<[IsThumb2]>;
1696263508Sdimdef t2PLIpci : T2Iplpci<1, "pli">,  Requires<[IsThumb2,HasV7]>;
1697263508Sdim
1698195098Sed//===----------------------------------------------------------------------===//
1699195340Sed//  Load / store multiple Instructions.
1700195340Sed//
1701195340Sed
1702226633Sdimmulticlass thumb2_ld_mult<string asm, InstrItinClass itin,
1703218893Sdim                            InstrItinClass itin_upd, bit L_bit> {
1704218893Sdim  def IA :
1705218893Sdim    T2XI<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
1706226633Sdim         itin, !strconcat(asm, "${p}.w\t$Rn, $regs"), []> {
1707218893Sdim    bits<4>  Rn;
1708218893Sdim    bits<16> regs;
1709195340Sed
1710218893Sdim    let Inst{31-27} = 0b11101;
1711218893Sdim    let Inst{26-25} = 0b00;
1712218893Sdim    let Inst{24-23} = 0b01;     // Increment After
1713218893Sdim    let Inst{22}    = 0;
1714218893Sdim    let Inst{21}    = 0;        // No writeback
1715218893Sdim    let Inst{20}    = L_bit;
1716218893Sdim    let Inst{19-16} = Rn;
1717228379Sdim    let Inst{15-0}  = regs;
1718218893Sdim  }
1719218893Sdim  def IA_UPD :
1720218893Sdim    T2XIt<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
1721226633Sdim          itin_upd, !strconcat(asm, "${p}.w\t$Rn!, $regs"), "$Rn = $wb", []> {
1722218893Sdim    bits<4>  Rn;
1723218893Sdim    bits<16> regs;
1724205218Srdivacky
1725218893Sdim    let Inst{31-27} = 0b11101;
1726218893Sdim    let Inst{26-25} = 0b00;
1727218893Sdim    let Inst{24-23} = 0b01;     // Increment After
1728218893Sdim    let Inst{22}    = 0;
1729218893Sdim    let Inst{21}    = 1;        // Writeback
1730218893Sdim    let Inst{20}    = L_bit;
1731218893Sdim    let Inst{19-16} = Rn;
1732228379Sdim    let Inst{15-0}  = regs;
1733218893Sdim  }
1734218893Sdim  def DB :
1735218893Sdim    T2XI<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
1736226633Sdim         itin, !strconcat(asm, "db${p}\t$Rn, $regs"), []> {
1737218893Sdim    bits<4>  Rn;
1738218893Sdim    bits<16> regs;
1739195340Sed
1740218893Sdim    let Inst{31-27} = 0b11101;
1741218893Sdim    let Inst{26-25} = 0b00;
1742218893Sdim    let Inst{24-23} = 0b10;     // Decrement Before
1743218893Sdim    let Inst{22}    = 0;
1744218893Sdim    let Inst{21}    = 0;        // No writeback
1745218893Sdim    let Inst{20}    = L_bit;
1746218893Sdim    let Inst{19-16} = Rn;
1747228379Sdim    let Inst{15-0}  = regs;
1748218893Sdim  }
1749218893Sdim  def DB_UPD :
1750218893Sdim    T2XIt<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
1751226633Sdim          itin_upd, !strconcat(asm, "db${p}\t$Rn!, $regs"), "$Rn = $wb", []> {
1752218893Sdim    bits<4>  Rn;
1753218893Sdim    bits<16> regs;
1754218893Sdim
1755218893Sdim    let Inst{31-27} = 0b11101;
1756218893Sdim    let Inst{26-25} = 0b00;
1757218893Sdim    let Inst{24-23} = 0b10;     // Decrement Before
1758218893Sdim    let Inst{22}    = 0;
1759218893Sdim    let Inst{21}    = 1;        // Writeback
1760218893Sdim    let Inst{20}    = L_bit;
1761218893Sdim    let Inst{19-16} = Rn;
1762228379Sdim    let Inst{15-0}  = regs;
1763218893Sdim  }
1764205218Srdivacky}
1765205218Srdivacky
1766218893Sdimlet neverHasSideEffects = 1 in {
1767218893Sdim
1768218893Sdimlet mayLoad = 1, hasExtraDefRegAllocReq = 1 in
1769226633Sdimdefm t2LDM : thumb2_ld_mult<"ldm", IIC_iLoad_m, IIC_iLoad_mu, 1>;
1770218893Sdim
1771226633Sdimmulticlass thumb2_st_mult<string asm, InstrItinClass itin,
1772226633Sdim                            InstrItinClass itin_upd, bit L_bit> {
1773226633Sdim  def IA :
1774226633Sdim    T2XI<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
1775226633Sdim         itin, !strconcat(asm, "${p}.w\t$Rn, $regs"), []> {
1776226633Sdim    bits<4>  Rn;
1777226633Sdim    bits<16> regs;
1778226633Sdim
1779226633Sdim    let Inst{31-27} = 0b11101;
1780226633Sdim    let Inst{26-25} = 0b00;
1781226633Sdim    let Inst{24-23} = 0b01;     // Increment After
1782226633Sdim    let Inst{22}    = 0;
1783226633Sdim    let Inst{21}    = 0;        // No writeback
1784226633Sdim    let Inst{20}    = L_bit;
1785226633Sdim    let Inst{19-16} = Rn;
1786226633Sdim    let Inst{15}    = 0;
1787226633Sdim    let Inst{14}    = regs{14};
1788226633Sdim    let Inst{13}    = 0;
1789226633Sdim    let Inst{12-0}  = regs{12-0};
1790226633Sdim  }
1791226633Sdim  def IA_UPD :
1792226633Sdim    T2XIt<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
1793226633Sdim          itin_upd, !strconcat(asm, "${p}.w\t$Rn!, $regs"), "$Rn = $wb", []> {
1794226633Sdim    bits<4>  Rn;
1795226633Sdim    bits<16> regs;
1796226633Sdim
1797226633Sdim    let Inst{31-27} = 0b11101;
1798226633Sdim    let Inst{26-25} = 0b00;
1799226633Sdim    let Inst{24-23} = 0b01;     // Increment After
1800226633Sdim    let Inst{22}    = 0;
1801226633Sdim    let Inst{21}    = 1;        // Writeback
1802226633Sdim    let Inst{20}    = L_bit;
1803226633Sdim    let Inst{19-16} = Rn;
1804226633Sdim    let Inst{15}    = 0;
1805226633Sdim    let Inst{14}    = regs{14};
1806226633Sdim    let Inst{13}    = 0;
1807226633Sdim    let Inst{12-0}  = regs{12-0};
1808226633Sdim  }
1809226633Sdim  def DB :
1810226633Sdim    T2XI<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
1811226633Sdim         itin, !strconcat(asm, "db${p}\t$Rn, $regs"), []> {
1812226633Sdim    bits<4>  Rn;
1813226633Sdim    bits<16> regs;
1814226633Sdim
1815226633Sdim    let Inst{31-27} = 0b11101;
1816226633Sdim    let Inst{26-25} = 0b00;
1817226633Sdim    let Inst{24-23} = 0b10;     // Decrement Before
1818226633Sdim    let Inst{22}    = 0;
1819226633Sdim    let Inst{21}    = 0;        // No writeback
1820226633Sdim    let Inst{20}    = L_bit;
1821226633Sdim    let Inst{19-16} = Rn;
1822226633Sdim    let Inst{15}    = 0;
1823226633Sdim    let Inst{14}    = regs{14};
1824226633Sdim    let Inst{13}    = 0;
1825226633Sdim    let Inst{12-0}  = regs{12-0};
1826226633Sdim  }
1827226633Sdim  def DB_UPD :
1828226633Sdim    T2XIt<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
1829226633Sdim          itin_upd, !strconcat(asm, "db${p}\t$Rn!, $regs"), "$Rn = $wb", []> {
1830226633Sdim    bits<4>  Rn;
1831226633Sdim    bits<16> regs;
1832226633Sdim
1833226633Sdim    let Inst{31-27} = 0b11101;
1834226633Sdim    let Inst{26-25} = 0b00;
1835226633Sdim    let Inst{24-23} = 0b10;     // Decrement Before
1836226633Sdim    let Inst{22}    = 0;
1837226633Sdim    let Inst{21}    = 1;        // Writeback
1838226633Sdim    let Inst{20}    = L_bit;
1839226633Sdim    let Inst{19-16} = Rn;
1840226633Sdim    let Inst{15}    = 0;
1841226633Sdim    let Inst{14}    = regs{14};
1842226633Sdim    let Inst{13}    = 0;
1843226633Sdim    let Inst{12-0}  = regs{12-0};
1844226633Sdim  }
1845226633Sdim}
1846226633Sdim
1847226633Sdim
1848218893Sdimlet mayStore = 1, hasExtraSrcRegAllocReq = 1 in
1849226633Sdimdefm t2STM : thumb2_st_mult<"stm", IIC_iStore_m, IIC_iStore_mu, 0>;
1850218893Sdim
1851218893Sdim} // neverHasSideEffects
1852218893Sdim
1853218893Sdim
1854195340Sed//===----------------------------------------------------------------------===//
1855194612Sed//  Move Instructions.
1856194612Sed//
1857194612Sed
1858194754Sedlet neverHasSideEffects = 1 in
1859226633Sdimdef t2MOVr : T2sTwoReg<(outs GPRnopc:$Rd), (ins GPR:$Rm), IIC_iMOVr,
1860263508Sdim                   "mov", ".w\t$Rd, $Rm", []>, Sched<[WriteALU]> {
1861201360Srdivacky  let Inst{31-27} = 0b11101;
1862201360Srdivacky  let Inst{26-25} = 0b01;
1863201360Srdivacky  let Inst{24-21} = 0b0010;
1864201360Srdivacky  let Inst{19-16} = 0b1111; // Rn
1865201360Srdivacky  let Inst{14-12} = 0b000;
1866201360Srdivacky  let Inst{7-4} = 0b0000;
1867201360Srdivacky}
1868234353Sdimdef : t2InstAlias<"mov${p}.w $Rd, $Rm", (t2MOVr GPRnopc:$Rd, GPR:$Rm,
1869234353Sdim                                                pred:$p, zero_reg)>;
1870226633Sdimdef : t2InstAlias<"movs${p}.w $Rd, $Rm", (t2MOVr GPRnopc:$Rd, GPR:$Rm,
1871226633Sdim                                                 pred:$p, CPSR)>;
1872226633Sdimdef : t2InstAlias<"movs${p} $Rd, $Rm", (t2MOVr GPRnopc:$Rd, GPR:$Rm,
1873226633Sdim                                               pred:$p, CPSR)>;
1874194612Sed
1875198090Srdivacky// AddedComplexity to ensure isel tries t2MOVi before t2MOVi16.
1876218893Sdimlet isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1,
1877218893Sdim    AddedComplexity = 1 in
1878218893Sdimdef t2MOVi : T2sOneRegImm<(outs rGPR:$Rd), (ins t2_so_imm:$imm), IIC_iMOVi,
1879218893Sdim                   "mov", ".w\t$Rd, $imm",
1880263508Sdim                   [(set rGPR:$Rd, t2_so_imm:$imm)]>, Sched<[WriteALU]> {
1881201360Srdivacky  let Inst{31-27} = 0b11110;
1882201360Srdivacky  let Inst{25} = 0;
1883201360Srdivacky  let Inst{24-21} = 0b0010;
1884201360Srdivacky  let Inst{19-16} = 0b1111; // Rn
1885201360Srdivacky  let Inst{15} = 0;
1886201360Srdivacky}
1887195098Sed
1888226633Sdim// cc_out is handled as part of the explicit mnemonic in the parser for 'mov'.
1889226633Sdim// Use aliases to get that to play nice here.
1890226633Sdimdef : t2InstAlias<"movs${p}.w $Rd, $imm", (t2MOVi rGPR:$Rd, t2_so_imm:$imm,
1891226633Sdim                                                pred:$p, CPSR)>;
1892226633Sdimdef : t2InstAlias<"movs${p} $Rd, $imm", (t2MOVi rGPR:$Rd, t2_so_imm:$imm,
1893226633Sdim                                                pred:$p, CPSR)>;
1894224145Sdim
1895226633Sdimdef : t2InstAlias<"mov${p}.w $Rd, $imm", (t2MOVi rGPR:$Rd, t2_so_imm:$imm,
1896226633Sdim                                                 pred:$p, zero_reg)>;
1897226633Sdimdef : t2InstAlias<"mov${p} $Rd, $imm", (t2MOVi rGPR:$Rd, t2_so_imm:$imm,
1898226633Sdim                                               pred:$p, zero_reg)>;
1899226633Sdim
1900218893Sdimlet isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in
1901226633Sdimdef t2MOVi16 : T2I<(outs rGPR:$Rd), (ins imm0_65535_expr:$imm), IIC_iMOVi,
1902218893Sdim                   "movw", "\t$Rd, $imm",
1903263508Sdim                   [(set rGPR:$Rd, imm0_65535:$imm)]>, Sched<[WriteALU]> {
1904201360Srdivacky  let Inst{31-27} = 0b11110;
1905201360Srdivacky  let Inst{25} = 1;
1906201360Srdivacky  let Inst{24-21} = 0b0010;
1907201360Srdivacky  let Inst{20} = 0; // The S bit.
1908201360Srdivacky  let Inst{15} = 0;
1909218893Sdim
1910218893Sdim  bits<4> Rd;
1911218893Sdim  bits<16> imm;
1912218893Sdim
1913218893Sdim  let Inst{11-8}  = Rd;
1914218893Sdim  let Inst{19-16} = imm{15-12};
1915218893Sdim  let Inst{26}    = imm{11};
1916218893Sdim  let Inst{14-12} = imm{10-8};
1917218893Sdim  let Inst{7-0}   = imm{7-0};
1918226633Sdim  let DecoderMethod = "DecodeT2MOVTWInstruction";
1919201360Srdivacky}
1920194612Sed
1921263508Sdimdef : t2InstAlias<"mov${p} $Rd, $imm", 
1922263508Sdim                  (t2MOVi16 rGPR:$Rd, imm256_65535_expr:$imm, pred:$p)>;
1923263508Sdim
1924218893Sdimdef t2MOVi16_ga_pcrel : PseudoInst<(outs rGPR:$Rd),
1925218893Sdim                                (ins i32imm:$addr, pclabel:$id), IIC_iMOVi, []>;
1926218893Sdim
1927218893Sdimlet Constraints = "$src = $Rd" in {
1928218893Sdimdef t2MOVTi16 : T2I<(outs rGPR:$Rd),
1929226633Sdim                    (ins rGPR:$src, imm0_65535_expr:$imm), IIC_iMOVi,
1930218893Sdim                    "movt", "\t$Rd, $imm",
1931218893Sdim                    [(set rGPR:$Rd,
1932263508Sdim                          (or (and rGPR:$src, 0xffff), lo16AllZero:$imm))]>,
1933263508Sdim                          Sched<[WriteALU]> {
1934201360Srdivacky  let Inst{31-27} = 0b11110;
1935201360Srdivacky  let Inst{25} = 1;
1936201360Srdivacky  let Inst{24-21} = 0b0110;
1937201360Srdivacky  let Inst{20} = 0; // The S bit.
1938201360Srdivacky  let Inst{15} = 0;
1939218893Sdim
1940218893Sdim  bits<4> Rd;
1941218893Sdim  bits<16> imm;
1942218893Sdim
1943218893Sdim  let Inst{11-8}  = Rd;
1944218893Sdim  let Inst{19-16} = imm{15-12};
1945218893Sdim  let Inst{26}    = imm{11};
1946218893Sdim  let Inst{14-12} = imm{10-8};
1947218893Sdim  let Inst{7-0}   = imm{7-0};
1948226633Sdim  let DecoderMethod = "DecodeT2MOVTWInstruction";
1949201360Srdivacky}
1950194754Sed
1951218893Sdimdef t2MOVTi16_ga_pcrel : PseudoInst<(outs rGPR:$Rd),
1952263508Sdim                     (ins rGPR:$src, i32imm:$addr, pclabel:$id), IIC_iMOVi, []>,
1953263508Sdim                     Sched<[WriteALU]>;
1954218893Sdim} // Constraints
1955218893Sdim
1956212904Sdimdef : T2Pat<(or rGPR:$src, 0xffff0000), (t2MOVTi16 rGPR:$src, 0xffff)>;
1957198396Srdivacky
1958194612Sed//===----------------------------------------------------------------------===//
1959195340Sed//  Extend Instructions.
1960195340Sed//
1961195340Sed
1962195340Sed// Sign extenders
1963195340Sed
1964226633Sdimdef t2SXTB  : T2I_ext_rrot<0b100, "sxtb",
1965201360Srdivacky                              UnOpFrag<(sext_inreg node:$Src, i8)>>;
1966226633Sdimdef t2SXTH  : T2I_ext_rrot<0b000, "sxth",
1967201360Srdivacky                              UnOpFrag<(sext_inreg node:$Src, i16)>>;
1968226633Sdimdef t2SXTB16 : T2I_ext_rrot_sxtb16<0b010, "sxtb16">;
1969195340Sed
1970226633Sdimdef t2SXTAB : T2I_exta_rrot<0b100, "sxtab",
1971195340Sed                        BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS, i8))>>;
1972226633Sdimdef t2SXTAH : T2I_exta_rrot<0b000, "sxtah",
1973195340Sed                        BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS,i16))>>;
1974226633Sdimdef t2SXTAB16 : T2I_exta_rrot_np<0b010, "sxtab16">;
1975195340Sed
1976195340Sed// Zero extenders
1977195340Sed
1978195340Sedlet AddedComplexity = 16 in {
1979226633Sdimdef t2UXTB   : T2I_ext_rrot<0b101, "uxtb",
1980201360Srdivacky                               UnOpFrag<(and node:$Src, 0x000000FF)>>;
1981226633Sdimdef t2UXTH   : T2I_ext_rrot<0b001, "uxth",
1982201360Srdivacky                               UnOpFrag<(and node:$Src, 0x0000FFFF)>>;
1983226633Sdimdef t2UXTB16 : T2I_ext_rrot_uxtb16<0b011, "uxtb16",
1984201360Srdivacky                               UnOpFrag<(and node:$Src, 0x00FF00FF)>>;
1985195340Sed
1986212904Sdim// FIXME: This pattern incorrectly assumes the shl operator is a rotate.
1987212904Sdim//        The transformation should probably be done as a combiner action
1988212904Sdim//        instead so we can include a check for masking back in the upper
1989212904Sdim//        eight bits of the source into the lower eight bits of the result.
1990212904Sdim//def : T2Pat<(and (shl rGPR:$Src, (i32 8)), 0xFF00FF),
1991226633Sdim//            (t2UXTB16 rGPR:$Src, 3)>,
1992218893Sdim//          Requires<[HasT2ExtractPack, IsThumb2]>;
1993212904Sdimdef : T2Pat<(and (srl rGPR:$Src, (i32 8)), 0xFF00FF),
1994226633Sdim            (t2UXTB16 rGPR:$Src, 1)>,
1995218893Sdim        Requires<[HasT2ExtractPack, IsThumb2]>;
1996195340Sed
1997226633Sdimdef t2UXTAB : T2I_exta_rrot<0b101, "uxtab",
1998199989Srdivacky                           BinOpFrag<(add node:$LHS, (and node:$RHS, 0x00FF))>>;
1999226633Sdimdef t2UXTAH : T2I_exta_rrot<0b001, "uxtah",
2000199989Srdivacky                           BinOpFrag<(add node:$LHS, (and node:$RHS, 0xFFFF))>>;
2001226633Sdimdef t2UXTAB16 : T2I_exta_rrot_np<0b011, "uxtab16">;
2002195340Sed}
2003195340Sed
2004195340Sed//===----------------------------------------------------------------------===//
2005194612Sed//  Arithmetic Instructions.
2006194612Sed//
2007194612Sed
2008201360Srdivackydefm t2ADD  : T2I_bin_ii12rs<0b000, "add",
2009201360Srdivacky                             BinOpFrag<(add  node:$LHS, node:$RHS)>, 1>;
2010201360Srdivackydefm t2SUB  : T2I_bin_ii12rs<0b101, "sub",
2011201360Srdivacky                             BinOpFrag<(sub  node:$LHS, node:$RHS)>>;
2012194612Sed
2013194754Sed// ADD and SUB with 's' bit set. No 12-bit immediate (T4) variants.
2014226633Sdim//
2015226633Sdim// Currently, t2ADDS/t2SUBS are pseudo opcodes that exist only in the
2016226633Sdim// selection DAG. They are "lowered" to real t2ADD/t2SUB opcodes by
2017226633Sdim// AdjustInstrPostInstrSelection where we determine whether or not to
2018226633Sdim// set the "s" bit based on CPSR liveness.
2019226633Sdim//
2020226633Sdim// FIXME: Eliminate t2ADDS/t2SUBS pseudo opcodes after adding tablegen
2021226633Sdim// support for an optional CPSR definition that corresponds to the DAG
2022226633Sdim// node's second value. We can then eliminate the implicit def of CPSR.
2023234353Sdimdefm t2ADDS : T2I_bin_s_irs <IIC_iALUi, IIC_iALUr, IIC_iALUsi,
2024226633Sdim                             BinOpFrag<(ARMaddc node:$LHS, node:$RHS)>, 1>;
2025234353Sdimdefm t2SUBS : T2I_bin_s_irs <IIC_iALUi, IIC_iALUr, IIC_iALUsi,
2026226633Sdim                             BinOpFrag<(ARMsubc node:$LHS, node:$RHS)>>;
2027194612Sed
2028226633Sdimlet hasPostISelHook = 1 in {
2029201360Srdivackydefm t2ADC  : T2I_adde_sube_irs<0b1010, "adc",
2030226633Sdim              BinOpWithFlagFrag<(ARMadde node:$LHS, node:$RHS, node:$FLAG)>, 1>;
2031201360Srdivackydefm t2SBC  : T2I_adde_sube_irs<0b1011, "sbc",
2032226633Sdim              BinOpWithFlagFrag<(ARMsube node:$LHS, node:$RHS, node:$FLAG)>>;
2033226633Sdim}
2034194612Sed
2035198090Srdivacky// RSB
2036212904Sdimdefm t2RSB  : T2I_rbin_irs  <0b1110, "rsb",
2037201360Srdivacky                             BinOpFrag<(sub  node:$LHS, node:$RHS)>>;
2038226633Sdim
2039226633Sdim// FIXME: Eliminate them if we can write def : Pat patterns which defines
2040226633Sdim// CPSR and the implicit def of CPSR is not needed.
2041234353Sdimdefm t2RSBS : T2I_rbin_s_is <BinOpFrag<(ARMsubc node:$LHS, node:$RHS)>>;
2042194612Sed
2043194754Sed// (sub X, imm) gets canonicalized to (add X, -imm).  Match this form.
2044210299Sed// The assume-no-carry-in form uses the negation of the input since add/sub
2045210299Sed// assume opposite meanings of the carry flag (i.e., carry == !borrow).
2046210299Sed// See the definition of AddWithCarry() in the ARM ARM A2.2.1 for the gory
2047210299Sed// details.
2048210299Sed// The AddedComplexity preferences the first variant over the others since
2049210299Sed// it can be shrunk to a 16-bit wide encoding, while the others cannot.
2050198090Srdivackylet AddedComplexity = 1 in
2051249423Sdimdef : T2Pat<(add        GPR:$src, imm1_255_neg:$imm),
2052249423Sdim            (t2SUBri    GPR:$src, imm1_255_neg:$imm)>;
2053210299Seddef : T2Pat<(add        GPR:$src, t2_so_imm_neg:$imm),
2054210299Sed            (t2SUBri    GPR:$src, t2_so_imm_neg:$imm)>;
2055210299Seddef : T2Pat<(add        GPR:$src, imm0_4095_neg:$imm),
2056210299Sed            (t2SUBri12  GPR:$src, imm0_4095_neg:$imm)>;
2057239462Sdimdef : T2Pat<(add        GPR:$src, imm0_65535_neg:$imm),
2058239462Sdim            (t2SUBrr    GPR:$src, (t2MOVi16 (imm_neg_XFORM imm:$imm)))>;
2059239462Sdim
2060210299Sedlet AddedComplexity = 1 in
2061249423Sdimdef : T2Pat<(ARMaddc    rGPR:$src, imm1_255_neg:$imm),
2062249423Sdim            (t2SUBSri   rGPR:$src, imm1_255_neg:$imm)>;
2063226633Sdimdef : T2Pat<(ARMaddc    rGPR:$src, t2_so_imm_neg:$imm),
2064212904Sdim            (t2SUBSri   rGPR:$src, t2_so_imm_neg:$imm)>;
2065239462Sdimdef : T2Pat<(ARMaddc    rGPR:$src, imm0_65535_neg:$imm),
2066239462Sdim            (t2SUBSrr   rGPR:$src, (t2MOVi16 (imm_neg_XFORM imm:$imm)))>;
2067210299Sed// The with-carry-in form matches bitwise not instead of the negation.
2068210299Sed// Effectively, the inverse interpretation of the carry flag already accounts
2069210299Sed// for part of the negation.
2070210299Sedlet AddedComplexity = 1 in
2071226633Sdimdef : T2Pat<(ARMadde    rGPR:$src, imm0_255_not:$imm, CPSR),
2072221345Sdim            (t2SBCri    rGPR:$src, imm0_255_not:$imm)>;
2073226633Sdimdef : T2Pat<(ARMadde    rGPR:$src, t2_so_imm_not:$imm, CPSR),
2074221345Sdim            (t2SBCri    rGPR:$src, t2_so_imm_not:$imm)>;
2075239462Sdimdef : T2Pat<(ARMadde    rGPR:$src, imm0_65535_neg:$imm, CPSR),
2076243830Sdim            (t2SBCrr    rGPR:$src, (t2MOVi16 (imm_not_XFORM imm:$imm)))>;
2077194612Sed
2078204642Srdivacky// Select Bytes -- for disassembly only
2079194754Sed
2080218893Sdimdef t2SEL : T2ThreeReg<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
2081224145Sdim                NoItinerary, "sel", "\t$Rd, $Rn, $Rm", []>,
2082224145Sdim          Requires<[IsThumb2, HasThumb2DSP]> {
2083204642Srdivacky  let Inst{31-27} = 0b11111;
2084204642Srdivacky  let Inst{26-24} = 0b010;
2085204642Srdivacky  let Inst{23} = 0b1;
2086204642Srdivacky  let Inst{22-20} = 0b010;
2087204642Srdivacky  let Inst{15-12} = 0b1111;
2088204642Srdivacky  let Inst{7} = 0b1;
2089204642Srdivacky  let Inst{6-4} = 0b000;
2090204642Srdivacky}
2091204642Srdivacky
2092204642Srdivacky// A6.3.13, A6.3.14, A6.3.15 Parallel addition and subtraction (signed/unsigned)
2093204642Srdivacky// And Miscellaneous operations -- for disassembly only
2094212904Sdimclass T2I_pam<bits<3> op22_20, bits<4> op7_4, string opc,
2095218893Sdim              list<dag> pat = [/* For disassembly only; pattern left blank */],
2096218893Sdim              dag iops = (ins rGPR:$Rn, rGPR:$Rm),
2097218893Sdim              string asm = "\t$Rd, $Rn, $Rm">
2098224145Sdim  : T2I<(outs rGPR:$Rd), iops, NoItinerary, opc, asm, pat>,
2099224145Sdim    Requires<[IsThumb2, HasThumb2DSP]> {
2100204642Srdivacky  let Inst{31-27} = 0b11111;
2101204642Srdivacky  let Inst{26-23} = 0b0101;
2102204642Srdivacky  let Inst{22-20} = op22_20;
2103204642Srdivacky  let Inst{15-12} = 0b1111;
2104204642Srdivacky  let Inst{7-4} = op7_4;
2105218893Sdim
2106218893Sdim  bits<4> Rd;
2107218893Sdim  bits<4> Rn;
2108218893Sdim  bits<4> Rm;
2109218893Sdim
2110218893Sdim  let Inst{11-8}  = Rd;
2111218893Sdim  let Inst{19-16} = Rn;
2112218893Sdim  let Inst{3-0}   = Rm;
2113204642Srdivacky}
2114204642Srdivacky
2115204642Srdivacky// Saturating add/subtract -- for disassembly only
2116204642Srdivacky
2117212904Sdimdef t2QADD    : T2I_pam<0b000, 0b1000, "qadd",
2118218893Sdim                        [(set rGPR:$Rd, (int_arm_qadd rGPR:$Rn, rGPR:$Rm))],
2119218893Sdim                        (ins rGPR:$Rm, rGPR:$Rn), "\t$Rd, $Rm, $Rn">;
2120204642Srdivackydef t2QADD16  : T2I_pam<0b001, 0b0001, "qadd16">;
2121204642Srdivackydef t2QADD8   : T2I_pam<0b000, 0b0001, "qadd8">;
2122204642Srdivackydef t2QASX    : T2I_pam<0b010, 0b0001, "qasx">;
2123218893Sdimdef t2QDADD   : T2I_pam<0b000, 0b1001, "qdadd", [],
2124218893Sdim                        (ins rGPR:$Rm, rGPR:$Rn), "\t$Rd, $Rm, $Rn">;
2125218893Sdimdef t2QDSUB   : T2I_pam<0b000, 0b1011, "qdsub", [],
2126218893Sdim                        (ins rGPR:$Rm, rGPR:$Rn), "\t$Rd, $Rm, $Rn">;
2127204642Srdivackydef t2QSAX    : T2I_pam<0b110, 0b0001, "qsax">;
2128212904Sdimdef t2QSUB    : T2I_pam<0b000, 0b1010, "qsub",
2129218893Sdim                        [(set rGPR:$Rd, (int_arm_qsub rGPR:$Rn, rGPR:$Rm))],
2130218893Sdim                        (ins rGPR:$Rm, rGPR:$Rn), "\t$Rd, $Rm, $Rn">;
2131204642Srdivackydef t2QSUB16  : T2I_pam<0b101, 0b0001, "qsub16">;
2132204642Srdivackydef t2QSUB8   : T2I_pam<0b100, 0b0001, "qsub8">;
2133204642Srdivackydef t2UQADD16 : T2I_pam<0b001, 0b0101, "uqadd16">;
2134204642Srdivackydef t2UQADD8  : T2I_pam<0b000, 0b0101, "uqadd8">;
2135204642Srdivackydef t2UQASX   : T2I_pam<0b010, 0b0101, "uqasx">;
2136204642Srdivackydef t2UQSAX   : T2I_pam<0b110, 0b0101, "uqsax">;
2137204642Srdivackydef t2UQSUB16 : T2I_pam<0b101, 0b0101, "uqsub16">;
2138204642Srdivackydef t2UQSUB8  : T2I_pam<0b100, 0b0101, "uqsub8">;
2139204642Srdivacky
2140204642Srdivacky// Signed/Unsigned add/subtract -- for disassembly only
2141204642Srdivacky
2142204642Srdivackydef t2SASX    : T2I_pam<0b010, 0b0000, "sasx">;
2143204642Srdivackydef t2SADD16  : T2I_pam<0b001, 0b0000, "sadd16">;
2144204642Srdivackydef t2SADD8   : T2I_pam<0b000, 0b0000, "sadd8">;
2145204642Srdivackydef t2SSAX    : T2I_pam<0b110, 0b0000, "ssax">;
2146204642Srdivackydef t2SSUB16  : T2I_pam<0b101, 0b0000, "ssub16">;
2147204642Srdivackydef t2SSUB8   : T2I_pam<0b100, 0b0000, "ssub8">;
2148204642Srdivackydef t2UASX    : T2I_pam<0b010, 0b0100, "uasx">;
2149204642Srdivackydef t2UADD16  : T2I_pam<0b001, 0b0100, "uadd16">;
2150204642Srdivackydef t2UADD8   : T2I_pam<0b000, 0b0100, "uadd8">;
2151204642Srdivackydef t2USAX    : T2I_pam<0b110, 0b0100, "usax">;
2152204642Srdivackydef t2USUB16  : T2I_pam<0b101, 0b0100, "usub16">;
2153204642Srdivackydef t2USUB8   : T2I_pam<0b100, 0b0100, "usub8">;
2154204642Srdivacky
2155204642Srdivacky// Signed/Unsigned halving add/subtract -- for disassembly only
2156204642Srdivacky
2157204642Srdivackydef t2SHASX   : T2I_pam<0b010, 0b0010, "shasx">;
2158204642Srdivackydef t2SHADD16 : T2I_pam<0b001, 0b0010, "shadd16">;
2159204642Srdivackydef t2SHADD8  : T2I_pam<0b000, 0b0010, "shadd8">;
2160204642Srdivackydef t2SHSAX   : T2I_pam<0b110, 0b0010, "shsax">;
2161204642Srdivackydef t2SHSUB16 : T2I_pam<0b101, 0b0010, "shsub16">;
2162204642Srdivackydef t2SHSUB8  : T2I_pam<0b100, 0b0010, "shsub8">;
2163204642Srdivackydef t2UHASX   : T2I_pam<0b010, 0b0110, "uhasx">;
2164204642Srdivackydef t2UHADD16 : T2I_pam<0b001, 0b0110, "uhadd16">;
2165204642Srdivackydef t2UHADD8  : T2I_pam<0b000, 0b0110, "uhadd8">;
2166204642Srdivackydef t2UHSAX   : T2I_pam<0b110, 0b0110, "uhsax">;
2167204642Srdivackydef t2UHSUB16 : T2I_pam<0b101, 0b0110, "uhsub16">;
2168204642Srdivackydef t2UHSUB8  : T2I_pam<0b100, 0b0110, "uhsub8">;
2169204642Srdivacky
2170218893Sdim// Helper class for disassembly only
2171218893Sdim// A6.3.16 & A6.3.17
2172218893Sdim// T2Imac - Thumb2 multiply [accumulate, and absolute difference] instructions.
2173218893Sdimclass T2ThreeReg_mac<bit long, bits<3> op22_20, bits<4> op7_4, dag oops,
2174218893Sdim  dag iops, InstrItinClass itin, string opc, string asm, list<dag> pattern>
2175218893Sdim  : T2ThreeReg<oops, iops, itin, opc, asm, pattern> {
2176218893Sdim  let Inst{31-27} = 0b11111;
2177218893Sdim  let Inst{26-24} = 0b011;
2178218893Sdim  let Inst{23}    = long;
2179218893Sdim  let Inst{22-20} = op22_20;
2180218893Sdim  let Inst{7-4}   = op7_4;
2181218893Sdim}
2182218893Sdim
2183218893Sdimclass T2FourReg_mac<bit long, bits<3> op22_20, bits<4> op7_4, dag oops,
2184218893Sdim  dag iops, InstrItinClass itin, string opc, string asm, list<dag> pattern>
2185218893Sdim  : T2FourReg<oops, iops, itin, opc, asm, pattern> {
2186218893Sdim  let Inst{31-27} = 0b11111;
2187218893Sdim  let Inst{26-24} = 0b011;
2188218893Sdim  let Inst{23}    = long;
2189218893Sdim  let Inst{22-20} = op22_20;
2190218893Sdim  let Inst{7-4}   = op7_4;
2191218893Sdim}
2192218893Sdim
2193226633Sdim// Unsigned Sum of Absolute Differences [and Accumulate].
2194218893Sdimdef t2USAD8   : T2ThreeReg_mac<0, 0b111, 0b0000, (outs rGPR:$Rd),
2195218893Sdim                                           (ins rGPR:$Rn, rGPR:$Rm),
2196224145Sdim                        NoItinerary, "usad8", "\t$Rd, $Rn, $Rm", []>,
2197224145Sdim          Requires<[IsThumb2, HasThumb2DSP]> {
2198204642Srdivacky  let Inst{15-12} = 0b1111;
2199204642Srdivacky}
2200218893Sdimdef t2USADA8  : T2FourReg_mac<0, 0b111, 0b0000, (outs rGPR:$Rd),
2201218893Sdim                       (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), NoItinerary,
2202224145Sdim                        "usada8", "\t$Rd, $Rn, $Rm, $Ra", []>,
2203224145Sdim          Requires<[IsThumb2, HasThumb2DSP]>;
2204204642Srdivacky
2205226633Sdim// Signed/Unsigned saturate.
2206218893Sdimclass T2SatI<dag oops, dag iops, InstrItinClass itin,
2207218893Sdim           string opc, string asm, list<dag> pattern>
2208218893Sdim  : T2I<oops, iops, itin, opc, asm, pattern> {
2209218893Sdim  bits<4> Rd;
2210218893Sdim  bits<4> Rn;
2211218893Sdim  bits<5> sat_imm;
2212218893Sdim  bits<7> sh;
2213218893Sdim
2214218893Sdim  let Inst{11-8}  = Rd;
2215218893Sdim  let Inst{19-16} = Rn;
2216226633Sdim  let Inst{4-0}   = sat_imm;
2217226633Sdim  let Inst{21}    = sh{5};
2218218893Sdim  let Inst{14-12} = sh{4-2};
2219218893Sdim  let Inst{7-6}   = sh{1-0};
2220218893Sdim}
2221218893Sdim
2222218893Sdimdef t2SSAT: T2SatI<
2223226633Sdim              (outs rGPR:$Rd),
2224226633Sdim              (ins imm1_32:$sat_imm, rGPR:$Rn, t2_shift_imm:$sh),
2225226633Sdim              NoItinerary, "ssat", "\t$Rd, $sat_imm, $Rn$sh", []> {
2226204642Srdivacky  let Inst{31-27} = 0b11110;
2227204642Srdivacky  let Inst{25-22} = 0b1100;
2228204642Srdivacky  let Inst{20} = 0;
2229204642Srdivacky  let Inst{15} = 0;
2230226633Sdim  let Inst{5}  = 0;
2231204642Srdivacky}
2232204642Srdivacky
2233218893Sdimdef t2SSAT16: T2SatI<
2234226633Sdim                (outs rGPR:$Rd), (ins imm1_16:$sat_imm, rGPR:$Rn), NoItinerary,
2235226633Sdim                "ssat16", "\t$Rd, $sat_imm, $Rn", []>,
2236224145Sdim          Requires<[IsThumb2, HasThumb2DSP]> {
2237204642Srdivacky  let Inst{31-27} = 0b11110;
2238204642Srdivacky  let Inst{25-22} = 0b1100;
2239204642Srdivacky  let Inst{20} = 0;
2240204642Srdivacky  let Inst{15} = 0;
2241204642Srdivacky  let Inst{21} = 1;        // sh = '1'
2242204642Srdivacky  let Inst{14-12} = 0b000; // imm3 = '000'
2243204642Srdivacky  let Inst{7-6} = 0b00;    // imm2 = '00'
2244226633Sdim  let Inst{5-4} = 0b00;
2245204642Srdivacky}
2246204642Srdivacky
2247218893Sdimdef t2USAT: T2SatI<
2248226633Sdim               (outs rGPR:$Rd),
2249226633Sdim               (ins imm0_31:$sat_imm, rGPR:$Rn, t2_shift_imm:$sh),
2250226633Sdim                NoItinerary, "usat", "\t$Rd, $sat_imm, $Rn$sh", []> {
2251204642Srdivacky  let Inst{31-27} = 0b11110;
2252204642Srdivacky  let Inst{25-22} = 0b1110;
2253204642Srdivacky  let Inst{20} = 0;
2254204642Srdivacky  let Inst{15} = 0;
2255204642Srdivacky}
2256204642Srdivacky
2257226633Sdimdef t2USAT16: T2SatI<(outs rGPR:$Rd), (ins imm0_15:$sat_imm, rGPR:$Rn),
2258224145Sdim                     NoItinerary,
2259226633Sdim                     "usat16", "\t$Rd, $sat_imm, $Rn", []>,
2260224145Sdim          Requires<[IsThumb2, HasThumb2DSP]> {
2261226633Sdim  let Inst{31-22} = 0b1111001110;
2262204642Srdivacky  let Inst{20} = 0;
2263204642Srdivacky  let Inst{15} = 0;
2264204642Srdivacky  let Inst{21} = 1;        // sh = '1'
2265204642Srdivacky  let Inst{14-12} = 0b000; // imm3 = '000'
2266204642Srdivacky  let Inst{7-6} = 0b00;    // imm2 = '00'
2267226633Sdim  let Inst{5-4} = 0b00;
2268204642Srdivacky}
2269204642Srdivacky
2270212904Sdimdef : T2Pat<(int_arm_ssat GPR:$a, imm:$pos), (t2SSAT imm:$pos, GPR:$a, 0)>;
2271212904Sdimdef : T2Pat<(int_arm_usat GPR:$a, imm:$pos), (t2USAT imm:$pos, GPR:$a, 0)>;
2272212904Sdim
2273194754Sed//===----------------------------------------------------------------------===//
2274195098Sed//  Shift and rotate Instructions.
2275195098Sed//
2276195098Sed
2277226633Sdimdefm t2LSL  : T2I_sh_ir<0b00, "lsl", imm0_31,
2278239462Sdim                        BinOpFrag<(shl  node:$LHS, node:$RHS)>>;
2279226633Sdimdefm t2LSR  : T2I_sh_ir<0b01, "lsr", imm_sr,
2280239462Sdim                        BinOpFrag<(srl  node:$LHS, node:$RHS)>>;
2281226633Sdimdefm t2ASR  : T2I_sh_ir<0b10, "asr", imm_sr,
2282239462Sdim                        BinOpFrag<(sra  node:$LHS, node:$RHS)>>;
2283226633Sdimdefm t2ROR  : T2I_sh_ir<0b11, "ror", imm0_31,
2284239462Sdim                        BinOpFrag<(rotr node:$LHS, node:$RHS)>>;
2285195098Sed
2286221345Sdim// (rotr x, (and y, 0x...1f)) ==> (ROR x, y)
2287239462Sdimdef : T2Pat<(rotr rGPR:$lhs, (and rGPR:$rhs, lo5AllOne)),
2288239462Sdim            (t2RORrr rGPR:$lhs, rGPR:$rhs)>;
2289221345Sdim
2290198090Srdivackylet Uses = [CPSR] in {
2291218893Sdimdef t2RRX : T2sTwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm), IIC_iMOVsi,
2292218893Sdim                   "rrx", "\t$Rd, $Rm",
2293263508Sdim                   [(set rGPR:$Rd, (ARMrrx rGPR:$Rm))]>, Sched<[WriteALU]> {
2294201360Srdivacky  let Inst{31-27} = 0b11101;
2295201360Srdivacky  let Inst{26-25} = 0b01;
2296201360Srdivacky  let Inst{24-21} = 0b0010;
2297201360Srdivacky  let Inst{19-16} = 0b1111; // Rn
2298201360Srdivacky  let Inst{14-12} = 0b000;
2299201360Srdivacky  let Inst{7-4} = 0b0011;
2300198090Srdivacky}
2301201360Srdivacky}
2302195098Sed
2303218893Sdimlet isCodeGenOnly = 1, Defs = [CPSR] in {
2304218893Sdimdef t2MOVsrl_flag : T2TwoRegShiftImm<
2305218893Sdim                        (outs rGPR:$Rd), (ins rGPR:$Rm), IIC_iMOVsi,
2306218893Sdim                        "lsrs", ".w\t$Rd, $Rm, #1",
2307263508Sdim                        [(set rGPR:$Rd, (ARMsrl_flag rGPR:$Rm))]>,
2308263508Sdim                        Sched<[WriteALU]> {
2309201360Srdivacky  let Inst{31-27} = 0b11101;
2310201360Srdivacky  let Inst{26-25} = 0b01;
2311201360Srdivacky  let Inst{24-21} = 0b0010;
2312201360Srdivacky  let Inst{20} = 1; // The S bit.
2313201360Srdivacky  let Inst{19-16} = 0b1111; // Rn
2314201360Srdivacky  let Inst{5-4} = 0b01; // Shift type.
2315201360Srdivacky  // Shift amount = Inst{14-12:7-6} = 1.
2316201360Srdivacky  let Inst{14-12} = 0b000;
2317201360Srdivacky  let Inst{7-6} = 0b01;
2318201360Srdivacky}
2319218893Sdimdef t2MOVsra_flag : T2TwoRegShiftImm<
2320218893Sdim                        (outs rGPR:$Rd), (ins rGPR:$Rm), IIC_iMOVsi,
2321218893Sdim                        "asrs", ".w\t$Rd, $Rm, #1",
2322263508Sdim                        [(set rGPR:$Rd, (ARMsra_flag rGPR:$Rm))]>,
2323263508Sdim                        Sched<[WriteALU]> {
2324201360Srdivacky  let Inst{31-27} = 0b11101;
2325201360Srdivacky  let Inst{26-25} = 0b01;
2326201360Srdivacky  let Inst{24-21} = 0b0010;
2327201360Srdivacky  let Inst{20} = 1; // The S bit.
2328201360Srdivacky  let Inst{19-16} = 0b1111; // Rn
2329201360Srdivacky  let Inst{5-4} = 0b10; // Shift type.
2330201360Srdivacky  // Shift amount = Inst{14-12:7-6} = 1.
2331201360Srdivacky  let Inst{14-12} = 0b000;
2332201360Srdivacky  let Inst{7-6} = 0b01;
2333198090Srdivacky}
2334201360Srdivacky}
2335198090Srdivacky
2336195098Sed//===----------------------------------------------------------------------===//
2337194754Sed//  Bitwise Instructions.
2338194754Sed//
2339194754Sed
2340201360Srdivackydefm t2AND  : T2I_bin_w_irs<0b0000, "and",
2341218893Sdim                            IIC_iBITi, IIC_iBITr, IIC_iBITsi,
2342239462Sdim                            BinOpFrag<(and node:$LHS, node:$RHS)>, 1>;
2343201360Srdivackydefm t2ORR  : T2I_bin_w_irs<0b0010, "orr",
2344218893Sdim                            IIC_iBITi, IIC_iBITr, IIC_iBITsi,
2345239462Sdim                            BinOpFrag<(or  node:$LHS, node:$RHS)>, 1>;
2346201360Srdivackydefm t2EOR  : T2I_bin_w_irs<0b0100, "eor",
2347218893Sdim                            IIC_iBITi, IIC_iBITr, IIC_iBITsi,
2348239462Sdim                            BinOpFrag<(xor node:$LHS, node:$RHS)>, 1>;
2349194754Sed
2350201360Srdivackydefm t2BIC  : T2I_bin_w_irs<0b0001, "bic",
2351218893Sdim                            IIC_iBITi, IIC_iBITr, IIC_iBITsi,
2352239462Sdim                            BinOpFrag<(and node:$LHS, (not node:$RHS))>>;
2353194754Sed
2354218893Sdimclass T2BitFI<dag oops, dag iops, InstrItinClass itin,
2355218893Sdim              string opc, string asm, list<dag> pattern>
2356218893Sdim    : T2I<oops, iops, itin, opc, asm, pattern> {
2357218893Sdim  bits<4> Rd;
2358218893Sdim  bits<5> msb;
2359218893Sdim  bits<5> lsb;
2360212904Sdim
2361218893Sdim  let Inst{11-8}  = Rd;
2362218893Sdim  let Inst{4-0}   = msb{4-0};
2363218893Sdim  let Inst{14-12} = lsb{4-2};
2364218893Sdim  let Inst{7-6}   = lsb{1-0};
2365218893Sdim}
2366218893Sdim
2367218893Sdimclass T2TwoRegBitFI<dag oops, dag iops, InstrItinClass itin,
2368218893Sdim              string opc, string asm, list<dag> pattern>
2369218893Sdim    : T2BitFI<oops, iops, itin, opc, asm, pattern> {
2370218893Sdim  bits<4> Rn;
2371218893Sdim
2372218893Sdim  let Inst{19-16} = Rn;
2373218893Sdim}
2374218893Sdim
2375218893Sdimlet Constraints = "$src = $Rd" in
2376218893Sdimdef t2BFC : T2BitFI<(outs rGPR:$Rd), (ins rGPR:$src, bf_inv_mask_imm:$imm),
2377218893Sdim                IIC_iUNAsi, "bfc", "\t$Rd, $imm",
2378218893Sdim                [(set rGPR:$Rd, (and rGPR:$src, bf_inv_mask_imm:$imm))]> {
2379201360Srdivacky  let Inst{31-27} = 0b11110;
2380221345Sdim  let Inst{26} = 0; // should be 0.
2381201360Srdivacky  let Inst{25} = 1;
2382201360Srdivacky  let Inst{24-20} = 0b10110;
2383201360Srdivacky  let Inst{19-16} = 0b1111; // Rn
2384201360Srdivacky  let Inst{15} = 0;
2385221345Sdim  let Inst{5} = 0; // should be 0.
2386218893Sdim
2387218893Sdim  bits<10> imm;
2388218893Sdim  let msb{4-0} = imm{9-5};
2389218893Sdim  let lsb{4-0} = imm{4-0};
2390201360Srdivacky}
2391194754Sed
2392218893Sdimdef t2SBFX: T2TwoRegBitFI<
2393226633Sdim                (outs rGPR:$Rd), (ins rGPR:$Rn, imm0_31:$lsb, imm1_32:$msb),
2394218893Sdim                 IIC_iUNAsi, "sbfx", "\t$Rd, $Rn, $lsb, $msb", []> {
2395201360Srdivacky  let Inst{31-27} = 0b11110;
2396201360Srdivacky  let Inst{25} = 1;
2397201360Srdivacky  let Inst{24-20} = 0b10100;
2398201360Srdivacky  let Inst{15} = 0;
2399201360Srdivacky}
2400198090Srdivacky
2401218893Sdimdef t2UBFX: T2TwoRegBitFI<
2402226633Sdim                (outs rGPR:$Rd), (ins rGPR:$Rn, imm0_31:$lsb, imm1_32:$msb),
2403218893Sdim                 IIC_iUNAsi, "ubfx", "\t$Rd, $Rn, $lsb, $msb", []> {
2404201360Srdivacky  let Inst{31-27} = 0b11110;
2405201360Srdivacky  let Inst{25} = 1;
2406201360Srdivacky  let Inst{24-20} = 0b11100;
2407201360Srdivacky  let Inst{15} = 0;
2408201360Srdivacky}
2409198090Srdivacky
2410203954Srdivacky// A8.6.18  BFI - Bitfield insert (Encoding T1)
2411218893Sdimlet Constraints = "$src = $Rd" in {
2412218893Sdim  def t2BFI : T2TwoRegBitFI<(outs rGPR:$Rd),
2413218893Sdim                  (ins rGPR:$src, rGPR:$Rn, bf_inv_mask_imm:$imm),
2414218893Sdim                  IIC_iBITi, "bfi", "\t$Rd, $Rn, $imm",
2415218893Sdim                  [(set rGPR:$Rd, (ARMbfi rGPR:$src, rGPR:$Rn,
2416218893Sdim                                   bf_inv_mask_imm:$imm))]> {
2417218893Sdim    let Inst{31-27} = 0b11110;
2418221345Sdim    let Inst{26} = 0; // should be 0.
2419218893Sdim    let Inst{25} = 1;
2420218893Sdim    let Inst{24-20} = 0b10110;
2421218893Sdim    let Inst{15} = 0;
2422221345Sdim    let Inst{5} = 0; // should be 0.
2423218893Sdim
2424218893Sdim    bits<10> imm;
2425218893Sdim    let msb{4-0} = imm{9-5};
2426218893Sdim    let lsb{4-0} = imm{4-0};
2427218893Sdim  }
2428203954Srdivacky}
2429198090Srdivacky
2430218893Sdimdefm t2ORN  : T2I_bin_irs<0b0011, "orn",
2431218893Sdim                          IIC_iBITi, IIC_iBITr, IIC_iBITsi,
2432239462Sdim                          BinOpFrag<(or node:$LHS, (not node:$RHS))>, 0, "">;
2433194754Sed
2434226633Sdim/// T2I_un_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a
2435226633Sdim/// unary operation that produces a value. These are predicable and can be
2436226633Sdim/// changed to modify CPSR.
2437226633Sdimmulticlass T2I_un_irs<bits<4> opcod, string opc,
2438226633Sdim                     InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
2439249423Sdim                      PatFrag opnode,
2440249423Sdim                      bit Cheap = 0, bit ReMat = 0, bit MoveImm = 0> {
2441226633Sdim   // shifted imm
2442226633Sdim   def i : T2sOneRegImm<(outs rGPR:$Rd), (ins t2_so_imm:$imm), iii,
2443226633Sdim                opc, "\t$Rd, $imm",
2444263508Sdim                [(set rGPR:$Rd, (opnode t2_so_imm:$imm))]>, Sched<[WriteALU]> {
2445226633Sdim     let isAsCheapAsAMove = Cheap;
2446226633Sdim     let isReMaterializable = ReMat;
2447249423Sdim     let isMoveImm = MoveImm;
2448226633Sdim     let Inst{31-27} = 0b11110;
2449226633Sdim     let Inst{25} = 0;
2450226633Sdim     let Inst{24-21} = opcod;
2451226633Sdim     let Inst{19-16} = 0b1111; // Rn
2452226633Sdim     let Inst{15} = 0;
2453226633Sdim   }
2454226633Sdim   // register
2455226633Sdim   def r : T2sTwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm), iir,
2456226633Sdim                opc, ".w\t$Rd, $Rm",
2457263508Sdim                [(set rGPR:$Rd, (opnode rGPR:$Rm))]>, Sched<[WriteALU]> {
2458226633Sdim     let Inst{31-27} = 0b11101;
2459226633Sdim     let Inst{26-25} = 0b01;
2460226633Sdim     let Inst{24-21} = opcod;
2461226633Sdim     let Inst{19-16} = 0b1111; // Rn
2462226633Sdim     let Inst{14-12} = 0b000; // imm3
2463226633Sdim     let Inst{7-6} = 0b00; // imm2
2464226633Sdim     let Inst{5-4} = 0b00; // type
2465226633Sdim   }
2466226633Sdim   // shifted register
2467226633Sdim   def s : T2sOneRegShiftedReg<(outs rGPR:$Rd), (ins t2_so_reg:$ShiftedRm), iis,
2468226633Sdim                opc, ".w\t$Rd, $ShiftedRm",
2469263508Sdim                [(set rGPR:$Rd, (opnode t2_so_reg:$ShiftedRm))]>,
2470263508Sdim                Sched<[WriteALU]> {
2471226633Sdim     let Inst{31-27} = 0b11101;
2472226633Sdim     let Inst{26-25} = 0b01;
2473226633Sdim     let Inst{24-21} = opcod;
2474226633Sdim     let Inst{19-16} = 0b1111; // Rn
2475226633Sdim   }
2476226633Sdim}
2477226633Sdim
2478195098Sed// Prefer over of t2EORri ra, rb, -1 because mvn has 16-bit version
2479195098Sedlet AddedComplexity = 1 in
2480218893Sdimdefm t2MVN  : T2I_un_irs <0b0011, "mvn",
2481218893Sdim                          IIC_iMVNi, IIC_iMVNr, IIC_iMVNsi,
2482249423Sdim                          UnOpFrag<(not node:$Src)>, 1, 1, 1>;
2483194754Sed
2484212904Sdimlet AddedComplexity = 1 in
2485212904Sdimdef : T2Pat<(and     rGPR:$src, t2_so_imm_not:$imm),
2486212904Sdim            (t2BICri rGPR:$src, t2_so_imm_not:$imm)>;
2487198090Srdivacky
2488239462Sdim// top16Zero - answer true if the upper 16 bits of $src are 0, false otherwise
2489239462Sdimdef top16Zero: PatLeaf<(i32 rGPR:$src), [{
2490239462Sdim  return CurDAG->MaskedValueIsZero(SDValue(N,0), APInt::getHighBitsSet(32, 16));
2491239462Sdim  }]>;
2492239462Sdim
2493239462Sdim// so_imm_notSext is needed instead of so_imm_not, as the value of imm
2494239462Sdim// will match the extended, not the original bitWidth for $src.
2495239462Sdimdef : T2Pat<(and top16Zero:$src, t2_so_imm_notSext:$imm),
2496239462Sdim            (t2BICri rGPR:$src, t2_so_imm_notSext:$imm)>;
2497239462Sdim
2498239462Sdim
2499198090Srdivacky// FIXME: Disable this pattern on Darwin to workaround an assembler bug.
2500212904Sdimdef : T2Pat<(or      rGPR:$src, t2_so_imm_not:$imm),
2501212904Sdim            (t2ORNri rGPR:$src, t2_so_imm_not:$imm)>,
2502198090Srdivacky            Requires<[IsThumb2]>;
2503198090Srdivacky
2504195098Seddef : T2Pat<(t2_so_imm_not:$src),
2505195098Sed            (t2MVNi t2_so_imm_not:$src)>;
2506194754Sed
2507194754Sed//===----------------------------------------------------------------------===//
2508194754Sed//  Multiply Instructions.
2509194754Sed//
2510195098Sedlet isCommutable = 1 in
2511218893Sdimdef t2MUL: T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMUL32,
2512218893Sdim                "mul", "\t$Rd, $Rn, $Rm",
2513218893Sdim                [(set rGPR:$Rd, (mul rGPR:$Rn, rGPR:$Rm))]> {
2514201360Srdivacky  let Inst{31-27} = 0b11111;
2515201360Srdivacky  let Inst{26-23} = 0b0110;
2516201360Srdivacky  let Inst{22-20} = 0b000;
2517201360Srdivacky  let Inst{15-12} = 0b1111; // Ra = 0b1111 (no accumulate)
2518201360Srdivacky  let Inst{7-4} = 0b0000; // Multiply
2519201360Srdivacky}
2520194754Sed
2521218893Sdimdef t2MLA: T2FourReg<
2522218893Sdim                (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC32,
2523218893Sdim                "mla", "\t$Rd, $Rn, $Rm, $Ra",
2524243830Sdim                [(set rGPR:$Rd, (add (mul rGPR:$Rn, rGPR:$Rm), rGPR:$Ra))]>,
2525243830Sdim           Requires<[IsThumb2, UseMulOps]> {
2526201360Srdivacky  let Inst{31-27} = 0b11111;
2527201360Srdivacky  let Inst{26-23} = 0b0110;
2528201360Srdivacky  let Inst{22-20} = 0b000;
2529201360Srdivacky  let Inst{7-4} = 0b0000; // Multiply
2530201360Srdivacky}
2531194754Sed
2532218893Sdimdef t2MLS: T2FourReg<
2533218893Sdim                (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC32,
2534218893Sdim                "mls", "\t$Rd, $Rn, $Rm, $Ra",
2535243830Sdim                [(set rGPR:$Rd, (sub rGPR:$Ra, (mul rGPR:$Rn, rGPR:$Rm)))]>,
2536243830Sdim           Requires<[IsThumb2, UseMulOps]> {
2537201360Srdivacky  let Inst{31-27} = 0b11111;
2538201360Srdivacky  let Inst{26-23} = 0b0110;
2539201360Srdivacky  let Inst{22-20} = 0b000;
2540201360Srdivacky  let Inst{7-4} = 0b0001; // Multiply and Subtract
2541201360Srdivacky}
2542194754Sed
2543198090Srdivacky// Extra precision multiplies with low / high results
2544198090Srdivackylet neverHasSideEffects = 1 in {
2545198090Srdivackylet isCommutable = 1 in {
2546218893Sdimdef t2SMULL : T2MulLong<0b000, 0b0000,
2547226633Sdim                  (outs rGPR:$RdLo, rGPR:$RdHi),
2548218893Sdim                  (ins rGPR:$Rn, rGPR:$Rm), IIC_iMUL64,
2549226633Sdim                   "smull", "\t$RdLo, $RdHi, $Rn, $Rm", []>;
2550194754Sed
2551218893Sdimdef t2UMULL : T2MulLong<0b010, 0b0000,
2552218893Sdim                  (outs rGPR:$RdLo, rGPR:$RdHi),
2553218893Sdim                  (ins rGPR:$Rn, rGPR:$Rm), IIC_iMUL64,
2554218893Sdim                   "umull", "\t$RdLo, $RdHi, $Rn, $Rm", []>;
2555201360Srdivacky} // isCommutable
2556198090Srdivacky
2557198090Srdivacky// Multiply + accumulate
2558243830Sdimdef t2SMLAL : T2MlaLong<0b100, 0b0000,
2559218893Sdim                  (outs rGPR:$RdLo, rGPR:$RdHi),
2560243830Sdim                  (ins rGPR:$Rn, rGPR:$Rm, rGPR:$RLo, rGPR:$RHi), IIC_iMAC64,
2561243830Sdim                  "smlal", "\t$RdLo, $RdHi, $Rn, $Rm", []>,
2562243830Sdim                  RegConstraint<"$RLo = $RdLo, $RHi = $RdHi">;
2563198090Srdivacky
2564243830Sdimdef t2UMLAL : T2MlaLong<0b110, 0b0000,
2565218893Sdim                  (outs rGPR:$RdLo, rGPR:$RdHi),
2566243830Sdim                  (ins rGPR:$Rn, rGPR:$Rm, rGPR:$RLo, rGPR:$RHi), IIC_iMAC64,
2567243830Sdim                  "umlal", "\t$RdLo, $RdHi, $Rn, $Rm", []>,
2568243830Sdim                  RegConstraint<"$RLo = $RdLo, $RHi = $RdHi">;
2569198090Srdivacky
2570218893Sdimdef t2UMAAL : T2MulLong<0b110, 0b0110,
2571218893Sdim                  (outs rGPR:$RdLo, rGPR:$RdHi),
2572218893Sdim                  (ins rGPR:$Rn, rGPR:$Rm), IIC_iMAC64,
2573224145Sdim                  "umaal", "\t$RdLo, $RdHi, $Rn, $Rm", []>,
2574224145Sdim          Requires<[IsThumb2, HasThumb2DSP]>;
2575198090Srdivacky} // neverHasSideEffects
2576198090Srdivacky
2577204642Srdivacky// Rounding variants of the below included for disassembly only
2578204642Srdivacky
2579198090Srdivacky// Most significant word multiply
2580218893Sdimdef t2SMMUL : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMUL32,
2581218893Sdim                  "smmul", "\t$Rd, $Rn, $Rm",
2582224145Sdim                  [(set rGPR:$Rd, (mulhs rGPR:$Rn, rGPR:$Rm))]>,
2583224145Sdim          Requires<[IsThumb2, HasThumb2DSP]> {
2584201360Srdivacky  let Inst{31-27} = 0b11111;
2585201360Srdivacky  let Inst{26-23} = 0b0110;
2586201360Srdivacky  let Inst{22-20} = 0b101;
2587201360Srdivacky  let Inst{15-12} = 0b1111; // Ra = 0b1111 (no accumulate)
2588201360Srdivacky  let Inst{7-4} = 0b0000; // No Rounding (Inst{4} = 0)
2589201360Srdivacky}
2590198090Srdivacky
2591218893Sdimdef t2SMMULR : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMUL32,
2592224145Sdim                  "smmulr", "\t$Rd, $Rn, $Rm", []>,
2593224145Sdim          Requires<[IsThumb2, HasThumb2DSP]> {
2594204642Srdivacky  let Inst{31-27} = 0b11111;
2595204642Srdivacky  let Inst{26-23} = 0b0110;
2596204642Srdivacky  let Inst{22-20} = 0b101;
2597204642Srdivacky  let Inst{15-12} = 0b1111; // Ra = 0b1111 (no accumulate)
2598204642Srdivacky  let Inst{7-4} = 0b0001; // Rounding (Inst{4} = 1)
2599204642Srdivacky}
2600204642Srdivacky
2601218893Sdimdef t2SMMLA : T2FourReg<
2602218893Sdim        (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC32,
2603218893Sdim                "smmla", "\t$Rd, $Rn, $Rm, $Ra",
2604224145Sdim                [(set rGPR:$Rd, (add (mulhs rGPR:$Rm, rGPR:$Rn), rGPR:$Ra))]>,
2605243830Sdim              Requires<[IsThumb2, HasThumb2DSP, UseMulOps]> {
2606201360Srdivacky  let Inst{31-27} = 0b11111;
2607201360Srdivacky  let Inst{26-23} = 0b0110;
2608201360Srdivacky  let Inst{22-20} = 0b101;
2609201360Srdivacky  let Inst{7-4} = 0b0000; // No Rounding (Inst{4} = 0)
2610201360Srdivacky}
2611198090Srdivacky
2612218893Sdimdef t2SMMLAR: T2FourReg<
2613218893Sdim        (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC32,
2614224145Sdim                  "smmlar", "\t$Rd, $Rn, $Rm, $Ra", []>,
2615224145Sdim          Requires<[IsThumb2, HasThumb2DSP]> {
2616204642Srdivacky  let Inst{31-27} = 0b11111;
2617204642Srdivacky  let Inst{26-23} = 0b0110;
2618204642Srdivacky  let Inst{22-20} = 0b101;
2619204642Srdivacky  let Inst{7-4} = 0b0001; // Rounding (Inst{4} = 1)
2620204642Srdivacky}
2621198090Srdivacky
2622218893Sdimdef t2SMMLS: T2FourReg<
2623218893Sdim        (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC32,
2624218893Sdim                "smmls", "\t$Rd, $Rn, $Rm, $Ra",
2625224145Sdim                [(set rGPR:$Rd, (sub rGPR:$Ra, (mulhs rGPR:$Rn, rGPR:$Rm)))]>,
2626243830Sdim             Requires<[IsThumb2, HasThumb2DSP, UseMulOps]> {
2627201360Srdivacky  let Inst{31-27} = 0b11111;
2628201360Srdivacky  let Inst{26-23} = 0b0110;
2629201360Srdivacky  let Inst{22-20} = 0b110;
2630201360Srdivacky  let Inst{7-4} = 0b0000; // No Rounding (Inst{4} = 0)
2631201360Srdivacky}
2632198090Srdivacky
2633218893Sdimdef t2SMMLSR:T2FourReg<
2634218893Sdim        (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC32,
2635224145Sdim                "smmlsr", "\t$Rd, $Rn, $Rm, $Ra", []>,
2636224145Sdim          Requires<[IsThumb2, HasThumb2DSP]> {
2637204642Srdivacky  let Inst{31-27} = 0b11111;
2638204642Srdivacky  let Inst{26-23} = 0b0110;
2639204642Srdivacky  let Inst{22-20} = 0b110;
2640204642Srdivacky  let Inst{7-4} = 0b0001; // Rounding (Inst{4} = 1)
2641204642Srdivacky}
2642204642Srdivacky
2643198090Srdivackymulticlass T2I_smul<string opc, PatFrag opnode> {
2644218893Sdim  def BB : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMUL16,
2645218893Sdim              !strconcat(opc, "bb"), "\t$Rd, $Rn, $Rm",
2646218893Sdim              [(set rGPR:$Rd, (opnode (sext_inreg rGPR:$Rn, i16),
2647224145Sdim                                      (sext_inreg rGPR:$Rm, i16)))]>,
2648224145Sdim          Requires<[IsThumb2, HasThumb2DSP]> {
2649201360Srdivacky    let Inst{31-27} = 0b11111;
2650201360Srdivacky    let Inst{26-23} = 0b0110;
2651201360Srdivacky    let Inst{22-20} = 0b001;
2652201360Srdivacky    let Inst{15-12} = 0b1111; // Ra = 0b1111 (no accumulate)
2653201360Srdivacky    let Inst{7-6} = 0b00;
2654201360Srdivacky    let Inst{5-4} = 0b00;
2655201360Srdivacky  }
2656198090Srdivacky
2657218893Sdim  def BT : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMUL16,
2658218893Sdim              !strconcat(opc, "bt"), "\t$Rd, $Rn, $Rm",
2659218893Sdim              [(set rGPR:$Rd, (opnode (sext_inreg rGPR:$Rn, i16),
2660224145Sdim                                      (sra rGPR:$Rm, (i32 16))))]>,
2661224145Sdim          Requires<[IsThumb2, HasThumb2DSP]> {
2662201360Srdivacky    let Inst{31-27} = 0b11111;
2663201360Srdivacky    let Inst{26-23} = 0b0110;
2664201360Srdivacky    let Inst{22-20} = 0b001;
2665201360Srdivacky    let Inst{15-12} = 0b1111; // Ra = 0b1111 (no accumulate)
2666201360Srdivacky    let Inst{7-6} = 0b00;
2667201360Srdivacky    let Inst{5-4} = 0b01;
2668201360Srdivacky  }
2669198090Srdivacky
2670218893Sdim  def TB : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMUL16,
2671218893Sdim              !strconcat(opc, "tb"), "\t$Rd, $Rn, $Rm",
2672218893Sdim              [(set rGPR:$Rd, (opnode (sra rGPR:$Rn, (i32 16)),
2673224145Sdim                                      (sext_inreg rGPR:$Rm, i16)))]>,
2674224145Sdim          Requires<[IsThumb2, HasThumb2DSP]> {
2675201360Srdivacky    let Inst{31-27} = 0b11111;
2676201360Srdivacky    let Inst{26-23} = 0b0110;
2677201360Srdivacky    let Inst{22-20} = 0b001;
2678201360Srdivacky    let Inst{15-12} = 0b1111; // Ra = 0b1111 (no accumulate)
2679201360Srdivacky    let Inst{7-6} = 0b00;
2680201360Srdivacky    let Inst{5-4} = 0b10;
2681201360Srdivacky  }
2682198090Srdivacky
2683218893Sdim  def TT : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMUL16,
2684218893Sdim              !strconcat(opc, "tt"), "\t$Rd, $Rn, $Rm",
2685218893Sdim              [(set rGPR:$Rd, (opnode (sra rGPR:$Rn, (i32 16)),
2686224145Sdim                                      (sra rGPR:$Rm, (i32 16))))]>,
2687224145Sdim          Requires<[IsThumb2, HasThumb2DSP]> {
2688201360Srdivacky    let Inst{31-27} = 0b11111;
2689201360Srdivacky    let Inst{26-23} = 0b0110;
2690201360Srdivacky    let Inst{22-20} = 0b001;
2691201360Srdivacky    let Inst{15-12} = 0b1111; // Ra = 0b1111 (no accumulate)
2692201360Srdivacky    let Inst{7-6} = 0b00;
2693201360Srdivacky    let Inst{5-4} = 0b11;
2694201360Srdivacky  }
2695198090Srdivacky
2696218893Sdim  def WB : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMUL16,
2697218893Sdim              !strconcat(opc, "wb"), "\t$Rd, $Rn, $Rm",
2698218893Sdim              [(set rGPR:$Rd, (sra (opnode rGPR:$Rn,
2699224145Sdim                                    (sext_inreg rGPR:$Rm, i16)), (i32 16)))]>,
2700224145Sdim          Requires<[IsThumb2, HasThumb2DSP]> {
2701201360Srdivacky    let Inst{31-27} = 0b11111;
2702201360Srdivacky    let Inst{26-23} = 0b0110;
2703201360Srdivacky    let Inst{22-20} = 0b011;
2704201360Srdivacky    let Inst{15-12} = 0b1111; // Ra = 0b1111 (no accumulate)
2705201360Srdivacky    let Inst{7-6} = 0b00;
2706201360Srdivacky    let Inst{5-4} = 0b00;
2707201360Srdivacky  }
2708198090Srdivacky
2709218893Sdim  def WT : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMUL16,
2710218893Sdim              !strconcat(opc, "wt"), "\t$Rd, $Rn, $Rm",
2711218893Sdim              [(set rGPR:$Rd, (sra (opnode rGPR:$Rn,
2712224145Sdim                                    (sra rGPR:$Rm, (i32 16))), (i32 16)))]>,
2713224145Sdim          Requires<[IsThumb2, HasThumb2DSP]> {
2714201360Srdivacky    let Inst{31-27} = 0b11111;
2715201360Srdivacky    let Inst{26-23} = 0b0110;
2716201360Srdivacky    let Inst{22-20} = 0b011;
2717201360Srdivacky    let Inst{15-12} = 0b1111; // Ra = 0b1111 (no accumulate)
2718201360Srdivacky    let Inst{7-6} = 0b00;
2719201360Srdivacky    let Inst{5-4} = 0b01;
2720201360Srdivacky  }
2721198090Srdivacky}
2722198090Srdivacky
2723198090Srdivacky
2724198090Srdivackymulticlass T2I_smla<string opc, PatFrag opnode> {
2725218893Sdim  def BB : T2FourReg<
2726218893Sdim        (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC16,
2727218893Sdim              !strconcat(opc, "bb"), "\t$Rd, $Rn, $Rm, $Ra",
2728218893Sdim              [(set rGPR:$Rd, (add rGPR:$Ra,
2729218893Sdim                               (opnode (sext_inreg rGPR:$Rn, i16),
2730224145Sdim                                       (sext_inreg rGPR:$Rm, i16))))]>,
2731243830Sdim           Requires<[IsThumb2, HasThumb2DSP, UseMulOps]> {
2732201360Srdivacky    let Inst{31-27} = 0b11111;
2733201360Srdivacky    let Inst{26-23} = 0b0110;
2734201360Srdivacky    let Inst{22-20} = 0b001;
2735201360Srdivacky    let Inst{7-6} = 0b00;
2736201360Srdivacky    let Inst{5-4} = 0b00;
2737201360Srdivacky  }
2738198090Srdivacky
2739218893Sdim  def BT : T2FourReg<
2740218893Sdim       (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC16,
2741218893Sdim             !strconcat(opc, "bt"), "\t$Rd, $Rn, $Rm, $Ra",
2742218893Sdim             [(set rGPR:$Rd, (add rGPR:$Ra, (opnode (sext_inreg rGPR:$Rn, i16),
2743224145Sdim                                                 (sra rGPR:$Rm, (i32 16)))))]>,
2744243830Sdim           Requires<[IsThumb2, HasThumb2DSP, UseMulOps]> {
2745201360Srdivacky    let Inst{31-27} = 0b11111;
2746201360Srdivacky    let Inst{26-23} = 0b0110;
2747201360Srdivacky    let Inst{22-20} = 0b001;
2748201360Srdivacky    let Inst{7-6} = 0b00;
2749201360Srdivacky    let Inst{5-4} = 0b01;
2750201360Srdivacky  }
2751198090Srdivacky
2752218893Sdim  def TB : T2FourReg<
2753218893Sdim        (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC16,
2754218893Sdim              !strconcat(opc, "tb"), "\t$Rd, $Rn, $Rm, $Ra",
2755218893Sdim              [(set rGPR:$Rd, (add rGPR:$Ra, (opnode (sra rGPR:$Rn, (i32 16)),
2756224145Sdim                                               (sext_inreg rGPR:$Rm, i16))))]>,
2757243830Sdim           Requires<[IsThumb2, HasThumb2DSP, UseMulOps]> {
2758201360Srdivacky    let Inst{31-27} = 0b11111;
2759201360Srdivacky    let Inst{26-23} = 0b0110;
2760201360Srdivacky    let Inst{22-20} = 0b001;
2761201360Srdivacky    let Inst{7-6} = 0b00;
2762201360Srdivacky    let Inst{5-4} = 0b10;
2763201360Srdivacky  }
2764198090Srdivacky
2765218893Sdim  def TT : T2FourReg<
2766218893Sdim        (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC16,
2767218893Sdim              !strconcat(opc, "tt"), "\t$Rd, $Rn, $Rm, $Ra",
2768218893Sdim             [(set rGPR:$Rd, (add rGPR:$Ra, (opnode (sra rGPR:$Rn, (i32 16)),
2769224145Sdim                                                 (sra rGPR:$Rm, (i32 16)))))]>,
2770243830Sdim           Requires<[IsThumb2, HasThumb2DSP, UseMulOps]> {
2771201360Srdivacky    let Inst{31-27} = 0b11111;
2772201360Srdivacky    let Inst{26-23} = 0b0110;
2773201360Srdivacky    let Inst{22-20} = 0b001;
2774201360Srdivacky    let Inst{7-6} = 0b00;
2775201360Srdivacky    let Inst{5-4} = 0b11;
2776201360Srdivacky  }
2777198090Srdivacky
2778218893Sdim  def WB : T2FourReg<
2779218893Sdim        (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC16,
2780218893Sdim              !strconcat(opc, "wb"), "\t$Rd, $Rn, $Rm, $Ra",
2781218893Sdim              [(set rGPR:$Rd, (add rGPR:$Ra, (sra (opnode rGPR:$Rn,
2782224145Sdim                                    (sext_inreg rGPR:$Rm, i16)), (i32 16))))]>,
2783243830Sdim           Requires<[IsThumb2, HasThumb2DSP, UseMulOps]> {
2784201360Srdivacky    let Inst{31-27} = 0b11111;
2785201360Srdivacky    let Inst{26-23} = 0b0110;
2786201360Srdivacky    let Inst{22-20} = 0b011;
2787201360Srdivacky    let Inst{7-6} = 0b00;
2788201360Srdivacky    let Inst{5-4} = 0b00;
2789201360Srdivacky  }
2790198090Srdivacky
2791218893Sdim  def WT : T2FourReg<
2792218893Sdim        (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC16,
2793218893Sdim              !strconcat(opc, "wt"), "\t$Rd, $Rn, $Rm, $Ra",
2794218893Sdim              [(set rGPR:$Rd, (add rGPR:$Ra, (sra (opnode rGPR:$Rn,
2795224145Sdim                                      (sra rGPR:$Rm, (i32 16))), (i32 16))))]>,
2796243830Sdim           Requires<[IsThumb2, HasThumb2DSP, UseMulOps]> {
2797201360Srdivacky    let Inst{31-27} = 0b11111;
2798201360Srdivacky    let Inst{26-23} = 0b0110;
2799201360Srdivacky    let Inst{22-20} = 0b011;
2800201360Srdivacky    let Inst{7-6} = 0b00;
2801201360Srdivacky    let Inst{5-4} = 0b01;
2802201360Srdivacky  }
2803198090Srdivacky}
2804198090Srdivacky
2805198090Srdivackydefm t2SMUL : T2I_smul<"smul", BinOpFrag<(mul node:$LHS, node:$RHS)>>;
2806198090Srdivackydefm t2SMLA : T2I_smla<"smla", BinOpFrag<(mul node:$LHS, node:$RHS)>>;
2807198090Srdivacky
2808226633Sdim// Halfword multiple accumulate long: SMLAL<x><y>
2809218893Sdimdef t2SMLALBB : T2FourReg_mac<1, 0b100, 0b1000, (outs rGPR:$Ra,rGPR:$Rd),
2810218893Sdim         (ins rGPR:$Rn,rGPR:$Rm), IIC_iMAC64, "smlalbb", "\t$Ra, $Rd, $Rn, $Rm",
2811224145Sdim           [/* For disassembly only; pattern left blank */]>,
2812224145Sdim          Requires<[IsThumb2, HasThumb2DSP]>;
2813218893Sdimdef t2SMLALBT : T2FourReg_mac<1, 0b100, 0b1001, (outs rGPR:$Ra,rGPR:$Rd),
2814218893Sdim         (ins rGPR:$Rn,rGPR:$Rm), IIC_iMAC64, "smlalbt", "\t$Ra, $Rd, $Rn, $Rm",
2815224145Sdim           [/* For disassembly only; pattern left blank */]>,
2816224145Sdim          Requires<[IsThumb2, HasThumb2DSP]>;
2817218893Sdimdef t2SMLALTB : T2FourReg_mac<1, 0b100, 0b1010, (outs rGPR:$Ra,rGPR:$Rd),
2818218893Sdim         (ins rGPR:$Rn,rGPR:$Rm), IIC_iMAC64, "smlaltb", "\t$Ra, $Rd, $Rn, $Rm",
2819224145Sdim           [/* For disassembly only; pattern left blank */]>,
2820224145Sdim          Requires<[IsThumb2, HasThumb2DSP]>;
2821218893Sdimdef t2SMLALTT : T2FourReg_mac<1, 0b100, 0b1011, (outs rGPR:$Ra,rGPR:$Rd),
2822218893Sdim         (ins rGPR:$Rn,rGPR:$Rm), IIC_iMAC64, "smlaltt", "\t$Ra, $Rd, $Rn, $Rm",
2823224145Sdim           [/* For disassembly only; pattern left blank */]>,
2824224145Sdim          Requires<[IsThumb2, HasThumb2DSP]>;
2825198090Srdivacky
2826204642Srdivacky// Dual halfword multiple: SMUAD, SMUSD, SMLAD, SMLSD, SMLALD, SMLSLD
2827218893Sdimdef t2SMUAD: T2ThreeReg_mac<
2828218893Sdim            0, 0b010, 0b0000, (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm),
2829224145Sdim            IIC_iMAC32, "smuad", "\t$Rd, $Rn, $Rm", []>,
2830224145Sdim          Requires<[IsThumb2, HasThumb2DSP]> {
2831204642Srdivacky  let Inst{15-12} = 0b1111;
2832204642Srdivacky}
2833218893Sdimdef t2SMUADX:T2ThreeReg_mac<
2834218893Sdim            0, 0b010, 0b0001, (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm),
2835224145Sdim            IIC_iMAC32, "smuadx", "\t$Rd, $Rn, $Rm", []>,
2836224145Sdim          Requires<[IsThumb2, HasThumb2DSP]> {
2837204642Srdivacky  let Inst{15-12} = 0b1111;
2838204642Srdivacky}
2839218893Sdimdef t2SMUSD: T2ThreeReg_mac<
2840218893Sdim            0, 0b100, 0b0000, (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm),
2841224145Sdim            IIC_iMAC32, "smusd", "\t$Rd, $Rn, $Rm", []>,
2842224145Sdim          Requires<[IsThumb2, HasThumb2DSP]> {
2843204642Srdivacky  let Inst{15-12} = 0b1111;
2844204642Srdivacky}
2845218893Sdimdef t2SMUSDX:T2ThreeReg_mac<
2846218893Sdim            0, 0b100, 0b0001, (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm),
2847224145Sdim            IIC_iMAC32, "smusdx", "\t$Rd, $Rn, $Rm", []>,
2848224145Sdim          Requires<[IsThumb2, HasThumb2DSP]> {
2849204642Srdivacky  let Inst{15-12} = 0b1111;
2850204642Srdivacky}
2851226633Sdimdef t2SMLAD   : T2FourReg_mac<
2852218893Sdim            0, 0b010, 0b0000, (outs rGPR:$Rd),
2853218893Sdim            (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC32, "smlad",
2854224145Sdim            "\t$Rd, $Rn, $Rm, $Ra", []>,
2855224145Sdim          Requires<[IsThumb2, HasThumb2DSP]>;
2856218893Sdimdef t2SMLADX  : T2FourReg_mac<
2857218893Sdim            0, 0b010, 0b0001, (outs rGPR:$Rd),
2858218893Sdim            (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC32, "smladx",
2859224145Sdim            "\t$Rd, $Rn, $Rm, $Ra", []>,
2860224145Sdim          Requires<[IsThumb2, HasThumb2DSP]>;
2861218893Sdimdef t2SMLSD   : T2FourReg_mac<0, 0b100, 0b0000, (outs rGPR:$Rd),
2862218893Sdim            (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC32, "smlsd",
2863224145Sdim            "\t$Rd, $Rn, $Rm, $Ra", []>,
2864224145Sdim          Requires<[IsThumb2, HasThumb2DSP]>;
2865218893Sdimdef t2SMLSDX  : T2FourReg_mac<0, 0b100, 0b0001, (outs rGPR:$Rd),
2866218893Sdim            (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC32, "smlsdx",
2867224145Sdim            "\t$Rd, $Rn, $Rm, $Ra", []>,
2868224145Sdim          Requires<[IsThumb2, HasThumb2DSP]>;
2869218893Sdimdef t2SMLALD  : T2FourReg_mac<1, 0b100, 0b1100, (outs rGPR:$Ra,rGPR:$Rd),
2870226633Sdim                        (ins rGPR:$Rn, rGPR:$Rm), IIC_iMAC64, "smlald",
2871226633Sdim                        "\t$Ra, $Rd, $Rn, $Rm", []>,
2872224145Sdim          Requires<[IsThumb2, HasThumb2DSP]>;
2873218893Sdimdef t2SMLALDX : T2FourReg_mac<1, 0b100, 0b1101, (outs rGPR:$Ra,rGPR:$Rd),
2874226633Sdim                        (ins rGPR:$Rn,rGPR:$Rm), IIC_iMAC64, "smlaldx",
2875226633Sdim                        "\t$Ra, $Rd, $Rn, $Rm", []>,
2876224145Sdim          Requires<[IsThumb2, HasThumb2DSP]>;
2877218893Sdimdef t2SMLSLD  : T2FourReg_mac<1, 0b101, 0b1100, (outs rGPR:$Ra,rGPR:$Rd),
2878226633Sdim                        (ins rGPR:$Rn,rGPR:$Rm), IIC_iMAC64, "smlsld",
2879226633Sdim                        "\t$Ra, $Rd, $Rn, $Rm", []>,
2880224145Sdim          Requires<[IsThumb2, HasThumb2DSP]>;
2881218893Sdimdef t2SMLSLDX : T2FourReg_mac<1, 0b101, 0b1101, (outs rGPR:$Ra,rGPR:$Rd),
2882218893Sdim                        (ins rGPR:$Rm,rGPR:$Rn), IIC_iMAC64, "smlsldx",
2883226633Sdim                        "\t$Ra, $Rd, $Rn, $Rm", []>,
2884224145Sdim          Requires<[IsThumb2, HasThumb2DSP]>;
2885204642Srdivacky
2886194754Sed//===----------------------------------------------------------------------===//
2887224145Sdim//  Division Instructions.
2888224145Sdim//  Signed and unsigned division on v7-M
2889224145Sdim//
2890243830Sdimdef t2SDIV : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iDIV,
2891224145Sdim                 "sdiv", "\t$Rd, $Rn, $Rm",
2892224145Sdim                 [(set rGPR:$Rd, (sdiv rGPR:$Rn, rGPR:$Rm))]>,
2893224145Sdim                 Requires<[HasDivide, IsThumb2]> {
2894224145Sdim  let Inst{31-27} = 0b11111;
2895224145Sdim  let Inst{26-21} = 0b011100;
2896224145Sdim  let Inst{20} = 0b1;
2897224145Sdim  let Inst{15-12} = 0b1111;
2898224145Sdim  let Inst{7-4} = 0b1111;
2899224145Sdim}
2900224145Sdim
2901243830Sdimdef t2UDIV : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iDIV,
2902224145Sdim                 "udiv", "\t$Rd, $Rn, $Rm",
2903224145Sdim                 [(set rGPR:$Rd, (udiv rGPR:$Rn, rGPR:$Rm))]>,
2904224145Sdim                 Requires<[HasDivide, IsThumb2]> {
2905224145Sdim  let Inst{31-27} = 0b11111;
2906224145Sdim  let Inst{26-21} = 0b011101;
2907224145Sdim  let Inst{20} = 0b1;
2908224145Sdim  let Inst{15-12} = 0b1111;
2909224145Sdim  let Inst{7-4} = 0b1111;
2910224145Sdim}
2911224145Sdim
2912224145Sdim//===----------------------------------------------------------------------===//
2913194754Sed//  Misc. Arithmetic Instructions.
2914194754Sed//
2915194754Sed
2916204642Srdivackyclass T2I_misc<bits<2> op1, bits<2> op2, dag oops, dag iops,
2917204642Srdivacky      InstrItinClass itin, string opc, string asm, list<dag> pattern>
2918218893Sdim  : T2ThreeReg<oops, iops, itin, opc, asm, pattern> {
2919201360Srdivacky  let Inst{31-27} = 0b11111;
2920201360Srdivacky  let Inst{26-22} = 0b01010;
2921201360Srdivacky  let Inst{21-20} = op1;
2922201360Srdivacky  let Inst{15-12} = 0b1111;
2923201360Srdivacky  let Inst{7-6} = 0b10;
2924201360Srdivacky  let Inst{5-4} = op2;
2925218893Sdim  let Rn{3-0} = Rm;
2926201360Srdivacky}
2927194754Sed
2928218893Sdimdef t2CLZ : T2I_misc<0b11, 0b00, (outs rGPR:$Rd), (ins rGPR:$Rm), IIC_iUNAr,
2929263508Sdim                    "clz", "\t$Rd, $Rm", [(set rGPR:$Rd, (ctlz rGPR:$Rm))]>,
2930263508Sdim                    Sched<[WriteALU]>;
2931194754Sed
2932218893Sdimdef t2RBIT : T2I_misc<0b01, 0b10, (outs rGPR:$Rd), (ins rGPR:$Rm), IIC_iUNAr,
2933218893Sdim                      "rbit", "\t$Rd, $Rm",
2934263508Sdim                      [(set rGPR:$Rd, (ARMrbit rGPR:$Rm))]>,
2935263508Sdim                      Sched<[WriteALU]>;
2936202878Srdivacky
2937218893Sdimdef t2REV : T2I_misc<0b01, 0b00, (outs rGPR:$Rd), (ins rGPR:$Rm), IIC_iUNAr,
2938263508Sdim                 "rev", ".w\t$Rd, $Rm", [(set rGPR:$Rd, (bswap rGPR:$Rm))]>,
2939263508Sdim                 Sched<[WriteALU]>;
2940201360Srdivacky
2941218893Sdimdef t2REV16 : T2I_misc<0b01, 0b01, (outs rGPR:$Rd), (ins rGPR:$Rm), IIC_iUNAr,
2942218893Sdim                       "rev16", ".w\t$Rd, $Rm",
2943263508Sdim                [(set rGPR:$Rd, (rotr (bswap rGPR:$Rm), (i32 16)))]>,
2944263508Sdim                Sched<[WriteALU]>;
2945194754Sed
2946218893Sdimdef t2REVSH : T2I_misc<0b01, 0b11, (outs rGPR:$Rd), (ins rGPR:$Rm), IIC_iUNAr,
2947218893Sdim                       "revsh", ".w\t$Rd, $Rm",
2948263508Sdim                 [(set rGPR:$Rd, (sra (bswap rGPR:$Rm), (i32 16)))]>,
2949263508Sdim                 Sched<[WriteALU]>;
2950194754Sed
2951224145Sdimdef : T2Pat<(or (sra (shl rGPR:$Rm, (i32 24)), (i32 16)),
2952224145Sdim                (and (srl rGPR:$Rm, (i32 8)), 0xFF)),
2953221345Sdim            (t2REVSH rGPR:$Rm)>;
2954221345Sdim
2955218893Sdimdef t2PKHBT : T2ThreeReg<
2956226633Sdim            (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, pkh_lsl_amt:$sh),
2957218893Sdim                  IIC_iBITsi, "pkhbt", "\t$Rd, $Rn, $Rm$sh",
2958218893Sdim                  [(set rGPR:$Rd, (or (and rGPR:$Rn, 0xFFFF),
2959226633Sdim                                      (and (shl rGPR:$Rm, pkh_lsl_amt:$sh),
2960208599Srdivacky                                           0xFFFF0000)))]>,
2961263508Sdim                  Requires<[HasT2ExtractPack, IsThumb2]>,
2962263508Sdim                  Sched<[WriteALUsi, ReadALU]> {
2963201360Srdivacky  let Inst{31-27} = 0b11101;
2964201360Srdivacky  let Inst{26-25} = 0b01;
2965201360Srdivacky  let Inst{24-20} = 0b01100;
2966201360Srdivacky  let Inst{5} = 0; // BT form
2967201360Srdivacky  let Inst{4} = 0;
2968218893Sdim
2969226633Sdim  bits<5> sh;
2970226633Sdim  let Inst{14-12} = sh{4-2};
2971226633Sdim  let Inst{7-6}   = sh{1-0};
2972201360Srdivacky}
2973194754Sed
2974198090Srdivacky// Alternate cases for PKHBT where identities eliminate some nodes.
2975212904Sdimdef : T2Pat<(or (and rGPR:$src1, 0xFFFF), (and rGPR:$src2, 0xFFFF0000)),
2976212904Sdim            (t2PKHBT rGPR:$src1, rGPR:$src2, 0)>,
2977218893Sdim            Requires<[HasT2ExtractPack, IsThumb2]>;
2978212904Sdimdef : T2Pat<(or (and rGPR:$src1, 0xFFFF), (shl rGPR:$src2, imm16_31:$sh)),
2979226633Sdim            (t2PKHBT rGPR:$src1, rGPR:$src2, imm16_31:$sh)>,
2980218893Sdim            Requires<[HasT2ExtractPack, IsThumb2]>;
2981198090Srdivacky
2982212904Sdim// Note: Shifts of 1-15 bits will be transformed to srl instead of sra and
2983212904Sdim// will match the pattern below.
2984218893Sdimdef t2PKHTB : T2ThreeReg<
2985226633Sdim                  (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, pkh_asr_amt:$sh),
2986218893Sdim                  IIC_iBITsi, "pkhtb", "\t$Rd, $Rn, $Rm$sh",
2987218893Sdim                  [(set rGPR:$Rd, (or (and rGPR:$Rn, 0xFFFF0000),
2988226633Sdim                                       (and (sra rGPR:$Rm, pkh_asr_amt:$sh),
2989212904Sdim                                            0xFFFF)))]>,
2990263508Sdim                  Requires<[HasT2ExtractPack, IsThumb2]>,
2991263508Sdim                  Sched<[WriteALUsi, ReadALU]> {
2992201360Srdivacky  let Inst{31-27} = 0b11101;
2993201360Srdivacky  let Inst{26-25} = 0b01;
2994201360Srdivacky  let Inst{24-20} = 0b01100;
2995201360Srdivacky  let Inst{5} = 1; // TB form
2996201360Srdivacky  let Inst{4} = 0;
2997218893Sdim
2998226633Sdim  bits<5> sh;
2999226633Sdim  let Inst{14-12} = sh{4-2};
3000226633Sdim  let Inst{7-6}   = sh{1-0};
3001201360Srdivacky}
3002198090Srdivacky
3003198090Srdivacky// Alternate cases for PKHTB where identities eliminate some nodes.  Note that
3004198090Srdivacky// a shift amount of 0 is *not legal* here, it is PKHBT instead.
3005263508Sdim// We also can not replace a srl (17..31) by an arithmetic shift we would use in
3006263508Sdim// pkhtb src1, src2, asr (17..31).
3007263508Sdimdef : T2Pat<(or (and rGPR:$src1, 0xFFFF0000), (srl rGPR:$src2, imm16:$sh)),
3008263508Sdim            (t2PKHTB rGPR:$src1, rGPR:$src2, imm16:$sh)>,
3009263508Sdim            Requires<[HasT2ExtractPack, IsThumb2]>;
3010263508Sdimdef : T2Pat<(or (and rGPR:$src1, 0xFFFF0000), (sra rGPR:$src2, imm16_31:$sh)),
3011226633Sdim            (t2PKHTB rGPR:$src1, rGPR:$src2, imm16_31:$sh)>,
3012218893Sdim            Requires<[HasT2ExtractPack, IsThumb2]>;
3013212904Sdimdef : T2Pat<(or (and rGPR:$src1, 0xFFFF0000),
3014212904Sdim                (and (srl rGPR:$src2, imm1_15:$sh), 0xFFFF)),
3015226633Sdim            (t2PKHTB rGPR:$src1, rGPR:$src2, imm1_15:$sh)>,
3016218893Sdim            Requires<[HasT2ExtractPack, IsThumb2]>;
3017198090Srdivacky
3018194754Sed//===----------------------------------------------------------------------===//
3019263508Sdim// CRC32 Instructions
3020263508Sdim//
3021263508Sdim// Polynomials:
3022263508Sdim// + CRC32{B,H,W}       0x04C11DB7
3023263508Sdim// + CRC32C{B,H,W}      0x1EDC6F41
3024263508Sdim//
3025263508Sdim
3026263508Sdimclass T2I_crc32<bit C, bits<2> sz, string suffix, SDPatternOperator builtin>
3027263508Sdim  : T2ThreeRegNoP<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), NoItinerary,
3028263508Sdim               !strconcat("crc32", suffix, "\t$Rd, $Rn, $Rm"),
3029263508Sdim               [(set rGPR:$Rd, (builtin rGPR:$Rn, rGPR:$Rm))]>,
3030263508Sdim               Requires<[IsThumb2, HasV8, HasCRC]> {
3031263508Sdim  let Inst{31-27} = 0b11111;
3032263508Sdim  let Inst{26-21} = 0b010110;
3033263508Sdim  let Inst{20}    = C;
3034263508Sdim  let Inst{15-12} = 0b1111;
3035263508Sdim  let Inst{7-6}   = 0b10;
3036263508Sdim  let Inst{5-4}   = sz;
3037263508Sdim}
3038263508Sdim
3039263508Sdimdef t2CRC32B  : T2I_crc32<0, 0b00, "b", int_arm_crc32b>;
3040263508Sdimdef t2CRC32CB : T2I_crc32<1, 0b00, "cb", int_arm_crc32cb>;
3041263508Sdimdef t2CRC32H  : T2I_crc32<0, 0b01, "h", int_arm_crc32h>;
3042263508Sdimdef t2CRC32CH : T2I_crc32<1, 0b01, "ch", int_arm_crc32ch>;
3043263508Sdimdef t2CRC32W  : T2I_crc32<0, 0b10, "w", int_arm_crc32w>;
3044263508Sdimdef t2CRC32CW : T2I_crc32<1, 0b10, "cw", int_arm_crc32cw>;
3045263508Sdim
3046263508Sdim//===----------------------------------------------------------------------===//
3047194754Sed//  Comparison Instructions...
3048194754Sed//
3049201360Srdivackydefm t2CMP  : T2I_cmp_irs<0b1101, "cmp",
3050218893Sdim                          IIC_iCMPi, IIC_iCMPr, IIC_iCMPsi,
3051239462Sdim                          BinOpFrag<(ARMcmp node:$LHS, node:$RHS)>>;
3052194754Sed
3053226633Sdimdef : T2Pat<(ARMcmpZ  GPRnopc:$lhs, t2_so_imm:$imm),
3054226633Sdim            (t2CMPri  GPRnopc:$lhs, t2_so_imm:$imm)>;
3055226633Sdimdef : T2Pat<(ARMcmpZ  GPRnopc:$lhs, rGPR:$rhs),
3056226633Sdim            (t2CMPrr  GPRnopc:$lhs, rGPR:$rhs)>;
3057226633Sdimdef : T2Pat<(ARMcmpZ  GPRnopc:$lhs, t2_so_reg:$rhs),
3058226633Sdim            (t2CMPrs  GPRnopc:$lhs, t2_so_reg:$rhs)>;
3059218893Sdim
3060239462Sdimlet isCompare = 1, Defs = [CPSR] in {
3061239462Sdim   // shifted imm
3062239462Sdim   def t2CMNri : T2OneRegCmpImm<
3063239462Sdim                (outs), (ins GPRnopc:$Rn, t2_so_imm:$imm), IIC_iCMPi,
3064239462Sdim                "cmn", ".w\t$Rn, $imm",
3065263508Sdim                [(ARMcmn GPRnopc:$Rn, (ineg t2_so_imm:$imm))]>,
3066263508Sdim                Sched<[WriteCMP, ReadALU]> {
3067239462Sdim     let Inst{31-27} = 0b11110;
3068239462Sdim     let Inst{25} = 0;
3069239462Sdim     let Inst{24-21} = 0b1000;
3070239462Sdim     let Inst{20} = 1; // The S bit.
3071239462Sdim     let Inst{15} = 0;
3072239462Sdim     let Inst{11-8} = 0b1111; // Rd
3073239462Sdim   }
3074239462Sdim   // register
3075239462Sdim   def t2CMNzrr : T2TwoRegCmp<
3076239462Sdim                (outs), (ins GPRnopc:$Rn, rGPR:$Rm), IIC_iCMPr,
3077239462Sdim                "cmn", ".w\t$Rn, $Rm",
3078239462Sdim                [(BinOpFrag<(ARMcmpZ node:$LHS,(ineg node:$RHS))>
3079263508Sdim                  GPRnopc:$Rn, rGPR:$Rm)]>, Sched<[WriteCMP, ReadALU, ReadALU]> {
3080239462Sdim     let Inst{31-27} = 0b11101;
3081239462Sdim     let Inst{26-25} = 0b01;
3082239462Sdim     let Inst{24-21} = 0b1000;
3083239462Sdim     let Inst{20} = 1; // The S bit.
3084239462Sdim     let Inst{14-12} = 0b000; // imm3
3085239462Sdim     let Inst{11-8} = 0b1111; // Rd
3086239462Sdim     let Inst{7-6} = 0b00; // imm2
3087239462Sdim     let Inst{5-4} = 0b00; // type
3088239462Sdim   }
3089239462Sdim   // shifted register
3090239462Sdim   def t2CMNzrs : T2OneRegCmpShiftedReg<
3091239462Sdim                (outs), (ins GPRnopc:$Rn, t2_so_reg:$ShiftedRm), IIC_iCMPsi,
3092239462Sdim                "cmn", ".w\t$Rn, $ShiftedRm",
3093239462Sdim                [(BinOpFrag<(ARMcmpZ node:$LHS,(ineg node:$RHS))>
3094263508Sdim                  GPRnopc:$Rn, t2_so_reg:$ShiftedRm)]>,
3095263508Sdim                  Sched<[WriteCMPsi, ReadALU, ReadALU]> {
3096239462Sdim     let Inst{31-27} = 0b11101;
3097239462Sdim     let Inst{26-25} = 0b01;
3098239462Sdim     let Inst{24-21} = 0b1000;
3099239462Sdim     let Inst{20} = 1; // The S bit.
3100239462Sdim     let Inst{11-8} = 0b1111; // Rd
3101239462Sdim   }
3102239462Sdim}
3103194754Sed
3104239462Sdim// Assembler aliases w/o the ".w" suffix.
3105239462Sdim// No alias here for 'rr' version as not all instantiations of this multiclass
3106239462Sdim// want one (CMP in particular, does not).
3107239462Sdimdef : t2InstAlias<"cmn${p} $Rn, $imm",
3108239462Sdim   (t2CMNri GPRnopc:$Rn, t2_so_imm:$imm, pred:$p)>;
3109239462Sdimdef : t2InstAlias<"cmn${p} $Rn, $shift",
3110239462Sdim   (t2CMNzrs GPRnopc:$Rn, t2_so_reg:$shift, pred:$p)>;
3111194754Sed
3112239462Sdimdef : T2Pat<(ARMcmp  GPR:$src, t2_so_imm_neg:$imm),
3113239462Sdim            (t2CMNri GPR:$src, t2_so_imm_neg:$imm)>;
3114194754Sed
3115239462Sdimdef : T2Pat<(ARMcmpZ GPRnopc:$src, t2_so_imm_neg:$imm),
3116239462Sdim            (t2CMNri GPRnopc:$src, t2_so_imm_neg:$imm)>;
3117239462Sdim
3118201360Srdivackydefm t2TST  : T2I_cmp_irs<0b0000, "tst",
3119218893Sdim                          IIC_iTSTi, IIC_iTSTr, IIC_iTSTsi,
3120239462Sdim                         BinOpFrag<(ARMcmpZ (and_su node:$LHS, node:$RHS), 0)>>;
3121201360Srdivackydefm t2TEQ  : T2I_cmp_irs<0b0100, "teq",
3122218893Sdim                          IIC_iTSTi, IIC_iTSTr, IIC_iTSTsi,
3123239462Sdim                         BinOpFrag<(ARMcmpZ (xor_su node:$LHS, node:$RHS), 0)>>;
3124194754Sed
3125198090Srdivacky// Conditional moves
3126208599Srdivackylet neverHasSideEffects = 1 in {
3127234353Sdim
3128239462Sdimlet isCommutable = 1, isSelect = 1 in
3129224145Sdimdef t2MOVCCr : t2PseudoInst<(outs rGPR:$Rd),
3130263508Sdim                            (ins rGPR:$false, rGPR:$Rm, cmovpred:$p),
3131224145Sdim                            4, IIC_iCMOVr,
3132263508Sdim                            [(set rGPR:$Rd, (ARMcmov rGPR:$false, rGPR:$Rm,
3133263508Sdim                                                     cmovpred:$p))]>,
3134263508Sdim               RegConstraint<"$false = $Rd">, Sched<[WriteALU]>;
3135198090Srdivacky
3136218893Sdimlet isMoveImm = 1 in
3137263508Sdimdef t2MOVCCi
3138263508Sdim    : t2PseudoInst<(outs rGPR:$Rd),
3139263508Sdim                   (ins rGPR:$false, t2_so_imm:$imm, cmovpred:$p),
3140224145Sdim                   4, IIC_iCMOVi,
3141263508Sdim                   [(set rGPR:$Rd, (ARMcmov rGPR:$false,t2_so_imm:$imm,
3142263508Sdim                                            cmovpred:$p))]>,
3143263508Sdim      RegConstraint<"$false = $Rd">, Sched<[WriteALU]>;
3144198090Srdivacky
3145224145Sdimlet isCodeGenOnly = 1 in {
3146218893Sdimlet isMoveImm = 1 in
3147263508Sdimdef t2MOVCCi16
3148263508Sdim    : t2PseudoInst<(outs rGPR:$Rd),
3149263508Sdim                   (ins  rGPR:$false, imm0_65535_expr:$imm, cmovpred:$p),
3150263508Sdim                   4, IIC_iCMOVi,
3151263508Sdim                   [(set rGPR:$Rd, (ARMcmov rGPR:$false, imm0_65535:$imm,
3152263508Sdim                                            cmovpred:$p))]>,
3153263508Sdim      RegConstraint<"$false = $Rd">, Sched<[WriteALU]>;
3154218893Sdim
3155263508Sdimlet isMoveImm = 1 in
3156263508Sdimdef t2MVNCCi
3157263508Sdim    : t2PseudoInst<(outs rGPR:$Rd),
3158263508Sdim                   (ins rGPR:$false, t2_so_imm:$imm, cmovpred:$p),
3159263508Sdim                   4, IIC_iCMOVi,
3160263508Sdim                   [(set rGPR:$Rd,
3161263508Sdim                         (ARMcmov rGPR:$false, t2_so_imm_not:$imm,
3162263508Sdim                                  cmovpred:$p))]>,
3163263508Sdim      RegConstraint<"$false = $Rd">, Sched<[WriteALU]>;
3164218893Sdim
3165263508Sdimclass MOVCCShPseudo<SDPatternOperator opnode, Operand ty>
3166263508Sdim    : t2PseudoInst<(outs rGPR:$Rd),
3167263508Sdim                   (ins rGPR:$false, rGPR:$Rm, i32imm:$imm, cmovpred:$p),
3168263508Sdim                   4, IIC_iCMOVsi,
3169263508Sdim                   [(set rGPR:$Rd, (ARMcmov rGPR:$false,
3170263508Sdim                                            (opnode rGPR:$Rm, (i32 ty:$imm)),
3171263508Sdim                                            cmovpred:$p))]>,
3172263508Sdim      RegConstraint<"$false = $Rd">, Sched<[WriteALU]>;
3173218893Sdim
3174263508Sdimdef t2MOVCClsl : MOVCCShPseudo<shl,  imm0_31>;
3175263508Sdimdef t2MOVCClsr : MOVCCShPseudo<srl,  imm_sr>;
3176263508Sdimdef t2MOVCCasr : MOVCCShPseudo<sra,  imm_sr>;
3177263508Sdimdef t2MOVCCror : MOVCCShPseudo<rotr, imm0_31>;
3178218893Sdim
3179218893Sdimlet isMoveImm = 1 in
3180263508Sdimdef t2MOVCCi32imm
3181263508Sdim    : t2PseudoInst<(outs rGPR:$dst),
3182263508Sdim                   (ins rGPR:$false, i32imm:$src, cmovpred:$p),
3183263508Sdim                   8, IIC_iCMOVix2,
3184263508Sdim                   [(set rGPR:$dst, (ARMcmov rGPR:$false, imm:$src,
3185263508Sdim                                             cmovpred:$p))]>,
3186263508Sdim      RegConstraint<"$false = $dst">;
3187224145Sdim} // isCodeGenOnly = 1
3188234353Sdim
3189208599Srdivacky} // neverHasSideEffects
3190198090Srdivacky
3191195340Sed//===----------------------------------------------------------------------===//
3192200581Srdivacky// Atomic operations intrinsics
3193200581Srdivacky//
3194200581Srdivacky
3195200581Srdivacky// memory barriers protect the atomic sequences
3196200581Srdivackylet hasSideEffects = 1 in {
3197263508Sdimdef t2DMB : T2I<(outs), (ins memb_opt:$opt), NoItinerary,
3198263508Sdim                "dmb", "\t$opt", [(int_arm_dmb (i32 imm0_15:$opt))]>,
3199263508Sdim                Requires<[HasDB]> {
3200218893Sdim  bits<4> opt;
3201218893Sdim  let Inst{31-4} = 0xf3bf8f5;
3202218893Sdim  let Inst{3-0} = opt;
3203200581Srdivacky}
3204200581Srdivacky}
3205200581Srdivacky
3206263508Sdimdef t2DSB : T2I<(outs), (ins memb_opt:$opt), NoItinerary,
3207263508Sdim                "dsb", "\t$opt", [(int_arm_dsb (i32 imm0_15:$opt))]>,
3208263508Sdim                Requires<[HasDB]> {
3209218893Sdim  bits<4> opt;
3210218893Sdim  let Inst{31-4} = 0xf3bf8f4;
3211218893Sdim  let Inst{3-0} = opt;
3212204642Srdivacky}
3213204642Srdivacky
3214263508Sdimdef t2ISB : T2I<(outs), (ins instsyncb_opt:$opt), NoItinerary,
3215263508Sdim                "isb", "\t$opt", []>, Requires<[HasDB]> {
3216226633Sdim  bits<4> opt;
3217218893Sdim  let Inst{31-4} = 0xf3bf8f6;
3218226633Sdim  let Inst{3-0} = opt;
3219204642Srdivacky}
3220204642Srdivacky
3221263508Sdimclass T2I_ldrex<bits<4> opcod, dag oops, dag iops, AddrMode am, int sz,
3222201360Srdivacky                InstrItinClass itin, string opc, string asm, string cstr,
3223201360Srdivacky                list<dag> pattern, bits<4> rt2 = 0b1111>
3224201360Srdivacky  : Thumb2I<oops, iops, am, sz, itin, opc, asm, cstr, pattern> {
3225201360Srdivacky  let Inst{31-27} = 0b11101;
3226201360Srdivacky  let Inst{26-20} = 0b0001101;
3227201360Srdivacky  let Inst{11-8} = rt2;
3228263508Sdim  let Inst{7-4} = opcod;
3229201360Srdivacky  let Inst{3-0} = 0b1111;
3230218893Sdim
3231221345Sdim  bits<4> addr;
3232218893Sdim  bits<4> Rt;
3233221345Sdim  let Inst{19-16} = addr;
3234218893Sdim  let Inst{15-12} = Rt;
3235201360Srdivacky}
3236263508Sdimclass T2I_strex<bits<4> opcod, dag oops, dag iops, AddrMode am, int sz,
3237201360Srdivacky                InstrItinClass itin, string opc, string asm, string cstr,
3238201360Srdivacky                list<dag> pattern, bits<4> rt2 = 0b1111>
3239201360Srdivacky  : Thumb2I<oops, iops, am, sz, itin, opc, asm, cstr, pattern> {
3240201360Srdivacky  let Inst{31-27} = 0b11101;
3241201360Srdivacky  let Inst{26-20} = 0b0001100;
3242201360Srdivacky  let Inst{11-8} = rt2;
3243263508Sdim  let Inst{7-4} = opcod;
3244218893Sdim
3245218893Sdim  bits<4> Rd;
3246221345Sdim  bits<4> addr;
3247218893Sdim  bits<4> Rt;
3248221345Sdim  let Inst{3-0}  = Rd;
3249221345Sdim  let Inst{19-16} = addr;
3250218893Sdim  let Inst{15-12} = Rt;
3251201360Srdivacky}
3252201360Srdivacky
3253200581Srdivackylet mayLoad = 1 in {
3254263508Sdimdef t2LDREXB : T2I_ldrex<0b0100, (outs rGPR:$Rt), (ins addr_offset_none:$addr),
3255224145Sdim                         AddrModeNone, 4, NoItinerary,
3256263508Sdim                         "ldrexb", "\t$Rt, $addr", "",
3257263508Sdim                         [(set rGPR:$Rt, (ldrex_1 addr_offset_none:$addr))]>;
3258263508Sdimdef t2LDREXH : T2I_ldrex<0b0101, (outs rGPR:$Rt), (ins addr_offset_none:$addr),
3259224145Sdim                         AddrModeNone, 4, NoItinerary,
3260263508Sdim                         "ldrexh", "\t$Rt, $addr", "",
3261263508Sdim                         [(set rGPR:$Rt, (ldrex_2 addr_offset_none:$addr))]>;
3262226633Sdimdef t2LDREX  : Thumb2I<(outs rGPR:$Rt), (ins t2addrmode_imm0_1020s4:$addr),
3263224145Sdim                       AddrModeNone, 4, NoItinerary,
3264263508Sdim                       "ldrex", "\t$Rt, $addr", "",
3265263508Sdim                     [(set rGPR:$Rt, (ldrex_4 t2addrmode_imm0_1020s4:$addr))]> {
3266226633Sdim  bits<4> Rt;
3267226633Sdim  bits<12> addr;
3268201360Srdivacky  let Inst{31-27} = 0b11101;
3269201360Srdivacky  let Inst{26-20} = 0b0000101;
3270226633Sdim  let Inst{19-16} = addr{11-8};
3271226633Sdim  let Inst{15-12} = Rt;
3272201360Srdivacky  let Inst{11-8} = 0b1111;
3273226633Sdim  let Inst{7-0} = addr{7-0};
3274200581Srdivacky}
3275223017Sdimlet hasExtraDefRegAllocReq = 1 in
3276263508Sdimdef t2LDREXD : T2I_ldrex<0b0111, (outs rGPR:$Rt, rGPR:$Rt2),
3277226633Sdim                         (ins addr_offset_none:$addr),
3278224145Sdim                         AddrModeNone, 4, NoItinerary,
3279221345Sdim                         "ldrexd", "\t$Rt, $Rt2, $addr", "",
3280218893Sdim                         [], {?, ?, ?, ?}> {
3281218893Sdim  bits<4> Rt2;
3282218893Sdim  let Inst{11-8} = Rt2;
3283201360Srdivacky}
3284263508Sdimdef t2LDAEXB : T2I_ldrex<0b1100, (outs rGPR:$Rt), (ins addr_offset_none:$addr),
3285263508Sdim                         AddrModeNone, 4, NoItinerary,
3286263508Sdim                         "ldaexb", "\t$Rt, $addr", "",
3287263508Sdim                         []>, Requires<[IsThumb, HasV8]>;
3288263508Sdimdef t2LDAEXH : T2I_ldrex<0b1101, (outs rGPR:$Rt), (ins addr_offset_none:$addr),
3289263508Sdim                         AddrModeNone, 4, NoItinerary,
3290263508Sdim                         "ldaexh", "\t$Rt, $addr", "",
3291263508Sdim                         []>, Requires<[IsThumb, HasV8]>;
3292263508Sdimdef t2LDAEX  : Thumb2I<(outs rGPR:$Rt), (ins addr_offset_none:$addr),
3293263508Sdim                       AddrModeNone, 4, NoItinerary,
3294263508Sdim                       "ldaex", "\t$Rt, $addr", "",
3295263508Sdim                     []>, Requires<[IsThumb, HasV8]> {
3296263508Sdim  bits<4> Rt;
3297263508Sdim  bits<4> addr;
3298263508Sdim  let Inst{31-27} = 0b11101;
3299263508Sdim  let Inst{26-20} = 0b0001101;
3300263508Sdim  let Inst{19-16} = addr;
3301263508Sdim  let Inst{15-12} = Rt;
3302263508Sdim  let Inst{11-8} = 0b1111;
3303263508Sdim  let Inst{7-0} = 0b11101111;
3304218893Sdim}
3305263508Sdimlet hasExtraDefRegAllocReq = 1 in
3306263508Sdimdef t2LDAEXD : T2I_ldrex<0b1111, (outs rGPR:$Rt, rGPR:$Rt2),
3307263508Sdim                         (ins addr_offset_none:$addr),
3308263508Sdim                         AddrModeNone, 4, NoItinerary,
3309263508Sdim                         "ldaexd", "\t$Rt, $Rt2, $addr", "",
3310263508Sdim                         [], {?, ?, ?, ?}>, Requires<[IsThumb, HasV8]> {
3311263508Sdim  bits<4> Rt2;
3312263508Sdim  let Inst{11-8} = Rt2;
3313200581Srdivacky
3314263508Sdim  let Inst{7} = 1;
3315263508Sdim}
3316263508Sdim}
3317263508Sdim
3318218893Sdimlet mayStore = 1, Constraints = "@earlyclobber $Rd" in {
3319263508Sdimdef t2STREXB : T2I_strex<0b0100, (outs rGPR:$Rd),
3320226633Sdim                         (ins rGPR:$Rt, addr_offset_none:$addr),
3321224145Sdim                         AddrModeNone, 4, NoItinerary,
3322263508Sdim                         "strexb", "\t$Rd, $Rt, $addr", "",
3323263508Sdim                         [(set rGPR:$Rd, (strex_1 rGPR:$Rt,
3324263508Sdim                                                  addr_offset_none:$addr))]>;
3325263508Sdimdef t2STREXH : T2I_strex<0b0101, (outs rGPR:$Rd),
3326226633Sdim                         (ins rGPR:$Rt, addr_offset_none:$addr),
3327224145Sdim                         AddrModeNone, 4, NoItinerary,
3328263508Sdim                         "strexh", "\t$Rd, $Rt, $addr", "",
3329263508Sdim                         [(set rGPR:$Rd, (strex_2 rGPR:$Rt,
3330263508Sdim                                                  addr_offset_none:$addr))]>;
3331263508Sdim
3332226633Sdimdef t2STREX  : Thumb2I<(outs rGPR:$Rd), (ins rGPR:$Rt,
3333226633Sdim                             t2addrmode_imm0_1020s4:$addr),
3334224145Sdim                  AddrModeNone, 4, NoItinerary,
3335221345Sdim                  "strex", "\t$Rd, $Rt, $addr", "",
3336263508Sdim                  [(set rGPR:$Rd, (strex_4 rGPR:$Rt,
3337263508Sdim                                           t2addrmode_imm0_1020s4:$addr))]> {
3338226633Sdim  bits<4> Rd;
3339226633Sdim  bits<4> Rt;
3340226633Sdim  bits<12> addr;
3341201360Srdivacky  let Inst{31-27} = 0b11101;
3342201360Srdivacky  let Inst{26-20} = 0b0000100;
3343226633Sdim  let Inst{19-16} = addr{11-8};
3344226633Sdim  let Inst{15-12} = Rt;
3345218893Sdim  let Inst{11-8}  = Rd;
3346226633Sdim  let Inst{7-0} = addr{7-0};
3347200581Srdivacky}
3348234353Sdimlet hasExtraSrcRegAllocReq = 1 in
3349263508Sdimdef t2STREXD : T2I_strex<0b0111, (outs rGPR:$Rd),
3350226633Sdim                         (ins rGPR:$Rt, rGPR:$Rt2, addr_offset_none:$addr),
3351224145Sdim                         AddrModeNone, 4, NoItinerary,
3352221345Sdim                         "strexd", "\t$Rd, $Rt, $Rt2, $addr", "", [],
3353218893Sdim                         {?, ?, ?, ?}> {
3354218893Sdim  bits<4> Rt2;
3355218893Sdim  let Inst{11-8} = Rt2;
3356201360Srdivacky}
3357263508Sdimdef t2STLEXB : T2I_strex<0b1100, (outs rGPR:$Rd),
3358263508Sdim                         (ins rGPR:$Rt, addr_offset_none:$addr),
3359263508Sdim                         AddrModeNone, 4, NoItinerary,
3360263508Sdim                         "stlexb", "\t$Rd, $Rt, $addr", "",
3361263508Sdim                         []>, Requires<[IsThumb, HasV8]>;
3362263508Sdim
3363263508Sdimdef t2STLEXH : T2I_strex<0b1101, (outs rGPR:$Rd),
3364263508Sdim                         (ins rGPR:$Rt, addr_offset_none:$addr),
3365263508Sdim                         AddrModeNone, 4, NoItinerary,
3366263508Sdim                         "stlexh", "\t$Rd, $Rt, $addr", "",
3367263508Sdim                         []>, Requires<[IsThumb, HasV8]>;
3368263508Sdim
3369263508Sdimdef t2STLEX  : Thumb2I<(outs rGPR:$Rd), (ins rGPR:$Rt,
3370263508Sdim                             addr_offset_none:$addr),
3371263508Sdim                  AddrModeNone, 4, NoItinerary,
3372263508Sdim                  "stlex", "\t$Rd, $Rt, $addr", "",
3373263508Sdim                  []>, Requires<[IsThumb, HasV8]> {
3374263508Sdim  bits<4> Rd;
3375263508Sdim  bits<4> Rt;
3376263508Sdim  bits<4> addr;
3377263508Sdim  let Inst{31-27} = 0b11101;
3378263508Sdim  let Inst{26-20} = 0b0001100;
3379263508Sdim  let Inst{19-16} = addr;
3380263508Sdim  let Inst{15-12} = Rt;
3381263508Sdim  let Inst{11-4}  = 0b11111110;
3382263508Sdim  let Inst{3-0}   = Rd;
3383234353Sdim}
3384263508Sdimlet hasExtraSrcRegAllocReq = 1 in
3385263508Sdimdef t2STLEXD : T2I_strex<0b1111, (outs rGPR:$Rd),
3386263508Sdim                         (ins rGPR:$Rt, rGPR:$Rt2, addr_offset_none:$addr),
3387263508Sdim                         AddrModeNone, 4, NoItinerary,
3388263508Sdim                         "stlexd", "\t$Rd, $Rt, $Rt2, $addr", "", [],
3389263508Sdim                         {?, ?, ?, ?}>, Requires<[IsThumb, HasV8]> {
3390263508Sdim  bits<4> Rt2;
3391263508Sdim  let Inst{11-8} = Rt2;
3392263508Sdim}
3393263508Sdim}
3394200581Srdivacky
3395263508Sdimdef t2CLREX : T2I<(outs), (ins), NoItinerary, "clrex", "", [(int_arm_clrex)]>,
3396218893Sdim            Requires<[IsThumb2, HasV7]>  {
3397218893Sdim  let Inst{31-16} = 0xf3bf;
3398204642Srdivacky  let Inst{15-14} = 0b10;
3399218893Sdim  let Inst{13} = 0;
3400204642Srdivacky  let Inst{12} = 0;
3401218893Sdim  let Inst{11-8} = 0b1111;
3402204642Srdivacky  let Inst{7-4} = 0b0010;
3403218893Sdim  let Inst{3-0} = 0b1111;
3404204642Srdivacky}
3405204642Srdivacky
3406263508Sdimdef : T2Pat<(and (ldrex_1 addr_offset_none:$addr), 0xff),
3407263508Sdim            (t2LDREXB addr_offset_none:$addr)>;
3408263508Sdimdef : T2Pat<(and (ldrex_2 addr_offset_none:$addr), 0xffff),
3409263508Sdim            (t2LDREXH addr_offset_none:$addr)>;
3410263508Sdimdef : T2Pat<(strex_1 (and GPR:$Rt, 0xff), addr_offset_none:$addr),
3411263508Sdim            (t2STREXB GPR:$Rt, addr_offset_none:$addr)>;
3412263508Sdimdef : T2Pat<(strex_2 (and GPR:$Rt, 0xffff), addr_offset_none:$addr),
3413263508Sdim            (t2STREXH GPR:$Rt, addr_offset_none:$addr)>;
3414263508Sdim
3415200581Srdivacky//===----------------------------------------------------------------------===//
3416198090Srdivacky// SJLJ Exception handling intrinsics
3417198090Srdivacky//   eh_sjlj_setjmp() is an instruction sequence to store the return
3418198090Srdivacky//   address and save #0 in R0 for the non-longjmp case.
3419198090Srdivacky//   Since by its nature we may be coming from some other function to get
3420198090Srdivacky//   here, and we're using the stack frame for the containing function to
3421198090Srdivacky//   save/restore registers, we can't keep anything live in regs across
3422198090Srdivacky//   the eh_sjlj_setjmp(), else it will almost certainly have been tromped upon
3423221345Sdim//   when we get here from a longjmp(). We force everything out of registers
3424198090Srdivacky//   except for our own input by listing the relevant registers in Defs. By
3425198090Srdivacky//   doing so, we also cause the prologue/epilogue code to actively preserve
3426198090Srdivacky//   all of the callee-saved resgisters, which is exactly what we want.
3427210299Sed//   $val is a scratch register for our use.
3428203954Srdivackylet Defs =
3429223017Sdim  [ R0,  R1,  R2,  R3,  R4,  R5,  R6,  R7,  R8,  R9,  R10, R11, R12, LR, CPSR,
3430234353Sdim    Q0, Q1, Q2, Q3, Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15],
3431234353Sdim  hasSideEffects = 1, isBarrier = 1, isCodeGenOnly = 1,
3432234353Sdim  usesCustomInserter = 1 in {
3433212904Sdim  def t2Int_eh_sjlj_setjmp : Thumb2XI<(outs), (ins tGPR:$src, tGPR:$val),
3434224145Sdim                               AddrModeNone, 0, NoItinerary, "", "",
3435212904Sdim                          [(set R0, (ARMeh_sjlj_setjmp tGPR:$src, tGPR:$val))]>,
3436207618Srdivacky                             Requires<[IsThumb2, HasVFP2]>;
3437198090Srdivacky}
3438198090Srdivacky
3439207618Srdivackylet Defs =
3440223017Sdim  [ R0,  R1,  R2,  R3,  R4,  R5,  R6,  R7,  R8,  R9,  R10, R11, R12, LR, CPSR ],
3441234353Sdim  hasSideEffects = 1, isBarrier = 1, isCodeGenOnly = 1,
3442234353Sdim  usesCustomInserter = 1 in {
3443212904Sdim  def t2Int_eh_sjlj_setjmp_nofp : Thumb2XI<(outs), (ins tGPR:$src, tGPR:$val),
3444224145Sdim                               AddrModeNone, 0, NoItinerary, "", "",
3445212904Sdim                          [(set R0, (ARMeh_sjlj_setjmp tGPR:$src, tGPR:$val))]>,
3446207618Srdivacky                                  Requires<[IsThumb2, NoVFP]>;
3447207618Srdivacky}
3448198090Srdivacky
3449198090Srdivacky
3450198090Srdivacky//===----------------------------------------------------------------------===//
3451195340Sed// Control-Flow Instructions
3452195340Sed//
3453194754Sed
3454198090Srdivacky// FIXME: remove when we have a way to marking a MI with these properties.
3455198090Srdivacky// FIXME: Should pc be an implicit operand like PICADD, etc?
3456198090Srdivackylet isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1,
3457218893Sdim    hasExtraDefRegAllocReq = 1, isCodeGenOnly = 1 in
3458224145Sdimdef t2LDMIA_RET: t2PseudoExpand<(outs GPR:$wb), (ins GPR:$Rn, pred:$p,
3459224145Sdim                                                   reglist:$regs, variable_ops),
3460224145Sdim                              4, IIC_iLoad_mBr, [],
3461224145Sdim            (t2LDMIA_UPD GPR:$wb, GPR:$Rn, pred:$p, reglist:$regs)>,
3462224145Sdim                         RegConstraint<"$Rn = $wb">;
3463218893Sdim
3464195340Sedlet isBranch = 1, isTerminator = 1, isBarrier = 1 in {
3465195340Sedlet isPredicable = 1 in
3466226633Sdimdef t2B   : T2I<(outs), (ins uncondbrtarget:$target), IIC_Br,
3467226633Sdim                 "b", ".w\t$target",
3468263508Sdim                 [(br bb:$target)]>, Sched<[WriteBr]> {
3469201360Srdivacky  let Inst{31-27} = 0b11110;
3470201360Srdivacky  let Inst{15-14} = 0b10;
3471201360Srdivacky  let Inst{12} = 1;
3472218893Sdim
3473243830Sdim  bits<24> target;
3474263508Sdim  let Inst{26} = target{23};
3475263508Sdim  let Inst{13} = target{22};
3476263508Sdim  let Inst{11} = target{21};
3477243830Sdim  let Inst{25-16} = target{20-11};
3478218893Sdim  let Inst{10-0} = target{10-0};
3479234353Sdim  let DecoderMethod = "DecodeT2BInstruction";
3480263508Sdim  let AsmMatchConverter = "cvtThumbBranches"; 
3481263508Sdim} 
3482195340Sed
3483195340Sedlet isNotDuplicable = 1, isIndirectBranch = 1 in {
3484218893Sdimdef t2BR_JT : t2PseudoInst<(outs),
3485218893Sdim          (ins GPR:$target, GPR:$index, i32imm:$jt, i32imm:$id),
3486224145Sdim           0, IIC_Br,
3487263508Sdim          [(ARMbr2jt GPR:$target, GPR:$index, tjumptable:$jt, imm:$id)]>,
3488263508Sdim          Sched<[WriteBr]>;
3489195340Sed
3490198090Srdivacky// FIXME: Add a non-pc based case that can be predicated.
3491218893Sdimdef t2TBB_JT : t2PseudoInst<(outs),
3492263508Sdim        (ins GPR:$index, i32imm:$jt, i32imm:$id), 0, IIC_Br, []>,
3493263508Sdim        Sched<[WriteBr]>;
3494195340Sed
3495218893Sdimdef t2TBH_JT : t2PseudoInst<(outs),
3496263508Sdim        (ins GPR:$index, i32imm:$jt, i32imm:$id), 0, IIC_Br, []>,
3497263508Sdim        Sched<[WriteBr]>;
3498204642Srdivacky
3499226633Sdimdef t2TBB : T2I<(outs), (ins addrmode_tbb:$addr), IIC_Br,
3500263508Sdim                    "tbb", "\t$addr", []>, Sched<[WriteBrTbl]> {
3501218893Sdim  bits<4> Rn;
3502218893Sdim  bits<4> Rm;
3503218893Sdim  let Inst{31-20} = 0b111010001101;
3504218893Sdim  let Inst{19-16} = Rn;
3505218893Sdim  let Inst{15-5} = 0b11110000000;
3506218893Sdim  let Inst{4} = 0; // B form
3507218893Sdim  let Inst{3-0} = Rm;
3508226633Sdim
3509226633Sdim  let DecoderMethod = "DecodeThumbTableBranch";
3510204642Srdivacky}
3511204642Srdivacky
3512226633Sdimdef t2TBH : T2I<(outs), (ins addrmode_tbh:$addr), IIC_Br,
3513263508Sdim                   "tbh", "\t$addr", []>, Sched<[WriteBrTbl]> {
3514218893Sdim  bits<4> Rn;
3515218893Sdim  bits<4> Rm;
3516218893Sdim  let Inst{31-20} = 0b111010001101;
3517218893Sdim  let Inst{19-16} = Rn;
3518218893Sdim  let Inst{15-5} = 0b11110000000;
3519218893Sdim  let Inst{4} = 1; // H form
3520218893Sdim  let Inst{3-0} = Rm;
3521226633Sdim
3522226633Sdim  let DecoderMethod = "DecodeThumbTableBranch";
3523204642Srdivacky}
3524198090Srdivacky} // isNotDuplicable, isIndirectBranch
3525198090Srdivacky
3526195340Sed} // isBranch, isTerminator, isBarrier
3527195340Sed
3528195340Sed// FIXME: should be able to write a pattern for ARMBrcond, but can't use
3529226633Sdim// a two-value operand where a dag node expects ", "two operands. :(
3530195340Sedlet isBranch = 1, isTerminator = 1 in
3531198090Srdivackydef t2Bcc : T2I<(outs), (ins brtarget:$target), IIC_Br,
3532198892Srdivacky                "b", ".w\t$target",
3533263508Sdim                [/*(ARMbrcond bb:$target, imm:$cc)*/]>, Sched<[WriteBr]> {
3534201360Srdivacky  let Inst{31-27} = 0b11110;
3535201360Srdivacky  let Inst{15-14} = 0b10;
3536201360Srdivacky  let Inst{12} = 0;
3537218893Sdim
3538218893Sdim  bits<4> p;
3539218893Sdim  let Inst{25-22} = p;
3540218893Sdim
3541218893Sdim  bits<21> target;
3542218893Sdim  let Inst{26} = target{20};
3543218893Sdim  let Inst{11} = target{19};
3544218893Sdim  let Inst{13} = target{18};
3545218893Sdim  let Inst{21-16} = target{17-12};
3546218893Sdim  let Inst{10-0} = target{11-1};
3547226633Sdim
3548226633Sdim  let DecoderMethod = "DecodeThumb2BCCInstruction";
3549263508Sdim  let AsmMatchConverter = "cvtThumbBranches";
3550201360Srdivacky}
3551195340Sed
3552234353Sdim// Tail calls. The IOS version of thumb tail calls uses a t2 branch, so
3553224145Sdim// it goes here.
3554224145Sdimlet isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
3555234353Sdim  // IOS version.
3556234353Sdim  let Uses = [SP] in
3557226633Sdim  def tTAILJMPd: tPseudoExpand<(outs),
3558239462Sdim                   (ins uncondbrtarget:$dst, pred:$p),
3559224145Sdim                   4, IIC_Br, [],
3560226633Sdim                   (t2B uncondbrtarget:$dst, pred:$p)>,
3561263508Sdim                 Requires<[IsThumb2, IsIOS]>, Sched<[WriteBr]>;
3562224145Sdim}
3563198090Srdivacky
3564198090Srdivacky// IT block
3565210299Sedlet Defs = [ITSTATE] in
3566198090Srdivackydef t2IT : Thumb2XI<(outs), (ins it_pred:$cc, it_mask:$mask),
3567224145Sdim                    AddrModeNone, 2,  IIC_iALUx,
3568263508Sdim                    "it$mask\t$cc", "", []>,
3569263508Sdim           ComplexDeprecationPredicate<"IT"> {
3570201360Srdivacky  // 16-bit instruction.
3571201360Srdivacky  let Inst{31-16} = 0x0000;
3572201360Srdivacky  let Inst{15-8} = 0b10111111;
3573218893Sdim
3574218893Sdim  bits<4> cc;
3575218893Sdim  bits<4> mask;
3576218893Sdim  let Inst{7-4} = cc;
3577218893Sdim  let Inst{3-0} = mask;
3578226633Sdim
3579226633Sdim  let DecoderMethod = "DecodeIT";
3580201360Srdivacky}
3581198090Srdivacky
3582204642Srdivacky// Branch and Exchange Jazelle -- for disassembly only
3583204642Srdivacky// Rm = Inst{19-16}
3584263508Sdimdef t2BXJ : T2I<(outs), (ins rGPR:$func), NoItinerary, "bxj", "\t$func", []>,
3585263508Sdim    Sched<[WriteBr]> {
3586226633Sdim  bits<4> func;
3587204642Srdivacky  let Inst{31-27} = 0b11110;
3588204642Srdivacky  let Inst{26} = 0;
3589204642Srdivacky  let Inst{25-20} = 0b111100;
3590218893Sdim  let Inst{19-16} = func;
3591226633Sdim  let Inst{15-0} = 0b1000111100000000;
3592204642Srdivacky}
3593204642Srdivacky
3594226633Sdim// Compare and branch on zero / non-zero
3595226633Sdimlet isBranch = 1, isTerminator = 1 in {
3596226633Sdim  def tCBZ  : T1I<(outs), (ins tGPR:$Rn, t_cbtarget:$target), IIC_Br,
3597226633Sdim                  "cbz\t$Rn, $target", []>,
3598226633Sdim              T1Misc<{0,0,?,1,?,?,?}>,
3599263508Sdim              Requires<[IsThumb2]>, Sched<[WriteBr]> {
3600226633Sdim    // A8.6.27
3601226633Sdim    bits<6> target;
3602226633Sdim    bits<3> Rn;
3603226633Sdim    let Inst{9}   = target{5};
3604226633Sdim    let Inst{7-3} = target{4-0};
3605226633Sdim    let Inst{2-0} = Rn;
3606226633Sdim  }
3607226633Sdim
3608226633Sdim  def tCBNZ : T1I<(outs), (ins tGPR:$Rn, t_cbtarget:$target), IIC_Br,
3609226633Sdim                  "cbnz\t$Rn, $target", []>,
3610226633Sdim              T1Misc<{1,0,?,1,?,?,?}>,
3611263508Sdim              Requires<[IsThumb2]>, Sched<[WriteBr]> {
3612226633Sdim    // A8.6.27
3613226633Sdim    bits<6> target;
3614226633Sdim    bits<3> Rn;
3615226633Sdim    let Inst{9}   = target{5};
3616226633Sdim    let Inst{7-3} = target{4-0};
3617226633Sdim    let Inst{2-0} = Rn;
3618226633Sdim  }
3619226633Sdim}
3620226633Sdim
3621226633Sdim
3622226633Sdim// Change Processor State is a system instruction.
3623218893Sdim// FIXME: Since the asm parser has currently no clean way to handle optional
3624218893Sdim// operands, create 3 versions of the same instruction. Once there's a clean
3625218893Sdim// framework to represent optional operands, change this behavior.
3626218893Sdimclass t2CPS<dag iops, string asm_op> : T2XI<(outs), iops, NoItinerary,
3627226633Sdim            !strconcat("cps", asm_op), []> {
3628218893Sdim  bits<2> imod;
3629218893Sdim  bits<3> iflags;
3630218893Sdim  bits<5> mode;
3631218893Sdim  bit M;
3632218893Sdim
3633251662Sdim  let Inst{31-11} = 0b111100111010111110000;
3634218893Sdim  let Inst{10-9}  = imod;
3635218893Sdim  let Inst{8}     = M;
3636218893Sdim  let Inst{7-5}   = iflags;
3637218893Sdim  let Inst{4-0}   = mode;
3638226633Sdim  let DecoderMethod = "DecodeT2CPSInstruction";
3639204642Srdivacky}
3640204642Srdivacky
3641218893Sdimlet M = 1 in
3642218893Sdim  def t2CPS3p : t2CPS<(ins imod_op:$imod, iflags_op:$iflags, i32imm:$mode),
3643263508Sdim                      "$imod\t$iflags, $mode">;
3644218893Sdimlet mode = 0, M = 0 in
3645218893Sdim  def t2CPS2p : t2CPS<(ins imod_op:$imod, iflags_op:$iflags),
3646218893Sdim                      "$imod.w\t$iflags">;
3647218893Sdimlet imod = 0, iflags = 0, M = 1 in
3648226633Sdim  def t2CPS1p : t2CPS<(ins imm0_31:$mode), "\t$mode">;
3649218893Sdim
3650263508Sdimdef : t2InstAlias<"cps$imod.w $iflags, $mode",
3651263508Sdim                   (t2CPS3p imod_op:$imod, iflags_op:$iflags, i32imm:$mode), 0>;
3652263508Sdimdef : t2InstAlias<"cps.w $mode", (t2CPS1p imm0_31:$mode), 0>;
3653263508Sdim
3654204642Srdivacky// A6.3.4 Branches and miscellaneous control
3655204642Srdivacky// Table A6-14 Change Processor State, and hint instructions
3656263508Sdimdef t2HINT : T2I<(outs), (ins imm0_239:$imm), NoItinerary, "hint", ".w\t$imm",[]> {
3657263508Sdim  bits<8> imm;
3658251662Sdim  let Inst{31-3} = 0b11110011101011111000000000000;
3659263508Sdim  let Inst{7-0} = imm;
3660204642Srdivacky}
3661204642Srdivacky
3662263508Sdimdef : t2InstAlias<"hint$p $imm", (t2HINT imm0_239:$imm, pred:$p)>;
3663239462Sdimdef : t2InstAlias<"nop$p.w", (t2HINT 0, pred:$p)>;
3664239462Sdimdef : t2InstAlias<"yield$p.w", (t2HINT 1, pred:$p)>;
3665239462Sdimdef : t2InstAlias<"wfe$p.w", (t2HINT 2, pred:$p)>;
3666239462Sdimdef : t2InstAlias<"wfi$p.w", (t2HINT 3, pred:$p)>;
3667239462Sdimdef : t2InstAlias<"sev$p.w", (t2HINT 4, pred:$p)>;
3668263508Sdimdef : t2InstAlias<"sevl$p.w", (t2HINT 5, pred:$p)> {
3669263508Sdim  let Predicates = [IsThumb2, HasV8];
3670263508Sdim}
3671204642Srdivacky
3672224145Sdimdef t2DBG : T2I<(outs), (ins imm0_15:$opt), NoItinerary, "dbg", "\t$opt", []> {
3673226633Sdim  bits<4> opt;
3674226633Sdim  let Inst{31-20} = 0b111100111010;
3675226633Sdim  let Inst{19-16} = 0b1111;
3676226633Sdim  let Inst{15-8} = 0b10000000;
3677204642Srdivacky  let Inst{7-4} = 0b1111;
3678218893Sdim  let Inst{3-0} = opt;
3679204642Srdivacky}
3680204642Srdivacky
3681226633Sdim// Secure Monitor Call is a system instruction.
3682204642Srdivacky// Option = Inst{19-16}
3683251662Sdimdef t2SMC : T2I<(outs), (ins imm0_15:$opt), NoItinerary, "smc", "\t$opt", 
3684251662Sdim                []>, Requires<[IsThumb2, HasTrustZone]> {
3685204642Srdivacky  let Inst{31-27} = 0b11110;
3686204642Srdivacky  let Inst{26-20} = 0b1111111;
3687204642Srdivacky  let Inst{15-12} = 0b1000;
3688204642Srdivacky
3689218893Sdim  bits<4> opt;
3690218893Sdim  let Inst{19-16} = opt;
3691204642Srdivacky}
3692204642Srdivacky
3693263508Sdimclass T2DCPS<bits<2> opt, string opc>
3694263508Sdim  : T2I<(outs), (ins), NoItinerary, opc, "", []>, Requires<[IsThumb2, HasV8]> {
3695263508Sdim  let Inst{31-27} = 0b11110;
3696263508Sdim  let Inst{26-20} = 0b1111000;
3697263508Sdim  let Inst{19-16} = 0b1111;
3698263508Sdim  let Inst{15-12} = 0b1000;
3699263508Sdim  let Inst{11-2} = 0b0000000000;
3700263508Sdim  let Inst{1-0} = opt;
3701263508Sdim}
3702263508Sdim
3703263508Sdimdef t2DCPS1 : T2DCPS<0b01, "dcps1">;
3704263508Sdimdef t2DCPS2 : T2DCPS<0b10, "dcps2">;
3705263508Sdimdef t2DCPS3 : T2DCPS<0b11, "dcps3">;
3706263508Sdim
3707226633Sdimclass T2SRS<bits<2> Op, bit W, dag oops, dag iops, InstrItinClass itin,
3708226633Sdim            string opc, string asm, list<dag> pattern>
3709218893Sdim  : T2I<oops, iops, itin, opc, asm, pattern> {
3710218893Sdim  bits<5> mode;
3711226633Sdim  let Inst{31-25} = 0b1110100;
3712226633Sdim  let Inst{24-23} = Op;
3713226633Sdim  let Inst{22} = 0;
3714226633Sdim  let Inst{21} = W;
3715226633Sdim  let Inst{20-16} = 0b01101;
3716226633Sdim  let Inst{15-5} = 0b11000000000;
3717218893Sdim  let Inst{4-0} = mode{4-0};
3718204642Srdivacky}
3719204642Srdivacky
3720226633Sdim// Store Return State is a system instruction.
3721226633Sdimdef t2SRSDB_UPD : T2SRS<0b00, 1, (outs), (ins imm0_31:$mode), NoItinerary,
3722226633Sdim                        "srsdb", "\tsp!, $mode", []>;
3723226633Sdimdef t2SRSDB  : T2SRS<0b00, 0, (outs), (ins imm0_31:$mode), NoItinerary,
3724226633Sdim                     "srsdb","\tsp, $mode", []>;
3725226633Sdimdef t2SRSIA_UPD : T2SRS<0b11, 1, (outs), (ins imm0_31:$mode), NoItinerary,
3726226633Sdim                        "srsia","\tsp!, $mode", []>;
3727226633Sdimdef t2SRSIA  : T2SRS<0b11, 0, (outs), (ins imm0_31:$mode), NoItinerary,
3728226633Sdim                     "srsia","\tsp, $mode", []>;
3729204642Srdivacky
3730249423Sdim
3731249423Sdimdef : t2InstAlias<"srsdb${p} $mode", (t2SRSDB imm0_31:$mode, pred:$p)>;
3732249423Sdimdef : t2InstAlias<"srsdb${p} $mode!", (t2SRSDB_UPD imm0_31:$mode, pred:$p)>;
3733249423Sdim
3734249423Sdimdef : t2InstAlias<"srsia${p} $mode", (t2SRSIA imm0_31:$mode, pred:$p)>;
3735249423Sdimdef : t2InstAlias<"srsia${p} $mode!", (t2SRSIA_UPD imm0_31:$mode, pred:$p)>;
3736249423Sdim
3737226633Sdim// Return From Exception is a system instruction.
3738218893Sdimclass T2RFE<bits<12> op31_20, dag oops, dag iops, InstrItinClass itin,
3739218893Sdim          string opc, string asm, list<dag> pattern>
3740218893Sdim  : T2I<oops, iops, itin, opc, asm, pattern> {
3741218893Sdim  let Inst{31-20} = op31_20{11-0};
3742204642Srdivacky
3743218893Sdim  bits<4> Rn;
3744218893Sdim  let Inst{19-16} = Rn;
3745221345Sdim  let Inst{15-0} = 0xc000;
3746204642Srdivacky}
3747204642Srdivacky
3748218893Sdimdef t2RFEDBW : T2RFE<0b111010000011,
3749221345Sdim                   (outs), (ins GPR:$Rn), NoItinerary, "rfedb", "\t$Rn!",
3750218893Sdim                   [/* For disassembly only; pattern left blank */]>;
3751218893Sdimdef t2RFEDB  : T2RFE<0b111010000001,
3752221345Sdim                   (outs), (ins GPR:$Rn), NoItinerary, "rfedb", "\t$Rn",
3753218893Sdim                   [/* For disassembly only; pattern left blank */]>;
3754218893Sdimdef t2RFEIAW : T2RFE<0b111010011011,
3755221345Sdim                   (outs), (ins GPR:$Rn), NoItinerary, "rfeia", "\t$Rn!",
3756218893Sdim                   [/* For disassembly only; pattern left blank */]>;
3757218893Sdimdef t2RFEIA  : T2RFE<0b111010011001,
3758221345Sdim                   (outs), (ins GPR:$Rn), NoItinerary, "rfeia", "\t$Rn",
3759218893Sdim                   [/* For disassembly only; pattern left blank */]>;
3760204642Srdivacky
3761263508Sdim// B9.3.19 SUBS PC, LR, #imm (Thumb2) system instruction.
3762263508Sdim// Exception return instruction is "subs pc, lr, #imm".
3763263508Sdimlet isReturn = 1, isBarrier = 1, isTerminator = 1, Defs = [PC] in
3764263508Sdimdef t2SUBS_PC_LR : T2I <(outs), (ins imm0_255:$imm), NoItinerary,
3765263508Sdim                        "subs", "\tpc, lr, $imm",
3766263508Sdim                        [(ARMintretflag imm0_255:$imm)]>,
3767263508Sdim                   Requires<[IsThumb2]> {
3768263508Sdim  let Inst{31-8} = 0b111100111101111010001111;
3769263508Sdim
3770263508Sdim  bits<8> imm;
3771263508Sdim  let Inst{7-0} = imm;
3772263508Sdim}
3773263508Sdim
3774194754Sed//===----------------------------------------------------------------------===//
3775194754Sed// Non-Instruction Patterns
3776194754Sed//
3777194754Sed
3778198090Srdivacky// 32-bit immediate using movw + movt.
3779218893Sdim// This is a single pseudo instruction to make it re-materializable.
3780218893Sdim// FIXME: Remove this when we can do generalized remat.
3781218893Sdimlet isReMaterializable = 1, isMoveImm = 1 in
3782218893Sdimdef t2MOVi32imm : PseudoInst<(outs rGPR:$dst), (ins i32imm:$src), IIC_iMOVix2,
3783218893Sdim                            [(set rGPR:$dst, (i32 imm:$src))]>,
3784218893Sdim                            Requires<[IsThumb, HasV6T2]>;
3785199481Srdivacky
3786218893Sdim// Pseudo instruction that combines movw + movt + add pc (if pic).
3787218893Sdim// It also makes it possible to rematerialize the instructions.
3788218893Sdim// FIXME: Remove this when we can do generalized remat and when machine licm
3789218893Sdim// can properly the instructions.
3790218893Sdimlet isReMaterializable = 1 in {
3791218893Sdimdef t2MOV_ga_pcrel : PseudoInst<(outs rGPR:$dst), (ins i32imm:$addr),
3792218893Sdim                                IIC_iMOVix2addpc,
3793218893Sdim                          [(set rGPR:$dst, (ARMWrapperPIC tglobaladdr:$addr))]>,
3794218893Sdim                          Requires<[IsThumb2, UseMovt]>;
3795218893Sdim
3796218893Sdimdef t2MOV_ga_dyn : PseudoInst<(outs rGPR:$dst), (ins i32imm:$addr),
3797218893Sdim                              IIC_iMOVix2,
3798218893Sdim                          [(set rGPR:$dst, (ARMWrapperDYN tglobaladdr:$addr))]>,
3799218893Sdim                          Requires<[IsThumb2, UseMovt]>;
3800218893Sdim}
3801218893Sdim
3802199989Srdivacky// ConstantPool, GlobalAddress, and JumpTable
3803199989Srdivackydef : T2Pat<(ARMWrapper  tglobaladdr :$dst), (t2LEApcrel tglobaladdr :$dst)>,
3804199989Srdivacky           Requires<[IsThumb2, DontUseMovt]>;
3805199989Srdivackydef : T2Pat<(ARMWrapper  tconstpool  :$dst), (t2LEApcrel tconstpool  :$dst)>;
3806199989Srdivackydef : T2Pat<(ARMWrapper  tglobaladdr :$dst), (t2MOVi32imm tglobaladdr :$dst)>,
3807199989Srdivacky           Requires<[IsThumb2, UseMovt]>;
3808199989Srdivacky
3809199989Srdivackydef : T2Pat<(ARMWrapperJT tjumptable:$dst, imm:$id),
3810199989Srdivacky            (t2LEApcrelJT tjumptable:$dst, imm:$id)>;
3811199989Srdivacky
3812199481Srdivacky// Pseudo instruction that combines ldr from constpool and add pc. This should
3813199481Srdivacky// be expanded into two instructions late to allow if-conversion and
3814199481Srdivacky// scheduling.
3815204642Srdivackylet canFoldAsLoad = 1, isReMaterializable = 1 in
3816218893Sdimdef t2LDRpci_pic : PseudoInst<(outs rGPR:$dst), (ins i32imm:$addr, pclabel:$cp),
3817218893Sdim                   IIC_iLoadiALU,
3818218893Sdim              [(set rGPR:$dst, (ARMpic_add (load (ARMWrapper tconstpool:$addr)),
3819199481Srdivacky                                           imm:$cp))]>,
3820199481Srdivacky               Requires<[IsThumb2]>;
3821204642Srdivacky
3822234353Sdim// Pseudo isntruction that combines movs + predicated rsbmi
3823226633Sdim// to implement integer ABS
3824226633Sdimlet usesCustomInserter = 1, Defs = [CPSR] in {
3825226633Sdimdef t2ABS : PseudoInst<(outs rGPR:$dst), (ins rGPR:$src),
3826226633Sdim                       NoItinerary, []>, Requires<[IsThumb2]>;
3827226633Sdim}
3828226633Sdim
3829204642Srdivacky//===----------------------------------------------------------------------===//
3830226633Sdim// Coprocessor load/store -- for disassembly only
3831226633Sdim//
3832226633Sdimclass T2CI<bits<4> op31_28, dag oops, dag iops, string opc, string asm>
3833226633Sdim  : T2I<oops, iops, NoItinerary, opc, asm, []> {
3834226633Sdim  let Inst{31-28} = op31_28;
3835226633Sdim  let Inst{27-25} = 0b110;
3836226633Sdim}
3837226633Sdim
3838226633Sdimmulticlass t2LdStCop<bits<4> op31_28, bit load, bit Dbit, string asm> {
3839226633Sdim  def _OFFSET : T2CI<op31_28,
3840226633Sdim                     (outs), (ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr),
3841226633Sdim                     asm, "\t$cop, $CRd, $addr"> {
3842226633Sdim    bits<13> addr;
3843226633Sdim    bits<4> cop;
3844226633Sdim    bits<4> CRd;
3845226633Sdim    let Inst{24} = 1; // P = 1
3846226633Sdim    let Inst{23} = addr{8};
3847226633Sdim    let Inst{22} = Dbit;
3848226633Sdim    let Inst{21} = 0; // W = 0
3849226633Sdim    let Inst{20} = load;
3850226633Sdim    let Inst{19-16} = addr{12-9};
3851226633Sdim    let Inst{15-12} = CRd;
3852226633Sdim    let Inst{11-8} = cop;
3853226633Sdim    let Inst{7-0} = addr{7-0};
3854226633Sdim    let DecoderMethod = "DecodeCopMemInstruction";
3855226633Sdim  }
3856226633Sdim  def _PRE : T2CI<op31_28,
3857263508Sdim                  (outs), (ins p_imm:$cop, c_imm:$CRd, addrmode5_pre:$addr),
3858226633Sdim                  asm, "\t$cop, $CRd, $addr!"> {
3859226633Sdim    bits<13> addr;
3860226633Sdim    bits<4> cop;
3861226633Sdim    bits<4> CRd;
3862226633Sdim    let Inst{24} = 1; // P = 1
3863226633Sdim    let Inst{23} = addr{8};
3864226633Sdim    let Inst{22} = Dbit;
3865226633Sdim    let Inst{21} = 1; // W = 1
3866226633Sdim    let Inst{20} = load;
3867226633Sdim    let Inst{19-16} = addr{12-9};
3868226633Sdim    let Inst{15-12} = CRd;
3869226633Sdim    let Inst{11-8} = cop;
3870226633Sdim    let Inst{7-0} = addr{7-0};
3871226633Sdim    let DecoderMethod = "DecodeCopMemInstruction";
3872226633Sdim  }
3873226633Sdim  def _POST: T2CI<op31_28,
3874226633Sdim                  (outs), (ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr,
3875226633Sdim                               postidx_imm8s4:$offset),
3876226633Sdim                 asm, "\t$cop, $CRd, $addr, $offset"> {
3877226633Sdim    bits<9> offset;
3878226633Sdim    bits<4> addr;
3879226633Sdim    bits<4> cop;
3880226633Sdim    bits<4> CRd;
3881226633Sdim    let Inst{24} = 0; // P = 0
3882226633Sdim    let Inst{23} = offset{8};
3883226633Sdim    let Inst{22} = Dbit;
3884226633Sdim    let Inst{21} = 1; // W = 1
3885226633Sdim    let Inst{20} = load;
3886226633Sdim    let Inst{19-16} = addr;
3887226633Sdim    let Inst{15-12} = CRd;
3888226633Sdim    let Inst{11-8} = cop;
3889226633Sdim    let Inst{7-0} = offset{7-0};
3890226633Sdim    let DecoderMethod = "DecodeCopMemInstruction";
3891226633Sdim  }
3892226633Sdim  def _OPTION : T2CI<op31_28, (outs),
3893226633Sdim                     (ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr,
3894226633Sdim                          coproc_option_imm:$option),
3895226633Sdim      asm, "\t$cop, $CRd, $addr, $option"> {
3896226633Sdim    bits<8> option;
3897226633Sdim    bits<4> addr;
3898226633Sdim    bits<4> cop;
3899226633Sdim    bits<4> CRd;
3900226633Sdim    let Inst{24} = 0; // P = 0
3901226633Sdim    let Inst{23} = 1; // U = 1
3902226633Sdim    let Inst{22} = Dbit;
3903226633Sdim    let Inst{21} = 0; // W = 0
3904226633Sdim    let Inst{20} = load;
3905226633Sdim    let Inst{19-16} = addr;
3906226633Sdim    let Inst{15-12} = CRd;
3907226633Sdim    let Inst{11-8} = cop;
3908226633Sdim    let Inst{7-0} = option;
3909226633Sdim    let DecoderMethod = "DecodeCopMemInstruction";
3910226633Sdim  }
3911226633Sdim}
3912226633Sdim
3913226633Sdimdefm t2LDC   : t2LdStCop<0b1110, 1, 0, "ldc">;
3914226633Sdimdefm t2LDCL  : t2LdStCop<0b1110, 1, 1, "ldcl">;
3915226633Sdimdefm t2STC   : t2LdStCop<0b1110, 0, 0, "stc">;
3916226633Sdimdefm t2STCL  : t2LdStCop<0b1110, 0, 1, "stcl">;
3917263508Sdimdefm t2LDC2  : t2LdStCop<0b1111, 1, 0, "ldc2">, Requires<[PreV8]>;
3918263508Sdimdefm t2LDC2L : t2LdStCop<0b1111, 1, 1, "ldc2l">, Requires<[PreV8]>;
3919263508Sdimdefm t2STC2  : t2LdStCop<0b1111, 0, 0, "stc2">, Requires<[PreV8]>;
3920263508Sdimdefm t2STC2L : t2LdStCop<0b1111, 0, 1, "stc2l">, Requires<[PreV8]>;
3921226633Sdim
3922226633Sdim
3923226633Sdim//===----------------------------------------------------------------------===//
3924204642Srdivacky// Move between special register and ARM core register -- for disassembly only
3925204642Srdivacky//
3926226633Sdim// Move to ARM core register from Special Register
3927204642Srdivacky
3928226633Sdim// A/R class MRS.
3929226633Sdim//
3930226633Sdim// A/R class can only move from CPSR or SPSR.
3931239462Sdimdef t2MRS_AR : T2I<(outs GPR:$Rd), (ins), NoItinerary, "mrs", "\t$Rd, apsr",
3932263508Sdim                  []>, Requires<[IsThumb2,IsNotMClass]> {
3933226633Sdim  bits<4> Rd;
3934226633Sdim  let Inst{31-12} = 0b11110011111011111000;
3935226633Sdim  let Inst{11-8} = Rd;
3936226633Sdim  let Inst{7-0} = 0b0000;
3937204642Srdivacky}
3938204642Srdivacky
3939226633Sdimdef : t2InstAlias<"mrs${p} $Rd, cpsr", (t2MRS_AR GPR:$Rd, pred:$p)>;
3940226633Sdim
3941239462Sdimdef t2MRSsys_AR: T2I<(outs GPR:$Rd), (ins), NoItinerary, "mrs", "\t$Rd, spsr",
3942263508Sdim                   []>, Requires<[IsThumb2,IsNotMClass]> {
3943218893Sdim  bits<4> Rd;
3944226633Sdim  let Inst{31-12} = 0b11110011111111111000;
3945218893Sdim  let Inst{11-8} = Rd;
3946226633Sdim  let Inst{7-0} = 0b0000;
3947226633Sdim}
3948226633Sdim
3949226633Sdim// M class MRS.
3950226633Sdim//
3951226633Sdim// This MRS has a mask field in bits 7-0 and can take more values than
3952226633Sdim// the A/R class (a full msr_mask).
3953226633Sdimdef t2MRS_M : T2I<(outs rGPR:$Rd), (ins msr_mask:$mask), NoItinerary,
3954226633Sdim                  "mrs", "\t$Rd, $mask", []>,
3955239462Sdim              Requires<[IsThumb,IsMClass]> {
3956226633Sdim  bits<4> Rd;
3957226633Sdim  bits<8> mask;
3958226633Sdim  let Inst{31-12} = 0b11110011111011111000;
3959226633Sdim  let Inst{11-8} = Rd;
3960218893Sdim  let Inst{19-16} = 0b1111;
3961226633Sdim  let Inst{7-0} = mask;
3962204642Srdivacky}
3963204642Srdivacky
3964218893Sdim
3965218893Sdim// Move from ARM core register to Special Register
3966218893Sdim//
3967226633Sdim// A/R class MSR.
3968226633Sdim//
3969218893Sdim// No need to have both system and application versions, the encodings are the
3970218893Sdim// same and the assembly parser has no way to distinguish between them. The mask
3971218893Sdim// operand contains the special register (R Bit) in bit 4 and bits 3-0 contains
3972218893Sdim// the mask with the fields to be accessed in the special register.
3973226633Sdimdef t2MSR_AR : T2I<(outs), (ins msr_mask:$mask, rGPR:$Rn),
3974226633Sdim                   NoItinerary, "msr", "\t$mask, $Rn", []>,
3975263508Sdim               Requires<[IsThumb2,IsNotMClass]> {
3976218893Sdim  bits<5> mask;
3977218893Sdim  bits<4> Rn;
3978226633Sdim  let Inst{31-21} = 0b11110011100;
3979226633Sdim  let Inst{20}    = mask{4}; // R Bit
3980218893Sdim  let Inst{19-16} = Rn;
3981226633Sdim  let Inst{15-12} = 0b1000;
3982218893Sdim  let Inst{11-8}  = mask{3-0};
3983226633Sdim  let Inst{7-0}   = 0;
3984204642Srdivacky}
3985204642Srdivacky
3986226633Sdim// M class MSR.
3987226633Sdim//
3988226633Sdim// Move from ARM core register to Special Register
3989226633Sdimdef t2MSR_M : T2I<(outs), (ins msr_mask:$SYSm, rGPR:$Rn),
3990226633Sdim                  NoItinerary, "msr", "\t$SYSm, $Rn", []>,
3991239462Sdim              Requires<[IsThumb,IsMClass]> {
3992239462Sdim  bits<12> SYSm;
3993226633Sdim  bits<4> Rn;
3994226633Sdim  let Inst{31-21} = 0b11110011100;
3995226633Sdim  let Inst{20}    = 0b0;
3996226633Sdim  let Inst{19-16} = Rn;
3997226633Sdim  let Inst{15-12} = 0b1000;
3998239462Sdim  let Inst{11-0}  = SYSm;
3999226633Sdim}
4000226633Sdim
4001226633Sdim
4002218893Sdim//===----------------------------------------------------------------------===//
4003224145Sdim// Move between coprocessor and ARM core register
4004218893Sdim//
4005218893Sdim
4006224145Sdimclass t2MovRCopro<bits<4> Op, string opc, bit direction, dag oops, dag iops,
4007223017Sdim                  list<dag> pattern>
4008263508Sdim  : T2Cop<Op, oops, iops, opc, "\t$cop, $opc1, $Rt, $CRn, $CRm, $opc2",
4009223017Sdim          pattern> {
4010218893Sdim  let Inst{27-24} = 0b1110;
4011218893Sdim  let Inst{20} = direction;
4012218893Sdim  let Inst{4} = 1;
4013218893Sdim
4014218893Sdim  bits<4> Rt;
4015218893Sdim  bits<4> cop;
4016218893Sdim  bits<3> opc1;
4017218893Sdim  bits<3> opc2;
4018218893Sdim  bits<4> CRm;
4019218893Sdim  bits<4> CRn;
4020218893Sdim
4021218893Sdim  let Inst{15-12} = Rt;
4022218893Sdim  let Inst{11-8}  = cop;
4023218893Sdim  let Inst{23-21} = opc1;
4024218893Sdim  let Inst{7-5}   = opc2;
4025218893Sdim  let Inst{3-0}   = CRm;
4026218893Sdim  let Inst{19-16} = CRn;
4027218893Sdim}
4028218893Sdim
4029224145Sdimclass t2MovRRCopro<bits<4> Op, string opc, bit direction,
4030224145Sdim                   list<dag> pattern = []>
4031224145Sdim  : T2Cop<Op, (outs),
4032224145Sdim          (ins p_imm:$cop, imm0_15:$opc1, GPR:$Rt, GPR:$Rt2, c_imm:$CRm),
4033263508Sdim          opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm", pattern> {
4034218893Sdim  let Inst{27-24} = 0b1100;
4035218893Sdim  let Inst{23-21} = 0b010;
4036218893Sdim  let Inst{20} = direction;
4037218893Sdim
4038218893Sdim  bits<4> Rt;
4039218893Sdim  bits<4> Rt2;
4040218893Sdim  bits<4> cop;
4041218893Sdim  bits<4> opc1;
4042218893Sdim  bits<4> CRm;
4043218893Sdim
4044218893Sdim  let Inst{15-12} = Rt;
4045218893Sdim  let Inst{19-16} = Rt2;
4046218893Sdim  let Inst{11-8}  = cop;
4047218893Sdim  let Inst{7-4}   = opc1;
4048218893Sdim  let Inst{3-0}   = CRm;
4049218893Sdim}
4050218893Sdim
4051224145Sdim/* from ARM core register to coprocessor */
4052224145Sdimdef t2MCR : t2MovRCopro<0b1110, "mcr", 0,
4053224145Sdim           (outs),
4054224145Sdim           (ins p_imm:$cop, imm0_7:$opc1, GPR:$Rt, c_imm:$CRn,
4055224145Sdim                c_imm:$CRm, imm0_7:$opc2),
4056224145Sdim           [(int_arm_mcr imm:$cop, imm:$opc1, GPR:$Rt, imm:$CRn,
4057263508Sdim                         imm:$CRm, imm:$opc2)]>,
4058263508Sdim           ComplexDeprecationPredicate<"MCR">;
4059263508Sdimdef : t2InstAlias<"mcr${p} $cop, $opc1, $Rt, $CRn, $CRm",
4060234353Sdim                  (t2MCR p_imm:$cop, imm0_7:$opc1, GPR:$Rt, c_imm:$CRn,
4061263508Sdim                         c_imm:$CRm, 0, pred:$p)>;
4062224145Sdimdef t2MCR2 : t2MovRCopro<0b1111, "mcr2", 0,
4063224145Sdim             (outs), (ins p_imm:$cop, imm0_7:$opc1, GPR:$Rt, c_imm:$CRn,
4064224145Sdim                          c_imm:$CRm, imm0_7:$opc2),
4065224145Sdim             [(int_arm_mcr2 imm:$cop, imm:$opc1, GPR:$Rt, imm:$CRn,
4066263508Sdim                            imm:$CRm, imm:$opc2)]> {
4067263508Sdim  let Predicates = [IsThumb2, PreV8];
4068263508Sdim}
4069263508Sdimdef : t2InstAlias<"mcr2${p} $cop, $opc1, $Rt, $CRn, $CRm",
4070234353Sdim                  (t2MCR2 p_imm:$cop, imm0_7:$opc1, GPR:$Rt, c_imm:$CRn,
4071263508Sdim                          c_imm:$CRm, 0, pred:$p)>;
4072224145Sdim
4073224145Sdim/* from coprocessor to ARM core register */
4074224145Sdimdef t2MRC : t2MovRCopro<0b1110, "mrc", 1,
4075263508Sdim             (outs GPRwithAPSR:$Rt), (ins p_imm:$cop, imm0_7:$opc1, c_imm:$CRn,
4076226633Sdim                                  c_imm:$CRm, imm0_7:$opc2), []>;
4077263508Sdimdef : t2InstAlias<"mrc${p} $cop, $opc1, $Rt, $CRn, $CRm",
4078263508Sdim                  (t2MRC GPRwithAPSR:$Rt, p_imm:$cop, imm0_7:$opc1, c_imm:$CRn,
4079263508Sdim                         c_imm:$CRm, 0, pred:$p)>;
4080224145Sdim
4081224145Sdimdef t2MRC2 : t2MovRCopro<0b1111, "mrc2", 1,
4082263508Sdim             (outs GPRwithAPSR:$Rt), (ins p_imm:$cop, imm0_7:$opc1, c_imm:$CRn,
4083263508Sdim                                  c_imm:$CRm, imm0_7:$opc2), []> {
4084263508Sdim  let Predicates = [IsThumb2, PreV8];
4085263508Sdim}
4086263508Sdimdef : t2InstAlias<"mrc2${p} $cop, $opc1, $Rt, $CRn, $CRm",
4087263508Sdim                  (t2MRC2 GPRwithAPSR:$Rt, p_imm:$cop, imm0_7:$opc1, c_imm:$CRn,
4088263508Sdim                          c_imm:$CRm, 0, pred:$p)>;
4089224145Sdim
4090224145Sdimdef : T2v6Pat<(int_arm_mrc  imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2),
4091224145Sdim              (t2MRC imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2)>;
4092224145Sdim
4093224145Sdimdef : T2v6Pat<(int_arm_mrc2 imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2),
4094224145Sdim              (t2MRC2 imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2)>;
4095224145Sdim
4096224145Sdim
4097224145Sdim/* from ARM core register to coprocessor */
4098224145Sdimdef t2MCRR : t2MovRRCopro<0b1110, "mcrr", 0,
4099224145Sdim                        [(int_arm_mcrr imm:$cop, imm:$opc1, GPR:$Rt, GPR:$Rt2,
4100224145Sdim                                       imm:$CRm)]>;
4101224145Sdimdef t2MCRR2 : t2MovRRCopro<0b1111, "mcrr2", 0,
4102223017Sdim                           [(int_arm_mcrr2 imm:$cop, imm:$opc1, GPR:$Rt,
4103263508Sdim                                           GPR:$Rt2, imm:$CRm)]> {
4104263508Sdim  let Predicates = [IsThumb2, PreV8];
4105263508Sdim}
4106263508Sdim
4107224145Sdim/* from coprocessor to ARM core register */
4108224145Sdimdef t2MRRC : t2MovRRCopro<0b1110, "mrrc", 1>;
4109218893Sdim
4110263508Sdimdef t2MRRC2 : t2MovRRCopro<0b1111, "mrrc2", 1> {
4111263508Sdim  let Predicates = [IsThumb2, PreV8];
4112263508Sdim}
4113224145Sdim
4114218893Sdim//===----------------------------------------------------------------------===//
4115224145Sdim// Other Coprocessor Instructions.
4116218893Sdim//
4117218893Sdim
4118263508Sdimdef t2CDP : T2Cop<0b1110, (outs), (ins p_imm:$cop, imm0_15:$opc1,
4119224145Sdim                 c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, imm0_7:$opc2),
4120263508Sdim                 "cdp", "\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2",
4121224145Sdim                 [(int_arm_cdp imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn,
4122224145Sdim                               imm:$CRm, imm:$opc2)]> {
4123224145Sdim  let Inst{27-24} = 0b1110;
4124224145Sdim
4125224145Sdim  bits<4> opc1;
4126224145Sdim  bits<4> CRn;
4127224145Sdim  bits<4> CRd;
4128224145Sdim  bits<4> cop;
4129224145Sdim  bits<3> opc2;
4130224145Sdim  bits<4> CRm;
4131224145Sdim
4132224145Sdim  let Inst{3-0}   = CRm;
4133224145Sdim  let Inst{4}     = 0;
4134224145Sdim  let Inst{7-5}   = opc2;
4135224145Sdim  let Inst{11-8}  = cop;
4136224145Sdim  let Inst{15-12} = CRd;
4137224145Sdim  let Inst{19-16} = CRn;
4138224145Sdim  let Inst{23-20} = opc1;
4139263508Sdim
4140263508Sdim  let Predicates = [IsThumb2, PreV8];
4141224145Sdim}
4142224145Sdim
4143224145Sdimdef t2CDP2 : T2Cop<0b1111, (outs), (ins p_imm:$cop, imm0_15:$opc1,
4144224145Sdim                   c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, imm0_7:$opc2),
4145263508Sdim                   "cdp2", "\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2",
4146223017Sdim                   [(int_arm_cdp2 imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn,
4147223017Sdim                                  imm:$CRm, imm:$opc2)]> {
4148218893Sdim  let Inst{27-24} = 0b1110;
4149218893Sdim
4150218893Sdim  bits<4> opc1;
4151218893Sdim  bits<4> CRn;
4152218893Sdim  bits<4> CRd;
4153218893Sdim  bits<4> cop;
4154218893Sdim  bits<3> opc2;
4155218893Sdim  bits<4> CRm;
4156218893Sdim
4157218893Sdim  let Inst{3-0}   = CRm;
4158218893Sdim  let Inst{4}     = 0;
4159218893Sdim  let Inst{7-5}   = opc2;
4160218893Sdim  let Inst{11-8}  = cop;
4161218893Sdim  let Inst{15-12} = CRd;
4162218893Sdim  let Inst{19-16} = CRn;
4163218893Sdim  let Inst{23-20} = opc1;
4164263508Sdim
4165263508Sdim  let Predicates = [IsThumb2, PreV8];
4166204642Srdivacky}
4167226633Sdim
4168226633Sdim
4169226633Sdim
4170226633Sdim//===----------------------------------------------------------------------===//
4171226633Sdim// Non-Instruction Patterns
4172226633Sdim//
4173226633Sdim
4174226633Sdim// SXT/UXT with no rotate
4175226633Sdimlet AddedComplexity = 16 in {
4176226633Sdimdef : T2Pat<(and rGPR:$Rm, 0x000000FF), (t2UXTB rGPR:$Rm, 0)>,
4177226633Sdim           Requires<[IsThumb2]>;
4178226633Sdimdef : T2Pat<(and rGPR:$Rm, 0x0000FFFF), (t2UXTH rGPR:$Rm, 0)>,
4179226633Sdim           Requires<[IsThumb2]>;
4180226633Sdimdef : T2Pat<(and rGPR:$Rm, 0x00FF00FF), (t2UXTB16 rGPR:$Rm, 0)>,
4181226633Sdim           Requires<[HasT2ExtractPack, IsThumb2]>;
4182226633Sdimdef : T2Pat<(add rGPR:$Rn, (and rGPR:$Rm, 0x00FF)),
4183226633Sdim            (t2UXTAB rGPR:$Rn, rGPR:$Rm, 0)>,
4184226633Sdim           Requires<[HasT2ExtractPack, IsThumb2]>;
4185226633Sdimdef : T2Pat<(add rGPR:$Rn, (and rGPR:$Rm, 0xFFFF)),
4186226633Sdim            (t2UXTAH rGPR:$Rn, rGPR:$Rm, 0)>,
4187226633Sdim           Requires<[HasT2ExtractPack, IsThumb2]>;
4188226633Sdim}
4189226633Sdim
4190226633Sdimdef : T2Pat<(sext_inreg rGPR:$Src, i8),  (t2SXTB rGPR:$Src, 0)>,
4191226633Sdim           Requires<[IsThumb2]>;
4192226633Sdimdef : T2Pat<(sext_inreg rGPR:$Src, i16), (t2SXTH rGPR:$Src, 0)>,
4193226633Sdim           Requires<[IsThumb2]>;
4194226633Sdimdef : T2Pat<(add rGPR:$Rn, (sext_inreg rGPR:$Rm, i8)),
4195226633Sdim            (t2SXTAB rGPR:$Rn, rGPR:$Rm, 0)>,
4196226633Sdim           Requires<[HasT2ExtractPack, IsThumb2]>;
4197226633Sdimdef : T2Pat<(add rGPR:$Rn, (sext_inreg rGPR:$Rm, i16)),
4198226633Sdim            (t2SXTAH rGPR:$Rn, rGPR:$Rm, 0)>,
4199226633Sdim           Requires<[HasT2ExtractPack, IsThumb2]>;
4200226633Sdim
4201226633Sdim// Atomic load/store patterns
4202226633Sdimdef : T2Pat<(atomic_load_8   t2addrmode_imm12:$addr),
4203226633Sdim            (t2LDRBi12  t2addrmode_imm12:$addr)>;
4204226633Sdimdef : T2Pat<(atomic_load_8   t2addrmode_negimm8:$addr),
4205226633Sdim            (t2LDRBi8   t2addrmode_negimm8:$addr)>;
4206226633Sdimdef : T2Pat<(atomic_load_8   t2addrmode_so_reg:$addr),
4207226633Sdim            (t2LDRBs    t2addrmode_so_reg:$addr)>;
4208226633Sdimdef : T2Pat<(atomic_load_16  t2addrmode_imm12:$addr),
4209226633Sdim            (t2LDRHi12  t2addrmode_imm12:$addr)>;
4210226633Sdimdef : T2Pat<(atomic_load_16  t2addrmode_negimm8:$addr),
4211226633Sdim            (t2LDRHi8   t2addrmode_negimm8:$addr)>;
4212226633Sdimdef : T2Pat<(atomic_load_16  t2addrmode_so_reg:$addr),
4213226633Sdim            (t2LDRHs    t2addrmode_so_reg:$addr)>;
4214226633Sdimdef : T2Pat<(atomic_load_32  t2addrmode_imm12:$addr),
4215226633Sdim            (t2LDRi12   t2addrmode_imm12:$addr)>;
4216226633Sdimdef : T2Pat<(atomic_load_32  t2addrmode_negimm8:$addr),
4217226633Sdim            (t2LDRi8    t2addrmode_negimm8:$addr)>;
4218226633Sdimdef : T2Pat<(atomic_load_32  t2addrmode_so_reg:$addr),
4219226633Sdim            (t2LDRs     t2addrmode_so_reg:$addr)>;
4220226633Sdimdef : T2Pat<(atomic_store_8  t2addrmode_imm12:$addr, GPR:$val),
4221226633Sdim            (t2STRBi12  GPR:$val, t2addrmode_imm12:$addr)>;
4222226633Sdimdef : T2Pat<(atomic_store_8  t2addrmode_negimm8:$addr, GPR:$val),
4223226633Sdim            (t2STRBi8   GPR:$val, t2addrmode_negimm8:$addr)>;
4224226633Sdimdef : T2Pat<(atomic_store_8  t2addrmode_so_reg:$addr, GPR:$val),
4225226633Sdim            (t2STRBs    GPR:$val, t2addrmode_so_reg:$addr)>;
4226226633Sdimdef : T2Pat<(atomic_store_16 t2addrmode_imm12:$addr, GPR:$val),
4227226633Sdim            (t2STRHi12  GPR:$val, t2addrmode_imm12:$addr)>;
4228226633Sdimdef : T2Pat<(atomic_store_16 t2addrmode_negimm8:$addr, GPR:$val),
4229226633Sdim            (t2STRHi8   GPR:$val, t2addrmode_negimm8:$addr)>;
4230226633Sdimdef : T2Pat<(atomic_store_16 t2addrmode_so_reg:$addr, GPR:$val),
4231226633Sdim            (t2STRHs    GPR:$val, t2addrmode_so_reg:$addr)>;
4232226633Sdimdef : T2Pat<(atomic_store_32 t2addrmode_imm12:$addr, GPR:$val),
4233226633Sdim            (t2STRi12   GPR:$val, t2addrmode_imm12:$addr)>;
4234226633Sdimdef : T2Pat<(atomic_store_32 t2addrmode_negimm8:$addr, GPR:$val),
4235226633Sdim            (t2STRi8    GPR:$val, t2addrmode_negimm8:$addr)>;
4236226633Sdimdef : T2Pat<(atomic_store_32 t2addrmode_so_reg:$addr, GPR:$val),
4237226633Sdim            (t2STRs     GPR:$val, t2addrmode_so_reg:$addr)>;
4238226633Sdim
4239263508Sdimlet AddedComplexity = 8 in {
4240263508Sdim  def : T2Pat<(atomic_load_acquire_8 addr_offset_none:$addr),  (t2LDAB addr_offset_none:$addr)>;
4241263508Sdim  def : T2Pat<(atomic_load_acquire_16 addr_offset_none:$addr), (t2LDAH addr_offset_none:$addr)>;
4242263508Sdim  def : T2Pat<(atomic_load_acquire_32 addr_offset_none:$addr), (t2LDA  addr_offset_none:$addr)>;
4243263508Sdim  def : T2Pat<(atomic_store_release_8 addr_offset_none:$addr, GPR:$val),  (t2STLB GPR:$val, addr_offset_none:$addr)>;
4244263508Sdim  def : T2Pat<(atomic_store_release_16 addr_offset_none:$addr, GPR:$val), (t2STLH GPR:$val, addr_offset_none:$addr)>;
4245263508Sdim  def : T2Pat<(atomic_store_release_32 addr_offset_none:$addr, GPR:$val), (t2STL  GPR:$val, addr_offset_none:$addr)>;
4246263508Sdim}
4247226633Sdim
4248263508Sdim
4249226633Sdim//===----------------------------------------------------------------------===//
4250226633Sdim// Assembler aliases
4251226633Sdim//
4252226633Sdim
4253226633Sdim// Aliases for ADC without the ".w" optional width specifier.
4254226633Sdimdef : t2InstAlias<"adc${s}${p} $Rd, $Rn, $Rm",
4255226633Sdim                  (t2ADCrr rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, pred:$p, cc_out:$s)>;
4256226633Sdimdef : t2InstAlias<"adc${s}${p} $Rd, $Rn, $ShiftedRm",
4257226633Sdim                  (t2ADCrs rGPR:$Rd, rGPR:$Rn, t2_so_reg:$ShiftedRm,
4258226633Sdim                           pred:$p, cc_out:$s)>;
4259226633Sdim
4260226633Sdim// Aliases for SBC without the ".w" optional width specifier.
4261226633Sdimdef : t2InstAlias<"sbc${s}${p} $Rd, $Rn, $Rm",
4262226633Sdim                  (t2SBCrr rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, pred:$p, cc_out:$s)>;
4263226633Sdimdef : t2InstAlias<"sbc${s}${p} $Rd, $Rn, $ShiftedRm",
4264226633Sdim                  (t2SBCrs rGPR:$Rd, rGPR:$Rn, t2_so_reg:$ShiftedRm,
4265226633Sdim                           pred:$p, cc_out:$s)>;
4266226633Sdim
4267226633Sdim// Aliases for ADD without the ".w" optional width specifier.
4268226633Sdimdef : t2InstAlias<"add${s}${p} $Rd, $Rn, $imm",
4269263508Sdim        (t2ADDri GPRnopc:$Rd, GPRnopc:$Rn, t2_so_imm:$imm, pred:$p, 
4270263508Sdim         cc_out:$s)>;
4271226633Sdimdef : t2InstAlias<"add${p} $Rd, $Rn, $imm",
4272226633Sdim           (t2ADDri12 GPRnopc:$Rd, GPR:$Rn, imm0_4095:$imm, pred:$p)>;
4273226633Sdimdef : t2InstAlias<"add${s}${p} $Rd, $Rn, $Rm",
4274226633Sdim              (t2ADDrr GPRnopc:$Rd, GPRnopc:$Rn, rGPR:$Rm, pred:$p, cc_out:$s)>;
4275226633Sdimdef : t2InstAlias<"add${s}${p} $Rd, $Rn, $ShiftedRm",
4276226633Sdim                  (t2ADDrs GPRnopc:$Rd, GPRnopc:$Rn, t2_so_reg:$ShiftedRm,
4277226633Sdim                           pred:$p, cc_out:$s)>;
4278234353Sdim// ... and with the destination and source register combined.
4279234353Sdimdef : t2InstAlias<"add${s}${p} $Rdn, $imm",
4280234353Sdim      (t2ADDri GPRnopc:$Rdn, GPRnopc:$Rdn, t2_so_imm:$imm, pred:$p, cc_out:$s)>;
4281234353Sdimdef : t2InstAlias<"add${p} $Rdn, $imm",
4282234353Sdim           (t2ADDri12 GPRnopc:$Rdn, GPRnopc:$Rdn, imm0_4095:$imm, pred:$p)>;
4283234353Sdimdef : t2InstAlias<"add${s}${p} $Rdn, $Rm",
4284234353Sdim            (t2ADDrr GPRnopc:$Rdn, GPRnopc:$Rdn, rGPR:$Rm, pred:$p, cc_out:$s)>;
4285234353Sdimdef : t2InstAlias<"add${s}${p} $Rdn, $ShiftedRm",
4286234353Sdim                  (t2ADDrs GPRnopc:$Rdn, GPRnopc:$Rdn, t2_so_reg:$ShiftedRm,
4287234353Sdim                           pred:$p, cc_out:$s)>;
4288226633Sdim
4289234353Sdim// add w/ negative immediates is just a sub.
4290234353Sdimdef : t2InstAlias<"add${s}${p} $Rd, $Rn, $imm",
4291234353Sdim        (t2SUBri GPRnopc:$Rd, GPRnopc:$Rn, t2_so_imm_neg:$imm, pred:$p,
4292234353Sdim                 cc_out:$s)>;
4293234353Sdimdef : t2InstAlias<"add${p} $Rd, $Rn, $imm",
4294234353Sdim           (t2SUBri12 GPRnopc:$Rd, GPR:$Rn, imm0_4095_neg:$imm, pred:$p)>;
4295234353Sdimdef : t2InstAlias<"add${s}${p} $Rdn, $imm",
4296234353Sdim      (t2SUBri GPRnopc:$Rdn, GPRnopc:$Rdn, t2_so_imm_neg:$imm, pred:$p,
4297234353Sdim               cc_out:$s)>;
4298234353Sdimdef : t2InstAlias<"add${p} $Rdn, $imm",
4299234353Sdim           (t2SUBri12 GPRnopc:$Rdn, GPRnopc:$Rdn, imm0_4095_neg:$imm, pred:$p)>;
4300234353Sdim
4301239462Sdimdef : t2InstAlias<"add${s}${p}.w $Rd, $Rn, $imm",
4302239462Sdim        (t2SUBri GPRnopc:$Rd, GPRnopc:$Rn, t2_so_imm_neg:$imm, pred:$p,
4303239462Sdim                 cc_out:$s)>;
4304239462Sdimdef : t2InstAlias<"addw${p} $Rd, $Rn, $imm",
4305239462Sdim           (t2SUBri12 GPRnopc:$Rd, GPR:$Rn, imm0_4095_neg:$imm, pred:$p)>;
4306239462Sdimdef : t2InstAlias<"add${s}${p}.w $Rdn, $imm",
4307239462Sdim      (t2SUBri GPRnopc:$Rdn, GPRnopc:$Rdn, t2_so_imm_neg:$imm, pred:$p,
4308239462Sdim               cc_out:$s)>;
4309239462Sdimdef : t2InstAlias<"addw${p} $Rdn, $imm",
4310239462Sdim           (t2SUBri12 GPRnopc:$Rdn, GPRnopc:$Rdn, imm0_4095_neg:$imm, pred:$p)>;
4311234353Sdim
4312239462Sdim
4313226633Sdim// Aliases for SUB without the ".w" optional width specifier.
4314226633Sdimdef : t2InstAlias<"sub${s}${p} $Rd, $Rn, $imm",
4315226633Sdim        (t2SUBri GPRnopc:$Rd, GPRnopc:$Rn, t2_so_imm:$imm, pred:$p, cc_out:$s)>;
4316226633Sdimdef : t2InstAlias<"sub${p} $Rd, $Rn, $imm",
4317226633Sdim           (t2SUBri12 GPRnopc:$Rd, GPR:$Rn, imm0_4095:$imm, pred:$p)>;
4318226633Sdimdef : t2InstAlias<"sub${s}${p} $Rd, $Rn, $Rm",
4319226633Sdim              (t2SUBrr GPRnopc:$Rd, GPRnopc:$Rn, rGPR:$Rm, pred:$p, cc_out:$s)>;
4320226633Sdimdef : t2InstAlias<"sub${s}${p} $Rd, $Rn, $ShiftedRm",
4321226633Sdim                  (t2SUBrs GPRnopc:$Rd, GPRnopc:$Rn, t2_so_reg:$ShiftedRm,
4322226633Sdim                           pred:$p, cc_out:$s)>;
4323234353Sdim// ... and with the destination and source register combined.
4324234353Sdimdef : t2InstAlias<"sub${s}${p} $Rdn, $imm",
4325234353Sdim      (t2SUBri GPRnopc:$Rdn, GPRnopc:$Rdn, t2_so_imm:$imm, pred:$p, cc_out:$s)>;
4326234353Sdimdef : t2InstAlias<"sub${p} $Rdn, $imm",
4327234353Sdim           (t2SUBri12 GPRnopc:$Rdn, GPRnopc:$Rdn, imm0_4095:$imm, pred:$p)>;
4328234353Sdimdef : t2InstAlias<"sub${s}${p}.w $Rdn, $Rm",
4329234353Sdim            (t2SUBrr GPRnopc:$Rdn, GPRnopc:$Rdn, rGPR:$Rm, pred:$p, cc_out:$s)>;
4330234353Sdimdef : t2InstAlias<"sub${s}${p} $Rdn, $Rm",
4331234353Sdim            (t2SUBrr GPRnopc:$Rdn, GPRnopc:$Rdn, rGPR:$Rm, pred:$p, cc_out:$s)>;
4332234353Sdimdef : t2InstAlias<"sub${s}${p} $Rdn, $ShiftedRm",
4333234353Sdim                  (t2SUBrs GPRnopc:$Rdn, GPRnopc:$Rdn, t2_so_reg:$ShiftedRm,
4334234353Sdim                           pred:$p, cc_out:$s)>;
4335226633Sdim
4336226633Sdim// Alias for compares without the ".w" optional width specifier.
4337226633Sdimdef : t2InstAlias<"cmn${p} $Rn, $Rm",
4338226633Sdim                  (t2CMNzrr GPRnopc:$Rn, rGPR:$Rm, pred:$p)>;
4339226633Sdimdef : t2InstAlias<"teq${p} $Rn, $Rm",
4340226633Sdim                  (t2TEQrr GPRnopc:$Rn, rGPR:$Rm, pred:$p)>;
4341226633Sdimdef : t2InstAlias<"tst${p} $Rn, $Rm",
4342226633Sdim                  (t2TSTrr GPRnopc:$Rn, rGPR:$Rm, pred:$p)>;
4343226633Sdim
4344226633Sdim// Memory barriers
4345263508Sdimdef : InstAlias<"dmb${p}", (t2DMB 0xf, pred:$p)>, Requires<[HasDB]>;
4346263508Sdimdef : InstAlias<"dsb${p}", (t2DSB 0xf, pred:$p)>, Requires<[HasDB]>;
4347263508Sdimdef : InstAlias<"isb${p}", (t2ISB 0xf, pred:$p)>, Requires<[HasDB]>;
4348226633Sdim
4349226633Sdim// Alias for LDR, LDRB, LDRH, LDRSB, and LDRSH without the ".w" optional
4350226633Sdim// width specifier.
4351226633Sdimdef : t2InstAlias<"ldr${p} $Rt, $addr",
4352226633Sdim                  (t2LDRi12 GPR:$Rt, t2addrmode_imm12:$addr, pred:$p)>;
4353226633Sdimdef : t2InstAlias<"ldrb${p} $Rt, $addr",
4354226633Sdim                  (t2LDRBi12 rGPR:$Rt, t2addrmode_imm12:$addr, pred:$p)>;
4355226633Sdimdef : t2InstAlias<"ldrh${p} $Rt, $addr",
4356226633Sdim                  (t2LDRHi12 rGPR:$Rt, t2addrmode_imm12:$addr, pred:$p)>;
4357226633Sdimdef : t2InstAlias<"ldrsb${p} $Rt, $addr",
4358226633Sdim                  (t2LDRSBi12 rGPR:$Rt, t2addrmode_imm12:$addr, pred:$p)>;
4359226633Sdimdef : t2InstAlias<"ldrsh${p} $Rt, $addr",
4360226633Sdim                  (t2LDRSHi12 rGPR:$Rt, t2addrmode_imm12:$addr, pred:$p)>;
4361226633Sdim
4362226633Sdimdef : t2InstAlias<"ldr${p} $Rt, $addr",
4363226633Sdim                  (t2LDRs GPR:$Rt, t2addrmode_so_reg:$addr, pred:$p)>;
4364226633Sdimdef : t2InstAlias<"ldrb${p} $Rt, $addr",
4365226633Sdim                  (t2LDRBs rGPR:$Rt, t2addrmode_so_reg:$addr, pred:$p)>;
4366226633Sdimdef : t2InstAlias<"ldrh${p} $Rt, $addr",
4367226633Sdim                  (t2LDRHs rGPR:$Rt, t2addrmode_so_reg:$addr, pred:$p)>;
4368226633Sdimdef : t2InstAlias<"ldrsb${p} $Rt, $addr",
4369226633Sdim                  (t2LDRSBs rGPR:$Rt, t2addrmode_so_reg:$addr, pred:$p)>;
4370226633Sdimdef : t2InstAlias<"ldrsh${p} $Rt, $addr",
4371226633Sdim                  (t2LDRSHs rGPR:$Rt, t2addrmode_so_reg:$addr, pred:$p)>;
4372226633Sdim
4373234353Sdimdef : t2InstAlias<"ldr${p} $Rt, $addr",
4374263508Sdim                  (t2LDRpci rGPR:$Rt, t2ldrlabel:$addr, pred:$p)>;
4375234353Sdimdef : t2InstAlias<"ldrb${p} $Rt, $addr",
4376234353Sdim                  (t2LDRBpci rGPR:$Rt, t2ldrlabel:$addr, pred:$p)>;
4377234353Sdimdef : t2InstAlias<"ldrh${p} $Rt, $addr",
4378234353Sdim                  (t2LDRHpci rGPR:$Rt, t2ldrlabel:$addr, pred:$p)>;
4379234353Sdimdef : t2InstAlias<"ldrsb${p} $Rt, $addr",
4380234353Sdim                  (t2LDRSBpci rGPR:$Rt, t2ldrlabel:$addr, pred:$p)>;
4381234353Sdimdef : t2InstAlias<"ldrsh${p} $Rt, $addr",
4382234353Sdim                  (t2LDRSHpci rGPR:$Rt, t2ldrlabel:$addr, pred:$p)>;
4383234353Sdim
4384234353Sdim// Alias for MVN with(out) the ".w" optional width specifier.
4385234353Sdimdef : t2InstAlias<"mvn${s}${p}.w $Rd, $imm",
4386234353Sdim           (t2MVNi rGPR:$Rd, t2_so_imm:$imm, pred:$p, cc_out:$s)>;
4387226633Sdimdef : t2InstAlias<"mvn${s}${p} $Rd, $Rm",
4388226633Sdim           (t2MVNr rGPR:$Rd, rGPR:$Rm, pred:$p, cc_out:$s)>;
4389226633Sdimdef : t2InstAlias<"mvn${s}${p} $Rd, $ShiftedRm",
4390226633Sdim           (t2MVNs rGPR:$Rd, t2_so_reg:$ShiftedRm, pred:$p, cc_out:$s)>;
4391226633Sdim
4392226633Sdim// PKHBT/PKHTB with default shift amount. PKHTB is equivalent to PKHBT when the
4393226633Sdim// shift amount is zero (i.e., unspecified).
4394226633Sdimdef : InstAlias<"pkhbt${p} $Rd, $Rn, $Rm",
4395226633Sdim                (t2PKHBT rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, 0, pred:$p)>,
4396226633Sdim            Requires<[HasT2ExtractPack, IsThumb2]>;
4397226633Sdimdef : InstAlias<"pkhtb${p} $Rd, $Rn, $Rm",
4398226633Sdim                (t2PKHBT rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, 0, pred:$p)>,
4399226633Sdim            Requires<[HasT2ExtractPack, IsThumb2]>;
4400226633Sdim
4401226633Sdim// PUSH/POP aliases for STM/LDM
4402226633Sdimdef : t2InstAlias<"push${p}.w $regs", (t2STMDB_UPD SP, pred:$p, reglist:$regs)>;
4403226633Sdimdef : t2InstAlias<"push${p} $regs", (t2STMDB_UPD SP, pred:$p, reglist:$regs)>;
4404226633Sdimdef : t2InstAlias<"pop${p}.w $regs", (t2LDMIA_UPD SP, pred:$p, reglist:$regs)>;
4405226633Sdimdef : t2InstAlias<"pop${p} $regs", (t2LDMIA_UPD SP, pred:$p, reglist:$regs)>;
4406226633Sdim
4407234353Sdim// STMIA/STMIA_UPD aliases w/o the optional .w suffix
4408234353Sdimdef : t2InstAlias<"stm${p} $Rn, $regs",
4409234353Sdim                  (t2STMIA GPR:$Rn, pred:$p, reglist:$regs)>;
4410234353Sdimdef : t2InstAlias<"stm${p} $Rn!, $regs",
4411234353Sdim                  (t2STMIA_UPD GPR:$Rn, pred:$p, reglist:$regs)>;
4412234353Sdim
4413234353Sdim// LDMIA/LDMIA_UPD aliases w/o the optional .w suffix
4414234353Sdimdef : t2InstAlias<"ldm${p} $Rn, $regs",
4415234353Sdim                  (t2LDMIA GPR:$Rn, pred:$p, reglist:$regs)>;
4416234353Sdimdef : t2InstAlias<"ldm${p} $Rn!, $regs",
4417234353Sdim                  (t2LDMIA_UPD GPR:$Rn, pred:$p, reglist:$regs)>;
4418234353Sdim
4419234353Sdim// STMDB/STMDB_UPD aliases w/ the optional .w suffix
4420234353Sdimdef : t2InstAlias<"stmdb${p}.w $Rn, $regs",
4421234353Sdim                  (t2STMDB GPR:$Rn, pred:$p, reglist:$regs)>;
4422234353Sdimdef : t2InstAlias<"stmdb${p}.w $Rn!, $regs",
4423234353Sdim                  (t2STMDB_UPD GPR:$Rn, pred:$p, reglist:$regs)>;
4424234353Sdim
4425234353Sdim// LDMDB/LDMDB_UPD aliases w/ the optional .w suffix
4426234353Sdimdef : t2InstAlias<"ldmdb${p}.w $Rn, $regs",
4427234353Sdim                  (t2LDMDB GPR:$Rn, pred:$p, reglist:$regs)>;
4428234353Sdimdef : t2InstAlias<"ldmdb${p}.w $Rn!, $regs",
4429234353Sdim                  (t2LDMDB_UPD GPR:$Rn, pred:$p, reglist:$regs)>;
4430234353Sdim
4431226633Sdim// Alias for REV/REV16/REVSH without the ".w" optional width specifier.
4432226633Sdimdef : t2InstAlias<"rev${p} $Rd, $Rm", (t2REV rGPR:$Rd, rGPR:$Rm, pred:$p)>;
4433226633Sdimdef : t2InstAlias<"rev16${p} $Rd, $Rm", (t2REV16 rGPR:$Rd, rGPR:$Rm, pred:$p)>;
4434226633Sdimdef : t2InstAlias<"revsh${p} $Rd, $Rm", (t2REVSH rGPR:$Rd, rGPR:$Rm, pred:$p)>;
4435226633Sdim
4436226633Sdim
4437226633Sdim// Alias for RSB without the ".w" optional width specifier, and with optional
4438226633Sdim// implied destination register.
4439226633Sdimdef : t2InstAlias<"rsb${s}${p} $Rd, $Rn, $imm",
4440226633Sdim           (t2RSBri rGPR:$Rd, rGPR:$Rn, t2_so_imm:$imm, pred:$p, cc_out:$s)>;
4441226633Sdimdef : t2InstAlias<"rsb${s}${p} $Rdn, $imm",
4442226633Sdim           (t2RSBri rGPR:$Rdn, rGPR:$Rdn, t2_so_imm:$imm, pred:$p, cc_out:$s)>;
4443226633Sdimdef : t2InstAlias<"rsb${s}${p} $Rdn, $Rm",
4444226633Sdim           (t2RSBrr rGPR:$Rdn, rGPR:$Rdn, rGPR:$Rm, pred:$p, cc_out:$s)>;
4445226633Sdimdef : t2InstAlias<"rsb${s}${p} $Rdn, $ShiftedRm",
4446226633Sdim           (t2RSBrs rGPR:$Rdn, rGPR:$Rdn, t2_so_reg:$ShiftedRm, pred:$p,
4447226633Sdim                    cc_out:$s)>;
4448226633Sdim
4449226633Sdim// SSAT/USAT optional shift operand.
4450226633Sdimdef : t2InstAlias<"ssat${p} $Rd, $sat_imm, $Rn",
4451226633Sdim                  (t2SSAT rGPR:$Rd, imm1_32:$sat_imm, rGPR:$Rn, 0, pred:$p)>;
4452226633Sdimdef : t2InstAlias<"usat${p} $Rd, $sat_imm, $Rn",
4453226633Sdim                  (t2USAT rGPR:$Rd, imm0_31:$sat_imm, rGPR:$Rn, 0, pred:$p)>;
4454226633Sdim
4455226633Sdim// STM w/o the .w suffix.
4456226633Sdimdef : t2InstAlias<"stm${p} $Rn, $regs",
4457226633Sdim                  (t2STMIA GPR:$Rn, pred:$p, reglist:$regs)>;
4458226633Sdim
4459226633Sdim// Alias for STR, STRB, and STRH without the ".w" optional
4460226633Sdim// width specifier.
4461226633Sdimdef : t2InstAlias<"str${p} $Rt, $addr",
4462226633Sdim                  (t2STRi12 GPR:$Rt, t2addrmode_imm12:$addr, pred:$p)>;
4463226633Sdimdef : t2InstAlias<"strb${p} $Rt, $addr",
4464226633Sdim                  (t2STRBi12 rGPR:$Rt, t2addrmode_imm12:$addr, pred:$p)>;
4465226633Sdimdef : t2InstAlias<"strh${p} $Rt, $addr",
4466226633Sdim                  (t2STRHi12 rGPR:$Rt, t2addrmode_imm12:$addr, pred:$p)>;
4467226633Sdim
4468226633Sdimdef : t2InstAlias<"str${p} $Rt, $addr",
4469226633Sdim                  (t2STRs GPR:$Rt, t2addrmode_so_reg:$addr, pred:$p)>;
4470226633Sdimdef : t2InstAlias<"strb${p} $Rt, $addr",
4471226633Sdim                  (t2STRBs rGPR:$Rt, t2addrmode_so_reg:$addr, pred:$p)>;
4472226633Sdimdef : t2InstAlias<"strh${p} $Rt, $addr",
4473226633Sdim                  (t2STRHs rGPR:$Rt, t2addrmode_so_reg:$addr, pred:$p)>;
4474226633Sdim
4475226633Sdim// Extend instruction optional rotate operand.
4476226633Sdimdef : t2InstAlias<"sxtab${p} $Rd, $Rn, $Rm",
4477226633Sdim                (t2SXTAB rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, 0, pred:$p)>;
4478226633Sdimdef : t2InstAlias<"sxtah${p} $Rd, $Rn, $Rm",
4479226633Sdim                (t2SXTAH rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, 0, pred:$p)>;
4480226633Sdimdef : t2InstAlias<"sxtab16${p} $Rd, $Rn, $Rm",
4481226633Sdim                (t2SXTAB16 rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, 0, pred:$p)>;
4482226633Sdim
4483226633Sdimdef : t2InstAlias<"sxtb${p} $Rd, $Rm",
4484226633Sdim                (t2SXTB rGPR:$Rd, rGPR:$Rm, 0, pred:$p)>;
4485226633Sdimdef : t2InstAlias<"sxtb16${p} $Rd, $Rm",
4486226633Sdim                (t2SXTB16 rGPR:$Rd, rGPR:$Rm, 0, pred:$p)>;
4487226633Sdimdef : t2InstAlias<"sxth${p} $Rd, $Rm",
4488226633Sdim                (t2SXTH rGPR:$Rd, rGPR:$Rm, 0, pred:$p)>;
4489226633Sdimdef : t2InstAlias<"sxtb${p}.w $Rd, $Rm",
4490226633Sdim                (t2SXTB rGPR:$Rd, rGPR:$Rm, 0, pred:$p)>;
4491226633Sdimdef : t2InstAlias<"sxth${p}.w $Rd, $Rm",
4492226633Sdim                (t2SXTH rGPR:$Rd, rGPR:$Rm, 0, pred:$p)>;
4493226633Sdim
4494226633Sdimdef : t2InstAlias<"uxtab${p} $Rd, $Rn, $Rm",
4495226633Sdim                (t2UXTAB rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, 0, pred:$p)>;
4496226633Sdimdef : t2InstAlias<"uxtah${p} $Rd, $Rn, $Rm",
4497226633Sdim                (t2UXTAH rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, 0, pred:$p)>;
4498226633Sdimdef : t2InstAlias<"uxtab16${p} $Rd, $Rn, $Rm",
4499226633Sdim                (t2UXTAB16 rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, 0, pred:$p)>;
4500226633Sdimdef : t2InstAlias<"uxtb${p} $Rd, $Rm",
4501226633Sdim                (t2UXTB rGPR:$Rd, rGPR:$Rm, 0, pred:$p)>;
4502226633Sdimdef : t2InstAlias<"uxtb16${p} $Rd, $Rm",
4503226633Sdim                (t2UXTB16 rGPR:$Rd, rGPR:$Rm, 0, pred:$p)>;
4504226633Sdimdef : t2InstAlias<"uxth${p} $Rd, $Rm",
4505226633Sdim                (t2UXTH rGPR:$Rd, rGPR:$Rm, 0, pred:$p)>;
4506226633Sdim
4507226633Sdimdef : t2InstAlias<"uxtb${p}.w $Rd, $Rm",
4508226633Sdim                (t2UXTB rGPR:$Rd, rGPR:$Rm, 0, pred:$p)>;
4509226633Sdimdef : t2InstAlias<"uxth${p}.w $Rd, $Rm",
4510226633Sdim                (t2UXTH rGPR:$Rd, rGPR:$Rm, 0, pred:$p)>;
4511226633Sdim
4512226633Sdim// Extend instruction w/o the ".w" optional width specifier.
4513226633Sdimdef : t2InstAlias<"uxtb${p} $Rd, $Rm$rot",
4514226633Sdim                  (t2UXTB rGPR:$Rd, rGPR:$Rm, rot_imm:$rot, pred:$p)>;
4515226633Sdimdef : t2InstAlias<"uxtb16${p} $Rd, $Rm$rot",
4516226633Sdim                  (t2UXTB16 rGPR:$Rd, rGPR:$Rm, rot_imm:$rot, pred:$p)>;
4517226633Sdimdef : t2InstAlias<"uxth${p} $Rd, $Rm$rot",
4518226633Sdim                  (t2UXTH rGPR:$Rd, rGPR:$Rm, rot_imm:$rot, pred:$p)>;
4519226633Sdim
4520226633Sdimdef : t2InstAlias<"sxtb${p} $Rd, $Rm$rot",
4521226633Sdim                  (t2SXTB rGPR:$Rd, rGPR:$Rm, rot_imm:$rot, pred:$p)>;
4522226633Sdimdef : t2InstAlias<"sxtb16${p} $Rd, $Rm$rot",
4523226633Sdim                  (t2SXTB16 rGPR:$Rd, rGPR:$Rm, rot_imm:$rot, pred:$p)>;
4524226633Sdimdef : t2InstAlias<"sxth${p} $Rd, $Rm$rot",
4525226633Sdim                  (t2SXTH rGPR:$Rd, rGPR:$Rm, rot_imm:$rot, pred:$p)>;
4526234353Sdim
4527234353Sdim
4528234353Sdim// "mov Rd, t2_so_imm_not" can be handled via "mvn" in assembly, just like
4529234353Sdim// for isel.
4530234353Sdimdef : t2InstAlias<"mov${p} $Rd, $imm",
4531234353Sdim                  (t2MVNi rGPR:$Rd, t2_so_imm_not:$imm, pred:$p, zero_reg)>;
4532234353Sdimdef : t2InstAlias<"mvn${p} $Rd, $imm",
4533234353Sdim                  (t2MOVi rGPR:$Rd, t2_so_imm_not:$imm, pred:$p, zero_reg)>;
4534234353Sdim// Same for AND <--> BIC
4535234353Sdimdef : t2InstAlias<"bic${s}${p} $Rd, $Rn, $imm",
4536263508Sdim                  (t2ANDri rGPR:$Rd, rGPR:$Rn, t2_so_imm_not:$imm,
4537234353Sdim                           pred:$p, cc_out:$s)>;
4538234353Sdimdef : t2InstAlias<"bic${s}${p} $Rdn, $imm",
4539263508Sdim                  (t2ANDri rGPR:$Rdn, rGPR:$Rdn, t2_so_imm_not:$imm,
4540234353Sdim                           pred:$p, cc_out:$s)>;
4541234353Sdimdef : t2InstAlias<"and${s}${p} $Rd, $Rn, $imm",
4542263508Sdim                  (t2BICri rGPR:$Rd, rGPR:$Rn, t2_so_imm_not:$imm,
4543234353Sdim                           pred:$p, cc_out:$s)>;
4544234353Sdimdef : t2InstAlias<"and${s}${p} $Rdn, $imm",
4545263508Sdim                  (t2BICri rGPR:$Rdn, rGPR:$Rdn, t2_so_imm_not:$imm,
4546234353Sdim                           pred:$p, cc_out:$s)>;
4547234353Sdim// Likewise, "add Rd, t2_so_imm_neg" -> sub
4548234353Sdimdef : t2InstAlias<"add${s}${p} $Rd, $Rn, $imm",
4549234353Sdim                  (t2SUBri GPRnopc:$Rd, GPRnopc:$Rn, t2_so_imm_neg:$imm,
4550234353Sdim                           pred:$p, cc_out:$s)>;
4551234353Sdimdef : t2InstAlias<"add${s}${p} $Rd, $imm",
4552234353Sdim                  (t2SUBri GPRnopc:$Rd, GPRnopc:$Rd, t2_so_imm_neg:$imm,
4553234353Sdim                           pred:$p, cc_out:$s)>;
4554234353Sdim// Same for CMP <--> CMN via t2_so_imm_neg
4555234353Sdimdef : t2InstAlias<"cmp${p} $Rd, $imm",
4556239462Sdim                  (t2CMNri rGPR:$Rd, t2_so_imm_neg:$imm, pred:$p)>;
4557234353Sdimdef : t2InstAlias<"cmn${p} $Rd, $imm",
4558234353Sdim                  (t2CMPri rGPR:$Rd, t2_so_imm_neg:$imm, pred:$p)>;
4559234353Sdim
4560234353Sdim
4561234353Sdim// Wide 'mul' encoding can be specified with only two operands.
4562234353Sdimdef : t2InstAlias<"mul${p} $Rn, $Rm",
4563234353Sdim                  (t2MUL rGPR:$Rn, rGPR:$Rm, rGPR:$Rn, pred:$p)>;
4564234353Sdim
4565234353Sdim// "neg" is and alias for "rsb rd, rn, #0"
4566234353Sdimdef : t2InstAlias<"neg${s}${p} $Rd, $Rm",
4567234353Sdim                  (t2RSBri rGPR:$Rd, rGPR:$Rm, 0, pred:$p, cc_out:$s)>;
4568234353Sdim
4569234353Sdim// MOV so_reg assembler pseudos. InstAlias isn't expressive enough for
4570234353Sdim// these, unfortunately.
4571234353Sdimdef t2MOVsi: t2AsmPseudo<"mov${p} $Rd, $shift",
4572234353Sdim                         (ins rGPR:$Rd, t2_so_reg:$shift, pred:$p)>;
4573234353Sdimdef t2MOVSsi: t2AsmPseudo<"movs${p} $Rd, $shift",
4574234353Sdim                          (ins rGPR:$Rd, t2_so_reg:$shift, pred:$p)>;
4575234353Sdim
4576234353Sdimdef t2MOVsr: t2AsmPseudo<"mov${p} $Rd, $shift",
4577234353Sdim                         (ins rGPR:$Rd, so_reg_reg:$shift, pred:$p)>;
4578234353Sdimdef t2MOVSsr: t2AsmPseudo<"movs${p} $Rd, $shift",
4579234353Sdim                          (ins rGPR:$Rd, so_reg_reg:$shift, pred:$p)>;
4580234353Sdim
4581234353Sdim// ADR w/o the .w suffix
4582234353Sdimdef : t2InstAlias<"adr${p} $Rd, $addr",
4583234353Sdim                  (t2ADR rGPR:$Rd, t2adrlabel:$addr, pred:$p)>;
4584234353Sdim
4585234353Sdim// LDR(literal) w/ alternate [pc, #imm] syntax.
4586234353Sdimdef t2LDRpcrel   : t2AsmPseudo<"ldr${p} $Rt, $addr",
4587263508Sdim                         (ins GPR:$Rt, t2ldr_pcrel_imm12:$addr, pred:$p)>;
4588234353Sdimdef t2LDRBpcrel  : t2AsmPseudo<"ldrb${p} $Rt, $addr",
4589234353Sdim                         (ins GPRnopc:$Rt, t2ldr_pcrel_imm12:$addr, pred:$p)>;
4590234353Sdimdef t2LDRHpcrel  : t2AsmPseudo<"ldrh${p} $Rt, $addr",
4591234353Sdim                         (ins GPRnopc:$Rt, t2ldr_pcrel_imm12:$addr, pred:$p)>;
4592234353Sdimdef t2LDRSBpcrel  : t2AsmPseudo<"ldrsb${p} $Rt, $addr",
4593234353Sdim                         (ins GPRnopc:$Rt, t2ldr_pcrel_imm12:$addr, pred:$p)>;
4594234353Sdimdef t2LDRSHpcrel  : t2AsmPseudo<"ldrsh${p} $Rt, $addr",
4595234353Sdim                         (ins GPRnopc:$Rt, t2ldr_pcrel_imm12:$addr, pred:$p)>;
4596234353Sdim    // Version w/ the .w suffix.
4597234353Sdimdef : t2InstAlias<"ldr${p}.w $Rt, $addr",
4598263508Sdim                  (t2LDRpcrel GPR:$Rt, t2ldr_pcrel_imm12:$addr, pred:$p), 0>;
4599234353Sdimdef : t2InstAlias<"ldrb${p}.w $Rt, $addr",
4600234353Sdim                  (t2LDRBpcrel GPRnopc:$Rt, t2ldr_pcrel_imm12:$addr, pred:$p)>;
4601234353Sdimdef : t2InstAlias<"ldrh${p}.w $Rt, $addr",
4602234353Sdim                  (t2LDRHpcrel GPRnopc:$Rt, t2ldr_pcrel_imm12:$addr, pred:$p)>;
4603234353Sdimdef : t2InstAlias<"ldrsb${p}.w $Rt, $addr",
4604234353Sdim                  (t2LDRSBpcrel GPRnopc:$Rt, t2ldr_pcrel_imm12:$addr, pred:$p)>;
4605234353Sdimdef : t2InstAlias<"ldrsh${p}.w $Rt, $addr",
4606234353Sdim                  (t2LDRSHpcrel GPRnopc:$Rt, t2ldr_pcrel_imm12:$addr, pred:$p)>;
4607234353Sdim
4608234353Sdimdef : t2InstAlias<"add${p} $Rd, pc, $imm",
4609234353Sdim                  (t2ADR rGPR:$Rd, imm0_4095:$imm, pred:$p)>;
4610263508Sdim
4611263508Sdim// PLD/PLDW/PLI with alternate literal form.
4612263508Sdimdef : t2InstAlias<"pld${p} $addr",
4613263508Sdim                  (t2PLDpci t2ldr_pcrel_imm12:$addr, pred:$p)>;
4614263508Sdimdef : InstAlias<"pli${p} $addr",
4615263508Sdim                 (t2PLIpci  t2ldr_pcrel_imm12:$addr, pred:$p)>,
4616263508Sdim      Requires<[IsThumb2,HasV7]>;
4617