ARMInstrThumb.td revision 194710
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, (i32 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, (i32 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, (i32 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, (i32 8)), 0xFF), 433 (or (and (shl tGPR:$src, (i32 8)), 0xFF00), 434 (or (and (srl tGPR:$src, (i32 8)), 0xFF0000), 435 (and (shl tGPR:$src, (i32 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), (i32 8)), 443 (shl tGPR:$src, (i32 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