ARMInstrThumb.td revision 194178
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
280def tADC : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
281               "adc $dst, $rhs",
282               [(set tGPR:$dst, (adde tGPR:$lhs, tGPR:$rhs))]>;
283
284def tADDS : TI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
285               "add $dst, $lhs, $rhs",
286               [(set tGPR:$dst, (addc tGPR:$lhs, tGPR:$rhs))]>;
287
288
289def tADDi3 : TI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
290                "add $dst, $lhs, $rhs",
291                [(set tGPR:$dst, (add tGPR:$lhs, imm0_7:$rhs))]>;
292
293def tADDi8 : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
294                 "add $dst, $rhs",
295                 [(set tGPR:$dst, (add tGPR:$lhs, imm8_255:$rhs))]>;
296
297def tADDrr : TI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
298                "add $dst, $lhs, $rhs",
299                [(set tGPR:$dst, (add tGPR:$lhs, tGPR:$rhs))]>;
300
301let neverHasSideEffects = 1 in
302def tADDhirr : TIt<(outs tGPR:$dst), (ins GPR:$lhs, GPR:$rhs),
303                   "add $dst, $rhs @ addhirr", []>;
304
305def tADDrPCi : TI<(outs tGPR:$dst), (ins i32imm:$rhs),
306                  "add $dst, pc, $rhs * 4", []>;
307
308def tADDrSPi : TI<(outs tGPR:$dst), (ins GPR:$sp, i32imm:$rhs),
309                  "add $dst, $sp, $rhs * 4 @ addrspi", []>;
310
311def tADDspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs),
312                  "add $dst, $rhs * 4", []>;
313
314def tAND : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
315                "and $dst, $rhs",
316                [(set tGPR:$dst, (and tGPR:$lhs, tGPR:$rhs))]>;
317
318def tASRri : TI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
319                "asr $dst, $lhs, $rhs",
320                [(set tGPR:$dst, (sra tGPR:$lhs, imm:$rhs))]>;
321
322def tASRrr : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
323                 "asr $dst, $rhs",
324                 [(set tGPR:$dst, (sra tGPR:$lhs, tGPR:$rhs))]>;
325
326def tBIC : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
327               "bic $dst, $rhs",
328               [(set tGPR:$dst, (and tGPR:$lhs, (not tGPR:$rhs)))]>;
329
330
331def tCMN : TI<(outs), (ins tGPR:$lhs, tGPR:$rhs),
332              "cmn $lhs, $rhs",
333              [(ARMcmp tGPR:$lhs, (ineg tGPR:$rhs))]>;
334
335def tCMPi8 : TI<(outs), (ins tGPR:$lhs, i32imm:$rhs),
336               "cmp $lhs, $rhs",
337               [(ARMcmp tGPR:$lhs, imm0_255:$rhs)]>;
338
339def tCMPr : TI<(outs), (ins tGPR:$lhs, tGPR:$rhs),
340               "cmp $lhs, $rhs",
341               [(ARMcmp tGPR:$lhs, tGPR:$rhs)]>;
342
343def tTST  : TI<(outs), (ins tGPR:$lhs, tGPR:$rhs),
344               "tst $lhs, $rhs",
345               [(ARMcmpNZ (and tGPR:$lhs, tGPR:$rhs), 0)]>;
346
347def tCMNNZ : TI<(outs), (ins tGPR:$lhs, tGPR:$rhs),
348                "cmn $lhs, $rhs",
349                [(ARMcmpNZ tGPR:$lhs, (ineg tGPR:$rhs))]>;
350
351def tCMPNZi8 : TI<(outs), (ins tGPR:$lhs, i32imm:$rhs),
352                 "cmp $lhs, $rhs",
353                 [(ARMcmpNZ tGPR:$lhs, imm0_255:$rhs)]>;
354
355def tCMPNZr : TI<(outs), (ins tGPR:$lhs, tGPR:$rhs),
356                 "cmp $lhs, $rhs",
357                 [(ARMcmpNZ tGPR:$lhs, tGPR:$rhs)]>;
358
359// TODO: A7-37: CMP(3) - cmp hi regs
360
361def tEOR : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
362               "eor $dst, $rhs",
363               [(set tGPR:$dst, (xor tGPR:$lhs, tGPR:$rhs))]>;
364
365def tLSLri : TI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
366                "lsl $dst, $lhs, $rhs",
367                [(set tGPR:$dst, (shl tGPR:$lhs, imm:$rhs))]>;
368
369def tLSLrr : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
370                 "lsl $dst, $rhs",
371                 [(set tGPR:$dst, (shl tGPR:$lhs, tGPR:$rhs))]>;
372
373def tLSRri : TI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
374                "lsr $dst, $lhs, $rhs",
375                [(set tGPR:$dst, (srl tGPR:$lhs, imm:$rhs))]>;
376
377def tLSRrr : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
378                 "lsr $dst, $rhs",
379                 [(set tGPR:$dst, (srl tGPR:$lhs, tGPR:$rhs))]>;
380
381// FIXME: This is not rematerializable because mov changes the condition code.
382def tMOVi8 : TI<(outs tGPR:$dst), (ins i32imm:$src),
383                 "mov $dst, $src",
384                 [(set tGPR:$dst, imm0_255:$src)]>;
385
386// TODO: A7-73: MOV(2) - mov setting flag.
387
388
389// Note: MOV(2) of two low regs updates the flags, so we emit this as 'cpy',
390// which is MOV(3).  This also supports high registers.
391let neverHasSideEffects = 1 in {
392def tMOVr       : TI<(outs tGPR:$dst), (ins tGPR:$src),
393                      "cpy $dst, $src", []>;
394def tMOVhir2lor : TI<(outs tGPR:$dst), (ins GPR:$src),
395                      "cpy $dst, $src\t@ hir2lor", []>;
396def tMOVlor2hir : TI<(outs GPR:$dst), (ins tGPR:$src),
397                      "cpy $dst, $src\t@ lor2hir", []>;
398def tMOVhir2hir : TI<(outs GPR:$dst), (ins GPR:$src),
399                      "cpy $dst, $src\t@ hir2hir", []>;
400} // neverHasSideEffects
401
402def tMUL : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
403               "mul $dst, $rhs",
404               [(set tGPR:$dst, (mul tGPR:$lhs, tGPR:$rhs))]>;
405
406def tMVN : TI<(outs tGPR:$dst), (ins tGPR:$src),
407              "mvn $dst, $src",
408              [(set tGPR:$dst, (not tGPR:$src))]>;
409
410def tNEG : TI<(outs tGPR:$dst), (ins tGPR:$src),
411              "neg $dst, $src",
412              [(set tGPR:$dst, (ineg tGPR:$src))]>;
413
414def tORR : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
415               "orr $dst, $rhs",
416               [(set tGPR:$dst, (or tGPR:$lhs, tGPR:$rhs))]>;
417
418
419def tREV : TI<(outs tGPR:$dst), (ins tGPR:$src),
420              "rev $dst, $src",
421              [(set tGPR:$dst, (bswap tGPR:$src))]>,
422              Requires<[IsThumb, HasV6]>;
423
424def tREV16 : TI<(outs tGPR:$dst), (ins tGPR:$src),
425                "rev16 $dst, $src",
426                [(set tGPR:$dst,
427                    (or (and (srl tGPR:$src, 8), 0xFF),
428                        (or (and (shl tGPR:$src, 8), 0xFF00),
429                            (or (and (srl tGPR:$src, 8), 0xFF0000),
430                                (and (shl tGPR:$src, 8), 0xFF000000)))))]>,
431                Requires<[IsThumb, HasV6]>;
432
433def tREVSH : TI<(outs tGPR:$dst), (ins tGPR:$src),
434                "revsh $dst, $src",
435                [(set tGPR:$dst,
436                   (sext_inreg
437                     (or (srl (and tGPR:$src, 0xFFFF), 8),
438                         (shl tGPR:$src, 8)), i16))]>,
439                Requires<[IsThumb, HasV6]>;
440
441def tROR : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
442                "ror $dst, $rhs",
443                [(set tGPR:$dst, (rotr tGPR:$lhs, tGPR:$rhs))]>;
444
445
446// Subtract with carry
447def tSBC : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
448                "sbc $dst, $rhs",
449                [(set tGPR:$dst, (sube tGPR:$lhs, tGPR:$rhs))]>;
450
451def tSUBS : TI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
452                "sub $dst, $lhs, $rhs",
453               [(set tGPR:$dst, (subc tGPR:$lhs, tGPR:$rhs))]>;
454
455
456// TODO: A7-96: STMIA - store multiple.
457
458def tSUBi3 : TI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
459                "sub $dst, $lhs, $rhs",
460                [(set tGPR:$dst, (add tGPR:$lhs, imm0_7_neg:$rhs))]>;
461
462def tSUBi8 : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
463                  "sub $dst, $rhs",
464                  [(set tGPR:$dst, (add tGPR:$lhs, imm8_255_neg:$rhs))]>;
465
466def tSUBrr : TI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
467                "sub $dst, $lhs, $rhs",
468                [(set tGPR:$dst, (sub tGPR:$lhs, tGPR:$rhs))]>;
469
470def tSUBspi : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
471                  "sub $dst, $rhs * 4", []>;
472
473def tSXTB  : TI<(outs tGPR:$dst), (ins tGPR:$src),
474                "sxtb $dst, $src",
475                [(set tGPR:$dst, (sext_inreg tGPR:$src, i8))]>,
476                Requires<[IsThumb, HasV6]>;
477def tSXTH  : TI<(outs tGPR:$dst), (ins tGPR:$src),
478                "sxth $dst, $src",
479                [(set tGPR:$dst, (sext_inreg tGPR:$src, i16))]>,
480                Requires<[IsThumb, HasV6]>;
481
482
483def tUXTB  : TI<(outs tGPR:$dst), (ins tGPR:$src),
484                "uxtb $dst, $src",
485                [(set tGPR:$dst, (and tGPR:$src, 0xFF))]>,
486                Requires<[IsThumb, HasV6]>;
487def tUXTH  : TI<(outs tGPR:$dst), (ins tGPR:$src),
488                "uxth $dst, $src",
489                [(set tGPR:$dst, (and tGPR:$src, 0xFFFF))]>,
490                Requires<[IsThumb, HasV6]>;
491
492
493// Conditional move tMOVCCr - Used to implement the Thumb SELECT_CC DAG operation.
494// Expanded by the scheduler into a branch sequence.
495let usesCustomDAGSchedInserter = 1 in  // Expanded by the scheduler.
496  def tMOVCCr :
497  PseudoInst<(outs tGPR:$dst), (ins tGPR:$false, tGPR:$true, pred:$cc),
498              "@ tMOVCCr $cc",
499              [/*(set tGPR:$dst, (ARMcmov tGPR:$false, tGPR:$true, imm:$cc))*/]>;
500
501// tLEApcrel - Load a pc-relative address into a register without offending the
502// assembler.
503def tLEApcrel : TIx2<(outs tGPR:$dst), (ins i32imm:$label),
504                    !strconcat(!strconcat(".set PCRELV${:uid}, ($label-(",
505                                          "${:private}PCRELL${:uid}+4))\n"),
506                               !strconcat("\tmov $dst, #PCRELV${:uid}\n",
507                                  "${:private}PCRELL${:uid}:\n\tadd $dst, pc")),
508                    []>;
509
510def tLEApcrelJT : TIx2<(outs tGPR:$dst), (ins i32imm:$label, i32imm:$id),
511          !strconcat(!strconcat(".set PCRELV${:uid}, (${label}_${id:no_hash}-(",
512                                         "${:private}PCRELL${:uid}+4))\n"),
513                     !strconcat("\tmov $dst, #PCRELV${:uid}\n",
514                                "${:private}PCRELL${:uid}:\n\tadd $dst, pc")),
515                    []>;
516
517//===----------------------------------------------------------------------===//
518// TLS Instructions
519//
520
521// __aeabi_read_tp preserves the registers r1-r3.
522let isCall = 1,
523  Defs = [R0, LR] in {
524  def tTPsoft  : TIx2<(outs), (ins),
525               "bl __aeabi_read_tp",
526               [(set R0, ARMthread_pointer)]>;
527}
528
529//===----------------------------------------------------------------------===//
530// Non-Instruction Patterns
531//
532
533// ConstantPool, GlobalAddress
534def : ThumbPat<(ARMWrapper  tglobaladdr :$dst), (tLEApcrel tglobaladdr :$dst)>;
535def : ThumbPat<(ARMWrapper  tconstpool  :$dst), (tLEApcrel tconstpool  :$dst)>;
536
537// JumpTable
538def : ThumbPat<(ARMWrapperJT tjumptable:$dst, imm:$id),
539               (tLEApcrelJT tjumptable:$dst, imm:$id)>;
540
541// Direct calls
542def : ThumbPat<(ARMtcall texternalsym:$func), (tBL texternalsym:$func)>;
543def : ThumbV5Pat<(ARMcall texternalsym:$func), (tBLXi texternalsym:$func)>;
544
545// Indirect calls to ARM routines
546def : ThumbV5Pat<(ARMcall tGPR:$dst), (tBLXr tGPR:$dst)>;
547
548// zextload i1 -> zextload i8
549def : ThumbPat<(zextloadi1 t_addrmode_s1:$addr),
550               (tLDRB t_addrmode_s1:$addr)>;
551
552// extload -> zextload
553def : ThumbPat<(extloadi1  t_addrmode_s1:$addr),  (tLDRB t_addrmode_s1:$addr)>;
554def : ThumbPat<(extloadi8  t_addrmode_s1:$addr),  (tLDRB t_addrmode_s1:$addr)>;
555def : ThumbPat<(extloadi16 t_addrmode_s2:$addr),  (tLDRH t_addrmode_s2:$addr)>;
556
557// Large immediate handling.
558
559// Two piece imms.
560def : ThumbPat<(i32 thumb_immshifted:$src),
561               (tLSLri (tMOVi8 (thumb_immshifted_val imm:$src)),
562                       (thumb_immshifted_shamt imm:$src))>;
563
564def : ThumbPat<(i32 imm0_255_comp:$src),
565               (tMVN (tMOVi8 (imm_comp_XFORM imm:$src)))>;
566