ARMInstrThumb.td revision 4a8979320ced9b38019f6f2c074f2d3dbe1b189e
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<[IsThumb1Only]>;
123
124def tADJCALLSTACKDOWN :
125PseudoInst<(outs), (ins i32imm:$amt),
126           "@ tADJCALLSTACKDOWN $amt",
127           [(ARMcallseq_start imm:$amt)]>, Requires<[IsThumb1Only]>;
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 : T1I<(outs), (ins), "bx lr", [(ARMretflag)]>;
159  // Alternative return instruction used by vararg functions.
160  def tBX_RET_vararg : T1I<(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 : T1I<(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  : T1Ix2<(outs), (ins i32imm:$func, variable_ops),
172                   "bl ${func:call}",
173                   [(ARMtcall tglobaladdr:$func)]>;
174  // ARMv5T and above
175  def tBLXi : T1Ix2<(outs), (ins i32imm:$func, variable_ops),
176                    "blx ${func:call}",
177                    [(ARMcall tglobaladdr:$func)]>, Requires<[HasV5T]>;
178  def tBLXr : T1I<(outs), (ins tGPR:$func, variable_ops),
179                  "blx $func",
180                  [(ARMtcall tGPR:$func)]>, Requires<[HasV5T]>;
181  // ARMv4T
182  def tBX : T1Ix2<(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   : T1I<(outs), (ins brtarget:$target), "b $target",
191                   [(br bb:$target)]>;
192
193  // Far jump
194  def tBfar : T1Ix2<(outs), (ins brtarget:$target), 
195                    "bl $target\t@ far jump",[]>;
196
197  def tBR_JTr : T1JTI<(outs),
198                      (ins tGPR:$target, jtblock_operand:$jt, i32imm:$id),
199                      "cpy pc, $target \n\t.align\t2\n$jt",
200                      [(ARMbrjt tGPR:$target, tjumptable:$jt, imm:$id)]>;
201  }
202}
203
204// FIXME: should be able to write a pattern for ARMBrcond, but can't use
205// a two-value operand where a dag node expects two operands. :(
206let isBranch = 1, isTerminator = 1 in
207  def tBcc : T1I<(outs), (ins brtarget:$target, pred:$cc), "b$cc $target",
208                 [/*(ARMbrcond bb:$target, imm:$cc)*/]>;
209
210//===----------------------------------------------------------------------===//
211//  Load Store Instructions.
212//
213
214let canFoldAsLoad = 1 in
215def tLDR : T1I4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr),
216               "ldr $dst, $addr",
217               [(set tGPR:$dst, (load t_addrmode_s4:$addr))]>;
218
219def tLDRB : T1I1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr),
220                "ldrb $dst, $addr",
221                [(set tGPR:$dst, (zextloadi8 t_addrmode_s1:$addr))]>;
222
223def tLDRH : T1I2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr),
224                "ldrh $dst, $addr",
225                [(set tGPR:$dst, (zextloadi16 t_addrmode_s2:$addr))]>;
226
227def tLDRSB : T1I1<(outs tGPR:$dst), (ins t_addrmode_rr:$addr),
228                 "ldrsb $dst, $addr",
229                 [(set tGPR:$dst, (sextloadi8 t_addrmode_rr:$addr))]>;
230
231def tLDRSH : T1I2<(outs tGPR:$dst), (ins t_addrmode_rr:$addr),
232                 "ldrsh $dst, $addr",
233                 [(set tGPR:$dst, (sextloadi16 t_addrmode_rr:$addr))]>;
234
235let canFoldAsLoad = 1 in
236def tLDRspi : T1Is<(outs tGPR:$dst), (ins t_addrmode_sp:$addr),
237                  "ldr $dst, $addr",
238                  [(set tGPR:$dst, (load t_addrmode_sp:$addr))]>;
239
240// Special instruction for restore. It cannot clobber condition register
241// when it's expanded by eliminateCallFramePseudoInstr().
242let canFoldAsLoad = 1, mayLoad = 1 in
243def tRestore : T1Is<(outs tGPR:$dst), (ins t_addrmode_sp:$addr),
244                    "ldr $dst, $addr", []>;
245
246// Load tconstpool
247let canFoldAsLoad = 1 in
248def tLDRpci : T1Is<(outs tGPR:$dst), (ins i32imm:$addr),
249                  "ldr $dst, $addr",
250                  [(set tGPR:$dst, (load (ARMWrapper tconstpool:$addr)))]>;
251
252// Special LDR for loads from non-pc-relative constpools.
253let canFoldAsLoad = 1, mayLoad = 1, isReMaterializable = 1 in
254def tLDRcp  : T1Is<(outs tGPR:$dst), (ins i32imm:$addr),
255                  "ldr $dst, $addr", []>;
256
257def tSTR : T1I4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr),
258               "str $src, $addr",
259               [(store tGPR:$src, t_addrmode_s4:$addr)]>;
260
261def tSTRB : T1I1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr),
262                 "strb $src, $addr",
263                 [(truncstorei8 tGPR:$src, t_addrmode_s1:$addr)]>;
264
265def tSTRH : T1I2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr),
266                 "strh $src, $addr",
267                 [(truncstorei16 tGPR:$src, t_addrmode_s2:$addr)]>;
268
269def tSTRspi : T1Is<(outs), (ins tGPR:$src, t_addrmode_sp:$addr),
270                   "str $src, $addr",
271                   [(store tGPR:$src, t_addrmode_sp:$addr)]>;
272
273let mayStore = 1 in {
274// Special instruction for spill. It cannot clobber condition register
275// when it's expanded by eliminateCallFramePseudoInstr().
276def tSpill : T1Is<(outs), (ins tGPR:$src, t_addrmode_sp:$addr),
277                  "str $src, $addr", []>;
278}
279
280//===----------------------------------------------------------------------===//
281//  Load / store multiple Instructions.
282//
283
284// TODO: A7-44: LDMIA - load multiple
285
286let mayLoad = 1 in
287def tPOP : T1I<(outs reglist:$dst1, variable_ops), (ins),
288               "pop $dst1", []>;
289
290let mayStore = 1 in
291def tPUSH : T1I<(outs), (ins reglist:$src1, variable_ops),
292                "push $src1", []>;
293
294//===----------------------------------------------------------------------===//
295//  Arithmetic Instructions.
296//
297
298// Add with carry register
299let isCommutable = 1, Defs = [CPSR], Uses = [CPSR] in
300def tADCS : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
301                "adc $dst, $rhs",
302                [(set tGPR:$dst, (adde tGPR:$lhs, tGPR:$rhs))]>;
303
304// Add immediate
305let Defs = [CPSR] in {
306def tADDi3 : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
307                "add $dst, $lhs, $rhs",
308                [(set tGPR:$dst, (add tGPR:$lhs, imm0_7:$rhs))]>;
309def tADDSi3 : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
310                 "add $dst, $lhs, $rhs",
311                 [(set tGPR:$dst, (addc tGPR:$lhs, imm0_7:$rhs))]>;
312}
313
314let Defs = [CPSR] in {
315def tADDi8 : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
316                 "add $dst, $rhs",
317                 [(set tGPR:$dst, (add tGPR:$lhs, imm8_255:$rhs))]>;
318def tADDSi8 : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
319                  "add $dst, $rhs",
320                  [(set tGPR:$dst, (addc tGPR:$lhs, imm8_255:$rhs))]>;
321}
322
323// Add register
324let isCommutable = 1, Defs = [CPSR] in {
325def tADDrr : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
326                "add $dst, $lhs, $rhs",
327                [(set tGPR:$dst, (add tGPR:$lhs, tGPR:$rhs))]>;
328def tADDSrr : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
329                 "add $dst, $lhs, $rhs",
330                 [(set tGPR:$dst, (addc tGPR:$lhs, tGPR:$rhs))]>;
331}
332
333let neverHasSideEffects = 1 in
334def tADDhirr : T1It<(outs tGPR:$dst), (ins GPR:$lhs, GPR:$rhs),
335                   "add $dst, $rhs @ addhirr", []>;
336
337// And register
338let isCommutable = 1, Defs = [CPSR] in
339def tAND : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
340                "and $dst, $rhs",
341                [(set tGPR:$dst, (and tGPR:$lhs, tGPR:$rhs))]>;
342
343// ASR immediate
344let Defs = [CPSR] in
345def tASRri : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
346                "asr $dst, $lhs, $rhs",
347                [(set tGPR:$dst, (sra tGPR:$lhs, (i32 imm:$rhs)))]>;
348
349// ASR register
350let Defs = [CPSR] in
351def tASRrr : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
352                 "asr $dst, $rhs",
353                 [(set tGPR:$dst, (sra tGPR:$lhs, tGPR:$rhs))]>;
354
355// BIC register
356let Defs = [CPSR] in
357def tBIC : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
358               "bic $dst, $rhs",
359               [(set tGPR:$dst, (and tGPR:$lhs, (not tGPR:$rhs)))]>;
360
361// CMN register
362let Defs = [CPSR] in {
363def tCMN : T1I<(outs), (ins tGPR:$lhs, tGPR:$rhs),
364              "cmn $lhs, $rhs",
365              [(ARMcmp tGPR:$lhs, (ineg tGPR:$rhs))]>;
366def tCMNZ : T1I<(outs), (ins tGPR:$lhs, tGPR:$rhs),
367               "cmn $lhs, $rhs",
368               [(ARMcmpZ tGPR:$lhs, (ineg tGPR:$rhs))]>;
369}
370
371// CMP immediate
372let Defs = [CPSR] in {
373def tCMPi8 : T1I<(outs), (ins tGPR:$lhs, i32imm:$rhs),
374               "cmp $lhs, $rhs",
375               [(ARMcmp tGPR:$lhs, imm0_255:$rhs)]>;
376def tCMPZi8 : T1I<(outs), (ins tGPR:$lhs, i32imm:$rhs),
377                "cmp $lhs, $rhs",
378                [(ARMcmpZ tGPR:$lhs, imm0_255:$rhs)]>;
379
380}
381
382// CMP register
383let Defs = [CPSR] in {
384def tCMPr : T1I<(outs), (ins tGPR:$lhs, tGPR:$rhs),
385               "cmp $lhs, $rhs",
386               [(ARMcmp tGPR:$lhs, tGPR:$rhs)]>;
387def tCMPZr : T1I<(outs), (ins tGPR:$lhs, tGPR:$rhs),
388                "cmp $lhs, $rhs",
389                [(ARMcmpZ tGPR:$lhs, tGPR:$rhs)]>;
390}
391
392// TODO: A7-37: CMP(3) - cmp hi regs
393
394// XOR register
395let isCommutable = 1, Defs = [CPSR] in
396def tEOR : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
397               "eor $dst, $rhs",
398               [(set tGPR:$dst, (xor tGPR:$lhs, tGPR:$rhs))]>;
399
400// LSL immediate
401let Defs = [CPSR] in
402def tLSLri : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
403                "lsl $dst, $lhs, $rhs",
404                [(set tGPR:$dst, (shl tGPR:$lhs, (i32 imm:$rhs)))]>;
405
406// LSL register
407let Defs = [CPSR] in
408def tLSLrr : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
409                 "lsl $dst, $rhs",
410                 [(set tGPR:$dst, (shl tGPR:$lhs, tGPR:$rhs))]>;
411
412// LSR immediate
413let Defs = [CPSR] in
414def tLSRri : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
415                "lsr $dst, $lhs, $rhs",
416                [(set tGPR:$dst, (srl tGPR:$lhs, (i32 imm:$rhs)))]>;
417
418// LSR register
419let Defs = [CPSR] in
420def tLSRrr : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
421                 "lsr $dst, $rhs",
422                 [(set tGPR:$dst, (srl tGPR:$lhs, tGPR:$rhs))]>;
423
424// move register
425let Defs = [CPSR] in
426def tMOVi8 : T1I<(outs tGPR:$dst), (ins i32imm:$src),
427                 "mov $dst, $src",
428                 [(set tGPR:$dst, imm0_255:$src)]>;
429
430// TODO: A7-73: MOV(2) - mov setting flag.
431
432
433// Note: MOV(2) of two low regs updates the flags, so we emit this as 'cpy',
434// which is MOV(3).  This also supports high registers.
435let neverHasSideEffects = 1 in {
436def tMOVr       : T1I<(outs tGPR:$dst), (ins tGPR:$src),
437                      "cpy $dst, $src", []>;
438def tMOVhir2lor : T1I<(outs tGPR:$dst), (ins GPR:$src),
439                      "cpy $dst, $src\t@ hir2lor", []>;
440def tMOVlor2hir : T1I<(outs GPR:$dst), (ins tGPR:$src),
441                      "cpy $dst, $src\t@ lor2hir", []>;
442def tMOVhir2hir : T1I<(outs GPR:$dst), (ins GPR:$src),
443                      "cpy $dst, $src\t@ hir2hir", []>;
444} // neverHasSideEffects
445
446// multiply register
447let isCommutable = 1, Defs = [CPSR] in
448def tMUL : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
449               "mul $dst, $rhs",
450               [(set tGPR:$dst, (mul tGPR:$lhs, tGPR:$rhs))]>;
451
452// move inverse register
453let Defs = [CPSR] in
454def tMVN : T1I<(outs tGPR:$dst), (ins tGPR:$src),
455              "mvn $dst, $src",
456              [(set tGPR:$dst, (not tGPR:$src))]>;
457
458// negate register
459let Defs = [CPSR] in
460def tNEG : T1I<(outs tGPR:$dst), (ins tGPR:$src),
461              "neg $dst, $src",
462              [(set tGPR:$dst, (ineg tGPR:$src))]>;
463
464// bitwise or register
465let isCommutable = 1, Defs = [CPSR] in
466def tORR : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
467               "orr $dst, $rhs",
468               [(set tGPR:$dst, (or tGPR:$lhs, tGPR:$rhs))]>;
469
470// swaps
471def tREV : T1I<(outs tGPR:$dst), (ins tGPR:$src),
472              "rev $dst, $src",
473              [(set tGPR:$dst, (bswap tGPR:$src))]>,
474              Requires<[IsThumb1Only, HasV6]>;
475
476def tREV16 : T1I<(outs tGPR:$dst), (ins tGPR:$src),
477                "rev16 $dst, $src",
478                [(set tGPR:$dst,
479                    (or (and (srl tGPR:$src, (i32 8)), 0xFF),
480                        (or (and (shl tGPR:$src, (i32 8)), 0xFF00),
481                            (or (and (srl tGPR:$src, (i32 8)), 0xFF0000),
482                                (and (shl tGPR:$src, (i32 8)), 0xFF000000)))))]>,
483                Requires<[IsThumb1Only, HasV6]>;
484
485def tREVSH : T1I<(outs tGPR:$dst), (ins tGPR:$src),
486                "revsh $dst, $src",
487                [(set tGPR:$dst,
488                   (sext_inreg
489                     (or (srl (and tGPR:$src, 0xFFFF), (i32 8)),
490                         (shl tGPR:$src, (i32 8))), i16))]>,
491                Requires<[IsThumb1Only, HasV6]>;
492
493// rotate right register
494let Defs = [CPSR] in
495def tROR : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
496                "ror $dst, $rhs",
497                [(set tGPR:$dst, (rotr tGPR:$lhs, tGPR:$rhs))]>;
498
499// Subtract with carry register
500let Defs = [CPSR], Uses = [CPSR] in
501def tSBCS : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
502                "sbc $dst, $rhs",
503                [(set tGPR:$dst, (sube tGPR:$lhs, tGPR:$rhs))]>;
504
505// Subtract immediate
506let Defs = [CPSR] in {
507def tSUBi3 : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
508                "sub $dst, $lhs, $rhs",
509                [(set tGPR:$dst, (add tGPR:$lhs, imm0_7_neg:$rhs))]>;
510def tSUBSi3 : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
511                 "sub $dst, $lhs, $rhs",
512                 [(set tGPR:$dst, (addc tGPR:$lhs, imm0_7_neg:$rhs))]>;
513}
514
515let Defs = [CPSR] in {
516def tSUBi8 : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
517                  "sub $dst, $rhs",
518                  [(set tGPR:$dst, (add tGPR:$lhs, imm8_255_neg:$rhs))]>;
519def tSUBSi8 : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
520                   "sub $dst, $rhs",
521                   [(set tGPR:$dst, (addc tGPR:$lhs, imm8_255_neg:$rhs))]>;
522}
523
524// subtract register
525let Defs = [CPSR] in {
526def tSUBrr : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
527                "sub $dst, $lhs, $rhs",
528                [(set tGPR:$dst, (sub tGPR:$lhs, tGPR:$rhs))]>;
529def tSUBSrr : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
530                "sub $dst, $lhs, $rhs",
531                [(set tGPR:$dst, (subc tGPR:$lhs, tGPR:$rhs))]>;
532}
533
534// TODO: A7-96: STMIA - store multiple.
535
536def tSUBspi : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
537                  "sub $dst, $rhs * 4", []>;
538
539// sign-extend byte
540def tSXTB  : T1I<(outs tGPR:$dst), (ins tGPR:$src),
541                "sxtb $dst, $src",
542                [(set tGPR:$dst, (sext_inreg tGPR:$src, i8))]>,
543                Requires<[IsThumb1Only, HasV6]>;
544
545// sign-extend short
546def tSXTH  : T1I<(outs tGPR:$dst), (ins tGPR:$src),
547                "sxth $dst, $src",
548                [(set tGPR:$dst, (sext_inreg tGPR:$src, i16))]>,
549                Requires<[IsThumb1Only, HasV6]>;
550
551// test
552let isCommutable = 1, Defs = [CPSR] in
553def tTST  : T1I<(outs), (ins tGPR:$lhs, tGPR:$rhs),
554               "tst $lhs, $rhs",
555               [(ARMcmpZ (and tGPR:$lhs, tGPR:$rhs), 0)]>;
556
557// zero-extend byte
558def tUXTB  : T1I<(outs tGPR:$dst), (ins tGPR:$src),
559                "uxtb $dst, $src",
560                [(set tGPR:$dst, (and tGPR:$src, 0xFF))]>,
561                Requires<[IsThumb1Only, HasV6]>;
562
563// zero-extend short
564def tUXTH  : T1I<(outs tGPR:$dst), (ins tGPR:$src),
565                "uxth $dst, $src",
566                [(set tGPR:$dst, (and tGPR:$src, 0xFFFF))]>,
567                Requires<[IsThumb1Only, HasV6]>;
568
569
570// Conditional move tMOVCCr - Used to implement the Thumb SELECT_CC DAG operation.
571// Expanded by the scheduler into a branch sequence.
572let usesCustomDAGSchedInserter = 1 in  // Expanded by the scheduler.
573  def tMOVCCr :
574  PseudoInst<(outs tGPR:$dst), (ins tGPR:$false, tGPR:$true, pred:$cc),
575              "@ tMOVCCr $cc",
576              [/*(set tGPR:$dst, (ARMcmov tGPR:$false, tGPR:$true, imm:$cc))*/]>;
577
578// tLEApcrel - Load a pc-relative address into a register without offending the
579// assembler.
580def tLEApcrel : T1Ix2<(outs tGPR:$dst), (ins i32imm:$label),
581                    !strconcat(!strconcat(".set PCRELV${:uid}, ($label-(",
582                                          "${:private}PCRELL${:uid}+4))\n"),
583                               !strconcat("\tmov $dst, #PCRELV${:uid}\n",
584                                  "${:private}PCRELL${:uid}:\n\tadd $dst, pc")),
585                    []>;
586
587def tLEApcrelJT : T1Ix2<(outs tGPR:$dst), (ins i32imm:$label, i32imm:$id),
588          !strconcat(!strconcat(".set PCRELV${:uid}, (${label}_${id:no_hash}-(",
589                                         "${:private}PCRELL${:uid}+4))\n"),
590                     !strconcat("\tmov $dst, #PCRELV${:uid}\n",
591                                "${:private}PCRELL${:uid}:\n\tadd $dst, pc")),
592                    []>;
593
594//===----------------------------------------------------------------------===//
595// TLS Instructions
596//
597
598// __aeabi_read_tp preserves the registers r1-r3.
599let isCall = 1,
600  Defs = [R0, LR] in {
601  def tTPsoft  : T1Ix2<(outs), (ins),
602               "bl __aeabi_read_tp",
603               [(set R0, ARMthread_pointer)]>;
604}
605
606//===----------------------------------------------------------------------===//
607// Non-Instruction Patterns
608//
609
610// ConstantPool, GlobalAddress
611def : TPat<(ARMWrapper  tglobaladdr :$dst), (tLEApcrel tglobaladdr :$dst)>;
612def : TPat<(ARMWrapper  tconstpool  :$dst), (tLEApcrel tconstpool  :$dst)>;
613
614// JumpTable
615def : TPat<(ARMWrapperJT tjumptable:$dst, imm:$id),
616           (tLEApcrelJT tjumptable:$dst, imm:$id)>;
617
618// Direct calls
619def : TPat<(ARMtcall texternalsym:$func), (tBL texternalsym:$func)>;
620def : Tv5Pat<(ARMcall texternalsym:$func), (tBLXi texternalsym:$func)>;
621
622// Indirect calls to ARM routines
623def : Tv5Pat<(ARMcall tGPR:$dst), (tBLXr tGPR:$dst)>;
624
625// zextload i1 -> zextload i8
626def : T1Pat<(zextloadi1 t_addrmode_s1:$addr),
627            (tLDRB t_addrmode_s1:$addr)>;
628
629// extload -> zextload
630def : T1Pat<(extloadi1  t_addrmode_s1:$addr),  (tLDRB t_addrmode_s1:$addr)>;
631def : T1Pat<(extloadi8  t_addrmode_s1:$addr),  (tLDRB t_addrmode_s1:$addr)>;
632def : T1Pat<(extloadi16 t_addrmode_s2:$addr),  (tLDRH t_addrmode_s2:$addr)>;
633
634// Large immediate handling.
635
636// Two piece imms.
637def : T1Pat<(i32 thumb_immshifted:$src),
638            (tLSLri (tMOVi8 (thumb_immshifted_val imm:$src)),
639                    (thumb_immshifted_shamt imm:$src))>;
640
641def : T1Pat<(i32 imm0_255_comp:$src),
642            (tMVN (tMOVi8 (imm_comp_XFORM imm:$src)))>;
643