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