1234353Sdim//===-- ARMInstrThumb.td - Thumb 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 Thumb instruction set.
11193323Sed//
12193323Sed//===----------------------------------------------------------------------===//
13193323Sed
14193323Sed//===----------------------------------------------------------------------===//
15193323Sed// Thumb specific DAG Nodes.
16193323Sed//
17193323Sed
18193323Seddef ARMtcall : SDNode<"ARMISD::tCALL", SDT_ARMcall,
19218893Sdim                      [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
20205407Srdivacky                       SDNPVariadic]>;
21193323Sed
22226633Sdimdef imm_sr_XFORM: SDNodeXForm<imm, [{
23226633Sdim  unsigned Imm = N->getZExtValue();
24226633Sdim  return CurDAG->getTargetConstant((Imm == 32 ? 0 : Imm), MVT::i32);
25226633Sdim}]>;
26226633Sdimdef ThumbSRImmAsmOperand: AsmOperandClass { let Name = "ImmThumbSR"; }
27226633Sdimdef imm_sr : Operand<i32>, PatLeaf<(imm), [{
28226633Sdim  uint64_t Imm = N->getZExtValue();
29226633Sdim  return Imm > 0 && Imm <= 32;
30226633Sdim}], imm_sr_XFORM> {
31226633Sdim  let PrintMethod = "printThumbSRImm";
32226633Sdim  let ParserMatchClass = ThumbSRImmAsmOperand;
33226633Sdim}
34226633Sdim
35193323Seddef imm_comp_XFORM : SDNodeXForm<imm, [{
36193323Sed  return CurDAG->getTargetConstant(~((uint32_t)N->getZExtValue()), MVT::i32);
37193323Sed}]>;
38193323Sed
39193323Seddef imm0_7_neg : PatLeaf<(i32 imm), [{
40193323Sed  return (uint32_t)-N->getZExtValue() < 8;
41193323Sed}], imm_neg_XFORM>;
42193323Sed
43193323Seddef imm0_255_comp : PatLeaf<(i32 imm), [{
44193323Sed  return ~((uint32_t)N->getZExtValue()) < 256;
45193323Sed}]>;
46193323Sed
47221345Sdimdef imm8_255 : ImmLeaf<i32, [{
48221345Sdim  return Imm >= 8 && Imm < 256;
49193323Sed}]>;
50193323Seddef imm8_255_neg : PatLeaf<(i32 imm), [{
51193323Sed  unsigned Val = -N->getZExtValue();
52193323Sed  return Val >= 8 && Val < 256;
53193323Sed}], imm_neg_XFORM>;
54193323Sed
55218893Sdim// Break imm's up into two pieces: an immediate + a left shift. This uses
56218893Sdim// thumb_immshifted to match and thumb_immshifted_val and thumb_immshifted_shamt
57218893Sdim// to get the val/shift pieces.
58193323Seddef thumb_immshifted : PatLeaf<(imm), [{
59193323Sed  return ARM_AM::isThumbImmShiftedVal((unsigned)N->getZExtValue());
60193323Sed}]>;
61193323Sed
62193323Seddef thumb_immshifted_val : SDNodeXForm<imm, [{
63193323Sed  unsigned V = ARM_AM::getThumbImmNonShiftedVal((unsigned)N->getZExtValue());
64193323Sed  return CurDAG->getTargetConstant(V, MVT::i32);
65193323Sed}]>;
66193323Sed
67193323Seddef thumb_immshifted_shamt : SDNodeXForm<imm, [{
68193323Sed  unsigned V = ARM_AM::getThumbImmValShift((unsigned)N->getZExtValue());
69193323Sed  return CurDAG->getTargetConstant(V, MVT::i32);
70193323Sed}]>;
71193323Sed
72199511Srdivacky// Scaled 4 immediate.
73226633Sdimdef t_imm0_1020s4_asmoperand: AsmOperandClass { let Name = "Imm0_1020s4"; }
74226633Sdimdef t_imm0_1020s4 : Operand<i32> {
75199511Srdivacky  let PrintMethod = "printThumbS4ImmOperand";
76226633Sdim  let ParserMatchClass = t_imm0_1020s4_asmoperand;
77224145Sdim  let OperandType = "OPERAND_IMMEDIATE";
78199511Srdivacky}
79199511Srdivacky
80226633Sdimdef t_imm0_508s4_asmoperand: AsmOperandClass { let Name = "Imm0_508s4"; }
81226633Sdimdef t_imm0_508s4 : Operand<i32> {
82226633Sdim  let PrintMethod = "printThumbS4ImmOperand";
83226633Sdim  let ParserMatchClass = t_imm0_508s4_asmoperand;
84226633Sdim  let OperandType = "OPERAND_IMMEDIATE";
85226633Sdim}
86234353Sdim// Alias use only, so no printer is necessary.
87234353Sdimdef t_imm0_508s4_neg_asmoperand: AsmOperandClass { let Name = "Imm0_508s4Neg"; }
88234353Sdimdef t_imm0_508s4_neg : Operand<i32> {
89234353Sdim  let ParserMatchClass = t_imm0_508s4_neg_asmoperand;
90234353Sdim  let OperandType = "OPERAND_IMMEDIATE";
91234353Sdim}
92226633Sdim
93193323Sed// Define Thumb specific addressing modes.
94193323Sed
95263508Sdim// unsigned 8-bit, 2-scaled memory offset
96263508Sdimclass OperandUnsignedOffset_b8s2 : AsmOperandClass {
97263508Sdim  let Name = "UnsignedOffset_b8s2";
98263508Sdim  let PredicateMethod = "isUnsignedOffset<8, 2>";
99263508Sdim}
100263508Sdim
101263508Sdimdef UnsignedOffset_b8s2 : OperandUnsignedOffset_b8s2;
102263508Sdim
103263508Sdim// thumb style PC relative operand. signed, 8 bits magnitude,
104263508Sdim// two bits shift. can be represented as either [pc, #imm], #imm,
105263508Sdim// or relocatable expression...
106263508Sdimdef ThumbMemPC : AsmOperandClass {
107263508Sdim  let Name = "ThumbMemPC";
108263508Sdim}
109263508Sdim
110224145Sdimlet OperandType = "OPERAND_PCREL" in {
111218893Sdimdef t_brtarget : Operand<OtherVT> {
112218893Sdim  let EncoderMethod = "getThumbBRTargetOpValue";
113226633Sdim  let DecoderMethod = "DecodeThumbBROperand";
114218893Sdim}
115218893Sdim
116263508Sdim// ADR instruction labels.
117263508Sdimdef t_adrlabel : Operand<i32> {
118263508Sdim  let EncoderMethod = "getThumbAdrLabelOpValue";
119263508Sdim  let PrintMethod = "printAdrLabelOperand<2>";
120263508Sdim  let ParserMatchClass = UnsignedOffset_b8s2;
121263508Sdim}
122263508Sdim
123218893Sdimdef t_bcctarget : Operand<i32> {
124218893Sdim  let EncoderMethod = "getThumbBCCTargetOpValue";
125226633Sdim  let DecoderMethod = "DecodeThumbBCCTargetOperand";
126218893Sdim}
127218893Sdim
128218893Sdimdef t_cbtarget : Operand<i32> {
129218893Sdim  let EncoderMethod = "getThumbCBTargetOpValue";
130226633Sdim  let DecoderMethod = "DecodeThumbCmpBROperand";
131218893Sdim}
132218893Sdim
133218893Sdimdef t_bltarget : Operand<i32> {
134218893Sdim  let EncoderMethod = "getThumbBLTargetOpValue";
135226633Sdim  let DecoderMethod = "DecodeThumbBLTargetOperand";
136218893Sdim}
137218893Sdim
138218893Sdimdef t_blxtarget : Operand<i32> {
139218893Sdim  let EncoderMethod = "getThumbBLXTargetOpValue";
140226633Sdim  let DecoderMethod = "DecodeThumbBLXOffset";
141218893Sdim}
142263508Sdim
143263508Sdim// t_addrmode_pc := <label> => pc + imm8 * 4
144263508Sdim//
145263508Sdimdef t_addrmode_pc : Operand<i32> {
146263508Sdim  let EncoderMethod = "getAddrModePCOpValue";
147263508Sdim  let DecoderMethod = "DecodeThumbAddrModePC";
148263508Sdim  let PrintMethod = "printThumbLdrLabelOperand";
149263508Sdim  let ParserMatchClass = ThumbMemPC;
150224145Sdim}
151263508Sdim}
152218893Sdim
153193323Sed// t_addrmode_rr := reg + reg
154193323Sed//
155226633Sdimdef t_addrmode_rr_asm_operand : AsmOperandClass { let Name = "MemThumbRR"; }
156193323Seddef t_addrmode_rr : Operand<i32>,
157193323Sed                    ComplexPattern<i32, 2, "SelectThumbAddrModeRR", []> {
158218893Sdim  let EncoderMethod = "getThumbAddrModeRegRegOpValue";
159193323Sed  let PrintMethod = "printThumbAddrModeRROperand";
160226633Sdim  let DecoderMethod = "DecodeThumbAddrModeRR";
161226633Sdim  let ParserMatchClass = t_addrmode_rr_asm_operand;
162193323Sed  let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg);
163193323Sed}
164193323Sed
165218893Sdim// t_addrmode_rrs := reg + reg
166193323Sed//
167226633Sdim// We use separate scaled versions because the Select* functions need
168226633Sdim// to explicitly check for a matching constant and return false here so that
169226633Sdim// the reg+imm forms will match instead. This is a horrible way to do that,
170226633Sdim// as it forces tight coupling between the methods, but it's how selectiondag
171226633Sdim// currently works.
172218893Sdimdef t_addrmode_rrs1 : Operand<i32>,
173218893Sdim                      ComplexPattern<i32, 2, "SelectThumbAddrModeRI5S1", []> {
174218893Sdim  let EncoderMethod = "getThumbAddrModeRegRegOpValue";
175218893Sdim  let PrintMethod = "printThumbAddrModeRROperand";
176226633Sdim  let DecoderMethod = "DecodeThumbAddrModeRR";
177226633Sdim  let ParserMatchClass = t_addrmode_rr_asm_operand;
178218893Sdim  let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg);
179193323Sed}
180218893Sdimdef t_addrmode_rrs2 : Operand<i32>,
181218893Sdim                      ComplexPattern<i32, 2, "SelectThumbAddrModeRI5S2", []> {
182218893Sdim  let EncoderMethod = "getThumbAddrModeRegRegOpValue";
183226633Sdim  let DecoderMethod = "DecodeThumbAddrModeRR";
184218893Sdim  let PrintMethod = "printThumbAddrModeRROperand";
185226633Sdim  let ParserMatchClass = t_addrmode_rr_asm_operand;
186218893Sdim  let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg);
187218893Sdim}
188218893Sdimdef t_addrmode_rrs4 : Operand<i32>,
189218893Sdim                      ComplexPattern<i32, 2, "SelectThumbAddrModeRI5S4", []> {
190218893Sdim  let EncoderMethod = "getThumbAddrModeRegRegOpValue";
191226633Sdim  let DecoderMethod = "DecodeThumbAddrModeRR";
192218893Sdim  let PrintMethod = "printThumbAddrModeRROperand";
193226633Sdim  let ParserMatchClass = t_addrmode_rr_asm_operand;
194218893Sdim  let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg);
195218893Sdim}
196193323Sed
197218893Sdim// t_addrmode_is4 := reg + imm5 * 4
198193323Sed//
199226633Sdimdef t_addrmode_is4_asm_operand : AsmOperandClass { let Name = "MemThumbRIs4"; }
200218893Sdimdef t_addrmode_is4 : Operand<i32>,
201218893Sdim                     ComplexPattern<i32, 2, "SelectThumbAddrModeImm5S4", []> {
202218893Sdim  let EncoderMethod = "getAddrModeISOpValue";
203226633Sdim  let DecoderMethod = "DecodeThumbAddrModeIS";
204218893Sdim  let PrintMethod = "printThumbAddrModeImm5S4Operand";
205226633Sdim  let ParserMatchClass = t_addrmode_is4_asm_operand;
206218893Sdim  let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm);
207193323Sed}
208193323Sed
209218893Sdim// t_addrmode_is2 := reg + imm5 * 2
210193323Sed//
211226633Sdimdef t_addrmode_is2_asm_operand : AsmOperandClass { let Name = "MemThumbRIs2"; }
212218893Sdimdef t_addrmode_is2 : Operand<i32>,
213218893Sdim                     ComplexPattern<i32, 2, "SelectThumbAddrModeImm5S2", []> {
214218893Sdim  let EncoderMethod = "getAddrModeISOpValue";
215226633Sdim  let DecoderMethod = "DecodeThumbAddrModeIS";
216218893Sdim  let PrintMethod = "printThumbAddrModeImm5S2Operand";
217226633Sdim  let ParserMatchClass = t_addrmode_is2_asm_operand;
218218893Sdim  let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm);
219193323Sed}
220193323Sed
221218893Sdim// t_addrmode_is1 := reg + imm5
222218893Sdim//
223226633Sdimdef t_addrmode_is1_asm_operand : AsmOperandClass { let Name = "MemThumbRIs1"; }
224218893Sdimdef t_addrmode_is1 : Operand<i32>,
225218893Sdim                     ComplexPattern<i32, 2, "SelectThumbAddrModeImm5S1", []> {
226218893Sdim  let EncoderMethod = "getAddrModeISOpValue";
227226633Sdim  let DecoderMethod = "DecodeThumbAddrModeIS";
228218893Sdim  let PrintMethod = "printThumbAddrModeImm5S1Operand";
229226633Sdim  let ParserMatchClass = t_addrmode_is1_asm_operand;
230218893Sdim  let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm);
231218893Sdim}
232218893Sdim
233193323Sed// t_addrmode_sp := sp + imm8 * 4
234193323Sed//
235226633Sdim// FIXME: This really shouldn't have an explicit SP operand at all. It should
236226633Sdim// be implicit, just like in the instruction encoding itself.
237226633Sdimdef t_addrmode_sp_asm_operand : AsmOperandClass { let Name = "MemThumbSPI"; }
238193323Seddef t_addrmode_sp : Operand<i32>,
239193323Sed                    ComplexPattern<i32, 2, "SelectThumbAddrModeSP", []> {
240218893Sdim  let EncoderMethod = "getAddrModeThumbSPOpValue";
241226633Sdim  let DecoderMethod = "DecodeThumbAddrModeSP";
242193323Sed  let PrintMethod = "printThumbAddrModeSPOperand";
243226633Sdim  let ParserMatchClass = t_addrmode_sp_asm_operand;
244202375Srdivacky  let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
245193323Sed}
246193323Sed
247193323Sed//===----------------------------------------------------------------------===//
248193323Sed//  Miscellaneous Instructions.
249193323Sed//
250193323Sed
251204642Srdivacky// FIXME: Marking these as hasSideEffects is necessary to prevent machine DCE
252204642Srdivacky// from removing one half of the matched pairs. That breaks PEI, which assumes
253204642Srdivacky// these will always be in pairs, and asserts if it finds otherwise. Better way?
254204642Srdivackylet Defs = [SP], Uses = [SP], hasSideEffects = 1 in {
255193323Seddef tADJCALLSTACKUP :
256218893Sdim  PseudoInst<(outs), (ins i32imm:$amt1, i32imm:$amt2), NoItinerary,
257218893Sdim             [(ARMcallseq_end imm:$amt1, imm:$amt2)]>,
258218893Sdim            Requires<[IsThumb, IsThumb1Only]>;
259193323Sed
260193323Seddef tADJCALLSTACKDOWN :
261218893Sdim  PseudoInst<(outs), (ins i32imm:$amt), NoItinerary,
262218893Sdim             [(ARMcallseq_start imm:$amt)]>,
263218893Sdim            Requires<[IsThumb, IsThumb1Only]>;
264193323Sed}
265193323Sed
266226633Sdimclass T1SystemEncoding<bits<8> opc>
267218893Sdim  : T1Encoding<0b101111> {
268226633Sdim  let Inst{9-8} = 0b11;
269226633Sdim  let Inst{7-0} = opc;
270218893Sdim}
271218893Sdim
272263508Sdimdef tHINT : T1pI<(outs), (ins imm0_15:$imm), NoItinerary, "hint", "\t$imm", []>,
273263508Sdim            T1SystemEncoding<0x00>,
274263508Sdim            Requires<[IsThumb, HasV6M]> {
275263508Sdim  bits<4> imm;
276263508Sdim  let Inst{7-4} = imm;
277263508Sdim}
278204642Srdivacky
279263508Sdimclass tHintAlias<string Asm, dag Result> : tInstAlias<Asm, Result> {
280263508Sdim  let Predicates = [IsThumb, HasV6M];
281263508Sdim}
282204642Srdivacky
283263508Sdimdef : tHintAlias<"nop$p", (tHINT 0, pred:$p)>; // A8.6.110
284263508Sdimdef : tHintAlias<"yield$p", (tHINT 1, pred:$p)>; // A8.6.410
285263508Sdimdef : tHintAlias<"wfe$p", (tHINT 2, pred:$p)>; // A8.6.408
286263508Sdimdef : tHintAlias<"wfi$p", (tHINT 3, pred:$p)>; // A8.6.409
287263508Sdimdef : tHintAlias<"sev$p", (tHINT 4, pred:$p)>; // A8.6.157
288263508Sdimdef : tInstAlias<"sevl$p", (tHINT 5, pred:$p)> {
289263508Sdim  let Predicates = [IsThumb2, HasV8];
290263508Sdim}
291263508Sdimdef : T2Pat<(int_arm_sevl), (tHINT 5)>;
292204642Srdivacky
293226633Sdim// The imm operand $val can be used by a debugger to store more information
294218893Sdim// about the breakpoint.
295226633Sdimdef tBKPT : T1I<(outs), (ins imm0_255:$val), NoItinerary, "bkpt\t$val",
296226633Sdim                []>,
297226633Sdim           T1Encoding<0b101111> {
298226633Sdim  let Inst{9-8} = 0b10;
299218893Sdim  // A8.6.22
300218893Sdim  bits<8> val;
301218893Sdim  let Inst{7-0} = val;
302218893Sdim}
303218893Sdim
304263508Sdimdef tHLT : T1I<(outs), (ins imm0_63:$val), NoItinerary, "hlt\t$val",
305263508Sdim                []>, T1Encoding<0b101110>, Requires<[IsThumb, HasV8]> {
306263508Sdim  let Inst{9-6} = 0b1010;
307263508Sdim  bits<6> val;
308263508Sdim  let Inst{5-0} = val;
309263508Sdim}
310263508Sdim
311226633Sdimdef tSETEND : T1I<(outs), (ins setend_op:$end), NoItinerary, "setend\t$end",
312263508Sdim                  []>, T1Encoding<0b101101>, Deprecated<HasV8Ops> {
313226633Sdim  bits<1> end;
314218893Sdim  // A8.6.156
315204642Srdivacky  let Inst{9-5} = 0b10010;
316218893Sdim  let Inst{4}   = 1;
317226633Sdim  let Inst{3}   = end;
318218893Sdim  let Inst{2-0} = 0b000;
319204642Srdivacky}
320204642Srdivacky
321218893Sdim// Change Processor State is a system instruction -- for disassembly only.
322218893Sdimdef tCPS : T1I<(outs), (ins imod_op:$imod, iflags_op:$iflags),
323226633Sdim                NoItinerary, "cps$imod $iflags", []>,
324218893Sdim           T1Misc<0b0110011> {
325218893Sdim  // A8.6.38 & B6.1.1
326218893Sdim  bit imod;
327218893Sdim  bits<3> iflags;
328218893Sdim
329218893Sdim  let Inst{4}   = imod;
330218893Sdim  let Inst{3}   = 0;
331218893Sdim  let Inst{2-0} = iflags;
332226633Sdim  let DecoderMethod = "DecodeThumbCPS";
333203954Srdivacky}
334203954Srdivacky
335198090Srdivacky// For both thumb1 and thumb2.
336218893Sdimlet isNotDuplicable = 1, isCodeGenOnly = 1 in
337218893Sdimdef tPICADD : TIt<(outs GPR:$dst), (ins GPR:$lhs, pclabel:$cp), IIC_iALUr, "",
338218893Sdim                  [(set GPR:$dst, (ARMpic_add GPR:$lhs, imm:$cp))]>,
339263508Sdim              T1Special<{0,0,?,?}>, Sched<[WriteALU]> {
340218893Sdim  // A8.6.6
341218893Sdim  bits<3> dst;
342218893Sdim  let Inst{6-3} = 0b1111; // Rm = pc
343218893Sdim  let Inst{2-0} = dst;
344201360Srdivacky}
345193323Sed
346218893Sdim// ADD <Rd>, sp, #<imm8>
347226633Sdim// FIXME: This should not be marked as having side effects, and it should be
348226633Sdim// rematerializable. Clearing the side effect bit causes miscompilations,
349226633Sdim// probably because the instruction can be moved around.
350226633Sdimdef tADDrSPi : T1pI<(outs tGPR:$dst), (ins GPRsp:$sp, t_imm0_1020s4:$imm),
351226633Sdim                    IIC_iALUi, "add", "\t$dst, $sp, $imm", []>,
352263508Sdim               T1Encoding<{1,0,1,0,1,?}>, Sched<[WriteALU]> {
353218893Sdim  // A6.2 & A8.6.8
354218893Sdim  bits<3> dst;
355226633Sdim  bits<8> imm;
356218893Sdim  let Inst{10-8} = dst;
357226633Sdim  let Inst{7-0}  = imm;
358226633Sdim  let DecoderMethod = "DecodeThumbAddSpecialReg";
359212904Sdim}
360195098Sed
361218893Sdim// ADD sp, sp, #<imm7>
362226633Sdimdef tADDspi : T1pIt<(outs GPRsp:$Rdn), (ins GPRsp:$Rn, t_imm0_508s4:$imm),
363226633Sdim                     IIC_iALUi, "add", "\t$Rdn, $imm", []>,
364263508Sdim              T1Misc<{0,0,0,0,0,?,?}>, Sched<[WriteALU]> {
365218893Sdim  // A6.2.5 & A8.6.8
366226633Sdim  bits<7> imm;
367226633Sdim  let Inst{6-0} = imm;
368226633Sdim  let DecoderMethod = "DecodeThumbAddSPImm";
369218893Sdim}
370195098Sed
371218893Sdim// SUB sp, sp, #<imm7>
372218893Sdim// FIXME: The encoding and the ASM string don't match up.
373226633Sdimdef tSUBspi : T1pIt<(outs GPRsp:$Rdn), (ins GPRsp:$Rn, t_imm0_508s4:$imm),
374226633Sdim                    IIC_iALUi, "sub", "\t$Rdn, $imm", []>,
375263508Sdim              T1Misc<{0,0,0,0,1,?,?}>, Sched<[WriteALU]> {
376218893Sdim  // A6.2.5 & A8.6.214
377226633Sdim  bits<7> imm;
378226633Sdim  let Inst{6-0} = imm;
379226633Sdim  let DecoderMethod = "DecodeThumbAddSPImm";
380218893Sdim}
381198090Srdivacky
382234353Sdimdef : tInstAlias<"add${p} sp, $imm",
383234353Sdim                 (tSUBspi SP, t_imm0_508s4_neg:$imm, pred:$p)>;
384234353Sdimdef : tInstAlias<"add${p} sp, sp, $imm",
385234353Sdim                 (tSUBspi SP, t_imm0_508s4_neg:$imm, pred:$p)>;
386234353Sdim
387226633Sdim// Can optionally specify SP as a three operand instruction.
388226633Sdimdef : tInstAlias<"add${p} sp, sp, $imm",
389226633Sdim                 (tADDspi SP, t_imm0_508s4:$imm, pred:$p)>;
390226633Sdimdef : tInstAlias<"sub${p} sp, sp, $imm",
391226633Sdim                 (tSUBspi SP, t_imm0_508s4:$imm, pred:$p)>;
392226633Sdim
393218893Sdim// ADD <Rm>, sp
394239462Sdimdef tADDrSP : T1pI<(outs GPR:$Rdn), (ins GPRsp:$sp, GPR:$Rn), IIC_iALUr,
395239462Sdim                   "add", "\t$Rdn, $sp, $Rn", []>,
396263508Sdim              T1Special<{0,0,?,?}>, Sched<[WriteALU]> {
397218893Sdim  // A8.6.9 Encoding T1
398226633Sdim  bits<4> Rdn;
399226633Sdim  let Inst{7}   = Rdn{3};
400218893Sdim  let Inst{6-3} = 0b1101;
401226633Sdim  let Inst{2-0} = Rdn{2-0};
402226633Sdim  let DecoderMethod = "DecodeThumbAddSPReg";
403201360Srdivacky}
404198090Srdivacky
405218893Sdim// ADD sp, <Rm>
406226633Sdimdef tADDspr : T1pIt<(outs GPRsp:$Rdn), (ins GPRsp:$Rn, GPR:$Rm), IIC_iALUr,
407226633Sdim                  "add", "\t$Rdn, $Rm", []>,
408263508Sdim              T1Special<{0,0,?,?}>, Sched<[WriteALU]> {
409201360Srdivacky  // A8.6.9 Encoding T2
410226633Sdim  bits<4> Rm;
411201360Srdivacky  let Inst{7} = 1;
412226633Sdim  let Inst{6-3} = Rm;
413201360Srdivacky  let Inst{2-0} = 0b101;
414226633Sdim  let DecoderMethod = "DecodeThumbAddSPReg";
415201360Srdivacky}
416195098Sed
417193323Sed//===----------------------------------------------------------------------===//
418193323Sed//  Control Flow Instructions.
419193323Sed//
420193323Sed
421198892Srdivacky// Indirect branches
422198892Srdivackylet isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
423223017Sdim  def tBX : TI<(outs), (ins GPR:$Rm, pred:$p), IIC_Br, "bx${p}\t$Rm", []>,
424263508Sdim            T1Special<{1,1,0,?}>, Sched<[WriteBr]> {
425223017Sdim    // A6.2.3 & A8.6.25
426223017Sdim    bits<4> Rm;
427223017Sdim    let Inst{6-3} = Rm;
428223017Sdim    let Inst{2-0} = 0b000;
429234353Sdim    let Unpredictable{2-0} = 0b111;
430223017Sdim  }
431198892Srdivacky}
432198892Srdivacky
433224145Sdimlet isReturn = 1, isTerminator = 1, isBarrier = 1 in {
434224145Sdim  def tBX_RET : tPseudoExpand<(outs), (ins pred:$p), 2, IIC_Br,
435263508Sdim                   [(ARMretflag)], (tBX LR, pred:$p)>, Sched<[WriteBr]>;
436224145Sdim
437224145Sdim  // Alternative return instruction used by vararg functions.
438224145Sdim  def tBX_RET_vararg : tPseudoExpand<(outs), (ins tGPR:$Rm, pred:$p),
439224145Sdim                   2, IIC_Br, [],
440263508Sdim                   (tBX GPR:$Rm, pred:$p)>, Sched<[WriteBr]>;
441218893Sdim}
442193323Sed
443218893Sdim// All calls clobber the non-callee saved registers. SP is marked as a use to
444218893Sdim// prevent stack-pointer assignments that appear immediately before calls from
445218893Sdim// potentially appearing dead.
446193323Sedlet isCall = 1,
447234353Sdim  Defs = [LR], Uses = [SP] in {
448198090Srdivacky  // Also used for Thumb2
449201360Srdivacky  def tBL  : TIx2<0b11110, 0b11, 1,
450239462Sdim                  (outs), (ins pred:$p, t_bltarget:$func), IIC_Br,
451226633Sdim                  "bl${p}\t$func",
452201360Srdivacky                  [(ARMtcall tglobaladdr:$func)]>,
453263508Sdim             Requires<[IsThumb]>, Sched<[WriteBrL]> {
454239462Sdim    bits<24> func;
455239462Sdim    let Inst{26} = func{23};
456218893Sdim    let Inst{25-16} = func{20-11};
457239462Sdim    let Inst{13} = func{22};
458239462Sdim    let Inst{11} = func{21};
459218893Sdim    let Inst{10-0} = func{10-0};
460218893Sdim  }
461198090Srdivacky
462198090Srdivacky  // ARMv5T and above, also used for Thumb2
463201360Srdivacky  def tBLXi : TIx2<0b11110, 0b11, 0,
464239462Sdim                 (outs), (ins pred:$p, t_blxtarget:$func), IIC_Br,
465226633Sdim                   "blx${p}\t$func",
466201360Srdivacky                   [(ARMcall tglobaladdr:$func)]>,
467263508Sdim              Requires<[IsThumb, HasV5T]>, Sched<[WriteBrL]> {
468239462Sdim    bits<24> func;
469239462Sdim    let Inst{26} = func{23};
470218893Sdim    let Inst{25-16} = func{20-11};
471239462Sdim    let Inst{13} = func{22};
472239462Sdim    let Inst{11} = func{21};
473218893Sdim    let Inst{10-1} = func{10-1};
474218893Sdim    let Inst{0} = 0; // func{0} is assumed zero
475218893Sdim  }
476198090Srdivacky
477198090Srdivacky  // Also used for Thumb2
478239462Sdim  def tBLXr : TI<(outs), (ins pred:$p, GPR:$func), IIC_Br,
479226633Sdim                  "blx${p}\t$func",
480198090Srdivacky                  [(ARMtcall GPR:$func)]>,
481234353Sdim              Requires<[IsThumb, HasV5T]>,
482263508Sdim              T1Special<{1,1,1,?}>, Sched<[WriteBrL]> { // A6.2.3 & A8.6.24;
483223017Sdim    bits<4> func;
484223017Sdim    let Inst{6-3} = func;
485223017Sdim    let Inst{2-0} = 0b000;
486223017Sdim  }
487198090Srdivacky
488193323Sed  // ARMv4T
489239462Sdim  def tBX_CALL : tPseudoInst<(outs), (ins tGPR:$func),
490224145Sdim                  4, IIC_Br,
491198090Srdivacky                  [(ARMcall_nolink tGPR:$func)]>,
492263508Sdim            Requires<[IsThumb, IsThumb1Only]>, Sched<[WriteBr]>;
493193323Sed}
494193323Sed
495218893Sdimlet isBranch = 1, isTerminator = 1, isBarrier = 1 in {
496218893Sdim  let isPredicable = 1 in
497226633Sdim  def tB   : T1pI<(outs), (ins t_brtarget:$target), IIC_Br,
498226633Sdim                 "b", "\t$target", [(br bb:$target)]>,
499263508Sdim             T1Encoding<{1,1,1,0,0,?}>, Sched<[WriteBr]> {
500218893Sdim    bits<11> target;
501218893Sdim    let Inst{10-0} = target;
502263508Sdim    let AsmMatchConverter = "cvtThumbBranches";
503263508Sdim }
504193323Sed
505193323Sed  // Far jump
506218893Sdim  // Just a pseudo for a tBL instruction. Needed to let regalloc know about
507218893Sdim  // the clobber of LR.
508198090Srdivacky  let Defs = [LR] in
509226633Sdim  def tBfar : tPseudoExpand<(outs), (ins t_bltarget:$target, pred:$p),
510263508Sdim                          4, IIC_Br, [], (tBL pred:$p, t_bltarget:$target)>,
511263508Sdim                          Sched<[WriteBrTbl]>;
512193323Sed
513218893Sdim  def tBR_JTr : tPseudoInst<(outs),
514218893Sdim                      (ins tGPR:$target, i32imm:$jt, i32imm:$id),
515224145Sdim                      0, IIC_Br,
516263508Sdim                      [(ARMbrjt tGPR:$target, tjumptable:$jt, imm:$id)]>,
517263508Sdim                      Sched<[WriteBrTbl]> {
518218893Sdim    list<Predicate> Predicates = [IsThumb, IsThumb1Only];
519193323Sed  }
520193323Sed}
521193323Sed
522193323Sed// FIXME: should be able to write a pattern for ARMBrcond, but can't use
523193323Sed// a two-value operand where a dag node expects two operands. :(
524193323Sedlet isBranch = 1, isTerminator = 1 in
525218893Sdim  def tBcc : T1I<(outs), (ins t_bcctarget:$target, pred:$p), IIC_Br,
526218893Sdim                 "b${p}\t$target",
527201360Srdivacky                 [/*(ARMbrcond bb:$target, imm:$cc)*/]>,
528263508Sdim             T1BranchCond<{1,1,0,1}>, Sched<[WriteBr]> {
529218893Sdim  bits<4> p;
530218893Sdim  bits<8> target;
531218893Sdim  let Inst{11-8} = p;
532218893Sdim  let Inst{7-0} = target;
533263508Sdim  let AsmMatchConverter = "cvtThumbBranches";
534218893Sdim}
535193323Sed
536263508Sdim
537224145Sdim// Tail calls
538224145Sdimlet isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
539234353Sdim  // IOS versions.
540234353Sdim  let Uses = [SP] in {
541239462Sdim    def tTAILJMPr : tPseudoExpand<(outs), (ins tcGPR:$dst),
542224145Sdim                     4, IIC_Br, [],
543224145Sdim                     (tBX GPR:$dst, (ops 14, zero_reg))>,
544263508Sdim                     Requires<[IsThumb]>, Sched<[WriteBr]>;
545224145Sdim  }
546234353Sdim  // tTAILJMPd: IOS version uses a Thumb2 branch (no Thumb1 tail calls
547234353Sdim  // on IOS), so it's in ARMInstrThumb2.td.
548234353Sdim  // Non-IOS version:
549234353Sdim  let Uses = [SP] in {
550226633Sdim    def tTAILJMPdND : tPseudoExpand<(outs),
551239462Sdim                   (ins t_brtarget:$dst, pred:$p),
552224145Sdim                   4, IIC_Br, [],
553226633Sdim                   (tB t_brtarget:$dst, pred:$p)>,
554263508Sdim                 Requires<[IsThumb, IsNotIOS]>, Sched<[WriteBr]>;
555224145Sdim  }
556224145Sdim}
557224145Sdim
558224145Sdim
559226633Sdim// A8.6.218 Supervisor Call (Software Interrupt)
560204642Srdivacky// A8.6.16 B: Encoding T1
561204642Srdivacky// If Inst{11-8} == 0b1111 then SEE SVC
562218893Sdimlet isCall = 1, Uses = [SP] in
563226633Sdimdef tSVC : T1pI<(outs), (ins imm0_255:$imm), IIC_Br,
564263508Sdim                "svc", "\t$imm", []>, Encoding16, Sched<[WriteBr]> {
565218893Sdim  bits<8> imm;
566204642Srdivacky  let Inst{15-12} = 0b1101;
567218893Sdim  let Inst{11-8}  = 0b1111;
568218893Sdim  let Inst{7-0}   = imm;
569204642Srdivacky}
570204642Srdivacky
571218893Sdim// The assembler uses 0xDEFE for a trap instruction.
572208599Srdivackylet isBarrier = 1, isTerminator = 1 in
573223017Sdimdef tTRAP : TI<(outs), (ins), IIC_Br,
574263508Sdim               "trap", [(trap)]>, Encoding16, Sched<[WriteBr]> {
575218893Sdim  let Inst = 0xdefe;
576204642Srdivacky}
577204642Srdivacky
578193323Sed//===----------------------------------------------------------------------===//
579193323Sed//  Load Store Instructions.
580193323Sed//
581193323Sed
582218893Sdim// Loads: reg/reg and reg/imm5
583204642Srdivackylet canFoldAsLoad = 1, isReMaterializable = 1 in
584218893Sdimmulticlass thumb_ld_rr_ri_enc<bits<3> reg_opc, bits<4> imm_opc,
585218893Sdim                              Operand AddrMode_r, Operand AddrMode_i,
586218893Sdim                              AddrMode am, InstrItinClass itin_r,
587218893Sdim                              InstrItinClass itin_i, string asm,
588218893Sdim                              PatFrag opnode> {
589218893Sdim  def r : // reg/reg
590218893Sdim    T1pILdStEncode<reg_opc,
591218893Sdim                   (outs tGPR:$Rt), (ins AddrMode_r:$addr),
592218893Sdim                   am, itin_r, asm, "\t$Rt, $addr",
593218893Sdim                   [(set tGPR:$Rt, (opnode AddrMode_r:$addr))]>;
594218893Sdim  def i : // reg/imm5
595218893Sdim    T1pILdStEncodeImm<imm_opc, 1 /* Load */,
596218893Sdim                      (outs tGPR:$Rt), (ins AddrMode_i:$addr),
597218893Sdim                      am, itin_i, asm, "\t$Rt, $addr",
598218893Sdim                      [(set tGPR:$Rt, (opnode AddrMode_i:$addr))]>;
599218893Sdim}
600218893Sdim// Stores: reg/reg and reg/imm5
601218893Sdimmulticlass thumb_st_rr_ri_enc<bits<3> reg_opc, bits<4> imm_opc,
602218893Sdim                              Operand AddrMode_r, Operand AddrMode_i,
603218893Sdim                              AddrMode am, InstrItinClass itin_r,
604218893Sdim                              InstrItinClass itin_i, string asm,
605218893Sdim                              PatFrag opnode> {
606218893Sdim  def r : // reg/reg
607218893Sdim    T1pILdStEncode<reg_opc,
608218893Sdim                   (outs), (ins tGPR:$Rt, AddrMode_r:$addr),
609218893Sdim                   am, itin_r, asm, "\t$Rt, $addr",
610218893Sdim                   [(opnode tGPR:$Rt, AddrMode_r:$addr)]>;
611218893Sdim  def i : // reg/imm5
612218893Sdim    T1pILdStEncodeImm<imm_opc, 0 /* Store */,
613218893Sdim                      (outs), (ins tGPR:$Rt, AddrMode_i:$addr),
614218893Sdim                      am, itin_i, asm, "\t$Rt, $addr",
615218893Sdim                      [(opnode tGPR:$Rt, AddrMode_i:$addr)]>;
616218893Sdim}
617193323Sed
618218893Sdim// A8.6.57 & A8.6.60
619218893Sdimdefm tLDR  : thumb_ld_rr_ri_enc<0b100, 0b0110, t_addrmode_rrs4,
620218893Sdim                                t_addrmode_is4, AddrModeT1_4,
621218893Sdim                                IIC_iLoad_r, IIC_iLoad_i, "ldr",
622218893Sdim                                UnOpFrag<(load node:$Src)>>;
623193323Sed
624218893Sdim// A8.6.64 & A8.6.61
625218893Sdimdefm tLDRB : thumb_ld_rr_ri_enc<0b110, 0b0111, t_addrmode_rrs1,
626218893Sdim                                t_addrmode_is1, AddrModeT1_1,
627218893Sdim                                IIC_iLoad_bh_r, IIC_iLoad_bh_i, "ldrb",
628218893Sdim                                UnOpFrag<(zextloadi8 node:$Src)>>;
629193323Sed
630218893Sdim// A8.6.76 & A8.6.73
631218893Sdimdefm tLDRH : thumb_ld_rr_ri_enc<0b101, 0b1000, t_addrmode_rrs2,
632218893Sdim                                t_addrmode_is2, AddrModeT1_2,
633218893Sdim                                IIC_iLoad_bh_r, IIC_iLoad_bh_i, "ldrh",
634218893Sdim                                UnOpFrag<(zextloadi16 node:$Src)>>;
635218893Sdim
636198090Srdivackylet AddedComplexity = 10 in
637218893Sdimdef tLDRSB :                    // A8.6.80
638226633Sdim  T1pILdStEncode<0b011, (outs tGPR:$Rt), (ins t_addrmode_rr:$addr),
639218893Sdim                 AddrModeT1_1, IIC_iLoad_bh_r,
640226633Sdim                 "ldrsb", "\t$Rt, $addr",
641226633Sdim                 [(set tGPR:$Rt, (sextloadi8 t_addrmode_rr:$addr))]>;
642193323Sed
643198090Srdivackylet AddedComplexity = 10 in
644218893Sdimdef tLDRSH :                    // A8.6.84
645226633Sdim  T1pILdStEncode<0b111, (outs tGPR:$Rt), (ins t_addrmode_rr:$addr),
646218893Sdim                 AddrModeT1_2, IIC_iLoad_bh_r,
647226633Sdim                 "ldrsh", "\t$Rt, $addr",
648226633Sdim                 [(set tGPR:$Rt, (sextloadi16 t_addrmode_rr:$addr))]>;
649193323Sed
650193323Sedlet canFoldAsLoad = 1 in
651218893Sdimdef tLDRspi : T1pIs<(outs tGPR:$Rt), (ins t_addrmode_sp:$addr), IIC_iLoad_i,
652218893Sdim                    "ldr", "\t$Rt, $addr",
653218893Sdim                    [(set tGPR:$Rt, (load t_addrmode_sp:$addr))]>,
654218893Sdim              T1LdStSP<{1,?,?}> {
655218893Sdim  bits<3> Rt;
656218893Sdim  bits<8> addr;
657218893Sdim  let Inst{10-8} = Rt;
658218893Sdim  let Inst{7-0} = addr;
659218893Sdim}
660193323Sed
661263508Sdimlet canFoldAsLoad = 1, isReMaterializable = 1 in
662218893Sdimdef tLDRpci : T1pIs<(outs tGPR:$Rt), (ins t_addrmode_pc:$addr), IIC_iLoad_i,
663263508Sdim                  "ldr", "\t$Rt, $addr",
664218893Sdim                  [(set tGPR:$Rt, (load (ARMWrapper tconstpool:$addr)))]>,
665218893Sdim              T1Encoding<{0,1,0,0,1,?}> {
666218893Sdim  // A6.2 & A8.6.59
667218893Sdim  bits<3> Rt;
668218893Sdim  bits<8> addr;
669218893Sdim  let Inst{10-8} = Rt;
670218893Sdim  let Inst{7-0}  = addr;
671218893Sdim}
672193323Sed
673218893Sdim// A8.6.194 & A8.6.192
674218893Sdimdefm tSTR  : thumb_st_rr_ri_enc<0b000, 0b0110, t_addrmode_rrs4,
675218893Sdim                                t_addrmode_is4, AddrModeT1_4,
676218893Sdim                                IIC_iStore_r, IIC_iStore_i, "str",
677218893Sdim                                BinOpFrag<(store node:$LHS, node:$RHS)>>;
678193323Sed
679218893Sdim// A8.6.197 & A8.6.195
680218893Sdimdefm tSTRB : thumb_st_rr_ri_enc<0b010, 0b0111, t_addrmode_rrs1,
681218893Sdim                                t_addrmode_is1, AddrModeT1_1,
682218893Sdim                                IIC_iStore_bh_r, IIC_iStore_bh_i, "strb",
683218893Sdim                                BinOpFrag<(truncstorei8 node:$LHS, node:$RHS)>>;
684193323Sed
685218893Sdim// A8.6.207 & A8.6.205
686218893Sdimdefm tSTRH : thumb_st_rr_ri_enc<0b001, 0b1000, t_addrmode_rrs2,
687224145Sdim                               t_addrmode_is2, AddrModeT1_2,
688224145Sdim                               IIC_iStore_bh_r, IIC_iStore_bh_i, "strh",
689224145Sdim                               BinOpFrag<(truncstorei16 node:$LHS, node:$RHS)>>;
690193323Sed
691193323Sed
692218893Sdimdef tSTRspi : T1pIs<(outs), (ins tGPR:$Rt, t_addrmode_sp:$addr), IIC_iStore_i,
693218893Sdim                    "str", "\t$Rt, $addr",
694218893Sdim                    [(store tGPR:$Rt, t_addrmode_sp:$addr)]>,
695218893Sdim              T1LdStSP<{0,?,?}> {
696218893Sdim  bits<3> Rt;
697218893Sdim  bits<8> addr;
698218893Sdim  let Inst{10-8} = Rt;
699218893Sdim  let Inst{7-0} = addr;
700218893Sdim}
701193323Sed
702193323Sed//===----------------------------------------------------------------------===//
703193323Sed//  Load / store multiple Instructions.
704193323Sed//
705193323Sed
706218893Sdim// These require base address to be written back or one of the loaded regs.
707218893Sdimlet neverHasSideEffects = 1 in {
708205218Srdivacky
709218893Sdimlet mayLoad = 1, hasExtraDefRegAllocReq = 1 in
710226633Sdimdef tLDMIA : T1I<(outs), (ins tGPR:$Rn, pred:$p, reglist:$regs, variable_ops),
711226633Sdim        IIC_iLoad_m, "ldm${p}\t$Rn, $regs", []>, T1Encoding<{1,1,0,0,1,?}> {
712226633Sdim  bits<3> Rn;
713226633Sdim  bits<8> regs;
714226633Sdim  let Inst{10-8} = Rn;
715226633Sdim  let Inst{7-0}  = regs;
716226633Sdim}
717193323Sed
718226633Sdim// Writeback version is just a pseudo, as there's no encoding difference.
719226633Sdim// Writeback happens iff the base register is not in the destination register
720226633Sdim// list.
721226633Sdimdef tLDMIA_UPD :
722226633Sdim    InstTemplate<AddrModeNone, 0, IndexModeNone, Pseudo, GenericDomain,
723226633Sdim                 "$Rn = $wb", IIC_iLoad_mu>,
724226633Sdim    PseudoInstExpansion<(tLDMIA tGPR:$Rn, pred:$p, reglist:$regs)> {
725226633Sdim  let Size = 2;
726226633Sdim  let OutOperandList = (outs GPR:$wb);
727226633Sdim  let InOperandList = (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops);
728226633Sdim  let Pattern = [];
729226633Sdim  let isCodeGenOnly = 1;
730226633Sdim  let isPseudo = 1;
731226633Sdim  list<Predicate> Predicates = [IsThumb];
732226633Sdim}
733226633Sdim
734226633Sdim// There is no non-writeback version of STM for Thumb.
735218893Sdimlet mayStore = 1, hasExtraSrcRegAllocReq = 1 in
736226633Sdimdef tSTMIA_UPD : Thumb1I<(outs GPR:$wb),
737226633Sdim                         (ins tGPR:$Rn, pred:$p, reglist:$regs, variable_ops),
738226633Sdim                         AddrModeNone, 2, IIC_iStore_mu,
739226633Sdim                         "stm${p}\t$Rn!, $regs", "$Rn = $wb", []>,
740226633Sdim                     T1Encoding<{1,1,0,0,0,?}> {
741226633Sdim  bits<3> Rn;
742226633Sdim  bits<8> regs;
743226633Sdim  let Inst{10-8} = Rn;
744226633Sdim  let Inst{7-0}  = regs;
745226633Sdim}
746223017Sdim
747218893Sdim} // neverHasSideEffects
748218893Sdim
749226633Sdimdef : InstAlias<"ldm${p} $Rn!, $regs",
750226633Sdim                (tLDMIA tGPR:$Rn, pred:$p, reglist:$regs)>,
751226633Sdim        Requires<[IsThumb, IsThumb1Only]>;
752226633Sdim
753198090Srdivackylet mayLoad = 1, Uses = [SP], Defs = [SP], hasExtraDefRegAllocReq = 1 in
754218893Sdimdef tPOP : T1I<(outs), (ins pred:$p, reglist:$regs, variable_ops),
755218893Sdim               IIC_iPop,
756218893Sdim               "pop${p}\t$regs", []>,
757218893Sdim           T1Misc<{1,1,0,?,?,?,?}> {
758218893Sdim  bits<16> regs;
759218893Sdim  let Inst{8}   = regs{15};
760218893Sdim  let Inst{7-0} = regs{7-0};
761218893Sdim}
762193323Sed
763198090Srdivackylet mayStore = 1, Uses = [SP], Defs = [SP], hasExtraSrcRegAllocReq = 1 in
764218893Sdimdef tPUSH : T1I<(outs), (ins pred:$p, reglist:$regs, variable_ops),
765218893Sdim                IIC_iStore_m,
766218893Sdim                "push${p}\t$regs", []>,
767218893Sdim            T1Misc<{0,1,0,?,?,?,?}> {
768218893Sdim  bits<16> regs;
769218893Sdim  let Inst{8}   = regs{14};
770218893Sdim  let Inst{7-0} = regs{7-0};
771218893Sdim}
772198090Srdivacky
773193323Sed//===----------------------------------------------------------------------===//
774193323Sed//  Arithmetic Instructions.
775193323Sed//
776193323Sed
777218893Sdim// Helper classes for encoding T1pI patterns:
778218893Sdimclass T1pIDPEncode<bits<4> opA, dag oops, dag iops, InstrItinClass itin,
779218893Sdim                   string opc, string asm, list<dag> pattern>
780218893Sdim    : T1pI<oops, iops, itin, opc, asm, pattern>,
781218893Sdim      T1DataProcessing<opA> {
782218893Sdim  bits<3> Rm;
783218893Sdim  bits<3> Rn;
784218893Sdim  let Inst{5-3} = Rm;
785218893Sdim  let Inst{2-0} = Rn;
786218893Sdim}
787218893Sdimclass T1pIMiscEncode<bits<7> opA, dag oops, dag iops, InstrItinClass itin,
788218893Sdim                     string opc, string asm, list<dag> pattern>
789218893Sdim    : T1pI<oops, iops, itin, opc, asm, pattern>,
790218893Sdim      T1Misc<opA> {
791218893Sdim  bits<3> Rm;
792218893Sdim  bits<3> Rd;
793218893Sdim  let Inst{5-3} = Rm;
794218893Sdim  let Inst{2-0} = Rd;
795218893Sdim}
796218893Sdim
797218893Sdim// Helper classes for encoding T1sI patterns:
798218893Sdimclass T1sIDPEncode<bits<4> opA, dag oops, dag iops, InstrItinClass itin,
799218893Sdim                   string opc, string asm, list<dag> pattern>
800218893Sdim    : T1sI<oops, iops, itin, opc, asm, pattern>,
801218893Sdim      T1DataProcessing<opA> {
802218893Sdim  bits<3> Rd;
803218893Sdim  bits<3> Rn;
804218893Sdim  let Inst{5-3} = Rn;
805218893Sdim  let Inst{2-0} = Rd;
806218893Sdim}
807218893Sdimclass T1sIGenEncode<bits<5> opA, dag oops, dag iops, InstrItinClass itin,
808218893Sdim                    string opc, string asm, list<dag> pattern>
809218893Sdim    : T1sI<oops, iops, itin, opc, asm, pattern>,
810218893Sdim      T1General<opA> {
811218893Sdim  bits<3> Rm;
812218893Sdim  bits<3> Rn;
813218893Sdim  bits<3> Rd;
814218893Sdim  let Inst{8-6} = Rm;
815218893Sdim  let Inst{5-3} = Rn;
816218893Sdim  let Inst{2-0} = Rd;
817218893Sdim}
818218893Sdimclass T1sIGenEncodeImm<bits<5> opA, dag oops, dag iops, InstrItinClass itin,
819218893Sdim                       string opc, string asm, list<dag> pattern>
820218893Sdim    : T1sI<oops, iops, itin, opc, asm, pattern>,
821218893Sdim      T1General<opA> {
822218893Sdim  bits<3> Rd;
823218893Sdim  bits<3> Rm;
824218893Sdim  let Inst{5-3} = Rm;
825218893Sdim  let Inst{2-0} = Rd;
826218893Sdim}
827218893Sdim
828218893Sdim// Helper classes for encoding T1sIt patterns:
829218893Sdimclass T1sItDPEncode<bits<4> opA, dag oops, dag iops, InstrItinClass itin,
830218893Sdim                    string opc, string asm, list<dag> pattern>
831218893Sdim    : T1sIt<oops, iops, itin, opc, asm, pattern>,
832218893Sdim      T1DataProcessing<opA> {
833218893Sdim  bits<3> Rdn;
834218893Sdim  bits<3> Rm;
835218893Sdim  let Inst{5-3} = Rm;
836218893Sdim  let Inst{2-0} = Rdn;
837218893Sdim}
838218893Sdimclass T1sItGenEncodeImm<bits<5> opA, dag oops, dag iops, InstrItinClass itin,
839218893Sdim                        string opc, string asm, list<dag> pattern>
840218893Sdim    : T1sIt<oops, iops, itin, opc, asm, pattern>,
841218893Sdim      T1General<opA> {
842218893Sdim  bits<3> Rdn;
843218893Sdim  bits<8> imm8;
844218893Sdim  let Inst{10-8} = Rdn;
845218893Sdim  let Inst{7-0}  = imm8;
846218893Sdim}
847218893Sdim
848195098Sed// Add with carry register
849198090Srdivackylet isCommutable = 1, Uses = [CPSR] in
850218893Sdimdef tADC :                      // A8.6.2
851218893Sdim  T1sItDPEncode<0b0101, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), IIC_iALUr,
852218893Sdim                "adc", "\t$Rdn, $Rm",
853263508Sdim                [(set tGPR:$Rdn, (adde tGPR:$Rn, tGPR:$Rm))]>, Sched<[WriteALU]>;
854193323Sed
855195098Sed// Add immediate
856218893Sdimdef tADDi3 :                    // A8.6.4 T1
857226633Sdim  T1sIGenEncodeImm<0b01110, (outs tGPR:$Rd), (ins tGPR:$Rm, imm0_7:$imm3),
858224145Sdim                   IIC_iALUi,
859218893Sdim                   "add", "\t$Rd, $Rm, $imm3",
860263508Sdim                   [(set tGPR:$Rd, (add tGPR:$Rm, imm0_7:$imm3))]>,
861263508Sdim                   Sched<[WriteALU]> {
862218893Sdim  bits<3> imm3;
863218893Sdim  let Inst{8-6} = imm3;
864218893Sdim}
865193323Sed
866218893Sdimdef tADDi8 :                    // A8.6.4 T2
867226633Sdim  T1sItGenEncodeImm<{1,1,0,?,?}, (outs tGPR:$Rdn),
868226633Sdim                    (ins tGPR:$Rn, imm0_255:$imm8), IIC_iALUi,
869218893Sdim                    "add", "\t$Rdn, $imm8",
870263508Sdim                    [(set tGPR:$Rdn, (add tGPR:$Rn, imm8_255:$imm8))]>,
871263508Sdim                    Sched<[WriteALU]>;
872193323Sed
873195098Sed// Add register
874198090Srdivackylet isCommutable = 1 in
875218893Sdimdef tADDrr :                    // A8.6.6 T1
876218893Sdim  T1sIGenEncode<0b01100, (outs tGPR:$Rd), (ins tGPR:$Rn, tGPR:$Rm),
877218893Sdim                IIC_iALUr,
878218893Sdim                "add", "\t$Rd, $Rn, $Rm",
879263508Sdim                [(set tGPR:$Rd, (add tGPR:$Rn, tGPR:$Rm))]>, Sched<[WriteALU]>;
880193323Sed
881194178Sedlet neverHasSideEffects = 1 in
882218893Sdimdef tADDhirr : T1pIt<(outs GPR:$Rdn), (ins GPR:$Rn, GPR:$Rm), IIC_iALUr,
883218893Sdim                     "add", "\t$Rdn, $Rm", []>,
884263508Sdim               T1Special<{0,0,?,?}>, Sched<[WriteALU]> {
885218893Sdim  // A8.6.6 T2
886218893Sdim  bits<4> Rdn;
887218893Sdim  bits<4> Rm;
888218893Sdim  let Inst{7}   = Rdn{3};
889218893Sdim  let Inst{6-3} = Rm;
890218893Sdim  let Inst{2-0} = Rdn{2-0};
891218893Sdim}
892193323Sed
893218893Sdim// AND register
894198090Srdivackylet isCommutable = 1 in
895218893Sdimdef tAND :                      // A8.6.12
896218893Sdim  T1sItDPEncode<0b0000, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm),
897218893Sdim                IIC_iBITr,
898218893Sdim                "and", "\t$Rdn, $Rm",
899263508Sdim                [(set tGPR:$Rdn, (and tGPR:$Rn, tGPR:$Rm))]>, Sched<[WriteALU]>;
900193323Sed
901195098Sed// ASR immediate
902218893Sdimdef tASRri :                    // A8.6.14
903226633Sdim  T1sIGenEncodeImm<{0,1,0,?,?}, (outs tGPR:$Rd), (ins tGPR:$Rm, imm_sr:$imm5),
904218893Sdim                   IIC_iMOVsi,
905218893Sdim                   "asr", "\t$Rd, $Rm, $imm5",
906263508Sdim                   [(set tGPR:$Rd, (sra tGPR:$Rm, (i32 imm_sr:$imm5)))]>,
907263508Sdim                   Sched<[WriteALU]> {
908218893Sdim  bits<5> imm5;
909218893Sdim  let Inst{10-6} = imm5;
910218893Sdim}
911193323Sed
912195098Sed// ASR register
913218893Sdimdef tASRrr :                    // A8.6.15
914218893Sdim  T1sItDPEncode<0b0100, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm),
915218893Sdim                IIC_iMOVsr,
916218893Sdim                "asr", "\t$Rdn, $Rm",
917263508Sdim                [(set tGPR:$Rdn, (sra tGPR:$Rn, tGPR:$Rm))]>, Sched<[WriteALU]>;
918193323Sed
919195098Sed// BIC register
920218893Sdimdef tBIC :                      // A8.6.20
921218893Sdim  T1sItDPEncode<0b1110, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm),
922218893Sdim                IIC_iBITr,
923218893Sdim                "bic", "\t$Rdn, $Rm",
924263508Sdim                [(set tGPR:$Rdn, (and tGPR:$Rn, (not tGPR:$Rm)))]>,
925263508Sdim                Sched<[WriteALU]>;
926193323Sed
927195098Sed// CMN register
928218893Sdimlet isCompare = 1, Defs = [CPSR] in {
929202878Srdivacky//FIXME: Disable CMN, as CCodes are backwards from compare expectations
930202878Srdivacky//       Compare-to-zero still works out, just not the relationals
931218893Sdim//def tCMN :                     // A8.6.33
932218893Sdim//  T1pIDPEncode<0b1011, (outs), (ins tGPR:$lhs, tGPR:$rhs),
933218893Sdim//               IIC_iCMPr,
934218893Sdim//               "cmn", "\t$lhs, $rhs",
935218893Sdim//               [(ARMcmp tGPR:$lhs, (ineg tGPR:$rhs))]>;
936193323Sed
937218893Sdimdef tCMNz :                     // A8.6.33
938218893Sdim  T1pIDPEncode<0b1011, (outs), (ins tGPR:$Rn, tGPR:$Rm),
939218893Sdim               IIC_iCMPr,
940218893Sdim               "cmn", "\t$Rn, $Rm",
941263508Sdim               [(ARMcmpZ tGPR:$Rn, (ineg tGPR:$Rm))]>, Sched<[WriteCMP]>;
942218893Sdim
943218893Sdim} // isCompare = 1, Defs = [CPSR]
944218893Sdim
945195098Sed// CMP immediate
946218893Sdimlet isCompare = 1, Defs = [CPSR] in {
947226633Sdimdef tCMPi8 : T1pI<(outs), (ins tGPR:$Rn, imm0_255:$imm8), IIC_iCMPi,
948218893Sdim                  "cmp", "\t$Rn, $imm8",
949218893Sdim                  [(ARMcmp tGPR:$Rn, imm0_255:$imm8)]>,
950263508Sdim             T1General<{1,0,1,?,?}>, Sched<[WriteCMP]> {
951218893Sdim  // A8.6.35
952218893Sdim  bits<3> Rn;
953218893Sdim  bits<8> imm8;
954218893Sdim  let Inst{10-8} = Rn;
955218893Sdim  let Inst{7-0}  = imm8;
956195098Sed}
957195098Sed
958195098Sed// CMP register
959218893Sdimdef tCMPr :                     // A8.6.36 T1
960218893Sdim  T1pIDPEncode<0b1010, (outs), (ins tGPR:$Rn, tGPR:$Rm),
961218893Sdim               IIC_iCMPr,
962218893Sdim               "cmp", "\t$Rn, $Rm",
963263508Sdim               [(ARMcmp tGPR:$Rn, tGPR:$Rm)]>, Sched<[WriteCMP]>;
964198090Srdivacky
965218893Sdimdef tCMPhir : T1pI<(outs), (ins GPR:$Rn, GPR:$Rm), IIC_iCMPr,
966218893Sdim                   "cmp", "\t$Rn, $Rm", []>,
967263508Sdim              T1Special<{0,1,?,?}>, Sched<[WriteCMP]> {
968218893Sdim  // A8.6.36 T2
969218893Sdim  bits<4> Rm;
970218893Sdim  bits<4> Rn;
971218893Sdim  let Inst{7}   = Rn{3};
972218893Sdim  let Inst{6-3} = Rm;
973218893Sdim  let Inst{2-0} = Rn{2-0};
974195098Sed}
975218893Sdim} // isCompare = 1, Defs = [CPSR]
976193323Sed
977193323Sed
978195098Sed// XOR register
979198090Srdivackylet isCommutable = 1 in
980218893Sdimdef tEOR :                      // A8.6.45
981218893Sdim  T1sItDPEncode<0b0001, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm),
982218893Sdim                IIC_iBITr,
983218893Sdim                "eor", "\t$Rdn, $Rm",
984263508Sdim                [(set tGPR:$Rdn, (xor tGPR:$Rn, tGPR:$Rm))]>, Sched<[WriteALU]>;
985193323Sed
986195098Sed// LSL immediate
987218893Sdimdef tLSLri :                    // A8.6.88
988226633Sdim  T1sIGenEncodeImm<{0,0,0,?,?}, (outs tGPR:$Rd), (ins tGPR:$Rm, imm0_31:$imm5),
989218893Sdim                   IIC_iMOVsi,
990218893Sdim                   "lsl", "\t$Rd, $Rm, $imm5",
991263508Sdim                   [(set tGPR:$Rd, (shl tGPR:$Rm, (i32 imm:$imm5)))]>,
992263508Sdim                   Sched<[WriteALU]> {
993218893Sdim  bits<5> imm5;
994218893Sdim  let Inst{10-6} = imm5;
995218893Sdim}
996193323Sed
997195098Sed// LSL register
998218893Sdimdef tLSLrr :                    // A8.6.89
999218893Sdim  T1sItDPEncode<0b0010, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm),
1000218893Sdim                IIC_iMOVsr,
1001218893Sdim                "lsl", "\t$Rdn, $Rm",
1002263508Sdim                [(set tGPR:$Rdn, (shl tGPR:$Rn, tGPR:$Rm))]>, Sched<[WriteALU]>;
1003193323Sed
1004195098Sed// LSR immediate
1005218893Sdimdef tLSRri :                    // A8.6.90
1006226633Sdim  T1sIGenEncodeImm<{0,0,1,?,?}, (outs tGPR:$Rd), (ins tGPR:$Rm, imm_sr:$imm5),
1007218893Sdim                   IIC_iMOVsi,
1008218893Sdim                   "lsr", "\t$Rd, $Rm, $imm5",
1009263508Sdim                   [(set tGPR:$Rd, (srl tGPR:$Rm, (i32 imm_sr:$imm5)))]>,
1010263508Sdim                   Sched<[WriteALU]> {
1011218893Sdim  bits<5> imm5;
1012218893Sdim  let Inst{10-6} = imm5;
1013218893Sdim}
1014193323Sed
1015195098Sed// LSR register
1016218893Sdimdef tLSRrr :                    // A8.6.91
1017218893Sdim  T1sItDPEncode<0b0011, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm),
1018218893Sdim                IIC_iMOVsr,
1019218893Sdim                "lsr", "\t$Rdn, $Rm",
1020263508Sdim                [(set tGPR:$Rdn, (srl tGPR:$Rn, tGPR:$Rm))]>, Sched<[WriteALU]>;
1021193323Sed
1022218893Sdim// Move register
1023218893Sdimlet isMoveImm = 1 in
1024224145Sdimdef tMOVi8 : T1sI<(outs tGPR:$Rd), (ins imm0_255:$imm8), IIC_iMOVi,
1025218893Sdim                  "mov", "\t$Rd, $imm8",
1026218893Sdim                  [(set tGPR:$Rd, imm0_255:$imm8)]>,
1027263508Sdim             T1General<{1,0,0,?,?}>, Sched<[WriteALU]> {
1028218893Sdim  // A8.6.96
1029218893Sdim  bits<3> Rd;
1030218893Sdim  bits<8> imm8;
1031218893Sdim  let Inst{10-8} = Rd;
1032218893Sdim  let Inst{7-0}  = imm8;
1033218893Sdim}
1034226633Sdim// Because we have an explicit tMOVSr below, we need an alias to handle
1035226633Sdim// the immediate "movs" form here. Blech.
1036226633Sdimdef : tInstAlias <"movs $Rdn, $imm",
1037226633Sdim                 (tMOVi8 tGPR:$Rdn, CPSR, imm0_255:$imm, 14, 0)>;
1038193323Sed
1039224145Sdim// A7-73: MOV(2) - mov setting flag.
1040193323Sed
1041194178Sedlet neverHasSideEffects = 1 in {
1042224145Sdimdef tMOVr : Thumb1pI<(outs GPR:$Rd), (ins GPR:$Rm), AddrModeNone,
1043224145Sdim                      2, IIC_iMOVr,
1044224145Sdim                      "mov", "\t$Rd, $Rm", "", []>,
1045263508Sdim                  T1Special<{1,0,?,?}>, Sched<[WriteALU]> {
1046218893Sdim  // A8.6.97
1047218893Sdim  bits<4> Rd;
1048218893Sdim  bits<4> Rm;
1049224145Sdim  let Inst{7}   = Rd{3};
1050224145Sdim  let Inst{6-3} = Rm;
1051218893Sdim  let Inst{2-0} = Rd{2-0};
1052218893Sdim}
1053198090Srdivackylet Defs = [CPSR] in
1054218893Sdimdef tMOVSr      : T1I<(outs tGPR:$Rd), (ins tGPR:$Rm), IIC_iMOVr,
1055263508Sdim                      "movs\t$Rd, $Rm", []>, Encoding16, Sched<[WriteALU]> {
1056218893Sdim  // A8.6.97
1057218893Sdim  bits<3> Rd;
1058218893Sdim  bits<3> Rm;
1059201360Srdivacky  let Inst{15-6} = 0b0000000000;
1060218893Sdim  let Inst{5-3}  = Rm;
1061218893Sdim  let Inst{2-0}  = Rd;
1062201360Srdivacky}
1063194178Sed} // neverHasSideEffects
1064193323Sed
1065218893Sdim// Multiply register
1066198090Srdivackylet isCommutable = 1 in
1067218893Sdimdef tMUL :                      // A8.6.105 T1
1068226633Sdim  Thumb1sI<(outs tGPR:$Rd), (ins tGPR:$Rn, tGPR:$Rm), AddrModeNone, 2,
1069226633Sdim           IIC_iMUL32, "mul", "\t$Rd, $Rn, $Rm", "$Rm = $Rd",
1070226633Sdim           [(set tGPR:$Rd, (mul tGPR:$Rn, tGPR:$Rm))]>,
1071226633Sdim      T1DataProcessing<0b1101> {
1072226633Sdim  bits<3> Rd;
1073226633Sdim  bits<3> Rn;
1074226633Sdim  let Inst{5-3} = Rn;
1075226633Sdim  let Inst{2-0} = Rd;
1076226633Sdim  let AsmMatchConverter = "cvtThumbMultiply";
1077226633Sdim}
1078193323Sed
1079226633Sdimdef :tInstAlias<"mul${s}${p} $Rdm, $Rn", (tMUL tGPR:$Rdm, s_cc_out:$s, tGPR:$Rn,
1080226633Sdim                                               pred:$p)>;
1081226633Sdim
1082218893Sdim// Move inverse register
1083218893Sdimdef tMVN :                      // A8.6.107
1084218893Sdim  T1sIDPEncode<0b1111, (outs tGPR:$Rd), (ins tGPR:$Rn), IIC_iMVNr,
1085218893Sdim               "mvn", "\t$Rd, $Rn",
1086263508Sdim               [(set tGPR:$Rd, (not tGPR:$Rn))]>, Sched<[WriteALU]>;
1087193323Sed
1088218893Sdim// Bitwise or register
1089198090Srdivackylet isCommutable = 1 in
1090218893Sdimdef tORR :                      // A8.6.114
1091218893Sdim  T1sItDPEncode<0b1100, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm),
1092218893Sdim                IIC_iBITr,
1093218893Sdim                "orr", "\t$Rdn, $Rm",
1094263508Sdim                [(set tGPR:$Rdn, (or tGPR:$Rn, tGPR:$Rm))]>, Sched<[WriteALU]>;
1095193323Sed
1096218893Sdim// Swaps
1097218893Sdimdef tREV :                      // A8.6.134
1098218893Sdim  T1pIMiscEncode<{1,0,1,0,0,0,?}, (outs tGPR:$Rd), (ins tGPR:$Rm),
1099218893Sdim                 IIC_iUNAr,
1100218893Sdim                 "rev", "\t$Rd, $Rm",
1101218893Sdim                 [(set tGPR:$Rd, (bswap tGPR:$Rm))]>,
1102263508Sdim                 Requires<[IsThumb, IsThumb1Only, HasV6]>, Sched<[WriteALU]>;
1103193323Sed
1104218893Sdimdef tREV16 :                    // A8.6.135
1105218893Sdim  T1pIMiscEncode<{1,0,1,0,0,1,?}, (outs tGPR:$Rd), (ins tGPR:$Rm),
1106218893Sdim                 IIC_iUNAr,
1107218893Sdim                 "rev16", "\t$Rd, $Rm",
1108224145Sdim             [(set tGPR:$Rd, (rotr (bswap tGPR:$Rm), (i32 16)))]>,
1109263508Sdim                Requires<[IsThumb, IsThumb1Only, HasV6]>, Sched<[WriteALU]>;
1110193323Sed
1111218893Sdimdef tREVSH :                    // A8.6.136
1112218893Sdim  T1pIMiscEncode<{1,0,1,0,1,1,?}, (outs tGPR:$Rd), (ins tGPR:$Rm),
1113218893Sdim                 IIC_iUNAr,
1114218893Sdim                 "revsh", "\t$Rd, $Rm",
1115224145Sdim                 [(set tGPR:$Rd, (sra (bswap tGPR:$Rm), (i32 16)))]>,
1116263508Sdim                 Requires<[IsThumb, IsThumb1Only, HasV6]>, Sched<[WriteALU]>;
1117193323Sed
1118218893Sdim// Rotate right register
1119218893Sdimdef tROR :                      // A8.6.139
1120218893Sdim  T1sItDPEncode<0b0111, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm),
1121218893Sdim                IIC_iMOVsr,
1122218893Sdim                "ror", "\t$Rdn, $Rm",
1123263508Sdim                [(set tGPR:$Rdn, (rotr tGPR:$Rn, tGPR:$Rm))]>,
1124263508Sdim                Sched<[WriteALU]>;
1125193323Sed
1126218893Sdim// Negate register
1127218893Sdimdef tRSB :                      // A8.6.141
1128218893Sdim  T1sIDPEncode<0b1001, (outs tGPR:$Rd), (ins tGPR:$Rn),
1129218893Sdim               IIC_iALUi,
1130218893Sdim               "rsb", "\t$Rd, $Rn, #0",
1131263508Sdim               [(set tGPR:$Rd, (ineg tGPR:$Rn))]>, Sched<[WriteALU]>;
1132198090Srdivacky
1133195098Sed// Subtract with carry register
1134198090Srdivackylet Uses = [CPSR] in
1135218893Sdimdef tSBC :                      // A8.6.151
1136218893Sdim  T1sItDPEncode<0b0110, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm),
1137218893Sdim                IIC_iALUr,
1138218893Sdim                "sbc", "\t$Rdn, $Rm",
1139263508Sdim                [(set tGPR:$Rdn, (sube tGPR:$Rn, tGPR:$Rm))]>,
1140263508Sdim                Sched<[WriteALU]>;
1141193323Sed
1142195098Sed// Subtract immediate
1143218893Sdimdef tSUBi3 :                    // A8.6.210 T1
1144226633Sdim  T1sIGenEncodeImm<0b01111, (outs tGPR:$Rd), (ins tGPR:$Rm, imm0_7:$imm3),
1145218893Sdim                   IIC_iALUi,
1146218893Sdim                   "sub", "\t$Rd, $Rm, $imm3",
1147263508Sdim                   [(set tGPR:$Rd, (add tGPR:$Rm, imm0_7_neg:$imm3))]>,
1148263508Sdim                   Sched<[WriteALU]> {
1149218893Sdim  bits<3> imm3;
1150218893Sdim  let Inst{8-6} = imm3;
1151218893Sdim}
1152193323Sed
1153218893Sdimdef tSUBi8 :                    // A8.6.210 T2
1154226633Sdim  T1sItGenEncodeImm<{1,1,1,?,?}, (outs tGPR:$Rdn),
1155226633Sdim                    (ins tGPR:$Rn, imm0_255:$imm8), IIC_iALUi,
1156218893Sdim                    "sub", "\t$Rdn, $imm8",
1157263508Sdim                    [(set tGPR:$Rdn, (add tGPR:$Rn, imm8_255_neg:$imm8))]>,
1158263508Sdim                    Sched<[WriteALU]>;
1159193323Sed
1160218893Sdim// Subtract register
1161218893Sdimdef tSUBrr :                    // A8.6.212
1162218893Sdim  T1sIGenEncode<0b01101, (outs tGPR:$Rd), (ins tGPR:$Rn, tGPR:$Rm),
1163218893Sdim                IIC_iALUr,
1164218893Sdim                "sub", "\t$Rd, $Rn, $Rm",
1165263508Sdim                [(set tGPR:$Rd, (sub tGPR:$Rn, tGPR:$Rm))]>,
1166263508Sdim                Sched<[WriteALU]>;
1167193323Sed
1168218893Sdim// Sign-extend byte
1169218893Sdimdef tSXTB :                     // A8.6.222
1170218893Sdim  T1pIMiscEncode<{0,0,1,0,0,1,?}, (outs tGPR:$Rd), (ins tGPR:$Rm),
1171218893Sdim                 IIC_iUNAr,
1172218893Sdim                 "sxtb", "\t$Rd, $Rm",
1173218893Sdim                 [(set tGPR:$Rd, (sext_inreg tGPR:$Rm, i8))]>,
1174263508Sdim                 Requires<[IsThumb, IsThumb1Only, HasV6]>,
1175263508Sdim                 Sched<[WriteALU]>;
1176195098Sed
1177218893Sdim// Sign-extend short
1178218893Sdimdef tSXTH :                     // A8.6.224
1179218893Sdim  T1pIMiscEncode<{0,0,1,0,0,0,?}, (outs tGPR:$Rd), (ins tGPR:$Rm),
1180218893Sdim                 IIC_iUNAr,
1181218893Sdim                 "sxth", "\t$Rd, $Rm",
1182218893Sdim                 [(set tGPR:$Rd, (sext_inreg tGPR:$Rm, i16))]>,
1183263508Sdim                 Requires<[IsThumb, IsThumb1Only, HasV6]>,
1184263508Sdim                 Sched<[WriteALU]>;
1185193323Sed
1186218893Sdim// Test
1187218893Sdimlet isCompare = 1, isCommutable = 1, Defs = [CPSR] in
1188218893Sdimdef tTST :                      // A8.6.230
1189218893Sdim  T1pIDPEncode<0b1000, (outs), (ins tGPR:$Rn, tGPR:$Rm), IIC_iTSTr,
1190218893Sdim               "tst", "\t$Rn, $Rm",
1191263508Sdim               [(ARMcmpZ (and_su tGPR:$Rn, tGPR:$Rm), 0)]>,
1192263508Sdim               Sched<[WriteALU]>;
1193193323Sed
1194218893Sdim// Zero-extend byte
1195218893Sdimdef tUXTB :                     // A8.6.262
1196218893Sdim  T1pIMiscEncode<{0,0,1,0,1,1,?}, (outs tGPR:$Rd), (ins tGPR:$Rm),
1197218893Sdim                 IIC_iUNAr,
1198218893Sdim                 "uxtb", "\t$Rd, $Rm",
1199218893Sdim                 [(set tGPR:$Rd, (and tGPR:$Rm, 0xFF))]>,
1200263508Sdim                 Requires<[IsThumb, IsThumb1Only, HasV6]>,
1201263508Sdim                 Sched<[WriteALU]>;
1202195098Sed
1203218893Sdim// Zero-extend short
1204218893Sdimdef tUXTH :                     // A8.6.264
1205218893Sdim  T1pIMiscEncode<{0,0,1,0,1,0,?}, (outs tGPR:$Rd), (ins tGPR:$Rm),
1206218893Sdim                 IIC_iUNAr,
1207218893Sdim                 "uxth", "\t$Rd, $Rm",
1208218893Sdim                 [(set tGPR:$Rd, (and tGPR:$Rm, 0xFFFF))]>,
1209263508Sdim                 Requires<[IsThumb, IsThumb1Only, HasV6]>, Sched<[WriteALU]>;
1210193323Sed
1211204642Srdivacky// Conditional move tMOVCCr - Used to implement the Thumb SELECT_CC operation.
1212198892Srdivacky// Expanded after instruction selection into a branch sequence.
1213198892Srdivackylet usesCustomInserter = 1 in  // Expanded after instruction selection.
1214198090Srdivacky  def tMOVCCr_pseudo :
1215263508Sdim  PseudoInst<(outs tGPR:$dst), (ins tGPR:$false, tGPR:$true, cmovpred:$p),
1216263508Sdim             NoItinerary,
1217263508Sdim             [(set tGPR:$dst, (ARMcmov tGPR:$false, tGPR:$true, cmovpred:$p))]>;
1218193323Sed
1219193323Sed// tLEApcrel - Load a pc-relative address into a register without offending the
1220193323Sed// assembler.
1221193323Sed
1222218893Sdimdef tADR : T1I<(outs tGPR:$Rd), (ins t_adrlabel:$addr, pred:$p),
1223226633Sdim               IIC_iALUi, "adr{$p}\t$Rd, $addr", []>,
1224263508Sdim               T1Encoding<{1,0,1,0,0,?}>, Sched<[WriteALU]> {
1225218893Sdim  bits<3> Rd;
1226218893Sdim  bits<8> addr;
1227218893Sdim  let Inst{10-8} = Rd;
1228218893Sdim  let Inst{7-0} = addr;
1229226633Sdim  let DecoderMethod = "DecodeThumbAddSpecialReg";
1230218893Sdim}
1231193323Sed
1232218893Sdimlet neverHasSideEffects = 1, isReMaterializable = 1 in
1233218893Sdimdef tLEApcrel   : tPseudoInst<(outs tGPR:$Rd), (ins i32imm:$label, pred:$p),
1234263508Sdim                              2, IIC_iALUi, []>, Sched<[WriteALU]>;
1235218893Sdim
1236243830Sdimlet hasSideEffects = 1 in
1237218893Sdimdef tLEApcrelJT : tPseudoInst<(outs tGPR:$Rd),
1238218893Sdim                              (ins i32imm:$label, nohash_imm:$id, pred:$p),
1239263508Sdim                              2, IIC_iALUi, []>, Sched<[WriteALU]>;
1240218893Sdim
1241193323Sed//===----------------------------------------------------------------------===//
1242193323Sed// TLS Instructions
1243193323Sed//
1244193323Sed
1245193323Sed// __aeabi_read_tp preserves the registers r1-r3.
1246224145Sdim// This is a pseudo inst so that we can get the encoding right,
1247224145Sdim// complete with fixup for the aeabi_read_tp function.
1248224145Sdimlet isCall = 1, Defs = [R0, R12, LR, CPSR], Uses = [SP] in
1249224145Sdimdef tTPsoft : tPseudoInst<(outs), (ins), 4, IIC_Br,
1250263508Sdim                          [(set R0, ARMthread_pointer)]>,
1251263508Sdim                          Sched<[WriteBr]>;
1252193323Sed
1253218893Sdim//===----------------------------------------------------------------------===//
1254200581Srdivacky// SJLJ Exception handling intrinsics
1255223017Sdim//
1256208599Srdivacky
1257218893Sdim// eh_sjlj_setjmp() is an instruction sequence to store the return address and
1258218893Sdim// save #0 in R0 for the non-longjmp case.  Since by its nature we may be coming
1259218893Sdim// from some other function to get here, and we're using the stack frame for the
1260218893Sdim// containing function to save/restore registers, we can't keep anything live in
1261218893Sdim// regs across the eh_sjlj_setjmp(), else it will almost certainly have been
1262221345Sdim// tromped upon when we get here from a longjmp(). We force everything out of
1263218893Sdim// registers except for our own input by listing the relevant registers in
1264218893Sdim// Defs. By doing so, we also cause the prologue/epilogue code to actively
1265218893Sdim// preserve all of the callee-saved resgisters, which is exactly what we want.
1266218893Sdim// $val is a scratch register for our use.
1267223017Sdimlet Defs = [ R0,  R1,  R2,  R3,  R4,  R5,  R6,  R7, R12, CPSR ],
1268234353Sdim    hasSideEffects = 1, isBarrier = 1, isCodeGenOnly = 1,
1269234353Sdim    usesCustomInserter = 1 in
1270218893Sdimdef tInt_eh_sjlj_setjmp : ThumbXI<(outs),(ins tGPR:$src, tGPR:$val),
1271224145Sdim                                  AddrModeNone, 0, NoItinerary, "","",
1272218893Sdim                          [(set R0, (ARMeh_sjlj_setjmp tGPR:$src, tGPR:$val))]>;
1273218893Sdim
1274234353Sdim// FIXME: Non-IOS version(s)
1275218893Sdimlet isBarrier = 1, hasSideEffects = 1, isTerminator = 1, isCodeGenOnly = 1,
1276218893Sdim    Defs = [ R7, LR, SP ] in
1277208599Srdivackydef tInt_eh_sjlj_longjmp : XI<(outs), (ins GPR:$src, GPR:$scratch),
1278224145Sdim                              AddrModeNone, 0, IndexModeNone,
1279218893Sdim                              Pseudo, NoItinerary, "", "",
1280218893Sdim                              [(ARMeh_sjlj_longjmp GPR:$src, GPR:$scratch)]>,
1281234353Sdim                             Requires<[IsThumb, IsIOS]>;
1282208599Srdivacky
1283193323Sed//===----------------------------------------------------------------------===//
1284193323Sed// Non-Instruction Patterns
1285193323Sed//
1286193323Sed
1287218893Sdim// Comparisons
1288218893Sdimdef : T1Pat<(ARMcmpZ tGPR:$Rn, imm0_255:$imm8),
1289218893Sdim            (tCMPi8  tGPR:$Rn, imm0_255:$imm8)>;
1290218893Sdimdef : T1Pat<(ARMcmpZ tGPR:$Rn, tGPR:$Rm),
1291218893Sdim            (tCMPr   tGPR:$Rn, tGPR:$Rm)>;
1292218893Sdim
1293198090Srdivacky// Add with carry
1294198090Srdivackydef : T1Pat<(addc   tGPR:$lhs, imm0_7:$rhs),
1295198090Srdivacky            (tADDi3 tGPR:$lhs, imm0_7:$rhs)>;
1296198090Srdivackydef : T1Pat<(addc   tGPR:$lhs, imm8_255:$rhs),
1297198090Srdivacky            (tADDi8 tGPR:$lhs, imm8_255:$rhs)>;
1298198090Srdivackydef : T1Pat<(addc   tGPR:$lhs, tGPR:$rhs),
1299198090Srdivacky            (tADDrr tGPR:$lhs, tGPR:$rhs)>;
1300198090Srdivacky
1301198090Srdivacky// Subtract with carry
1302198090Srdivackydef : T1Pat<(addc   tGPR:$lhs, imm0_7_neg:$rhs),
1303198090Srdivacky            (tSUBi3 tGPR:$lhs, imm0_7_neg:$rhs)>;
1304198090Srdivackydef : T1Pat<(addc   tGPR:$lhs, imm8_255_neg:$rhs),
1305198090Srdivacky            (tSUBi8 tGPR:$lhs, imm8_255_neg:$rhs)>;
1306198090Srdivackydef : T1Pat<(subc   tGPR:$lhs, tGPR:$rhs),
1307198090Srdivacky            (tSUBrr tGPR:$lhs, tGPR:$rhs)>;
1308198090Srdivacky
1309193323Sed// ConstantPool, GlobalAddress
1310198090Srdivackydef : T1Pat<(ARMWrapper  tglobaladdr :$dst), (tLEApcrel tglobaladdr :$dst)>;
1311198090Srdivackydef : T1Pat<(ARMWrapper  tconstpool  :$dst), (tLEApcrel tconstpool  :$dst)>;
1312193323Sed
1313193323Sed// JumpTable
1314198090Srdivackydef : T1Pat<(ARMWrapperJT tjumptable:$dst, imm:$id),
1315198090Srdivacky            (tLEApcrelJT tjumptable:$dst, imm:$id)>;
1316193323Sed
1317193323Sed// Direct calls
1318198090Srdivackydef : T1Pat<(ARMtcall texternalsym:$func), (tBL texternalsym:$func)>,
1319234353Sdim      Requires<[IsThumb]>;
1320193323Sed
1321198090Srdivackydef : Tv5Pat<(ARMcall texternalsym:$func), (tBLXi texternalsym:$func)>,
1322234353Sdim      Requires<[IsThumb, HasV5T]>;
1323198090Srdivacky
1324193323Sed// Indirect calls to ARM routines
1325198090Srdivackydef : Tv5Pat<(ARMcall GPR:$dst), (tBLXr GPR:$dst)>,
1326234353Sdim      Requires<[IsThumb, HasV5T]>;
1327193323Sed
1328193323Sed// zextload i1 -> zextload i8
1329218893Sdimdef : T1Pat<(zextloadi1 t_addrmode_rrs1:$addr),
1330218893Sdim            (tLDRBr t_addrmode_rrs1:$addr)>;
1331218893Sdimdef : T1Pat<(zextloadi1 t_addrmode_is1:$addr),
1332218893Sdim            (tLDRBi t_addrmode_is1:$addr)>;
1333193323Sed
1334193323Sed// extload -> zextload
1335218893Sdimdef : T1Pat<(extloadi1  t_addrmode_rrs1:$addr), (tLDRBr t_addrmode_rrs1:$addr)>;
1336218893Sdimdef : T1Pat<(extloadi1  t_addrmode_is1:$addr),  (tLDRBi t_addrmode_is1:$addr)>;
1337218893Sdimdef : T1Pat<(extloadi8  t_addrmode_rrs1:$addr), (tLDRBr t_addrmode_rrs1:$addr)>;
1338218893Sdimdef : T1Pat<(extloadi8  t_addrmode_is1:$addr),  (tLDRBi t_addrmode_is1:$addr)>;
1339218893Sdimdef : T1Pat<(extloadi16 t_addrmode_rrs2:$addr), (tLDRHr t_addrmode_rrs2:$addr)>;
1340218893Sdimdef : T1Pat<(extloadi16 t_addrmode_is2:$addr),  (tLDRHi t_addrmode_is2:$addr)>;
1341193323Sed
1342198090Srdivacky// If it's impossible to use [r,r] address mode for sextload, select to
1343198090Srdivacky// ldr{b|h} + sxt{b|h} instead.
1344218893Sdimdef : T1Pat<(sextloadi8 t_addrmode_is1:$addr),
1345218893Sdim            (tSXTB (tLDRBi t_addrmode_is1:$addr))>,
1346218893Sdim      Requires<[IsThumb, IsThumb1Only, HasV6]>;
1347218893Sdimdef : T1Pat<(sextloadi8 t_addrmode_rrs1:$addr),
1348218893Sdim            (tSXTB (tLDRBr t_addrmode_rrs1:$addr))>,
1349218893Sdim      Requires<[IsThumb, IsThumb1Only, HasV6]>;
1350218893Sdimdef : T1Pat<(sextloadi16 t_addrmode_is2:$addr),
1351218893Sdim            (tSXTH (tLDRHi t_addrmode_is2:$addr))>,
1352218893Sdim      Requires<[IsThumb, IsThumb1Only, HasV6]>;
1353218893Sdimdef : T1Pat<(sextloadi16 t_addrmode_rrs2:$addr),
1354218893Sdim            (tSXTH (tLDRHr t_addrmode_rrs2:$addr))>,
1355218893Sdim      Requires<[IsThumb, IsThumb1Only, HasV6]>;
1356198090Srdivacky
1357218893Sdimdef : T1Pat<(sextloadi8 t_addrmode_rrs1:$addr),
1358218893Sdim            (tASRri (tLSLri (tLDRBr t_addrmode_rrs1:$addr), 24), 24)>;
1359218893Sdimdef : T1Pat<(sextloadi8 t_addrmode_is1:$addr),
1360218893Sdim            (tASRri (tLSLri (tLDRBi t_addrmode_is1:$addr), 24), 24)>;
1361218893Sdimdef : T1Pat<(sextloadi16 t_addrmode_rrs2:$addr),
1362218893Sdim            (tASRri (tLSLri (tLDRHr t_addrmode_rrs2:$addr), 16), 16)>;
1363218893Sdimdef : T1Pat<(sextloadi16 t_addrmode_is2:$addr),
1364218893Sdim            (tASRri (tLSLri (tLDRHi t_addrmode_is2:$addr), 16), 16)>;
1365198090Srdivacky
1366226633Sdimdef : T1Pat<(atomic_load_8 t_addrmode_is1:$src),
1367226633Sdim             (tLDRBi t_addrmode_is1:$src)>;
1368226633Sdimdef : T1Pat<(atomic_load_8 t_addrmode_rrs1:$src),
1369226633Sdim             (tLDRBr t_addrmode_rrs1:$src)>;
1370226633Sdimdef : T1Pat<(atomic_load_16 t_addrmode_is2:$src),
1371226633Sdim             (tLDRHi t_addrmode_is2:$src)>;
1372226633Sdimdef : T1Pat<(atomic_load_16 t_addrmode_rrs2:$src),
1373226633Sdim             (tLDRHr t_addrmode_rrs2:$src)>;
1374226633Sdimdef : T1Pat<(atomic_load_32 t_addrmode_is4:$src),
1375226633Sdim             (tLDRi t_addrmode_is4:$src)>;
1376226633Sdimdef : T1Pat<(atomic_load_32 t_addrmode_rrs4:$src),
1377226633Sdim             (tLDRr t_addrmode_rrs4:$src)>;
1378226633Sdimdef : T1Pat<(atomic_store_8 t_addrmode_is1:$ptr, tGPR:$val),
1379226633Sdim             (tSTRBi tGPR:$val, t_addrmode_is1:$ptr)>;
1380226633Sdimdef : T1Pat<(atomic_store_8 t_addrmode_rrs1:$ptr, tGPR:$val),
1381226633Sdim             (tSTRBr tGPR:$val, t_addrmode_rrs1:$ptr)>;
1382226633Sdimdef : T1Pat<(atomic_store_16 t_addrmode_is2:$ptr, tGPR:$val),
1383226633Sdim             (tSTRHi tGPR:$val, t_addrmode_is2:$ptr)>;
1384226633Sdimdef : T1Pat<(atomic_store_16 t_addrmode_rrs2:$ptr, tGPR:$val),
1385226633Sdim             (tSTRHr tGPR:$val, t_addrmode_rrs2:$ptr)>;
1386226633Sdimdef : T1Pat<(atomic_store_32 t_addrmode_is4:$ptr, tGPR:$val),
1387226633Sdim             (tSTRi tGPR:$val, t_addrmode_is4:$ptr)>;
1388226633Sdimdef : T1Pat<(atomic_store_32 t_addrmode_rrs4:$ptr, tGPR:$val),
1389226633Sdim             (tSTRr tGPR:$val, t_addrmode_rrs4:$ptr)>;
1390226633Sdim
1391193323Sed// Large immediate handling.
1392193323Sed
1393193323Sed// Two piece imms.
1394195098Seddef : T1Pat<(i32 thumb_immshifted:$src),
1395195098Sed            (tLSLri (tMOVi8 (thumb_immshifted_val imm:$src)),
1396195098Sed                    (thumb_immshifted_shamt imm:$src))>;
1397193323Sed
1398195098Seddef : T1Pat<(i32 imm0_255_comp:$src),
1399195098Sed            (tMVN (tMOVi8 (imm_comp_XFORM imm:$src)))>;
1400199481Srdivacky
1401199481Srdivacky// Pseudo instruction that combines ldr from constpool and add pc. This should
1402199481Srdivacky// be expanded into two instructions late to allow if-conversion and
1403199481Srdivacky// scheduling.
1404199481Srdivackylet isReMaterializable = 1 in
1405199481Srdivackydef tLDRpci_pic : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr, pclabel:$cp),
1406218893Sdim                             NoItinerary,
1407199481Srdivacky               [(set GPR:$dst, (ARMpic_add (load (ARMWrapper tconstpool:$addr)),
1408199481Srdivacky                                           imm:$cp))]>,
1409218893Sdim               Requires<[IsThumb, IsThumb1Only]>;
1410224145Sdim
1411224145Sdim// Pseudo-instruction for merged POP and return.
1412224145Sdim// FIXME: remove when we have a way to marking a MI with these properties.
1413224145Sdimlet isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1,
1414224145Sdim    hasExtraDefRegAllocReq = 1 in
1415224145Sdimdef tPOP_RET : tPseudoExpand<(outs), (ins pred:$p, reglist:$regs, variable_ops),
1416224145Sdim                           2, IIC_iPop_Br, [],
1417263508Sdim                           (tPOP pred:$p, reglist:$regs)>, Sched<[WriteBrL]>;
1418224145Sdim
1419224145Sdim// Indirect branch using "mov pc, $Rm"
1420224145Sdimlet isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
1421224145Sdim  def tBRIND : tPseudoExpand<(outs), (ins GPR:$Rm, pred:$p),
1422224145Sdim                  2, IIC_Br, [(brind GPR:$Rm)],
1423263508Sdim                  (tMOVr PC, GPR:$Rm, pred:$p)>, Sched<[WriteBr]>;
1424224145Sdim}
1425226633Sdim
1426226633Sdim
1427226633Sdim// In Thumb1, "nop" is encoded as a "mov r8, r8". Technically, the bf00
1428226633Sdim// encoding is available on ARMv6K, but we don't differentiate that finely.
1429226633Sdimdef : InstAlias<"nop", (tMOVr R8, R8, 14, 0)>,Requires<[IsThumb, IsThumb1Only]>;
1430226633Sdim
1431226633Sdim
1432226633Sdim// For round-trip assembly/disassembly, we have to handle a CPS instruction
1433226633Sdim// without any iflags. That's not, strictly speaking, valid syntax, but it's
1434239462Sdim// a useful extension and assembles to defined behaviour (the insn does
1435226633Sdim// nothing).
1436226633Sdimdef : tInstAlias<"cps$imod", (tCPS imod_op:$imod, 0)>;
1437226633Sdimdef : tInstAlias<"cps$imod", (tCPS imod_op:$imod, 0)>;
1438234353Sdim
1439234353Sdim// "neg" is and alias for "rsb rd, rn, #0"
1440234353Sdimdef : tInstAlias<"neg${s}${p} $Rd, $Rm",
1441234353Sdim                 (tRSB tGPR:$Rd, s_cc_out:$s, tGPR:$Rm, pred:$p)>;
1442234353Sdim
1443234353Sdim
1444234353Sdim// Implied destination operand forms for shifts.
1445234353Sdimdef : tInstAlias<"lsl${s}${p} $Rdm, $imm",
1446234353Sdim             (tLSLri tGPR:$Rdm, cc_out:$s, tGPR:$Rdm, imm0_31:$imm, pred:$p)>;
1447234353Sdimdef : tInstAlias<"lsr${s}${p} $Rdm, $imm",
1448234353Sdim             (tLSRri tGPR:$Rdm, cc_out:$s, tGPR:$Rdm, imm_sr:$imm, pred:$p)>;
1449234353Sdimdef : tInstAlias<"asr${s}${p} $Rdm, $imm",
1450234353Sdim             (tASRri tGPR:$Rdm, cc_out:$s, tGPR:$Rdm, imm_sr:$imm, pred:$p)>;
1451