ARMInstrThumb.td revision 8768bff8f38323e7fca82917cb9f94648423d706
1//===- ARMInstrThumb.td - Thumb support for ARM ---------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file describes the Thumb instruction set.
11//
12//===----------------------------------------------------------------------===//
13
14//===----------------------------------------------------------------------===//
15// Thumb specific DAG Nodes.
16//
17
18def ARMtcall : SDNode<"ARMISD::tCALL", SDT_ARMcall,
19                      [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
20
21def imm_neg_XFORM : SDNodeXForm<imm, [{
22  return CurDAG->getTargetConstant(-(int)N->getZExtValue(), MVT::i32);
23}]>;
24def imm_comp_XFORM : SDNodeXForm<imm, [{
25  return CurDAG->getTargetConstant(~((uint32_t)N->getZExtValue()), MVT::i32);
26}]>;
27
28
29/// imm0_7 predicate - True if the 32-bit immediate is in the range [0,7].
30def imm0_7 : PatLeaf<(i32 imm), [{
31  return (uint32_t)N->getZExtValue() < 8;
32}]>;
33def imm0_7_neg : PatLeaf<(i32 imm), [{
34  return (uint32_t)-N->getZExtValue() < 8;
35}], imm_neg_XFORM>;
36
37def imm0_255 : PatLeaf<(i32 imm), [{
38  return (uint32_t)N->getZExtValue() < 256;
39}]>;
40def imm0_255_comp : PatLeaf<(i32 imm), [{
41  return ~((uint32_t)N->getZExtValue()) < 256;
42}]>;
43
44def imm8_255 : PatLeaf<(i32 imm), [{
45  return (uint32_t)N->getZExtValue() >= 8 && (uint32_t)N->getZExtValue() < 256;
46}]>;
47def imm8_255_neg : PatLeaf<(i32 imm), [{
48  unsigned Val = -N->getZExtValue();
49  return Val >= 8 && Val < 256;
50}], imm_neg_XFORM>;
51
52// Break imm's up into two pieces: an immediate + a left shift.
53// This uses thumb_immshifted to match and thumb_immshifted_val and
54// thumb_immshifted_shamt to get the val/shift pieces.
55def thumb_immshifted : PatLeaf<(imm), [{
56  return ARM_AM::isThumbImmShiftedVal((unsigned)N->getZExtValue());
57}]>;
58
59def thumb_immshifted_val : SDNodeXForm<imm, [{
60  unsigned V = ARM_AM::getThumbImmNonShiftedVal((unsigned)N->getZExtValue());
61  return CurDAG->getTargetConstant(V, MVT::i32);
62}]>;
63
64def thumb_immshifted_shamt : SDNodeXForm<imm, [{
65  unsigned V = ARM_AM::getThumbImmValShift((unsigned)N->getZExtValue());
66  return CurDAG->getTargetConstant(V, MVT::i32);
67}]>;
68
69// Define Thumb specific addressing modes.
70
71// t_addrmode_rr := reg + reg
72//
73def t_addrmode_rr : Operand<i32>,
74                    ComplexPattern<i32, 2, "SelectThumbAddrModeRR", []> {
75  let PrintMethod = "printThumbAddrModeRROperand";
76  let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg);
77}
78
79// t_addrmode_s4 := reg + reg
80//                  reg + imm5 * 4
81//
82def t_addrmode_s4 : Operand<i32>,
83                    ComplexPattern<i32, 3, "SelectThumbAddrModeS4", []> {
84  let PrintMethod = "printThumbAddrModeS4Operand";
85  let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg);
86}
87
88// t_addrmode_s2 := reg + reg
89//                  reg + imm5 * 2
90//
91def t_addrmode_s2 : Operand<i32>,
92                    ComplexPattern<i32, 3, "SelectThumbAddrModeS2", []> {
93  let PrintMethod = "printThumbAddrModeS2Operand";
94  let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg);
95}
96
97// t_addrmode_s1 := reg + reg
98//                  reg + imm5
99//
100def t_addrmode_s1 : Operand<i32>,
101                    ComplexPattern<i32, 3, "SelectThumbAddrModeS1", []> {
102  let PrintMethod = "printThumbAddrModeS1Operand";
103  let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg);
104}
105
106// t_addrmode_sp := sp + imm8 * 4
107//
108def t_addrmode_sp : Operand<i32>,
109                    ComplexPattern<i32, 2, "SelectThumbAddrModeSP", []> {
110  let PrintMethod = "printThumbAddrModeSPOperand";
111  let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm);
112}
113
114//===----------------------------------------------------------------------===//
115//  Miscellaneous Instructions.
116//
117
118let Defs = [SP], Uses = [SP] in {
119def tADJCALLSTACKUP :
120PseudoInst<(outs), (ins i32imm:$amt1, i32imm:$amt2),
121           "@ tADJCALLSTACKUP $amt1",
122           [(ARMcallseq_end imm:$amt1, imm:$amt2)]>, Requires<[IsThumb]>;
123
124def tADJCALLSTACKDOWN :
125PseudoInst<(outs), (ins i32imm:$amt),
126           "@ tADJCALLSTACKDOWN $amt",
127           [(ARMcallseq_start imm:$amt)]>, Requires<[IsThumb]>;
128}
129
130let isNotDuplicable = 1 in
131def tPICADD : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, pclabel:$cp),
132                  "$cp:\n\tadd $dst, pc",
133                  [(set tGPR:$dst, (ARMpic_add tGPR:$lhs, imm:$cp))]>;
134
135// PC relative add.
136def tADDrPCi : T1I<(outs tGPR:$dst), (ins i32imm:$rhs),
137                  "add $dst, pc, $rhs * 4", []>;
138
139// ADD rd, sp, #imm8
140// FIXME: hard code sp?
141def tADDrSPi : T1I<(outs tGPR:$dst), (ins GPR:$sp, i32imm:$rhs),
142                  "add $dst, $sp, $rhs * 4 @ addrspi", []>;
143
144// ADD sp, sp, #imm7
145// FIXME: hard code sp?
146def tADDspi : T1It<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs),
147                  "add $dst, $rhs * 4", []>;
148
149// FIXME: Make use of the following?
150// ADD rm, sp, rm
151// ADD sp, rm
152
153//===----------------------------------------------------------------------===//
154//  Control Flow Instructions.
155//
156
157let isReturn = 1, isTerminator = 1 in {
158  def tBX_RET : TI<(outs), (ins), "bx lr", [(ARMretflag)]>;
159  // Alternative return instruction used by vararg functions.
160  def tBX_RET_vararg : TI<(outs), (ins tGPR:$target), "bx $target", []>;
161}
162
163// FIXME: remove when we have a way to marking a MI with these properties.
164let isReturn = 1, isTerminator = 1 in
165def tPOP_RET : TI<(outs reglist:$dst1, variable_ops), (ins),
166                   "pop $dst1", []>;
167
168let isCall = 1,
169  Defs = [R0, R1, R2, R3, LR,
170          D0, D1, D2, D3, D4, D5, D6, D7] in {
171  def tBL  : TIx2<(outs), (ins i32imm:$func, variable_ops),
172                   "bl ${func:call}",
173                   [(ARMtcall tglobaladdr:$func)]>;
174  // ARMv5T and above
175  def tBLXi : TIx2<(outs), (ins i32imm:$func, variable_ops),
176                    "blx ${func:call}",
177                    [(ARMcall tglobaladdr:$func)]>, Requires<[HasV5T]>;
178  def tBLXr : TI<(outs), (ins tGPR:$func, variable_ops),
179                  "blx $func",
180                  [(ARMtcall tGPR:$func)]>, Requires<[HasV5T]>;
181  // ARMv4T
182  def tBX : TIx2<(outs), (ins tGPR:$func, variable_ops),
183                  "cpy lr, pc\n\tbx $func",
184                  [(ARMcall_nolink tGPR:$func)]>;
185}
186
187let isBranch = 1, isTerminator = 1 in {
188  let isBarrier = 1 in {
189    let isPredicable = 1 in
190    def tB   : TI<(outs), (ins brtarget:$target), "b $target",
191                  [(br bb:$target)]>;
192
193  // Far jump
194  def tBfar : TIx2<(outs), (ins brtarget:$target), "bl $target\t@ far jump",[]>;
195
196  def tBR_JTr : TJTI<(outs),
197                     (ins tGPR:$target, jtblock_operand:$jt, i32imm:$id),
198                     "cpy pc, $target \n\t.align\t2\n$jt",
199                     [(ARMbrjt tGPR:$target, tjumptable:$jt, imm:$id)]>;
200  }
201}
202
203// FIXME: should be able to write a pattern for ARMBrcond, but can't use
204// a two-value operand where a dag node expects two operands. :(
205let isBranch = 1, isTerminator = 1 in
206  def tBcc : TI<(outs), (ins brtarget:$target, pred:$cc), "b$cc $target",
207                 [/*(ARMbrcond bb:$target, imm:$cc)*/]>;
208
209//===----------------------------------------------------------------------===//
210//  Load Store Instructions.
211//
212
213let canFoldAsLoad = 1 in
214def tLDR : TI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr),
215               "ldr $dst, $addr",
216               [(set tGPR:$dst, (load t_addrmode_s4:$addr))]>;
217
218def tLDRB : TI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr),
219                "ldrb $dst, $addr",
220                [(set tGPR:$dst, (zextloadi8 t_addrmode_s1:$addr))]>;
221
222def tLDRH : TI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr),
223                "ldrh $dst, $addr",
224                [(set tGPR:$dst, (zextloadi16 t_addrmode_s2:$addr))]>;
225
226def tLDRSB : TI1<(outs tGPR:$dst), (ins t_addrmode_rr:$addr),
227                 "ldrsb $dst, $addr",
228                 [(set tGPR:$dst, (sextloadi8 t_addrmode_rr:$addr))]>;
229
230def tLDRSH : TI2<(outs tGPR:$dst), (ins t_addrmode_rr:$addr),
231                 "ldrsh $dst, $addr",
232                 [(set tGPR:$dst, (sextloadi16 t_addrmode_rr:$addr))]>;
233
234let canFoldAsLoad = 1 in
235def tLDRspi : TIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr),
236                  "ldr $dst, $addr",
237                  [(set tGPR:$dst, (load t_addrmode_sp:$addr))]>;
238
239// Special instruction for restore. It cannot clobber condition register
240// when it's expanded by eliminateCallFramePseudoInstr().
241let canFoldAsLoad = 1, mayLoad = 1 in
242def tRestore : TIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr),
243                    "ldr $dst, $addr", []>;
244
245// Load tconstpool
246let canFoldAsLoad = 1 in
247def tLDRpci : TIs<(outs tGPR:$dst), (ins i32imm:$addr),
248                  "ldr $dst, $addr",
249                  [(set tGPR:$dst, (load (ARMWrapper tconstpool:$addr)))]>;
250
251// Special LDR for loads from non-pc-relative constpools.
252let canFoldAsLoad = 1, mayLoad = 1, isReMaterializable = 1 in
253def tLDRcp  : TIs<(outs tGPR:$dst), (ins i32imm:$addr),
254                  "ldr $dst, $addr", []>;
255
256def tSTR : TI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr),
257               "str $src, $addr",
258               [(store tGPR:$src, t_addrmode_s4:$addr)]>;
259
260def tSTRB : TI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr),
261                 "strb $src, $addr",
262                 [(truncstorei8 tGPR:$src, t_addrmode_s1:$addr)]>;
263
264def tSTRH : TI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr),
265                 "strh $src, $addr",
266                 [(truncstorei16 tGPR:$src, t_addrmode_s2:$addr)]>;
267
268def tSTRspi : TIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr),
269                   "str $src, $addr",
270                   [(store tGPR:$src, t_addrmode_sp:$addr)]>;
271
272let mayStore = 1 in {
273// Special instruction for spill. It cannot clobber condition register
274// when it's expanded by eliminateCallFramePseudoInstr().
275def tSpill : TIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr),
276                  "str $src, $addr", []>;
277}
278
279//===----------------------------------------------------------------------===//
280//  Load / store multiple Instructions.
281//
282
283// TODO: A7-44: LDMIA - load multiple
284
285let mayLoad = 1 in
286def tPOP : TI<(outs reglist:$dst1, variable_ops), (ins),
287               "pop $dst1", []>;
288
289let mayStore = 1 in
290def tPUSH : TI<(outs), (ins reglist:$src1, variable_ops),
291                "push $src1", []>;
292
293//===----------------------------------------------------------------------===//
294//  Arithmetic Instructions.
295//
296
297// Add with carry register
298let isCommutable = 1, Defs = [CPSR], Uses = [CPSR] in
299def tADCS : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
300                "adc $dst, $rhs",
301                [(set tGPR:$dst, (adde tGPR:$lhs, tGPR:$rhs))]>;
302
303// Add immediate
304let Defs = [CPSR] in {
305def tADDi3 : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
306                "add $dst, $lhs, $rhs",
307                [(set tGPR:$dst, (add tGPR:$lhs, imm0_7:$rhs))]>;
308def tADDSi3 : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
309                 "add $dst, $lhs, $rhs",
310                 [(set tGPR:$dst, (addc tGPR:$lhs, imm0_7:$rhs))]>;
311}
312
313let Defs = [CPSR] in {
314def tADDi8 : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
315                 "add $dst, $rhs",
316                 [(set tGPR:$dst, (add tGPR:$lhs, imm8_255:$rhs))]>;
317def tADDSi8 : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
318                  "add $dst, $rhs",
319                  [(set tGPR:$dst, (addc tGPR:$lhs, imm8_255:$rhs))]>;
320}
321
322// Add register
323let isCommutable = 1, Defs = [CPSR] in {
324def tADDrr : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
325                "add $dst, $lhs, $rhs",
326                [(set tGPR:$dst, (add tGPR:$lhs, tGPR:$rhs))]>;
327def tADDSrr : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
328                 "add $dst, $lhs, $rhs",
329                 [(set tGPR:$dst, (addc tGPR:$lhs, tGPR:$rhs))]>;
330}
331
332let neverHasSideEffects = 1 in
333def tADDhirr : T1It<(outs tGPR:$dst), (ins GPR:$lhs, GPR:$rhs),
334                   "add $dst, $rhs @ addhirr", []>;
335
336// And register
337let isCommutable = 1, Defs = [CPSR] in
338def tAND : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
339                "and $dst, $rhs",
340                [(set tGPR:$dst, (and tGPR:$lhs, tGPR:$rhs))]>;
341
342// ASR immediate
343let Defs = [CPSR] in
344def tASRri : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
345                "asr $dst, $lhs, $rhs",
346                [(set tGPR:$dst, (sra tGPR:$lhs, (i32 imm:$rhs)))]>;
347
348// ASR register
349let Defs = [CPSR] in
350def tASRrr : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
351                 "asr $dst, $rhs",
352                 [(set tGPR:$dst, (sra tGPR:$lhs, tGPR:$rhs))]>;
353
354// BIC register
355let Defs = [CPSR] in
356def tBIC : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
357               "bic $dst, $rhs",
358               [(set tGPR:$dst, (and tGPR:$lhs, (not tGPR:$rhs)))]>;
359
360// CMN register
361let Defs = [CPSR] in {
362def tCMN : T1I<(outs), (ins tGPR:$lhs, tGPR:$rhs),
363              "cmn $lhs, $rhs",
364              [(ARMcmp tGPR:$lhs, (ineg tGPR:$rhs))]>;
365def tCMNNZ : T1I<(outs), (ins tGPR:$lhs, tGPR:$rhs),
366                "cmn $lhs, $rhs",
367                [(ARMcmpNZ tGPR:$lhs, (ineg tGPR:$rhs))]>;
368}
369
370// CMP immediate
371let Defs = [CPSR] in {
372def tCMPi8 : T1I<(outs), (ins tGPR:$lhs, i32imm:$rhs),
373               "cmp $lhs, $rhs",
374               [(ARMcmp tGPR:$lhs, imm0_255:$rhs)]>;
375def tCMPNZi8 : T1I<(outs), (ins tGPR:$lhs, i32imm:$rhs),
376                 "cmp $lhs, $rhs",
377                 [(ARMcmpNZ tGPR:$lhs, imm0_255:$rhs)]>;
378
379}
380
381// CMP register
382let Defs = [CPSR] in {
383def tCMPr : T1I<(outs), (ins tGPR:$lhs, tGPR:$rhs),
384               "cmp $lhs, $rhs",
385               [(ARMcmp tGPR:$lhs, tGPR:$rhs)]>;
386def tCMPNZr : T1I<(outs), (ins tGPR:$lhs, tGPR:$rhs),
387                 "cmp $lhs, $rhs",
388                 [(ARMcmpNZ tGPR:$lhs, tGPR:$rhs)]>;
389}
390
391// TODO: A7-37: CMP(3) - cmp hi regs
392
393// XOR register
394let isCommutable = 1, Defs = [CPSR] in
395def tEOR : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
396               "eor $dst, $rhs",
397               [(set tGPR:$dst, (xor tGPR:$lhs, tGPR:$rhs))]>;
398
399// LSL immediate
400let Defs = [CPSR] in
401def tLSLri : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
402                "lsl $dst, $lhs, $rhs",
403                [(set tGPR:$dst, (shl tGPR:$lhs, (i32 imm:$rhs)))]>;
404
405// LSL register
406let Defs = [CPSR] in
407def tLSLrr : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
408                 "lsl $dst, $rhs",
409                 [(set tGPR:$dst, (shl tGPR:$lhs, tGPR:$rhs))]>;
410
411// LSR immediate
412let Defs = [CPSR] in
413def tLSRri : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
414                "lsr $dst, $lhs, $rhs",
415                [(set tGPR:$dst, (srl tGPR:$lhs, (i32 imm:$rhs)))]>;
416
417// LSR register
418let Defs = [CPSR] in
419def tLSRrr : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
420                 "lsr $dst, $rhs",
421                 [(set tGPR:$dst, (srl tGPR:$lhs, tGPR:$rhs))]>;
422
423// move register
424let Defs = [CPSR] in
425def tMOVi8 : T1I<(outs tGPR:$dst), (ins i32imm:$src),
426                 "mov $dst, $src",
427                 [(set tGPR:$dst, imm0_255:$src)]>;
428
429// TODO: A7-73: MOV(2) - mov setting flag.
430
431
432// Note: MOV(2) of two low regs updates the flags, so we emit this as 'cpy',
433// which is MOV(3).  This also supports high registers.
434let neverHasSideEffects = 1 in {
435def tMOVr       : T1I<(outs tGPR:$dst), (ins tGPR:$src),
436                      "cpy $dst, $src", []>;
437def tMOVhir2lor : T1I<(outs tGPR:$dst), (ins GPR:$src),
438                      "cpy $dst, $src\t@ hir2lor", []>;
439def tMOVlor2hir : T1I<(outs GPR:$dst), (ins tGPR:$src),
440                      "cpy $dst, $src\t@ lor2hir", []>;
441def tMOVhir2hir : T1I<(outs GPR:$dst), (ins GPR:$src),
442                      "cpy $dst, $src\t@ hir2hir", []>;
443} // neverHasSideEffects
444
445// multiply register
446let isCommutable = 1, Defs = [CPSR] in
447def tMUL : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
448               "mul $dst, $rhs",
449               [(set tGPR:$dst, (mul tGPR:$lhs, tGPR:$rhs))]>;
450
451// move inverse register
452let Defs = [CPSR] in
453def tMVN : T1I<(outs tGPR:$dst), (ins tGPR:$src),
454              "mvn $dst, $src",
455              [(set tGPR:$dst, (not tGPR:$src))]>;
456
457// negate register
458let Defs = [CPSR] in
459def tNEG : T1I<(outs tGPR:$dst), (ins tGPR:$src),
460              "neg $dst, $src",
461              [(set tGPR:$dst, (ineg tGPR:$src))]>;
462
463// bitwise or register
464let isCommutable = 1, Defs = [CPSR] in
465def tORR : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
466               "orr $dst, $rhs",
467               [(set tGPR:$dst, (or tGPR:$lhs, tGPR:$rhs))]>;
468
469// swaps
470def tREV : T1I<(outs tGPR:$dst), (ins tGPR:$src),
471              "rev $dst, $src",
472              [(set tGPR:$dst, (bswap tGPR:$src))]>,
473              Requires<[IsThumb, HasV6]>;
474
475def tREV16 : T1I<(outs tGPR:$dst), (ins tGPR:$src),
476                "rev16 $dst, $src",
477                [(set tGPR:$dst,
478                    (or (and (srl tGPR:$src, (i32 8)), 0xFF),
479                        (or (and (shl tGPR:$src, (i32 8)), 0xFF00),
480                            (or (and (srl tGPR:$src, (i32 8)), 0xFF0000),
481                                (and (shl tGPR:$src, (i32 8)), 0xFF000000)))))]>,
482                Requires<[IsThumb, HasV6]>;
483
484def tREVSH : T1I<(outs tGPR:$dst), (ins tGPR:$src),
485                "revsh $dst, $src",
486                [(set tGPR:$dst,
487                   (sext_inreg
488                     (or (srl (and tGPR:$src, 0xFFFF), (i32 8)),
489                         (shl tGPR:$src, (i32 8))), i16))]>,
490                Requires<[IsThumb, HasV6]>;
491
492// rotate right register
493let Defs = [CPSR] in
494def tROR : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
495                "ror $dst, $rhs",
496                [(set tGPR:$dst, (rotr tGPR:$lhs, tGPR:$rhs))]>;
497
498// Subtract with carry register
499let Defs = [CPSR], Uses = [CPSR] in
500def tSBCS : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
501                "sbc $dst, $rhs",
502                [(set tGPR:$dst, (sube tGPR:$lhs, tGPR:$rhs))]>;
503
504// Subtract immediate
505let Defs = [CPSR] in {
506def tSUBi3 : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
507                "sub $dst, $lhs, $rhs",
508                [(set tGPR:$dst, (add tGPR:$lhs, imm0_7_neg:$rhs))]>;
509def tSUBSi3 : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
510                 "sub $dst, $lhs, $rhs",
511                 [(set tGPR:$dst, (addc tGPR:$lhs, imm0_7_neg:$rhs))]>;
512}
513
514let Defs = [CPSR] in {
515def tSUBi8 : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
516                  "sub $dst, $rhs",
517                  [(set tGPR:$dst, (add tGPR:$lhs, imm8_255_neg:$rhs))]>;
518def tSUBSi8 : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
519                   "sub $dst, $rhs",
520                   [(set tGPR:$dst, (addc tGPR:$lhs, imm8_255_neg:$rhs))]>;
521}
522
523// subtract register
524let Defs = [CPSR] in {
525def tSUBrr : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
526                "sub $dst, $lhs, $rhs",
527                [(set tGPR:$dst, (sub tGPR:$lhs, tGPR:$rhs))]>;
528def tSUBSrr : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
529                "sub $dst, $lhs, $rhs",
530                [(set tGPR:$dst, (subc tGPR:$lhs, tGPR:$rhs))]>;
531}
532
533// TODO: A7-96: STMIA - store multiple.
534
535def tSUBspi : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
536                  "sub $dst, $rhs * 4", []>;
537
538// sign-extend byte
539def tSXTB  : T1I<(outs tGPR:$dst), (ins tGPR:$src),
540                "sxtb $dst, $src",
541                [(set tGPR:$dst, (sext_inreg tGPR:$src, i8))]>,
542                Requires<[IsThumb, HasV6]>;
543
544// sign-extend short
545def tSXTH  : T1I<(outs tGPR:$dst), (ins tGPR:$src),
546                "sxth $dst, $src",
547                [(set tGPR:$dst, (sext_inreg tGPR:$src, i16))]>,
548                Requires<[IsThumb, HasV6]>;
549
550// test
551let Defs = [CPSR] in
552def tTST  : T1I<(outs), (ins tGPR:$lhs, tGPR:$rhs),
553               "tst $lhs, $rhs",
554               [(ARMcmpNZ (and tGPR:$lhs, tGPR:$rhs), 0)]>;
555
556// zero-extend byte
557def tUXTB  : T1I<(outs tGPR:$dst), (ins tGPR:$src),
558                "uxtb $dst, $src",
559                [(set tGPR:$dst, (and tGPR:$src, 0xFF))]>,
560                Requires<[IsThumb, HasV6]>;
561
562// zero-extend short
563def tUXTH  : T1I<(outs tGPR:$dst), (ins tGPR:$src),
564                "uxth $dst, $src",
565                [(set tGPR:$dst, (and tGPR:$src, 0xFFFF))]>,
566                Requires<[IsThumb, HasV6]>;
567
568
569// Conditional move tMOVCCr - Used to implement the Thumb SELECT_CC DAG operation.
570// Expanded by the scheduler into a branch sequence.
571let usesCustomDAGSchedInserter = 1 in  // Expanded by the scheduler.
572  def tMOVCCr :
573  PseudoInst<(outs tGPR:$dst), (ins tGPR:$false, tGPR:$true, pred:$cc),
574              "@ tMOVCCr $cc",
575              [/*(set tGPR:$dst, (ARMcmov tGPR:$false, tGPR:$true, imm:$cc))*/]>;
576
577// tLEApcrel - Load a pc-relative address into a register without offending the
578// assembler.
579def tLEApcrel : TIx2<(outs tGPR:$dst), (ins i32imm:$label),
580                    !strconcat(!strconcat(".set PCRELV${:uid}, ($label-(",
581                                          "${:private}PCRELL${:uid}+4))\n"),
582                               !strconcat("\tmov $dst, #PCRELV${:uid}\n",
583                                  "${:private}PCRELL${:uid}:\n\tadd $dst, pc")),
584                    []>;
585
586def tLEApcrelJT : TIx2<(outs tGPR:$dst), (ins i32imm:$label, i32imm:$id),
587          !strconcat(!strconcat(".set PCRELV${:uid}, (${label}_${id:no_hash}-(",
588                                         "${:private}PCRELL${:uid}+4))\n"),
589                     !strconcat("\tmov $dst, #PCRELV${:uid}\n",
590                                "${:private}PCRELL${:uid}:\n\tadd $dst, pc")),
591                    []>;
592
593//===----------------------------------------------------------------------===//
594// TLS Instructions
595//
596
597// __aeabi_read_tp preserves the registers r1-r3.
598let isCall = 1,
599  Defs = [R0, LR] in {
600  def tTPsoft  : TIx2<(outs), (ins),
601               "bl __aeabi_read_tp",
602               [(set R0, ARMthread_pointer)]>;
603}
604
605//===----------------------------------------------------------------------===//
606// Non-Instruction Patterns
607//
608
609// ConstantPool, GlobalAddress
610def : ThumbPat<(ARMWrapper  tglobaladdr :$dst), (tLEApcrel tglobaladdr :$dst)>;
611def : ThumbPat<(ARMWrapper  tconstpool  :$dst), (tLEApcrel tconstpool  :$dst)>;
612
613// JumpTable
614def : ThumbPat<(ARMWrapperJT tjumptable:$dst, imm:$id),
615               (tLEApcrelJT tjumptable:$dst, imm:$id)>;
616
617// Direct calls
618def : ThumbPat<(ARMtcall texternalsym:$func), (tBL texternalsym:$func)>;
619def : ThumbV5Pat<(ARMcall texternalsym:$func), (tBLXi texternalsym:$func)>;
620
621// Indirect calls to ARM routines
622def : ThumbV5Pat<(ARMcall tGPR:$dst), (tBLXr tGPR:$dst)>;
623
624// zextload i1 -> zextload i8
625def : ThumbPat<(zextloadi1 t_addrmode_s1:$addr),
626               (tLDRB t_addrmode_s1:$addr)>;
627
628// extload -> zextload
629def : ThumbPat<(extloadi1  t_addrmode_s1:$addr),  (tLDRB t_addrmode_s1:$addr)>;
630def : ThumbPat<(extloadi8  t_addrmode_s1:$addr),  (tLDRB t_addrmode_s1:$addr)>;
631def : ThumbPat<(extloadi16 t_addrmode_s2:$addr),  (tLDRH t_addrmode_s2:$addr)>;
632
633// Large immediate handling.
634
635// Two piece imms.
636def : Thumb1Pat<(i32 thumb_immshifted:$src),
637                (tLSLri (tMOVi8 (thumb_immshifted_val imm:$src)),
638                        (thumb_immshifted_shamt imm:$src))>;
639
640def : Thumb1Pat<(i32 imm0_255_comp:$src),
641                (tMVN (tMOVi8 (imm_comp_XFORM imm:$src)))>;
642