ARMInstrThumb.td revision 212904
1193323Sed//===- ARMInstrThumb.td - Thumb support for ARM ---------------------------===//
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,
19205407Srdivacky                      [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag,
20205407Srdivacky                       SDNPVariadic]>;
21193323Sed
22193323Seddef imm_neg_XFORM : SDNodeXForm<imm, [{
23193323Sed  return CurDAG->getTargetConstant(-(int)N->getZExtValue(), MVT::i32);
24193323Sed}]>;
25193323Seddef imm_comp_XFORM : SDNodeXForm<imm, [{
26193323Sed  return CurDAG->getTargetConstant(~((uint32_t)N->getZExtValue()), MVT::i32);
27193323Sed}]>;
28193323Sed
29193323Sed
30193323Sed/// imm0_7 predicate - True if the 32-bit immediate is in the range [0,7].
31193323Seddef imm0_7 : PatLeaf<(i32 imm), [{
32193323Sed  return (uint32_t)N->getZExtValue() < 8;
33193323Sed}]>;
34193323Seddef imm0_7_neg : PatLeaf<(i32 imm), [{
35193323Sed  return (uint32_t)-N->getZExtValue() < 8;
36193323Sed}], imm_neg_XFORM>;
37193323Sed
38193323Seddef imm0_255 : PatLeaf<(i32 imm), [{
39193323Sed  return (uint32_t)N->getZExtValue() < 256;
40193323Sed}]>;
41193323Seddef imm0_255_comp : PatLeaf<(i32 imm), [{
42193323Sed  return ~((uint32_t)N->getZExtValue()) < 256;
43193323Sed}]>;
44193323Sed
45193323Seddef imm8_255 : PatLeaf<(i32 imm), [{
46193323Sed  return (uint32_t)N->getZExtValue() >= 8 && (uint32_t)N->getZExtValue() < 256;
47193323Sed}]>;
48193323Seddef imm8_255_neg : PatLeaf<(i32 imm), [{
49193323Sed  unsigned Val = -N->getZExtValue();
50193323Sed  return Val >= 8 && Val < 256;
51193323Sed}], imm_neg_XFORM>;
52193323Sed
53193323Sed// Break imm's up into two pieces: an immediate + a left shift.
54193323Sed// This uses thumb_immshifted to match and thumb_immshifted_val and
55193323Sed// thumb_immshifted_shamt to get the val/shift pieces.
56193323Seddef thumb_immshifted : PatLeaf<(imm), [{
57193323Sed  return ARM_AM::isThumbImmShiftedVal((unsigned)N->getZExtValue());
58193323Sed}]>;
59193323Sed
60193323Seddef thumb_immshifted_val : SDNodeXForm<imm, [{
61193323Sed  unsigned V = ARM_AM::getThumbImmNonShiftedVal((unsigned)N->getZExtValue());
62193323Sed  return CurDAG->getTargetConstant(V, MVT::i32);
63193323Sed}]>;
64193323Sed
65193323Seddef thumb_immshifted_shamt : SDNodeXForm<imm, [{
66193323Sed  unsigned V = ARM_AM::getThumbImmValShift((unsigned)N->getZExtValue());
67193323Sed  return CurDAG->getTargetConstant(V, MVT::i32);
68193323Sed}]>;
69193323Sed
70199511Srdivacky// Scaled 4 immediate.
71199511Srdivackydef t_imm_s4 : Operand<i32> {
72199511Srdivacky  let PrintMethod = "printThumbS4ImmOperand";
73199511Srdivacky}
74199511Srdivacky
75193323Sed// Define Thumb specific addressing modes.
76193323Sed
77193323Sed// t_addrmode_rr := reg + reg
78193323Sed//
79193323Seddef t_addrmode_rr : Operand<i32>,
80193323Sed                    ComplexPattern<i32, 2, "SelectThumbAddrModeRR", []> {
81193323Sed  let PrintMethod = "printThumbAddrModeRROperand";
82193323Sed  let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg);
83193323Sed}
84193323Sed
85193323Sed// t_addrmode_s4 := reg + reg
86193323Sed//                  reg + imm5 * 4
87193323Sed//
88193323Seddef t_addrmode_s4 : Operand<i32>,
89193323Sed                    ComplexPattern<i32, 3, "SelectThumbAddrModeS4", []> {
90193323Sed  let PrintMethod = "printThumbAddrModeS4Operand";
91193323Sed  let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg);
92193323Sed}
93193323Sed
94193323Sed// t_addrmode_s2 := reg + reg
95193323Sed//                  reg + imm5 * 2
96193323Sed//
97193323Seddef t_addrmode_s2 : Operand<i32>,
98193323Sed                    ComplexPattern<i32, 3, "SelectThumbAddrModeS2", []> {
99193323Sed  let PrintMethod = "printThumbAddrModeS2Operand";
100193323Sed  let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg);
101193323Sed}
102193323Sed
103193323Sed// t_addrmode_s1 := reg + reg
104193323Sed//                  reg + imm5
105193323Sed//
106193323Seddef t_addrmode_s1 : Operand<i32>,
107193323Sed                    ComplexPattern<i32, 3, "SelectThumbAddrModeS1", []> {
108193323Sed  let PrintMethod = "printThumbAddrModeS1Operand";
109193323Sed  let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg);
110193323Sed}
111193323Sed
112193323Sed// t_addrmode_sp := sp + imm8 * 4
113193323Sed//
114193323Seddef t_addrmode_sp : Operand<i32>,
115193323Sed                    ComplexPattern<i32, 2, "SelectThumbAddrModeSP", []> {
116193323Sed  let PrintMethod = "printThumbAddrModeSPOperand";
117202375Srdivacky  let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
118193323Sed}
119193323Sed
120193323Sed//===----------------------------------------------------------------------===//
121193323Sed//  Miscellaneous Instructions.
122193323Sed//
123193323Sed
124204642Srdivacky// FIXME: Marking these as hasSideEffects is necessary to prevent machine DCE
125204642Srdivacky// from removing one half of the matched pairs. That breaks PEI, which assumes
126204642Srdivacky// these will always be in pairs, and asserts if it finds otherwise. Better way?
127204642Srdivackylet Defs = [SP], Uses = [SP], hasSideEffects = 1 in {
128193323Seddef tADJCALLSTACKUP :
129198090SrdivackyPseudoInst<(outs), (ins i32imm:$amt1, i32imm:$amt2), NoItinerary,
130208599Srdivacky           "${:comment} tADJCALLSTACKUP $amt1",
131198090Srdivacky           [(ARMcallseq_end imm:$amt1, imm:$amt2)]>, Requires<[IsThumb1Only]>;
132193323Sed
133193323Seddef tADJCALLSTACKDOWN :
134198090SrdivackyPseudoInst<(outs), (ins i32imm:$amt), NoItinerary,
135208599Srdivacky           "${:comment} tADJCALLSTACKDOWN $amt",
136198090Srdivacky           [(ARMcallseq_start imm:$amt)]>, Requires<[IsThumb1Only]>;
137193323Sed}
138193323Sed
139204642Srdivackydef tNOP : T1pI<(outs), (ins), NoItinerary, "nop", "",
140204642Srdivacky                [/* For disassembly only; pattern left blank */]>,
141204642Srdivacky           T1Encoding<0b101111> {
142204642Srdivacky  let Inst{9-8} = 0b11;
143204642Srdivacky  let Inst{7-0} = 0b00000000;
144204642Srdivacky} 
145204642Srdivacky
146204642Srdivackydef tYIELD : T1pI<(outs), (ins), NoItinerary, "yield", "",
147204642Srdivacky                  [/* For disassembly only; pattern left blank */]>,
148204642Srdivacky             T1Encoding<0b101111> {
149204642Srdivacky  let Inst{9-8} = 0b11;
150204642Srdivacky  let Inst{7-0} = 0b00010000;
151204642Srdivacky} 
152204642Srdivacky
153204642Srdivackydef tWFE : T1pI<(outs), (ins), NoItinerary, "wfe", "",
154204642Srdivacky                [/* For disassembly only; pattern left blank */]>,
155204642Srdivacky           T1Encoding<0b101111> {
156204642Srdivacky  let Inst{9-8} = 0b11;
157204642Srdivacky  let Inst{7-0} = 0b00100000;
158204642Srdivacky} 
159204642Srdivacky
160204642Srdivackydef tWFI : T1pI<(outs), (ins), NoItinerary, "wfi", "",
161204642Srdivacky                [/* For disassembly only; pattern left blank */]>,
162204642Srdivacky           T1Encoding<0b101111> {
163204642Srdivacky  let Inst{9-8} = 0b11;
164204642Srdivacky  let Inst{7-0} = 0b00110000;
165204642Srdivacky} 
166204642Srdivacky
167204642Srdivackydef tSEV : T1pI<(outs), (ins), NoItinerary, "sev", "",
168204642Srdivacky                [/* For disassembly only; pattern left blank */]>,
169204642Srdivacky           T1Encoding<0b101111> {
170204642Srdivacky  let Inst{9-8} = 0b11;
171204642Srdivacky  let Inst{7-0} = 0b01000000;
172204642Srdivacky} 
173204642Srdivacky
174204642Srdivackydef tSETENDBE : T1I<(outs), (ins), NoItinerary, "setend\tbe",
175204642Srdivacky                    [/* For disassembly only; pattern left blank */]>,
176204642Srdivacky                T1Encoding<0b101101> {
177204642Srdivacky  let Inst{9-5} = 0b10010;
178204642Srdivacky  let Inst{3} = 1;
179204642Srdivacky}
180204642Srdivacky
181204642Srdivackydef tSETENDLE : T1I<(outs), (ins), NoItinerary, "setend\tle",
182204642Srdivacky                    [/* For disassembly only; pattern left blank */]>,
183204642Srdivacky                T1Encoding<0b101101> {
184204642Srdivacky  let Inst{9-5} = 0b10010;
185204642Srdivacky  let Inst{3} = 0;
186204642Srdivacky}
187204642Srdivacky
188203954Srdivacky// The i32imm operand $val can be used by a debugger to store more information
189203954Srdivacky// about the breakpoint.
190203954Srdivackydef tBKPT : T1I<(outs), (ins i32imm:$val), NoItinerary, "bkpt\t$val",
191203954Srdivacky                [/* For disassembly only; pattern left blank */]>,
192203954Srdivacky            T1Encoding<0b101111> {
193203954Srdivacky  let Inst{9-8} = 0b10;
194203954Srdivacky}
195203954Srdivacky
196204642Srdivacky// Change Processor State is a system instruction -- for disassembly only.
197204642Srdivacky// The singleton $opt operand contains the following information:
198204642Srdivacky// opt{4-0} = mode ==> don't care
199204642Srdivacky// opt{5} = changemode ==> 0 (false for 16-bit Thumb instr)
200204642Srdivacky// opt{8-6} = AIF from Inst{2-0}
201204642Srdivacky// opt{10-9} = 1:imod from Inst{4} with 0b10 as enable and 0b11 as disable
202204642Srdivacky//
203204642Srdivacky// The opt{4-0} and opt{5} sub-fields are to accommodate 32-bit Thumb and ARM
204204642Srdivacky// CPS which has more options.
205205218Srdivackydef tCPS : T1I<(outs), (ins cps_opt:$opt), NoItinerary, "cps$opt",
206204642Srdivacky              [/* For disassembly only; pattern left blank */]>,
207204642Srdivacky           T1Misc<0b0110011>;
208204642Srdivacky
209198090Srdivacky// For both thumb1 and thumb2.
210193323Sedlet isNotDuplicable = 1 in
211198090Srdivackydef tPICADD : TIt<(outs GPR:$dst), (ins GPR:$lhs, pclabel:$cp), IIC_iALUr,
212198892Srdivacky                 "\n$cp:\n\tadd\t$dst, pc",
213201360Srdivacky                 [(set GPR:$dst, (ARMpic_add GPR:$lhs, imm:$cp))]>,
214201360Srdivacky              T1Special<{0,0,?,?}> {
215201360Srdivacky  let Inst{6-3} = 0b1111; // A8.6.6 Rm = pc
216201360Srdivacky}
217193323Sed
218195098Sed// PC relative add.
219199511Srdivackydef tADDrPCi : T1I<(outs tGPR:$dst), (ins t_imm_s4:$rhs), IIC_iALUi,
220201360Srdivacky                  "add\t$dst, pc, $rhs", []>,
221201360Srdivacky               T1Encoding<{1,0,1,0,0,?}>; // A6.2 & A8.6.10
222195098Sed
223195098Sed// ADD rd, sp, #imm8
224212904Sdim// This is rematerializable, which is particularly useful for taking the
225212904Sdim// address of locals.
226212904Sdimlet isReMaterializable = 1 in {
227199511Srdivackydef tADDrSPi : T1I<(outs tGPR:$dst), (ins GPR:$sp, t_imm_s4:$rhs), IIC_iALUi,
228201360Srdivacky                  "add\t$dst, $sp, $rhs", []>,
229201360Srdivacky               T1Encoding<{1,0,1,0,1,?}>; // A6.2 & A8.6.8
230212904Sdim}
231195098Sed
232195098Sed// ADD sp, sp, #imm7
233199511Srdivackydef tADDspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), IIC_iALUi,
234201360Srdivacky                  "add\t$dst, $rhs", []>,
235201360Srdivacky              T1Misc<{0,0,0,0,0,?,?}>; // A6.2.5 & A8.6.8
236195098Sed
237198090Srdivacky// SUB sp, sp, #imm7
238199511Srdivackydef tSUBspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), IIC_iALUi,
239201360Srdivacky                  "sub\t$dst, $rhs", []>,
240201360Srdivacky              T1Misc<{0,0,0,0,1,?,?}>; // A6.2.5 & A8.6.215
241198090Srdivacky
242198090Srdivacky// ADD rm, sp
243198090Srdivackydef tADDrSP : TIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr,
244201360Srdivacky                  "add\t$dst, $rhs", []>,
245201360Srdivacky              T1Special<{0,0,?,?}> {
246201360Srdivacky  let Inst{6-3} = 0b1101; // A8.6.9 Encoding T1
247201360Srdivacky}
248198090Srdivacky
249195098Sed// ADD sp, rm
250198090Srdivackydef tADDspr : TIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr,
251201360Srdivacky                  "add\t$dst, $rhs", []>,
252201360Srdivacky              T1Special<{0,0,?,?}> {
253201360Srdivacky  // A8.6.9 Encoding T2
254201360Srdivacky  let Inst{7} = 1;
255201360Srdivacky  let Inst{2-0} = 0b101;
256201360Srdivacky}
257195098Sed
258193323Sed//===----------------------------------------------------------------------===//
259193323Sed//  Control Flow Instructions.
260193323Sed//
261193323Sed
262198090Srdivackylet isReturn = 1, isTerminator = 1, isBarrier = 1 in {
263201360Srdivacky  def tBX_RET : TI<(outs), (ins), IIC_Br, "bx\tlr", [(ARMretflag)]>,
264201360Srdivacky                T1Special<{1,1,0,?}> { // A6.2.3 & A8.6.25
265201360Srdivacky    let Inst{6-3} = 0b1110; // Rm = lr
266201360Srdivacky  }
267193323Sed  // Alternative return instruction used by vararg functions.
268204642Srdivacky  def tBX_RET_vararg : TI<(outs), (ins tGPR:$target), IIC_Br, "bx\t$target",[]>,
269201360Srdivacky                       T1Special<{1,1,0,?}>; // A6.2.3 & A8.6.25
270193323Sed}
271193323Sed
272198892Srdivacky// Indirect branches
273198892Srdivackylet isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
274198892Srdivacky  def tBRIND : TI<(outs), (ins GPR:$dst), IIC_Br, "mov\tpc, $dst",
275201360Srdivacky                  [(brind GPR:$dst)]>,
276202878Srdivacky               T1Special<{1,0,1,?}> {
277202375Srdivacky    // <Rd> = Inst{7:2-0} = pc
278201360Srdivacky    let Inst{2-0} = 0b111;
279201360Srdivacky  }
280198892Srdivacky}
281198892Srdivacky
282193323Sed// FIXME: remove when we have a way to marking a MI with these properties.
283198090Srdivackylet isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1,
284198090Srdivacky    hasExtraDefRegAllocReq = 1 in
285205218Srdivackydef tPOP_RET : T1I<(outs), (ins pred:$p, reglist:$dsts, variable_ops), IIC_Br,
286205218Srdivacky                   "pop${p}\t$dsts", []>,
287201360Srdivacky               T1Misc<{1,1,0,?,?,?,?}>;
288193323Sed
289193323Sedlet isCall = 1,
290198090Srdivacky  Defs = [R0,  R1,  R2,  R3,  R12, LR,
291198090Srdivacky          D0,  D1,  D2,  D3,  D4,  D5,  D6,  D7,
292198090Srdivacky          D16, D17, D18, D19, D20, D21, D22, D23,
293198090Srdivacky          D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR] in {
294198090Srdivacky  // Also used for Thumb2
295201360Srdivacky  def tBL  : TIx2<0b11110, 0b11, 1,
296204642Srdivacky                  (outs), (ins i32imm:$func, variable_ops), IIC_Br,
297201360Srdivacky                  "bl\t${func:call}",
298201360Srdivacky                  [(ARMtcall tglobaladdr:$func)]>,
299198090Srdivacky             Requires<[IsThumb, IsNotDarwin]>;
300198090Srdivacky
301198090Srdivacky  // ARMv5T and above, also used for Thumb2
302201360Srdivacky  def tBLXi : TIx2<0b11110, 0b11, 0,
303204642Srdivacky                   (outs), (ins i32imm:$func, variable_ops), IIC_Br,
304201360Srdivacky                   "blx\t${func:call}",
305201360Srdivacky                   [(ARMcall tglobaladdr:$func)]>,
306198090Srdivacky              Requires<[IsThumb, HasV5T, IsNotDarwin]>;
307198090Srdivacky
308198090Srdivacky  // Also used for Thumb2
309204642Srdivacky  def tBLXr : TI<(outs), (ins GPR:$func, variable_ops), IIC_Br,
310198892Srdivacky                  "blx\t$func",
311198090Srdivacky                  [(ARMtcall GPR:$func)]>,
312201360Srdivacky              Requires<[IsThumb, HasV5T, IsNotDarwin]>,
313201360Srdivacky              T1Special<{1,1,1,?}>; // A6.2.3 & A8.6.24;
314198090Srdivacky
315193323Sed  // ARMv4T
316201360Srdivacky  def tBX : TIx2<{?,?,?,?,?}, {?,?}, ?,
317204642Srdivacky                  (outs), (ins tGPR:$func, variable_ops), IIC_Br,
318198892Srdivacky                  "mov\tlr, pc\n\tbx\t$func",
319198090Srdivacky                  [(ARMcall_nolink tGPR:$func)]>,
320198090Srdivacky            Requires<[IsThumb1Only, IsNotDarwin]>;
321193323Sed}
322193323Sed
323198090Srdivacky// On Darwin R9 is call-clobbered.
324198090Srdivackylet isCall = 1,
325198090Srdivacky  Defs = [R0,  R1,  R2,  R3,  R9,  R12, LR,
326198090Srdivacky          D0,  D1,  D2,  D3,  D4,  D5,  D6,  D7,
327198090Srdivacky          D16, D17, D18, D19, D20, D21, D22, D23,
328198090Srdivacky          D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR] in {
329198090Srdivacky  // Also used for Thumb2
330201360Srdivacky  def tBLr9 : TIx2<0b11110, 0b11, 1,
331204642Srdivacky                   (outs), (ins i32imm:$func, variable_ops), IIC_Br,
332198892Srdivacky                   "bl\t${func:call}",
333198090Srdivacky                   [(ARMtcall tglobaladdr:$func)]>,
334198090Srdivacky              Requires<[IsThumb, IsDarwin]>;
335198090Srdivacky
336198090Srdivacky  // ARMv5T and above, also used for Thumb2
337201360Srdivacky  def tBLXi_r9 : TIx2<0b11110, 0b11, 0,
338204642Srdivacky                      (outs), (ins i32imm:$func, variable_ops), IIC_Br,
339198892Srdivacky                      "blx\t${func:call}",
340198090Srdivacky                      [(ARMcall tglobaladdr:$func)]>,
341198090Srdivacky                 Requires<[IsThumb, HasV5T, IsDarwin]>;
342198090Srdivacky
343198090Srdivacky  // Also used for Thumb2
344204642Srdivacky  def tBLXr_r9 : TI<(outs), (ins GPR:$func, variable_ops), IIC_Br,
345201360Srdivacky                    "blx\t$func",
346201360Srdivacky                    [(ARMtcall GPR:$func)]>,
347201360Srdivacky                 Requires<[IsThumb, HasV5T, IsDarwin]>,
348201360Srdivacky                 T1Special<{1,1,1,?}>; // A6.2.3 & A8.6.24
349198090Srdivacky
350198090Srdivacky  // ARMv4T
351201360Srdivacky  def tBXr9 : TIx2<{?,?,?,?,?}, {?,?}, ?,
352204642Srdivacky                   (outs), (ins tGPR:$func, variable_ops), IIC_Br,
353201360Srdivacky                   "mov\tlr, pc\n\tbx\t$func",
354201360Srdivacky                   [(ARMcall_nolink tGPR:$func)]>,
355198090Srdivacky              Requires<[IsThumb1Only, IsDarwin]>;
356198090Srdivacky}
357198090Srdivacky
358193323Sedlet isBranch = 1, isTerminator = 1 in {
359193323Sed  let isBarrier = 1 in {
360193323Sed    let isPredicable = 1 in
361198090Srdivacky    def tB   : T1I<(outs), (ins brtarget:$target), IIC_Br,
362201360Srdivacky                   "b\t$target", [(br bb:$target)]>,
363201360Srdivacky               T1Encoding<{1,1,1,0,0,?}>;
364193323Sed
365193323Sed  // Far jump
366198090Srdivacky  let Defs = [LR] in
367204642Srdivacky  def tBfar : TIx2<0b11110, 0b11, 1, (outs), (ins brtarget:$target), IIC_Br,
368208599Srdivacky                    "bl\t$target\t${:comment} far jump",[]>;
369193323Sed
370195340Sed  def tBR_JTr : T1JTI<(outs),
371195340Sed                      (ins tGPR:$target, jtblock_operand:$jt, i32imm:$id),
372212904Sdim                      IIC_Br, "mov\tpc, $target\n\t.align\t2$jt",
373201360Srdivacky                      [(ARMbrjt tGPR:$target, tjumptable:$jt, imm:$id)]>,
374201360Srdivacky                Encoding16 {
375201360Srdivacky    let Inst{15-7} = 0b010001101;
376201360Srdivacky    let Inst{2-0} = 0b111;
377193323Sed  }
378201360Srdivacky  }
379193323Sed}
380193323Sed
381193323Sed// FIXME: should be able to write a pattern for ARMBrcond, but can't use
382193323Sed// a two-value operand where a dag node expects two operands. :(
383193323Sedlet isBranch = 1, isTerminator = 1 in
384198090Srdivacky  def tBcc : T1I<(outs), (ins brtarget:$target, pred:$cc), IIC_Br,
385198892Srdivacky                 "b$cc\t$target",
386201360Srdivacky                 [/*(ARMbrcond bb:$target, imm:$cc)*/]>,
387201360Srdivacky             T1Encoding<{1,1,0,1,?,?}>;
388193323Sed
389198892Srdivacky// Compare and branch on zero / non-zero
390198892Srdivackylet isBranch = 1, isTerminator = 1 in {
391198892Srdivacky  def tCBZ  : T1I<(outs), (ins tGPR:$cmp, brtarget:$target), IIC_Br,
392201360Srdivacky                  "cbz\t$cmp, $target", []>,
393201360Srdivacky              T1Misc<{0,0,?,1,?,?,?}>;
394198892Srdivacky
395198892Srdivacky  def tCBNZ : T1I<(outs), (ins tGPR:$cmp, brtarget:$target), IIC_Br,
396201360Srdivacky                  "cbnz\t$cmp, $target", []>,
397201360Srdivacky              T1Misc<{1,0,?,1,?,?,?}>;
398198892Srdivacky}
399198892Srdivacky
400204642Srdivacky// A8.6.218 Supervisor Call (Software Interrupt) -- for disassembly only
401204642Srdivacky// A8.6.16 B: Encoding T1
402204642Srdivacky// If Inst{11-8} == 0b1111 then SEE SVC
403204642Srdivackylet isCall = 1 in {
404204642Srdivackydef tSVC : T1pI<(outs), (ins i32imm:$svc), IIC_Br, "svc", "\t$svc", []>,
405204642Srdivacky           Encoding16 {
406204642Srdivacky  let Inst{15-12} = 0b1101;
407204642Srdivacky  let Inst{11-8} = 0b1111;
408204642Srdivacky}
409204642Srdivacky}
410204642Srdivacky
411208599Srdivacky// A8.6.16 B: Encoding T1
412204642Srdivacky// If Inst{11-8} == 0b1110 then UNDEFINED
413208599Srdivacky// FIXME: Temporary emitted as raw bytes until this pseudo-op will be added to
414208599Srdivacky// binutils
415208599Srdivackylet isBarrier = 1, isTerminator = 1 in
416208599Srdivackydef tTRAP : TI<(outs), (ins), IIC_Br, 
417208599Srdivacky               ".short 0xdefe ${:comment} trap", [(trap)]>, Encoding16 {
418204642Srdivacky  let Inst{15-12} = 0b1101;
419204642Srdivacky  let Inst{11-8} = 0b1110;
420204642Srdivacky}
421204642Srdivacky
422193323Sed//===----------------------------------------------------------------------===//
423193323Sed//  Load Store Instructions.
424193323Sed//
425193323Sed
426204642Srdivackylet canFoldAsLoad = 1, isReMaterializable = 1 in
427204642Srdivackydef tLDR : T1pI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr), IIC_iLoadr,
428198892Srdivacky               "ldr", "\t$dst, $addr",
429201360Srdivacky               [(set tGPR:$dst, (load t_addrmode_s4:$addr))]>,
430201360Srdivacky           T1LdSt<0b100>;
431204642Srdivackydef tLDRi: T1pI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr), IIC_iLoadr,
432202375Srdivacky               "ldr", "\t$dst, $addr",
433202375Srdivacky               []>,
434202375Srdivacky           T1LdSt4Imm<{1,?,?}>;
435193323Sed
436198090Srdivackydef tLDRB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr), IIC_iLoadr,
437198892Srdivacky                "ldrb", "\t$dst, $addr",
438201360Srdivacky                [(set tGPR:$dst, (zextloadi8 t_addrmode_s1:$addr))]>,
439201360Srdivacky            T1LdSt<0b110>;
440202375Srdivackydef tLDRBi: T1pI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr), IIC_iLoadr,
441202375Srdivacky                "ldrb", "\t$dst, $addr",
442202375Srdivacky                []>,
443202375Srdivacky            T1LdSt1Imm<{1,?,?}>;
444193323Sed
445198090Srdivackydef tLDRH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr), IIC_iLoadr,
446198892Srdivacky                "ldrh", "\t$dst, $addr",
447201360Srdivacky                [(set tGPR:$dst, (zextloadi16 t_addrmode_s2:$addr))]>,
448201360Srdivacky            T1LdSt<0b101>;
449202375Srdivackydef tLDRHi: T1pI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr), IIC_iLoadr,
450202375Srdivacky                "ldrh", "\t$dst, $addr",
451202375Srdivacky                []>,
452202375Srdivacky            T1LdSt2Imm<{1,?,?}>;
453193323Sed
454198090Srdivackylet AddedComplexity = 10 in
455198090Srdivackydef tLDRSB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), IIC_iLoadr,
456198892Srdivacky                 "ldrsb", "\t$dst, $addr",
457201360Srdivacky                 [(set tGPR:$dst, (sextloadi8 t_addrmode_rr:$addr))]>,
458201360Srdivacky             T1LdSt<0b011>;
459193323Sed
460198090Srdivackylet AddedComplexity = 10 in
461198090Srdivackydef tLDRSH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), IIC_iLoadr,
462198892Srdivacky                 "ldrsh", "\t$dst, $addr",
463201360Srdivacky                 [(set tGPR:$dst, (sextloadi16 t_addrmode_rr:$addr))]>,
464201360Srdivacky             T1LdSt<0b111>;
465193323Sed
466193323Sedlet canFoldAsLoad = 1 in
467198090Srdivackydef tLDRspi : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), IIC_iLoadi,
468198892Srdivacky                  "ldr", "\t$dst, $addr",
469201360Srdivacky                  [(set tGPR:$dst, (load t_addrmode_sp:$addr))]>,
470201360Srdivacky              T1LdStSP<{1,?,?}>;
471193323Sed
472193323Sed// Special instruction for restore. It cannot clobber condition register
473193323Sed// when it's expanded by eliminateCallFramePseudoInstr().
474208599Srdivackylet canFoldAsLoad = 1, mayLoad = 1, neverHasSideEffects = 1 in
475198090Srdivackydef tRestore : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), IIC_iLoadi,
476201360Srdivacky                    "ldr", "\t$dst, $addr", []>,
477201360Srdivacky               T1LdStSP<{1,?,?}>;
478193323Sed
479193323Sed// Load tconstpool
480198892Srdivacky// FIXME: Use ldr.n to work around a Darwin assembler bug.
481204642Srdivackylet canFoldAsLoad = 1, isReMaterializable = 1 in
482198090Srdivackydef tLDRpci : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr), IIC_iLoadi,
483198892Srdivacky                  "ldr", ".n\t$dst, $addr",
484201360Srdivacky                  [(set tGPR:$dst, (load (ARMWrapper tconstpool:$addr)))]>,
485201360Srdivacky              T1Encoding<{0,1,0,0,1,?}>; // A6.2 & A8.6.59
486193323Sed
487193323Sed// Special LDR for loads from non-pc-relative constpools.
488208599Srdivackylet canFoldAsLoad = 1, mayLoad = 1, neverHasSideEffects = 1,
489208599Srdivacky    isReMaterializable = 1 in
490198090Srdivackydef tLDRcp  : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr), IIC_iLoadi,
491201360Srdivacky                  "ldr", "\t$dst, $addr", []>,
492201360Srdivacky              T1LdStSP<{1,?,?}>;
493193323Sed
494198090Srdivackydef tSTR : T1pI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr), IIC_iStorer,
495198892Srdivacky               "str", "\t$src, $addr",
496201360Srdivacky               [(store tGPR:$src, t_addrmode_s4:$addr)]>,
497201360Srdivacky           T1LdSt<0b000>;
498202375Srdivackydef tSTRi: T1pI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr), IIC_iStorer,
499202375Srdivacky               "str", "\t$src, $addr",
500202375Srdivacky               []>,
501202375Srdivacky           T1LdSt4Imm<{0,?,?}>;
502193323Sed
503198090Srdivackydef tSTRB : T1pI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr), IIC_iStorer,
504198892Srdivacky                 "strb", "\t$src, $addr",
505201360Srdivacky                 [(truncstorei8 tGPR:$src, t_addrmode_s1:$addr)]>,
506201360Srdivacky            T1LdSt<0b010>;
507202375Srdivackydef tSTRBi: T1pI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr), IIC_iStorer,
508202375Srdivacky                 "strb", "\t$src, $addr",
509202375Srdivacky                 []>,
510202375Srdivacky            T1LdSt1Imm<{0,?,?}>;
511193323Sed
512198090Srdivackydef tSTRH : T1pI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr), IIC_iStorer,
513198892Srdivacky                 "strh", "\t$src, $addr",
514201360Srdivacky                 [(truncstorei16 tGPR:$src, t_addrmode_s2:$addr)]>,
515201360Srdivacky            T1LdSt<0b001>;
516202375Srdivackydef tSTRHi: T1pI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr), IIC_iStorer,
517202375Srdivacky                 "strh", "\t$src, $addr",
518202375Srdivacky                 []>,
519202375Srdivacky            T1LdSt2Imm<{0,?,?}>;
520193323Sed
521198090Srdivackydef tSTRspi : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStorei,
522198892Srdivacky                   "str", "\t$src, $addr",
523201360Srdivacky                   [(store tGPR:$src, t_addrmode_sp:$addr)]>,
524201360Srdivacky              T1LdStSP<{0,?,?}>;
525193323Sed
526208599Srdivackylet mayStore = 1, neverHasSideEffects = 1 in {
527193323Sed// Special instruction for spill. It cannot clobber condition register
528193323Sed// when it's expanded by eliminateCallFramePseudoInstr().
529198090Srdivackydef tSpill : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStorei,
530201360Srdivacky                  "str", "\t$src, $addr", []>,
531201360Srdivacky             T1LdStSP<{0,?,?}>;
532193323Sed}
533193323Sed
534193323Sed//===----------------------------------------------------------------------===//
535193323Sed//  Load / store multiple Instructions.
536193323Sed//
537193323Sed
538198090Srdivacky// These requires base address to be written back or one of the loaded regs.
539208599Srdivackylet mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1 in {
540198090Srdivackydef tLDM : T1I<(outs),
541205218Srdivacky               (ins addrmode4:$addr, pred:$p, reglist:$dsts, variable_ops),
542198090Srdivacky               IIC_iLoadm,
543205218Srdivacky               "ldm${addr:submode}${p}\t$addr, $dsts", []>,
544201360Srdivacky           T1Encoding<{1,1,0,0,1,?}>; // A6.2 & A8.6.53
545193323Sed
546205218Srdivackydef tLDM_UPD : T1It<(outs tGPR:$wb),
547205218Srdivacky                    (ins addrmode4:$addr, pred:$p, reglist:$dsts, variable_ops),
548205218Srdivacky                    IIC_iLoadm,
549205407Srdivacky                    "ldm${addr:submode}${p}\t$addr!, $dsts",
550205218Srdivacky                    "$addr.addr = $wb", []>,
551205218Srdivacky               T1Encoding<{1,1,0,0,1,?}>; // A6.2 & A8.6.53
552208599Srdivacky} // mayLoad, neverHasSideEffects = 1, hasExtraDefRegAllocReq
553205218Srdivacky
554208599Srdivackylet mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in
555205218Srdivackydef tSTM_UPD : T1It<(outs tGPR:$wb),
556205218Srdivacky                    (ins addrmode4:$addr, pred:$p, reglist:$srcs, variable_ops),
557205218Srdivacky                    IIC_iStorem,
558205407Srdivacky                    "stm${addr:submode}${p}\t$addr!, $srcs",
559205218Srdivacky                    "$addr.addr = $wb", []>,
560201360Srdivacky           T1Encoding<{1,1,0,0,0,?}>; // A6.2 & A8.6.189
561193323Sed
562198090Srdivackylet mayLoad = 1, Uses = [SP], Defs = [SP], hasExtraDefRegAllocReq = 1 in
563205218Srdivackydef tPOP : T1I<(outs), (ins pred:$p, reglist:$dsts, variable_ops), IIC_Br,
564205218Srdivacky               "pop${p}\t$dsts", []>,
565201360Srdivacky           T1Misc<{1,1,0,?,?,?,?}>;
566193323Sed
567198090Srdivackylet mayStore = 1, Uses = [SP], Defs = [SP], hasExtraSrcRegAllocReq = 1 in
568205218Srdivackydef tPUSH : T1I<(outs), (ins pred:$p, reglist:$srcs, variable_ops), IIC_Br,
569205218Srdivacky                "push${p}\t$srcs", []>,
570201360Srdivacky            T1Misc<{0,1,0,?,?,?,?}>;
571198090Srdivacky
572193323Sed//===----------------------------------------------------------------------===//
573193323Sed//  Arithmetic Instructions.
574193323Sed//
575193323Sed
576195098Sed// Add with carry register
577198090Srdivackylet isCommutable = 1, Uses = [CPSR] in
578198090Srdivackydef tADC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr,
579198892Srdivacky                 "adc", "\t$dst, $rhs",
580201360Srdivacky                 [(set tGPR:$dst, (adde tGPR:$lhs, tGPR:$rhs))]>,
581201360Srdivacky           T1DataProcessing<0b0101>;
582193323Sed
583195098Sed// Add immediate
584198090Srdivackydef tADDi3 : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi,
585198892Srdivacky                   "add", "\t$dst, $lhs, $rhs",
586201360Srdivacky                   [(set tGPR:$dst, (add tGPR:$lhs, imm0_7:$rhs))]>,
587201360Srdivacky             T1General<0b01110>;
588193323Sed
589198090Srdivackydef tADDi8 : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi,
590198892Srdivacky                   "add", "\t$dst, $rhs",
591201360Srdivacky                   [(set tGPR:$dst, (add tGPR:$lhs, imm8_255:$rhs))]>,
592201360Srdivacky             T1General<{1,1,0,?,?}>;
593193323Sed
594195098Sed// Add register
595198090Srdivackylet isCommutable = 1 in
596198090Srdivackydef tADDrr : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr,
597198892Srdivacky                   "add", "\t$dst, $lhs, $rhs",
598201360Srdivacky                   [(set tGPR:$dst, (add tGPR:$lhs, tGPR:$rhs))]>,
599201360Srdivacky             T1General<0b01100>;
600193323Sed
601194178Sedlet neverHasSideEffects = 1 in
602198090Srdivackydef tADDhirr : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr,
603201360Srdivacky                     "add", "\t$dst, $rhs", []>,
604201360Srdivacky               T1Special<{0,0,?,?}>;
605193323Sed
606195098Sed// And register
607198090Srdivackylet isCommutable = 1 in
608198090Srdivackydef tAND : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr,
609198892Srdivacky                 "and", "\t$dst, $rhs",
610201360Srdivacky                 [(set tGPR:$dst, (and tGPR:$lhs, tGPR:$rhs))]>,
611201360Srdivacky           T1DataProcessing<0b0000>;
612193323Sed
613195098Sed// ASR immediate
614198090Srdivackydef tASRri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iMOVsi,
615198892Srdivacky                  "asr", "\t$dst, $lhs, $rhs",
616201360Srdivacky                  [(set tGPR:$dst, (sra tGPR:$lhs, (i32 imm:$rhs)))]>,
617201360Srdivacky             T1General<{0,1,0,?,?}>;
618193323Sed
619195098Sed// ASR register
620198090Srdivackydef tASRrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr,
621198892Srdivacky                   "asr", "\t$dst, $rhs",
622201360Srdivacky                   [(set tGPR:$dst, (sra tGPR:$lhs, tGPR:$rhs))]>,
623201360Srdivacky             T1DataProcessing<0b0100>;
624193323Sed
625195098Sed// BIC register
626198090Srdivackydef tBIC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr,
627198892Srdivacky                 "bic", "\t$dst, $rhs",
628201360Srdivacky                 [(set tGPR:$dst, (and tGPR:$lhs, (not tGPR:$rhs)))]>,
629201360Srdivacky           T1DataProcessing<0b1110>;
630193323Sed
631195098Sed// CMN register
632195098Sedlet Defs = [CPSR] in {
633202878Srdivacky//FIXME: Disable CMN, as CCodes are backwards from compare expectations
634202878Srdivacky//       Compare-to-zero still works out, just not the relationals
635202878Srdivacky//def tCMN : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr,
636202878Srdivacky//                "cmn", "\t$lhs, $rhs",
637202878Srdivacky//                [(ARMcmp tGPR:$lhs, (ineg tGPR:$rhs))]>,
638202878Srdivacky//           T1DataProcessing<0b1011>;
639201360Srdivackydef tCMNz : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr,
640198892Srdivacky                 "cmn", "\t$lhs, $rhs",
641201360Srdivacky                 [(ARMcmpZ tGPR:$lhs, (ineg tGPR:$rhs))]>,
642201360Srdivacky            T1DataProcessing<0b1011>;
643195098Sed}
644193323Sed
645195098Sed// CMP immediate
646195098Sedlet Defs = [CPSR] in {
647198090Srdivackydef tCMPi8 : T1pI<(outs), (ins tGPR:$lhs, i32imm:$rhs), IIC_iCMPi,
648198892Srdivacky                  "cmp", "\t$lhs, $rhs",
649201360Srdivacky                  [(ARMcmp tGPR:$lhs, imm0_255:$rhs)]>,
650201360Srdivacky             T1General<{1,0,1,?,?}>;
651198090Srdivackydef tCMPzi8 : T1pI<(outs), (ins tGPR:$lhs, i32imm:$rhs), IIC_iCMPi,
652198892Srdivacky                  "cmp", "\t$lhs, $rhs",
653201360Srdivacky                  [(ARMcmpZ tGPR:$lhs, imm0_255:$rhs)]>,
654201360Srdivacky              T1General<{1,0,1,?,?}>;
655195098Sed}
656195098Sed
657195098Sed// CMP register
658195098Sedlet Defs = [CPSR] in {
659198090Srdivackydef tCMPr : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr,
660198892Srdivacky                 "cmp", "\t$lhs, $rhs",
661201360Srdivacky                 [(ARMcmp tGPR:$lhs, tGPR:$rhs)]>,
662201360Srdivacky            T1DataProcessing<0b1010>;
663198090Srdivackydef tCMPzr : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr,
664198892Srdivacky                  "cmp", "\t$lhs, $rhs",
665201360Srdivacky                  [(ARMcmpZ tGPR:$lhs, tGPR:$rhs)]>,
666201360Srdivacky             T1DataProcessing<0b1010>;
667198090Srdivacky
668198090Srdivackydef tCMPhir : T1pI<(outs), (ins GPR:$lhs, GPR:$rhs), IIC_iCMPr,
669201360Srdivacky                   "cmp", "\t$lhs, $rhs", []>,
670201360Srdivacky              T1Special<{0,1,?,?}>;
671198090Srdivackydef tCMPzhir : T1pI<(outs), (ins GPR:$lhs, GPR:$rhs), IIC_iCMPr,
672201360Srdivacky                    "cmp", "\t$lhs, $rhs", []>,
673201360Srdivacky               T1Special<{0,1,?,?}>;
674195098Sed}
675193323Sed
676193323Sed
677195098Sed// XOR register
678198090Srdivackylet isCommutable = 1 in
679198090Srdivackydef tEOR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr,
680198892Srdivacky                 "eor", "\t$dst, $rhs",
681201360Srdivacky                 [(set tGPR:$dst, (xor tGPR:$lhs, tGPR:$rhs))]>,
682201360Srdivacky           T1DataProcessing<0b0001>;
683193323Sed
684195098Sed// LSL immediate
685198090Srdivackydef tLSLri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iMOVsi,
686198892Srdivacky                  "lsl", "\t$dst, $lhs, $rhs",
687201360Srdivacky                  [(set tGPR:$dst, (shl tGPR:$lhs, (i32 imm:$rhs)))]>,
688201360Srdivacky             T1General<{0,0,0,?,?}>;
689193323Sed
690195098Sed// LSL register
691198090Srdivackydef tLSLrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr,
692198892Srdivacky                   "lsl", "\t$dst, $rhs",
693201360Srdivacky                   [(set tGPR:$dst, (shl tGPR:$lhs, tGPR:$rhs))]>,
694201360Srdivacky             T1DataProcessing<0b0010>;
695193323Sed
696195098Sed// LSR immediate
697198090Srdivackydef tLSRri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iMOVsi,
698198892Srdivacky                  "lsr", "\t$dst, $lhs, $rhs",
699201360Srdivacky                  [(set tGPR:$dst, (srl tGPR:$lhs, (i32 imm:$rhs)))]>,
700201360Srdivacky             T1General<{0,0,1,?,?}>;
701193323Sed
702195098Sed// LSR register
703198090Srdivackydef tLSRrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr,
704198892Srdivacky                   "lsr", "\t$dst, $rhs",
705201360Srdivacky                   [(set tGPR:$dst, (srl tGPR:$lhs, tGPR:$rhs))]>,
706201360Srdivacky             T1DataProcessing<0b0011>;
707193323Sed
708195098Sed// move register
709198090Srdivackydef tMOVi8 : T1sI<(outs tGPR:$dst), (ins i32imm:$src), IIC_iMOVi,
710198892Srdivacky                  "mov", "\t$dst, $src",
711201360Srdivacky                  [(set tGPR:$dst, imm0_255:$src)]>,
712201360Srdivacky             T1General<{1,0,0,?,?}>;
713193323Sed
714193323Sed// TODO: A7-73: MOV(2) - mov setting flag.
715193323Sed
716193323Sed
717194178Sedlet neverHasSideEffects = 1 in {
718198090Srdivacky// FIXME: Make this predicable.
719198090Srdivackydef tMOVr       : T1I<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr,
720201360Srdivacky                      "mov\t$dst, $src", []>,
721201360Srdivacky                  T1Special<0b1000>;
722198090Srdivackylet Defs = [CPSR] in
723198090Srdivackydef tMOVSr      : T1I<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr,
724201360Srdivacky                       "movs\t$dst, $src", []>, Encoding16 {
725201360Srdivacky  let Inst{15-6} = 0b0000000000;
726201360Srdivacky}
727198090Srdivacky
728198090Srdivacky// FIXME: Make these predicable.
729198090Srdivackydef tMOVgpr2tgpr : T1I<(outs tGPR:$dst), (ins GPR:$src), IIC_iMOVr,
730201360Srdivacky                       "mov\t$dst, $src", []>,
731202878Srdivacky                   T1Special<{1,0,0,?}>;
732198090Srdivackydef tMOVtgpr2gpr : T1I<(outs GPR:$dst), (ins tGPR:$src), IIC_iMOVr,
733201360Srdivacky                       "mov\t$dst, $src", []>,
734202878Srdivacky                   T1Special<{1,0,?,0}>;
735198090Srdivackydef tMOVgpr2gpr  : T1I<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVr,
736201360Srdivacky                       "mov\t$dst, $src", []>,
737202878Srdivacky                   T1Special<{1,0,?,?}>;
738194178Sed} // neverHasSideEffects
739193323Sed
740195098Sed// multiply register
741198090Srdivackylet isCommutable = 1 in
742198090Srdivackydef tMUL : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMUL32,
743204792Srdivacky                 "mul", "\t$dst, $rhs, $dst", /* A8.6.105 MUL Encoding T1 */
744201360Srdivacky                 [(set tGPR:$dst, (mul tGPR:$lhs, tGPR:$rhs))]>,
745201360Srdivacky           T1DataProcessing<0b1101>;
746193323Sed
747195098Sed// move inverse register
748198090Srdivackydef tMVN : T1sI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr,
749198892Srdivacky                "mvn", "\t$dst, $src",
750201360Srdivacky                [(set tGPR:$dst, (not tGPR:$src))]>,
751201360Srdivacky           T1DataProcessing<0b1111>;
752193323Sed
753195098Sed// bitwise or register
754198090Srdivackylet isCommutable = 1 in
755198090Srdivackydef tORR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),  IIC_iALUr,
756198892Srdivacky                 "orr", "\t$dst, $rhs",
757201360Srdivacky                 [(set tGPR:$dst, (or tGPR:$lhs, tGPR:$rhs))]>,
758201360Srdivacky           T1DataProcessing<0b1100>;
759193323Sed
760195098Sed// swaps
761198090Srdivackydef tREV : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr,
762198892Srdivacky                "rev", "\t$dst, $src",
763198090Srdivacky                [(set tGPR:$dst, (bswap tGPR:$src))]>,
764201360Srdivacky                Requires<[IsThumb1Only, HasV6]>,
765201360Srdivacky           T1Misc<{1,0,1,0,0,0,?}>;
766193323Sed
767198090Srdivackydef tREV16 : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr,
768198892Srdivacky                  "rev16", "\t$dst, $src",
769198090Srdivacky             [(set tGPR:$dst,
770198090Srdivacky                   (or (and (srl tGPR:$src, (i32 8)), 0xFF),
771198090Srdivacky                       (or (and (shl tGPR:$src, (i32 8)), 0xFF00),
772198090Srdivacky                           (or (and (srl tGPR:$src, (i32 8)), 0xFF0000),
773198090Srdivacky                               (and (shl tGPR:$src, (i32 8)), 0xFF000000)))))]>,
774201360Srdivacky                Requires<[IsThumb1Only, HasV6]>,
775201360Srdivacky             T1Misc<{1,0,1,0,0,1,?}>;
776193323Sed
777198090Srdivackydef tREVSH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr,
778198892Srdivacky                  "revsh", "\t$dst, $src",
779198090Srdivacky                  [(set tGPR:$dst,
780198090Srdivacky                        (sext_inreg
781198090Srdivacky                          (or (srl (and tGPR:$src, 0xFF00), (i32 8)),
782198090Srdivacky                              (shl tGPR:$src, (i32 8))), i16))]>,
783201360Srdivacky                  Requires<[IsThumb1Only, HasV6]>,
784201360Srdivacky             T1Misc<{1,0,1,0,1,1,?}>;
785193323Sed
786195098Sed// rotate right register
787198090Srdivackydef tROR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr,
788198892Srdivacky                 "ror", "\t$dst, $rhs",
789201360Srdivacky                 [(set tGPR:$dst, (rotr tGPR:$lhs, tGPR:$rhs))]>,
790201360Srdivacky           T1DataProcessing<0b0111>;
791193323Sed
792198090Srdivacky// negate register
793198090Srdivackydef tRSB : T1sI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iALUi,
794198892Srdivacky                "rsb", "\t$dst, $src, #0",
795201360Srdivacky                [(set tGPR:$dst, (ineg tGPR:$src))]>,
796201360Srdivacky           T1DataProcessing<0b1001>;
797198090Srdivacky
798195098Sed// Subtract with carry register
799198090Srdivackylet Uses = [CPSR] in
800198090Srdivackydef tSBC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr,
801198892Srdivacky                 "sbc", "\t$dst, $rhs",
802201360Srdivacky                 [(set tGPR:$dst, (sube tGPR:$lhs, tGPR:$rhs))]>,
803201360Srdivacky           T1DataProcessing<0b0110>;
804193323Sed
805195098Sed// Subtract immediate
806198090Srdivackydef tSUBi3 : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi,
807198892Srdivacky                  "sub", "\t$dst, $lhs, $rhs",
808201360Srdivacky                  [(set tGPR:$dst, (add tGPR:$lhs, imm0_7_neg:$rhs))]>,
809201360Srdivacky             T1General<0b01111>;
810193323Sed
811198090Srdivackydef tSUBi8 : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi,
812198892Srdivacky                   "sub", "\t$dst, $rhs",
813201360Srdivacky                   [(set tGPR:$dst, (add tGPR:$lhs, imm8_255_neg:$rhs))]>,
814201360Srdivacky             T1General<{1,1,1,?,?}>;
815193323Sed
816195098Sed// subtract register
817198090Srdivackydef tSUBrr : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr,
818198892Srdivacky                  "sub", "\t$dst, $lhs, $rhs",
819201360Srdivacky                  [(set tGPR:$dst, (sub tGPR:$lhs, tGPR:$rhs))]>,
820201360Srdivacky             T1General<0b01101>;
821193323Sed
822195098Sed// TODO: A7-96: STMIA - store multiple.
823195098Sed
824195098Sed// sign-extend byte
825198090Srdivackydef tSXTB  : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr,
826198892Srdivacky                  "sxtb", "\t$dst, $src",
827198090Srdivacky                  [(set tGPR:$dst, (sext_inreg tGPR:$src, i8))]>,
828201360Srdivacky                  Requires<[IsThumb1Only, HasV6]>,
829201360Srdivacky             T1Misc<{0,0,1,0,0,1,?}>;
830195098Sed
831195098Sed// sign-extend short
832198090Srdivackydef tSXTH  : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr,
833198892Srdivacky                  "sxth", "\t$dst, $src",
834198090Srdivacky                  [(set tGPR:$dst, (sext_inreg tGPR:$src, i16))]>,
835201360Srdivacky                  Requires<[IsThumb1Only, HasV6]>,
836201360Srdivacky             T1Misc<{0,0,1,0,0,0,?}>;
837193323Sed
838195098Sed// test
839195098Sedlet isCommutable = 1, Defs = [CPSR] in
840198090Srdivackydef tTST  : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr,
841198892Srdivacky                 "tst", "\t$lhs, $rhs",
842201360Srdivacky                 [(ARMcmpZ (and tGPR:$lhs, tGPR:$rhs), 0)]>,
843201360Srdivacky            T1DataProcessing<0b1000>;
844193323Sed
845195098Sed// zero-extend byte
846198090Srdivackydef tUXTB  : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr,
847198892Srdivacky                  "uxtb", "\t$dst, $src",
848198090Srdivacky                  [(set tGPR:$dst, (and tGPR:$src, 0xFF))]>,
849201360Srdivacky                  Requires<[IsThumb1Only, HasV6]>,
850201360Srdivacky             T1Misc<{0,0,1,0,1,1,?}>;
851195098Sed
852195098Sed// zero-extend short
853198090Srdivackydef tUXTH  : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr,
854198892Srdivacky                  "uxth", "\t$dst, $src",
855198090Srdivacky                  [(set tGPR:$dst, (and tGPR:$src, 0xFFFF))]>,
856201360Srdivacky                  Requires<[IsThumb1Only, HasV6]>,
857201360Srdivacky             T1Misc<{0,0,1,0,1,0,?}>;
858193323Sed
859193323Sed
860204642Srdivacky// Conditional move tMOVCCr - Used to implement the Thumb SELECT_CC operation.
861198892Srdivacky// Expanded after instruction selection into a branch sequence.
862198892Srdivackylet usesCustomInserter = 1 in  // Expanded after instruction selection.
863198090Srdivacky  def tMOVCCr_pseudo :
864193323Sed  PseudoInst<(outs tGPR:$dst), (ins tGPR:$false, tGPR:$true, pred:$cc),
865208599Srdivacky              NoItinerary, "${:comment} tMOVCCr $cc",
866198090Srdivacky             [/*(set tGPR:$dst, (ARMcmov tGPR:$false, tGPR:$true, imm:$cc))*/]>;
867193323Sed
868198090Srdivacky
869198090Srdivacky// 16-bit movcc in IT blocks for Thumb2.
870208599Srdivackylet neverHasSideEffects = 1 in {
871198090Srdivackydef tMOVCCr : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iCMOVr,
872201360Srdivacky                    "mov", "\t$dst, $rhs", []>,
873202878Srdivacky              T1Special<{1,0,?,?}>;
874198090Srdivacky
875203954Srdivackydef tMOVCCi : T1pIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iCMOVi,
876201360Srdivacky                    "mov", "\t$dst, $rhs", []>,
877201360Srdivacky              T1General<{1,0,0,?,?}>;
878208599Srdivacky} // neverHasSideEffects
879198090Srdivacky
880193323Sed// tLEApcrel - Load a pc-relative address into a register without offending the
881193323Sed// assembler.
882208599Srdivackylet neverHasSideEffects = 1 in {
883208599Srdivackylet isReMaterializable = 1 in
884198090Srdivackydef tLEApcrel : T1I<(outs tGPR:$dst), (ins i32imm:$label, pred:$p), IIC_iALUi,
885201360Srdivacky                    "adr$p\t$dst, #$label", []>,
886201360Srdivacky                T1Encoding<{1,0,1,0,0,?}>; // A6.2 & A8.6.10
887193323Sed
888210299Sed} // neverHasSideEffects
889198090Srdivackydef tLEApcrelJT : T1I<(outs tGPR:$dst),
890198090Srdivacky                      (ins i32imm:$label, nohash_imm:$id, pred:$p),
891201360Srdivacky                      IIC_iALUi, "adr$p\t$dst, #${label}_${id}", []>,
892201360Srdivacky                  T1Encoding<{1,0,1,0,0,?}>; // A6.2 & A8.6.10
893193323Sed
894193323Sed//===----------------------------------------------------------------------===//
895193323Sed// TLS Instructions
896193323Sed//
897193323Sed
898193323Sed// __aeabi_read_tp preserves the registers r1-r3.
899193323Sedlet isCall = 1,
900193323Sed  Defs = [R0, LR] in {
901201360Srdivacky  def tTPsoft : TIx2<0b11110, 0b11, 1, (outs), (ins), IIC_Br,
902201360Srdivacky                     "bl\t__aeabi_read_tp",
903201360Srdivacky                     [(set R0, ARMthread_pointer)]>;
904193323Sed}
905193323Sed
906200581Srdivacky// SJLJ Exception handling intrinsics
907200581Srdivacky//   eh_sjlj_setjmp() is an instruction sequence to store the return
908200581Srdivacky//   address and save #0 in R0 for the non-longjmp case.
909200581Srdivacky//   Since by its nature we may be coming from some other function to get
910200581Srdivacky//   here, and we're using the stack frame for the containing function to
911200581Srdivacky//   save/restore registers, we can't keep anything live in regs across
912200581Srdivacky//   the eh_sjlj_setjmp(), else it will almost certainly have been tromped upon
913200581Srdivacky//   when we get here from a longjmp(). We force everthing out of registers
914200581Srdivacky//   except for our own input by listing the relevant registers in Defs. By
915200581Srdivacky//   doing so, we also cause the prologue/epilogue code to actively preserve
916200581Srdivacky//   all of the callee-saved resgisters, which is exactly what we want.
917210299Sed//   $val is a scratch register for our use.
918200581Srdivackylet Defs =
919210299Sed  [ R0,  R1,  R2,  R3,  R4,  R5,  R6,  R7, R12 ], hasSideEffects = 1,
920210299Sed   isBarrier = 1  in {
921203954Srdivacky  def tInt_eh_sjlj_setjmp : ThumbXI<(outs),(ins tGPR:$src, tGPR:$val),
922200581Srdivacky                              AddrModeNone, SizeSpecial, NoItinerary,
923210299Sed                              "mov\t$val, pc\t${:comment} begin eh.setjmp\n\t"
924210299Sed                              "adds\t$val, #7\n\t"
925210299Sed                              "str\t$val, [$src, #4]\n\t"
926210299Sed                              "movs\tr0, #0\n\t"
927210299Sed                              "b\t1f\n\t"
928210299Sed                              "movs\tr0, #1\t${:comment} end eh.setjmp\n\t"
929200581Srdivacky                              "1:", "",
930203954Srdivacky                   [(set R0, (ARMeh_sjlj_setjmp tGPR:$src, tGPR:$val))]>;
931200581Srdivacky}
932208599Srdivacky
933208599Srdivacky// FIXME: Non-Darwin version(s)
934208599Srdivackylet isBarrier = 1, hasSideEffects = 1, isTerminator = 1,
935208599Srdivacky    Defs = [ R7, LR, SP ] in {
936208599Srdivackydef tInt_eh_sjlj_longjmp : XI<(outs), (ins GPR:$src, GPR:$scratch),
937208599Srdivacky                             AddrModeNone, SizeSpecial, IndexModeNone,
938208599Srdivacky                             Pseudo, NoItinerary,
939208599Srdivacky                             "ldr\t$scratch, [$src, #8]\n\t"
940208599Srdivacky                             "mov\tsp, $scratch\n\t"
941208599Srdivacky                             "ldr\t$scratch, [$src, #4]\n\t"
942208599Srdivacky                             "ldr\tr7, [$src]\n\t"
943208599Srdivacky                             "bx\t$scratch", "",
944208599Srdivacky                         [(ARMeh_sjlj_longjmp GPR:$src, GPR:$scratch)]>,
945208599Srdivacky                                Requires<[IsThumb, IsDarwin]>;
946208599Srdivacky}
947208599Srdivacky
948193323Sed//===----------------------------------------------------------------------===//
949193323Sed// Non-Instruction Patterns
950193323Sed//
951193323Sed
952198090Srdivacky// Add with carry
953198090Srdivackydef : T1Pat<(addc   tGPR:$lhs, imm0_7:$rhs),
954198090Srdivacky            (tADDi3 tGPR:$lhs, imm0_7:$rhs)>;
955198090Srdivackydef : T1Pat<(addc   tGPR:$lhs, imm8_255:$rhs),
956198090Srdivacky            (tADDi8 tGPR:$lhs, imm8_255:$rhs)>;
957198090Srdivackydef : T1Pat<(addc   tGPR:$lhs, tGPR:$rhs),
958198090Srdivacky            (tADDrr tGPR:$lhs, tGPR:$rhs)>;
959198090Srdivacky
960198090Srdivacky// Subtract with carry
961198090Srdivackydef : T1Pat<(addc   tGPR:$lhs, imm0_7_neg:$rhs),
962198090Srdivacky            (tSUBi3 tGPR:$lhs, imm0_7_neg:$rhs)>;
963198090Srdivackydef : T1Pat<(addc   tGPR:$lhs, imm8_255_neg:$rhs),
964198090Srdivacky            (tSUBi8 tGPR:$lhs, imm8_255_neg:$rhs)>;
965198090Srdivackydef : T1Pat<(subc   tGPR:$lhs, tGPR:$rhs),
966198090Srdivacky            (tSUBrr tGPR:$lhs, tGPR:$rhs)>;
967198090Srdivacky
968193323Sed// ConstantPool, GlobalAddress
969198090Srdivackydef : T1Pat<(ARMWrapper  tglobaladdr :$dst), (tLEApcrel tglobaladdr :$dst)>;
970198090Srdivackydef : T1Pat<(ARMWrapper  tconstpool  :$dst), (tLEApcrel tconstpool  :$dst)>;
971193323Sed
972193323Sed// JumpTable
973198090Srdivackydef : T1Pat<(ARMWrapperJT tjumptable:$dst, imm:$id),
974198090Srdivacky            (tLEApcrelJT tjumptable:$dst, imm:$id)>;
975193323Sed
976193323Sed// Direct calls
977198090Srdivackydef : T1Pat<(ARMtcall texternalsym:$func), (tBL texternalsym:$func)>,
978198090Srdivacky      Requires<[IsThumb, IsNotDarwin]>;
979198090Srdivackydef : T1Pat<(ARMtcall texternalsym:$func), (tBLr9 texternalsym:$func)>,
980198090Srdivacky      Requires<[IsThumb, IsDarwin]>;
981193323Sed
982198090Srdivackydef : Tv5Pat<(ARMcall texternalsym:$func), (tBLXi texternalsym:$func)>,
983198090Srdivacky      Requires<[IsThumb, HasV5T, IsNotDarwin]>;
984198090Srdivackydef : Tv5Pat<(ARMcall texternalsym:$func), (tBLXi_r9 texternalsym:$func)>,
985198090Srdivacky      Requires<[IsThumb, HasV5T, IsDarwin]>;
986198090Srdivacky
987193323Sed// Indirect calls to ARM routines
988198090Srdivackydef : Tv5Pat<(ARMcall GPR:$dst), (tBLXr GPR:$dst)>,
989198090Srdivacky      Requires<[IsThumb, HasV5T, IsNotDarwin]>;
990198090Srdivackydef : Tv5Pat<(ARMcall GPR:$dst), (tBLXr_r9 GPR:$dst)>,
991198090Srdivacky      Requires<[IsThumb, HasV5T, IsDarwin]>;
992193323Sed
993193323Sed// zextload i1 -> zextload i8
994195340Seddef : T1Pat<(zextloadi1 t_addrmode_s1:$addr),
995195340Sed            (tLDRB t_addrmode_s1:$addr)>;
996193323Sed
997193323Sed// extload -> zextload
998195340Seddef : T1Pat<(extloadi1  t_addrmode_s1:$addr),  (tLDRB t_addrmode_s1:$addr)>;
999195340Seddef : T1Pat<(extloadi8  t_addrmode_s1:$addr),  (tLDRB t_addrmode_s1:$addr)>;
1000195340Seddef : T1Pat<(extloadi16 t_addrmode_s2:$addr),  (tLDRH t_addrmode_s2:$addr)>;
1001193323Sed
1002198090Srdivacky// If it's impossible to use [r,r] address mode for sextload, select to
1003198090Srdivacky// ldr{b|h} + sxt{b|h} instead.
1004198090Srdivackydef : T1Pat<(sextloadi8 t_addrmode_s1:$addr),
1005198090Srdivacky            (tSXTB (tLDRB t_addrmode_s1:$addr))>,
1006198090Srdivacky      Requires<[IsThumb1Only, HasV6]>;
1007198090Srdivackydef : T1Pat<(sextloadi16 t_addrmode_s2:$addr),
1008198090Srdivacky            (tSXTH (tLDRH t_addrmode_s2:$addr))>,
1009198090Srdivacky      Requires<[IsThumb1Only, HasV6]>;
1010198090Srdivacky
1011198090Srdivackydef : T1Pat<(sextloadi8 t_addrmode_s1:$addr),
1012198090Srdivacky            (tASRri (tLSLri (tLDRB t_addrmode_s1:$addr), 24), 24)>;
1013198090Srdivackydef : T1Pat<(sextloadi16 t_addrmode_s1:$addr),
1014198090Srdivacky            (tASRri (tLSLri (tLDRH t_addrmode_s1:$addr), 16), 16)>;
1015198090Srdivacky
1016193323Sed// Large immediate handling.
1017193323Sed
1018193323Sed// Two piece imms.
1019195098Seddef : T1Pat<(i32 thumb_immshifted:$src),
1020195098Sed            (tLSLri (tMOVi8 (thumb_immshifted_val imm:$src)),
1021195098Sed                    (thumb_immshifted_shamt imm:$src))>;
1022193323Sed
1023195098Seddef : T1Pat<(i32 imm0_255_comp:$src),
1024195098Sed            (tMVN (tMOVi8 (imm_comp_XFORM imm:$src)))>;
1025199481Srdivacky
1026199481Srdivacky// Pseudo instruction that combines ldr from constpool and add pc. This should
1027199481Srdivacky// be expanded into two instructions late to allow if-conversion and
1028199481Srdivacky// scheduling.
1029199481Srdivackylet isReMaterializable = 1 in
1030199481Srdivackydef tLDRpci_pic : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr, pclabel:$cp),
1031210299Sed                   NoItinerary,
1032210299Sed                   "${:comment} ldr.n\t$dst, $addr\n$cp:\n\tadd\t$dst, pc",
1033199481Srdivacky               [(set GPR:$dst, (ARMpic_add (load (ARMWrapper tconstpool:$addr)),
1034199481Srdivacky                                           imm:$cp))]>,
1035199481Srdivacky               Requires<[IsThumb1Only]>;
1036