Deleted Added
full compact
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)]>;
190 def tB : T1I<(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",[]>;
194 def tBfar : T1Ix2<(outs), (ins brtarget:$target),
195 "bl $target\t@ far jump",[]>;
196
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)]>;
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
206 def tBcc : TI<(outs), (ins brtarget:$target, pred:$cc), "b$cc $target",
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
214def tLDR : TI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr),
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
218def tLDRB : TI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr),
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
222def tLDRH : TI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr),
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
226def tLDRSB : TI1<(outs tGPR:$dst), (ins t_addrmode_rr:$addr),
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
230def tLDRSH : TI2<(outs tGPR:$dst), (ins t_addrmode_rr:$addr),
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
235def tLDRspi : TIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr),
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
242def tRestore : TIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr),
243def tRestore : T1Is<(outs tGPR:$dst), (ins t_addrmode_sp:$addr),
244 "ldr $dst, $addr", []>;
245
246// Load tconstpool
247let canFoldAsLoad = 1 in
247def tLDRpci : TIs<(outs tGPR:$dst), (ins i32imm:$addr),
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
253def tLDRcp : TIs<(outs tGPR:$dst), (ins i32imm:$addr),
254def tLDRcp : T1Is<(outs tGPR:$dst), (ins i32imm:$addr),
255 "ldr $dst, $addr", []>;
256
256def tSTR : TI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr),
257def tSTR : T1I4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr),
258 "str $src, $addr",
259 [(store tGPR:$src, t_addrmode_s4:$addr)]>;
260
260def tSTRB : TI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr),
261def tSTRB : T1I1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr),
262 "strb $src, $addr",
263 [(truncstorei8 tGPR:$src, t_addrmode_s1:$addr)]>;
264
264def tSTRH : TI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr),
265def tSTRH : T1I2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr),
266 "strh $src, $addr",
267 [(truncstorei16 tGPR:$src, t_addrmode_s2:$addr)]>;
268
268def tSTRspi : TIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr),
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().
275def tSpill : TIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr),
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 : TI<(outs reglist:$dst1, variable_ops), (ins),
288 "pop $dst1", []>;
289
290let mayStore = 1 in
291def tPUSH : TI<(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))]>;
365def tCMNNZ : T1I<(outs), (ins tGPR:$lhs, tGPR:$rhs),
366 "cmn $lhs, $rhs",
367 [(ARMcmpNZ 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)]>;
375def tCMPNZi8 : T1I<(outs), (ins tGPR:$lhs, i32imm:$rhs),
376 "cmp $lhs, $rhs",
377 [(ARMcmpNZ 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)]>;
386def tCMPNZr : T1I<(outs), (ins tGPR:$lhs, tGPR:$rhs),
387 "cmp $lhs, $rhs",
388 [(ARMcmpNZ 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<[IsThumb, 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<[IsThumb, 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<[IsThumb, 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<[IsThumb, 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<[IsThumb, HasV6]>;
550
551// test
552let isCommutable = 1, Defs = [CPSR] in
553def tTST : T1I<(outs), (ins tGPR:$lhs, tGPR:$rhs),
554 "tst $lhs, $rhs",
554 [(ARMcmpNZ (and tGPR:$lhs, tGPR:$rhs), 0)]>;
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<[IsThumb, 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<[IsThumb, 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 : TIx2<(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 : TIx2<(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 : TIx2<(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
625def : TPat<(zextloadi1 t_addrmode_s1:$addr),
626 (tLDRB t_addrmode_s1:$addr)>;
626def : T1Pat<(zextloadi1 t_addrmode_s1:$addr),
627 (tLDRB t_addrmode_s1:$addr)>;
628
629// extload -> zextload
629def : TPat<(extloadi1 t_addrmode_s1:$addr), (tLDRB t_addrmode_s1:$addr)>;
630def : TPat<(extloadi8 t_addrmode_s1:$addr), (tLDRB t_addrmode_s1:$addr)>;
631def : TPat<(extloadi16 t_addrmode_s2:$addr), (tLDRH t_addrmode_s2:$addr)>;
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)))>;