ARMInstrThumb.td revision 194612
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 : TIt<(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//===----------------------------------------------------------------------===//
136//  Control Flow Instructions.
137//
138
139let isReturn = 1, isTerminator = 1 in {
140  def tBX_RET : TI<(outs), (ins), "bx lr", [(ARMretflag)]>;
141  // Alternative return instruction used by vararg functions.
142  def tBX_RET_vararg : TI<(outs), (ins tGPR:$target), "bx $target", []>;
143}
144
145// FIXME: remove when we have a way to marking a MI with these properties.
146let isReturn = 1, isTerminator = 1 in
147def tPOP_RET : TI<(outs reglist:$dst1, variable_ops), (ins),
148                   "pop $dst1", []>;
149
150let isCall = 1,
151  Defs = [R0, R1, R2, R3, LR,
152          D0, D1, D2, D3, D4, D5, D6, D7] in {
153  def tBL  : TIx2<(outs), (ins i32imm:$func, variable_ops),
154                   "bl ${func:call}",
155                   [(ARMtcall tglobaladdr:$func)]>;
156  // ARMv5T and above
157  def tBLXi : TIx2<(outs), (ins i32imm:$func, variable_ops),
158                    "blx ${func:call}",
159                    [(ARMcall tglobaladdr:$func)]>, Requires<[HasV5T]>;
160  def tBLXr : TI<(outs), (ins tGPR:$func, variable_ops),
161                  "blx $func",
162                  [(ARMtcall tGPR:$func)]>, Requires<[HasV5T]>;
163  // ARMv4T
164  def tBX : TIx2<(outs), (ins tGPR:$func, variable_ops),
165                  "cpy lr, pc\n\tbx $func",
166                  [(ARMcall_nolink tGPR:$func)]>;
167}
168
169let isBranch = 1, isTerminator = 1 in {
170  let isBarrier = 1 in {
171    let isPredicable = 1 in
172    def tB   : TI<(outs), (ins brtarget:$target), "b $target",
173                  [(br bb:$target)]>;
174
175  // Far jump
176  def tBfar : TIx2<(outs), (ins brtarget:$target), "bl $target\t@ far jump",[]>;
177
178  def tBR_JTr : TJTI<(outs),
179                     (ins tGPR:$target, jtblock_operand:$jt, i32imm:$id),
180                     "cpy pc, $target \n\t.align\t2\n$jt",
181                     [(ARMbrjt tGPR:$target, tjumptable:$jt, imm:$id)]>;
182  }
183}
184
185// FIXME: should be able to write a pattern for ARMBrcond, but can't use
186// a two-value operand where a dag node expects two operands. :(
187let isBranch = 1, isTerminator = 1 in
188  def tBcc : TI<(outs), (ins brtarget:$target, pred:$cc), "b$cc $target",
189                 [/*(ARMbrcond bb:$target, imm:$cc)*/]>;
190
191//===----------------------------------------------------------------------===//
192//  Load Store Instructions.
193//
194
195let canFoldAsLoad = 1 in
196def tLDR : TI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr),
197               "ldr $dst, $addr",
198               [(set tGPR:$dst, (load t_addrmode_s4:$addr))]>;
199
200def tLDRB : TI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr),
201                "ldrb $dst, $addr",
202                [(set tGPR:$dst, (zextloadi8 t_addrmode_s1:$addr))]>;
203
204def tLDRH : TI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr),
205                "ldrh $dst, $addr",
206                [(set tGPR:$dst, (zextloadi16 t_addrmode_s2:$addr))]>;
207
208def tLDRSB : TI1<(outs tGPR:$dst), (ins t_addrmode_rr:$addr),
209                 "ldrsb $dst, $addr",
210                 [(set tGPR:$dst, (sextloadi8 t_addrmode_rr:$addr))]>;
211
212def tLDRSH : TI2<(outs tGPR:$dst), (ins t_addrmode_rr:$addr),
213                 "ldrsh $dst, $addr",
214                 [(set tGPR:$dst, (sextloadi16 t_addrmode_rr:$addr))]>;
215
216let canFoldAsLoad = 1 in
217def tLDRspi : TIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr),
218                  "ldr $dst, $addr",
219                  [(set tGPR:$dst, (load t_addrmode_sp:$addr))]>;
220
221// Special instruction for restore. It cannot clobber condition register
222// when it's expanded by eliminateCallFramePseudoInstr().
223let canFoldAsLoad = 1, mayLoad = 1 in
224def tRestore : TIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr),
225                    "ldr $dst, $addr", []>;
226
227// Load tconstpool
228let canFoldAsLoad = 1 in
229def tLDRpci : TIs<(outs tGPR:$dst), (ins i32imm:$addr),
230                  "ldr $dst, $addr",
231                  [(set tGPR:$dst, (load (ARMWrapper tconstpool:$addr)))]>;
232
233// Special LDR for loads from non-pc-relative constpools.
234let canFoldAsLoad = 1, mayLoad = 1, isReMaterializable = 1 in
235def tLDRcp  : TIs<(outs tGPR:$dst), (ins i32imm:$addr),
236                  "ldr $dst, $addr", []>;
237
238def tSTR : TI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr),
239               "str $src, $addr",
240               [(store tGPR:$src, t_addrmode_s4:$addr)]>;
241
242def tSTRB : TI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr),
243                 "strb $src, $addr",
244                 [(truncstorei8 tGPR:$src, t_addrmode_s1:$addr)]>;
245
246def tSTRH : TI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr),
247                 "strh $src, $addr",
248                 [(truncstorei16 tGPR:$src, t_addrmode_s2:$addr)]>;
249
250def tSTRspi : TIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr),
251                   "str $src, $addr",
252                   [(store tGPR:$src, t_addrmode_sp:$addr)]>;
253
254let mayStore = 1 in {
255// Special instruction for spill. It cannot clobber condition register
256// when it's expanded by eliminateCallFramePseudoInstr().
257def tSpill : TIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr),
258                  "str $src, $addr", []>;
259}
260
261//===----------------------------------------------------------------------===//
262//  Load / store multiple Instructions.
263//
264
265// TODO: A7-44: LDMIA - load multiple
266
267let mayLoad = 1 in
268def tPOP : TI<(outs reglist:$dst1, variable_ops), (ins),
269               "pop $dst1", []>;
270
271let mayStore = 1 in
272def tPUSH : TI<(outs), (ins reglist:$src1, variable_ops),
273                "push $src1", []>;
274
275//===----------------------------------------------------------------------===//
276//  Arithmetic Instructions.
277//
278
279// Add with carry
280let isCommutable = 1 in
281def tADC : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
282               "adc $dst, $rhs",
283               [(set tGPR:$dst, (adde tGPR:$lhs, tGPR:$rhs))]>;
284
285def tADDS : TI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
286               "add $dst, $lhs, $rhs",
287               [(set tGPR:$dst, (addc tGPR:$lhs, tGPR:$rhs))]>;
288
289
290def tADDi3 : TI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
291                "add $dst, $lhs, $rhs",
292                [(set tGPR:$dst, (add tGPR:$lhs, imm0_7:$rhs))]>;
293
294def tADDi8 : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
295                 "add $dst, $rhs",
296                 [(set tGPR:$dst, (add tGPR:$lhs, imm8_255:$rhs))]>;
297
298def tADDrr : TI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
299                "add $dst, $lhs, $rhs",
300                [(set tGPR:$dst, (add tGPR:$lhs, tGPR:$rhs))]>;
301
302let neverHasSideEffects = 1 in
303def tADDhirr : TIt<(outs tGPR:$dst), (ins GPR:$lhs, GPR:$rhs),
304                   "add $dst, $rhs @ addhirr", []>;
305
306def tADDrPCi : TI<(outs tGPR:$dst), (ins i32imm:$rhs),
307                  "add $dst, pc, $rhs * 4", []>;
308
309def tADDrSPi : TI<(outs tGPR:$dst), (ins GPR:$sp, i32imm:$rhs),
310                  "add $dst, $sp, $rhs * 4 @ addrspi", []>;
311
312def tADDspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs),
313                  "add $dst, $rhs * 4", []>;
314
315let isCommutable = 1 in
316def tAND : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
317                "and $dst, $rhs",
318                [(set tGPR:$dst, (and tGPR:$lhs, tGPR:$rhs))]>;
319
320def tASRri : TI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
321                "asr $dst, $lhs, $rhs",
322                [(set tGPR:$dst, (sra tGPR:$lhs, imm:$rhs))]>;
323
324def tASRrr : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
325                 "asr $dst, $rhs",
326                 [(set tGPR:$dst, (sra tGPR:$lhs, tGPR:$rhs))]>;
327
328def tBIC : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
329               "bic $dst, $rhs",
330               [(set tGPR:$dst, (and tGPR:$lhs, (not tGPR:$rhs)))]>;
331
332
333def tCMN : TI<(outs), (ins tGPR:$lhs, tGPR:$rhs),
334              "cmn $lhs, $rhs",
335              [(ARMcmp tGPR:$lhs, (ineg tGPR:$rhs))]>;
336
337def tCMPi8 : TI<(outs), (ins tGPR:$lhs, i32imm:$rhs),
338               "cmp $lhs, $rhs",
339               [(ARMcmp tGPR:$lhs, imm0_255:$rhs)]>;
340
341def tCMPr : TI<(outs), (ins tGPR:$lhs, tGPR:$rhs),
342               "cmp $lhs, $rhs",
343               [(ARMcmp tGPR:$lhs, tGPR:$rhs)]>;
344
345def tTST  : TI<(outs), (ins tGPR:$lhs, tGPR:$rhs),
346               "tst $lhs, $rhs",
347               [(ARMcmpNZ (and tGPR:$lhs, tGPR:$rhs), 0)]>;
348
349def tCMNNZ : TI<(outs), (ins tGPR:$lhs, tGPR:$rhs),
350                "cmn $lhs, $rhs",
351                [(ARMcmpNZ tGPR:$lhs, (ineg tGPR:$rhs))]>;
352
353def tCMPNZi8 : TI<(outs), (ins tGPR:$lhs, i32imm:$rhs),
354                 "cmp $lhs, $rhs",
355                 [(ARMcmpNZ tGPR:$lhs, imm0_255:$rhs)]>;
356
357def tCMPNZr : TI<(outs), (ins tGPR:$lhs, tGPR:$rhs),
358                 "cmp $lhs, $rhs",
359                 [(ARMcmpNZ tGPR:$lhs, tGPR:$rhs)]>;
360
361// TODO: A7-37: CMP(3) - cmp hi regs
362
363let isCommutable = 1 in
364def tEOR : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
365               "eor $dst, $rhs",
366               [(set tGPR:$dst, (xor tGPR:$lhs, tGPR:$rhs))]>;
367
368def tLSLri : TI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
369                "lsl $dst, $lhs, $rhs",
370                [(set tGPR:$dst, (shl tGPR:$lhs, imm:$rhs))]>;
371
372def tLSLrr : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
373                 "lsl $dst, $rhs",
374                 [(set tGPR:$dst, (shl tGPR:$lhs, tGPR:$rhs))]>;
375
376def tLSRri : TI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
377                "lsr $dst, $lhs, $rhs",
378                [(set tGPR:$dst, (srl tGPR:$lhs, imm:$rhs))]>;
379
380def tLSRrr : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
381                 "lsr $dst, $rhs",
382                 [(set tGPR:$dst, (srl tGPR:$lhs, tGPR:$rhs))]>;
383
384// FIXME: This is not rematerializable because mov changes the condition code.
385def tMOVi8 : TI<(outs tGPR:$dst), (ins i32imm:$src),
386                 "mov $dst, $src",
387                 [(set tGPR:$dst, imm0_255:$src)]>;
388
389// TODO: A7-73: MOV(2) - mov setting flag.
390
391
392// Note: MOV(2) of two low regs updates the flags, so we emit this as 'cpy',
393// which is MOV(3).  This also supports high registers.
394let neverHasSideEffects = 1 in {
395def tMOVr       : TI<(outs tGPR:$dst), (ins tGPR:$src),
396                      "cpy $dst, $src", []>;
397def tMOVhir2lor : TI<(outs tGPR:$dst), (ins GPR:$src),
398                      "cpy $dst, $src\t@ hir2lor", []>;
399def tMOVlor2hir : TI<(outs GPR:$dst), (ins tGPR:$src),
400                      "cpy $dst, $src\t@ lor2hir", []>;
401def tMOVhir2hir : TI<(outs GPR:$dst), (ins GPR:$src),
402                      "cpy $dst, $src\t@ hir2hir", []>;
403} // neverHasSideEffects
404
405let isCommutable = 1 in
406def tMUL : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
407               "mul $dst, $rhs",
408               [(set tGPR:$dst, (mul tGPR:$lhs, tGPR:$rhs))]>;
409
410def tMVN : TI<(outs tGPR:$dst), (ins tGPR:$src),
411              "mvn $dst, $src",
412              [(set tGPR:$dst, (not tGPR:$src))]>;
413
414def tNEG : TI<(outs tGPR:$dst), (ins tGPR:$src),
415              "neg $dst, $src",
416              [(set tGPR:$dst, (ineg tGPR:$src))]>;
417
418let isCommutable = 1 in
419def tORR : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
420               "orr $dst, $rhs",
421               [(set tGPR:$dst, (or tGPR:$lhs, tGPR:$rhs))]>;
422
423
424def tREV : TI<(outs tGPR:$dst), (ins tGPR:$src),
425              "rev $dst, $src",
426              [(set tGPR:$dst, (bswap tGPR:$src))]>,
427              Requires<[IsThumb, HasV6]>;
428
429def tREV16 : TI<(outs tGPR:$dst), (ins tGPR:$src),
430                "rev16 $dst, $src",
431                [(set tGPR:$dst,
432                    (or (and (srl tGPR:$src, 8), 0xFF),
433                        (or (and (shl tGPR:$src, 8), 0xFF00),
434                            (or (and (srl tGPR:$src, 8), 0xFF0000),
435                                (and (shl tGPR:$src, 8), 0xFF000000)))))]>,
436                Requires<[IsThumb, HasV6]>;
437
438def tREVSH : TI<(outs tGPR:$dst), (ins tGPR:$src),
439                "revsh $dst, $src",
440                [(set tGPR:$dst,
441                   (sext_inreg
442                     (or (srl (and tGPR:$src, 0xFFFF), 8),
443                         (shl tGPR:$src, 8)), i16))]>,
444                Requires<[IsThumb, HasV6]>;
445
446def tROR : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
447                "ror $dst, $rhs",
448                [(set tGPR:$dst, (rotr tGPR:$lhs, tGPR:$rhs))]>;
449
450
451// Subtract with carry
452def tSBC : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
453                "sbc $dst, $rhs",
454                [(set tGPR:$dst, (sube tGPR:$lhs, tGPR:$rhs))]>;
455
456def tSUBS : TI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
457                "sub $dst, $lhs, $rhs",
458               [(set tGPR:$dst, (subc tGPR:$lhs, tGPR:$rhs))]>;
459
460
461// TODO: A7-96: STMIA - store multiple.
462
463def tSUBi3 : TI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
464                "sub $dst, $lhs, $rhs",
465                [(set tGPR:$dst, (add tGPR:$lhs, imm0_7_neg:$rhs))]>;
466
467def tSUBi8 : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
468                  "sub $dst, $rhs",
469                  [(set tGPR:$dst, (add tGPR:$lhs, imm8_255_neg:$rhs))]>;
470
471def tSUBrr : TI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
472                "sub $dst, $lhs, $rhs",
473                [(set tGPR:$dst, (sub tGPR:$lhs, tGPR:$rhs))]>;
474
475def tSUBspi : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
476                  "sub $dst, $rhs * 4", []>;
477
478def tSXTB  : TI<(outs tGPR:$dst), (ins tGPR:$src),
479                "sxtb $dst, $src",
480                [(set tGPR:$dst, (sext_inreg tGPR:$src, i8))]>,
481                Requires<[IsThumb, HasV6]>;
482def tSXTH  : TI<(outs tGPR:$dst), (ins tGPR:$src),
483                "sxth $dst, $src",
484                [(set tGPR:$dst, (sext_inreg tGPR:$src, i16))]>,
485                Requires<[IsThumb, HasV6]>;
486
487
488def tUXTB  : TI<(outs tGPR:$dst), (ins tGPR:$src),
489                "uxtb $dst, $src",
490                [(set tGPR:$dst, (and tGPR:$src, 0xFF))]>,
491                Requires<[IsThumb, HasV6]>;
492def tUXTH  : TI<(outs tGPR:$dst), (ins tGPR:$src),
493                "uxth $dst, $src",
494                [(set tGPR:$dst, (and tGPR:$src, 0xFFFF))]>,
495                Requires<[IsThumb, HasV6]>;
496
497
498// Conditional move tMOVCCr - Used to implement the Thumb SELECT_CC DAG operation.
499// Expanded by the scheduler into a branch sequence.
500let usesCustomDAGSchedInserter = 1 in  // Expanded by the scheduler.
501  def tMOVCCr :
502  PseudoInst<(outs tGPR:$dst), (ins tGPR:$false, tGPR:$true, pred:$cc),
503              "@ tMOVCCr $cc",
504              [/*(set tGPR:$dst, (ARMcmov tGPR:$false, tGPR:$true, imm:$cc))*/]>;
505
506// tLEApcrel - Load a pc-relative address into a register without offending the
507// assembler.
508def tLEApcrel : TIx2<(outs tGPR:$dst), (ins i32imm:$label),
509                    !strconcat(!strconcat(".set PCRELV${:uid}, ($label-(",
510                                          "${:private}PCRELL${:uid}+4))\n"),
511                               !strconcat("\tmov $dst, #PCRELV${:uid}\n",
512                                  "${:private}PCRELL${:uid}:\n\tadd $dst, pc")),
513                    []>;
514
515def tLEApcrelJT : TIx2<(outs tGPR:$dst), (ins i32imm:$label, i32imm:$id),
516          !strconcat(!strconcat(".set PCRELV${:uid}, (${label}_${id:no_hash}-(",
517                                         "${:private}PCRELL${:uid}+4))\n"),
518                     !strconcat("\tmov $dst, #PCRELV${:uid}\n",
519                                "${:private}PCRELL${:uid}:\n\tadd $dst, pc")),
520                    []>;
521
522//===----------------------------------------------------------------------===//
523// TLS Instructions
524//
525
526// __aeabi_read_tp preserves the registers r1-r3.
527let isCall = 1,
528  Defs = [R0, LR] in {
529  def tTPsoft  : TIx2<(outs), (ins),
530               "bl __aeabi_read_tp",
531               [(set R0, ARMthread_pointer)]>;
532}
533
534//===----------------------------------------------------------------------===//
535// Non-Instruction Patterns
536//
537
538// ConstantPool, GlobalAddress
539def : ThumbPat<(ARMWrapper  tglobaladdr :$dst), (tLEApcrel tglobaladdr :$dst)>;
540def : ThumbPat<(ARMWrapper  tconstpool  :$dst), (tLEApcrel tconstpool  :$dst)>;
541
542// JumpTable
543def : ThumbPat<(ARMWrapperJT tjumptable:$dst, imm:$id),
544               (tLEApcrelJT tjumptable:$dst, imm:$id)>;
545
546// Direct calls
547def : ThumbPat<(ARMtcall texternalsym:$func), (tBL texternalsym:$func)>;
548def : ThumbV5Pat<(ARMcall texternalsym:$func), (tBLXi texternalsym:$func)>;
549
550// Indirect calls to ARM routines
551def : ThumbV5Pat<(ARMcall tGPR:$dst), (tBLXr tGPR:$dst)>;
552
553// zextload i1 -> zextload i8
554def : ThumbPat<(zextloadi1 t_addrmode_s1:$addr),
555               (tLDRB t_addrmode_s1:$addr)>;
556
557// extload -> zextload
558def : ThumbPat<(extloadi1  t_addrmode_s1:$addr),  (tLDRB t_addrmode_s1:$addr)>;
559def : ThumbPat<(extloadi8  t_addrmode_s1:$addr),  (tLDRB t_addrmode_s1:$addr)>;
560def : ThumbPat<(extloadi16 t_addrmode_s2:$addr),  (tLDRH t_addrmode_s2:$addr)>;
561
562// Large immediate handling.
563
564// Two piece imms.
565def : ThumbPat<(i32 thumb_immshifted:$src),
566               (tLSLri (tMOVi8 (thumb_immshifted_val imm:$src)),
567                       (thumb_immshifted_shamt imm:$src))>;
568
569def : ThumbPat<(i32 imm0_255_comp:$src),
570               (tMVN (tMOVi8 (imm_comp_XFORM imm:$src)))>;
571