ARMInstrThumb.td revision 27c016ba84f5607b3610f0ae63d36742ba0083f8
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<[IsThumb1Only]>; 123 124def tADJCALLSTACKDOWN : 125PseudoInst<(outs), (ins i32imm:$amt), 126 "@ tADJCALLSTACKDOWN $amt", 127 [(ARMcallseq_start imm:$amt)]>, Requires<[IsThumb1Only]>; 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 : T1I<(outs reglist:$dst1, variable_ops), (ins), 166 "pop $dst1", []>; 167 168let isCall = 1, 169 Defs = [R0, R1, R2, R3, R12, LR, 170 D0, D1, D2, D3, D4, D5, D6, D7, 171 D16, D17, D18, D19, D20, D21, D22, D23, 172 D24, D25, D26, D27, D28, D29, D31, D31, CPSR] in { 173 def tBL : T1Ix2<(outs), (ins i32imm:$func, variable_ops), 174 "bl ${func:call}", 175 [(ARMtcall tglobaladdr:$func)]>; 176 // ARMv5T and above 177 def tBLXi : T1Ix2<(outs), (ins i32imm:$func, variable_ops), 178 "blx ${func:call}", 179 [(ARMcall tglobaladdr:$func)]>, Requires<[HasV5T]>; 180 def tBLXr : T1I<(outs), (ins tGPR:$func, variable_ops), 181 "blx $func", 182 [(ARMtcall tGPR:$func)]>, Requires<[HasV5T]>; 183 // ARMv4T 184 def tBX : T1Ix2<(outs), (ins tGPR:$func, variable_ops), 185 "mov lr, pc\n\tbx $func", 186 [(ARMcall_nolink tGPR:$func)]>; 187} 188 189let isBranch = 1, isTerminator = 1 in { 190 let isBarrier = 1 in { 191 let isPredicable = 1 in 192 def tB : T1I<(outs), (ins brtarget:$target), "b $target", 193 [(br bb:$target)]>; 194 195 // Far jump 196 def tBfar : T1Ix2<(outs), (ins brtarget:$target), 197 "bl $target\t@ far jump",[]>; 198 199 def tBR_JTr : T1JTI<(outs), 200 (ins tGPR:$target, jtblock_operand:$jt, i32imm:$id), 201 "mov pc, $target \n\t.align\t2\n$jt", 202 [(ARMbrjt tGPR:$target, tjumptable:$jt, imm:$id)]>; 203 } 204} 205 206// FIXME: should be able to write a pattern for ARMBrcond, but can't use 207// a two-value operand where a dag node expects two operands. :( 208let isBranch = 1, isTerminator = 1 in 209 def tBcc : T1I<(outs), (ins brtarget:$target, pred:$cc), "b$cc $target", 210 [/*(ARMbrcond bb:$target, imm:$cc)*/]>; 211 212//===----------------------------------------------------------------------===// 213// Load Store Instructions. 214// 215 216let canFoldAsLoad = 1 in 217def tLDR : T1pI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr), 218 "ldr", " $dst, $addr", 219 [(set tGPR:$dst, (load t_addrmode_s4:$addr))]>; 220 221def tLDRB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr), 222 "ldrb", " $dst, $addr", 223 [(set tGPR:$dst, (zextloadi8 t_addrmode_s1:$addr))]>; 224 225def tLDRH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr), 226 "ldrh", " $dst, $addr", 227 [(set tGPR:$dst, (zextloadi16 t_addrmode_s2:$addr))]>; 228 229let AddedComplexity = 10 in 230def tLDRSB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), 231 "ldrsb", " $dst, $addr", 232 [(set tGPR:$dst, (sextloadi8 t_addrmode_rr:$addr))]>; 233 234let AddedComplexity = 10 in 235def tLDRSH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), 236 "ldrsh", " $dst, $addr", 237 [(set tGPR:$dst, (sextloadi16 t_addrmode_rr:$addr))]>; 238 239let canFoldAsLoad = 1 in 240def tLDRspi : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), 241 "ldr", " $dst, $addr", 242 [(set tGPR:$dst, (load t_addrmode_sp:$addr))]>; 243 244// Special instruction for restore. It cannot clobber condition register 245// when it's expanded by eliminateCallFramePseudoInstr(). 246let canFoldAsLoad = 1, mayLoad = 1 in 247def tRestore : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), 248 "ldr", " $dst, $addr", []>; 249 250// Load tconstpool 251let canFoldAsLoad = 1 in 252def tLDRpci : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr), 253 "ldr", " $dst, $addr", 254 [(set tGPR:$dst, (load (ARMWrapper tconstpool:$addr)))]>; 255 256// Special LDR for loads from non-pc-relative constpools. 257let canFoldAsLoad = 1, mayLoad = 1, isReMaterializable = 1 in 258def tLDRcp : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr), 259 "ldr", " $dst, $addr", []>; 260 261def tSTR : T1pI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr), 262 "str", " $src, $addr", 263 [(store tGPR:$src, t_addrmode_s4:$addr)]>; 264 265def tSTRB : T1pI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr), 266 "strb", " $src, $addr", 267 [(truncstorei8 tGPR:$src, t_addrmode_s1:$addr)]>; 268 269def tSTRH : T1pI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr), 270 "strh", " $src, $addr", 271 [(truncstorei16 tGPR:$src, t_addrmode_s2:$addr)]>; 272 273def tSTRspi : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), 274 "str", " $src, $addr", 275 [(store tGPR:$src, t_addrmode_sp:$addr)]>; 276 277let mayStore = 1 in { 278// Special instruction for spill. It cannot clobber condition register 279// when it's expanded by eliminateCallFramePseudoInstr(). 280def tSpill : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), 281 "str", " $src, $addr", []>; 282} 283 284//===----------------------------------------------------------------------===// 285// Load / store multiple Instructions. 286// 287 288// TODO: A7-44: LDMIA - load multiple 289// TODO: Allow these to be predicated 290 291let mayLoad = 1 in 292def tPOP : T1I<(outs reglist:$dst1, variable_ops), (ins), 293 "pop $dst1", []>; 294 295let mayStore = 1 in 296def tPUSH : T1I<(outs), (ins reglist:$src1, variable_ops), 297 "push $src1", []>; 298 299//===----------------------------------------------------------------------===// 300// Arithmetic Instructions. 301// 302 303// Add with carry register 304let isCommutable = 1, Uses = [CPSR] in 305def tADC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), 306 "adc", " $dst, $rhs", 307 [(set tGPR:$dst, (adde tGPR:$lhs, tGPR:$rhs))]>; 308 309// Add immediate 310def tADDi3 : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), 311 "add", " $dst, $lhs, $rhs", 312 [(set tGPR:$dst, (add tGPR:$lhs, imm0_7:$rhs))]>; 313 314def tADDi8 : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), 315 "add", " $dst, $rhs", 316 [(set tGPR:$dst, (add tGPR:$lhs, imm8_255:$rhs))]>; 317 318// Add register 319let isCommutable = 1 in 320def tADDrr : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), 321 "add", " $dst, $lhs, $rhs", 322 [(set tGPR:$dst, (add tGPR:$lhs, tGPR:$rhs))]>; 323 324let neverHasSideEffects = 1 in 325def tADDhirr : T1pIt<(outs tGPR:$dst), (ins GPR:$lhs, GPR:$rhs), 326 "add", " $dst, $rhs @ addhirr", []>; 327 328// And register 329let isCommutable = 1 in 330def tAND : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), 331 "and", " $dst, $rhs", 332 [(set tGPR:$dst, (and tGPR:$lhs, tGPR:$rhs))]>; 333 334// ASR immediate 335def tASRri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), 336 "asr", " $dst, $lhs, $rhs", 337 [(set tGPR:$dst, (sra tGPR:$lhs, (i32 imm:$rhs)))]>; 338 339// ASR register 340def tASRrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), 341 "asr", " $dst, $rhs", 342 [(set tGPR:$dst, (sra tGPR:$lhs, tGPR:$rhs))]>; 343 344// BIC register 345def tBIC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), 346 "bic", " $dst, $rhs", 347 [(set tGPR:$dst, (and tGPR:$lhs, (not tGPR:$rhs)))]>; 348 349// CMN register 350let Defs = [CPSR] in { 351def tCMN : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), 352 "cmn", " $lhs, $rhs", 353 [(ARMcmp tGPR:$lhs, (ineg tGPR:$rhs))]>; 354def tCMNZ : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), 355 "cmn", " $lhs, $rhs", 356 [(ARMcmpZ tGPR:$lhs, (ineg tGPR:$rhs))]>; 357} 358 359// CMP immediate 360let Defs = [CPSR] in { 361def tCMPi8 : T1pI<(outs), (ins tGPR:$lhs, i32imm:$rhs), 362 "cmp", " $lhs, $rhs", 363 [(ARMcmp tGPR:$lhs, imm0_255:$rhs)]>; 364def tCMPZi8 : T1pI<(outs), (ins tGPR:$lhs, i32imm:$rhs), 365 "cmp", " $lhs, $rhs", 366 [(ARMcmpZ tGPR:$lhs, imm0_255:$rhs)]>; 367 368} 369 370// CMP register 371let Defs = [CPSR] in { 372def tCMPr : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), 373 "cmp", " $lhs, $rhs", 374 [(ARMcmp tGPR:$lhs, tGPR:$rhs)]>; 375def tCMPZr : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), 376 "cmp", " $lhs, $rhs", 377 [(ARMcmpZ tGPR:$lhs, tGPR:$rhs)]>; 378 379// TODO: Make use of the followings cmp hi regs 380def tCMPhir : T1pI<(outs), (ins GPR:$lhs, GPR:$rhs), 381 "cmp", " $lhs, $rhs", []>; 382def tCMPZhir : T1pI<(outs), (ins GPR:$lhs, GPR:$rhs), 383 "cmp", " $lhs, $rhs", []>; 384} 385 386 387// XOR register 388let isCommutable = 1 in 389def tEOR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), 390 "eor", " $dst, $rhs", 391 [(set tGPR:$dst, (xor tGPR:$lhs, tGPR:$rhs))]>; 392 393// LSL immediate 394def tLSLri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), 395 "lsl", " $dst, $lhs, $rhs", 396 [(set tGPR:$dst, (shl tGPR:$lhs, (i32 imm:$rhs)))]>; 397 398// LSL register 399def tLSLrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), 400 "lsl", " $dst, $rhs", 401 [(set tGPR:$dst, (shl tGPR:$lhs, tGPR:$rhs))]>; 402 403// LSR immediate 404def tLSRri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), 405 "lsr", " $dst, $lhs, $rhs", 406 [(set tGPR:$dst, (srl tGPR:$lhs, (i32 imm:$rhs)))]>; 407 408// LSR register 409def tLSRrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), 410 "lsr", " $dst, $rhs", 411 [(set tGPR:$dst, (srl tGPR:$lhs, tGPR:$rhs))]>; 412 413// move register 414def tMOVi8 : T1sI<(outs tGPR:$dst), (ins i32imm:$src), 415 "mov", " $dst, $src", 416 [(set tGPR:$dst, imm0_255:$src)]>; 417 418// TODO: A7-73: MOV(2) - mov setting flag. 419 420 421let neverHasSideEffects = 1 in { 422// FIXME: Make this predicable. 423def tMOVr : T1I<(outs tGPR:$dst), (ins tGPR:$src), 424 "mov $dst, $src", []>; 425let Defs = [CPSR] in 426def tMOVSr : T1I<(outs tGPR:$dst), (ins tGPR:$src), 427 "movs $dst, $src", []>; 428 429// FIXME: Make these predicable. 430def tMOVgpr2tgpr : T1I<(outs tGPR:$dst), (ins GPR:$src), 431 "mov $dst, $src\t@ hir2lor", []>; 432def tMOVtgpr2gpr : T1I<(outs GPR:$dst), (ins tGPR:$src), 433 "mov $dst, $src\t@ lor2hir", []>; 434def tMOVgpr2gpr : T1I<(outs GPR:$dst), (ins GPR:$src), 435 "mov $dst, $src\t@ hir2hir", []>; 436} // neverHasSideEffects 437 438// multiply register 439let isCommutable = 1 in 440def tMUL : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), 441 "mul", " $dst, $rhs", 442 [(set tGPR:$dst, (mul tGPR:$lhs, tGPR:$rhs))]>; 443 444// move inverse register 445def tMVN : T1sI<(outs tGPR:$dst), (ins tGPR:$src), 446 "mvn", " $dst, $src", 447 [(set tGPR:$dst, (not tGPR:$src))]>; 448 449// bitwise or register 450let isCommutable = 1 in 451def tORR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), 452 "orr", " $dst, $rhs", 453 [(set tGPR:$dst, (or tGPR:$lhs, tGPR:$rhs))]>; 454 455// swaps 456def tREV : T1pI<(outs tGPR:$dst), (ins tGPR:$src), 457 "rev", " $dst, $src", 458 [(set tGPR:$dst, (bswap tGPR:$src))]>, 459 Requires<[IsThumb1Only, HasV6]>; 460 461def tREV16 : T1pI<(outs tGPR:$dst), (ins tGPR:$src), 462 "rev16", " $dst, $src", 463 [(set tGPR:$dst, 464 (or (and (srl tGPR:$src, (i32 8)), 0xFF), 465 (or (and (shl tGPR:$src, (i32 8)), 0xFF00), 466 (or (and (srl tGPR:$src, (i32 8)), 0xFF0000), 467 (and (shl tGPR:$src, (i32 8)), 0xFF000000)))))]>, 468 Requires<[IsThumb1Only, HasV6]>; 469 470def tREVSH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), 471 "revsh", " $dst, $src", 472 [(set tGPR:$dst, 473 (sext_inreg 474 (or (srl (and tGPR:$src, 0xFFFF), (i32 8)), 475 (shl tGPR:$src, (i32 8))), i16))]>, 476 Requires<[IsThumb1Only, HasV6]>; 477 478// rotate right register 479def tROR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), 480 "ror", " $dst, $rhs", 481 [(set tGPR:$dst, (rotr tGPR:$lhs, tGPR:$rhs))]>; 482 483// negate register 484def tRSB : T1sI<(outs tGPR:$dst), (ins tGPR:$src), 485 "rsb", " $dst, $src, #0", 486 [(set tGPR:$dst, (ineg tGPR:$src))]>; 487 488// Subtract with carry register 489let Uses = [CPSR] in 490def tSBC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), 491 "sbc", " $dst, $rhs", 492 [(set tGPR:$dst, (sube tGPR:$lhs, tGPR:$rhs))]>; 493 494// Subtract immediate 495def tSUBi3 : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), 496 "sub", " $dst, $lhs, $rhs", 497 [(set tGPR:$dst, (add tGPR:$lhs, imm0_7_neg:$rhs))]>; 498 499def tSUBi8 : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), 500 "sub", " $dst, $rhs", 501 [(set tGPR:$dst, (add tGPR:$lhs, imm8_255_neg:$rhs))]>; 502 503// subtract register 504def tSUBrr : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), 505 "sub", " $dst, $lhs, $rhs", 506 [(set tGPR:$dst, (sub tGPR:$lhs, tGPR:$rhs))]>; 507 508// TODO: A7-96: STMIA - store multiple. 509 510def tSUBspi : T1It<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs), 511 "sub $dst, $rhs * 4", []>; 512 513// sign-extend byte 514def tSXTB : T1pI<(outs tGPR:$dst), (ins tGPR:$src), 515 "sxtb", " $dst, $src", 516 [(set tGPR:$dst, (sext_inreg tGPR:$src, i8))]>, 517 Requires<[IsThumb1Only, HasV6]>; 518 519// sign-extend short 520def tSXTH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), 521 "sxth", " $dst, $src", 522 [(set tGPR:$dst, (sext_inreg tGPR:$src, i16))]>, 523 Requires<[IsThumb1Only, HasV6]>; 524 525// test 526let isCommutable = 1, Defs = [CPSR] in 527def tTST : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), 528 "tst", " $lhs, $rhs", 529 [(ARMcmpZ (and tGPR:$lhs, tGPR:$rhs), 0)]>; 530 531// zero-extend byte 532def tUXTB : T1pI<(outs tGPR:$dst), (ins tGPR:$src), 533 "uxtb", " $dst, $src", 534 [(set tGPR:$dst, (and tGPR:$src, 0xFF))]>, 535 Requires<[IsThumb1Only, HasV6]>; 536 537// zero-extend short 538def tUXTH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), 539 "uxth", " $dst, $src", 540 [(set tGPR:$dst, (and tGPR:$src, 0xFFFF))]>, 541 Requires<[IsThumb1Only, HasV6]>; 542 543 544// Conditional move tMOVCCr - Used to implement the Thumb SELECT_CC DAG operation. 545// Expanded by the scheduler into a branch sequence. 546// FIXME: Add actual movcc in IT blocks for Thumb2. 547let usesCustomDAGSchedInserter = 1 in // Expanded by the scheduler. 548 def tMOVCCr : 549 PseudoInst<(outs tGPR:$dst), (ins tGPR:$false, tGPR:$true, pred:$cc), 550 "@ tMOVCCr $cc", 551 [/*(set tGPR:$dst, (ARMcmov tGPR:$false, tGPR:$true, imm:$cc))*/]>; 552 553// tLEApcrel - Load a pc-relative address into a register without offending the 554// assembler. 555def tLEApcrel : T1I<(outs tGPR:$dst), (ins i32imm:$label), 556 "adr $dst, #$label", []>; 557 558def tLEApcrelJT : T1I<(outs tGPR:$dst), (ins i32imm:$label, i32imm:$id), 559 "adr $dst, #${label}_${id:no_hash}", []>; 560 561//===----------------------------------------------------------------------===// 562// TLS Instructions 563// 564 565// __aeabi_read_tp preserves the registers r1-r3. 566let isCall = 1, 567 Defs = [R0, LR] in { 568 def tTPsoft : T1Ix2<(outs), (ins), 569 "bl __aeabi_read_tp", 570 [(set R0, ARMthread_pointer)]>; 571} 572 573//===----------------------------------------------------------------------===// 574// Non-Instruction Patterns 575// 576 577// Add with carry 578def : T1Pat<(addc tGPR:$lhs, imm0_7:$rhs), 579 (tADDi3 tGPR:$lhs, imm0_7:$rhs)>; 580def : T1Pat<(addc tGPR:$lhs, imm8_255:$rhs), 581 (tADDi3 tGPR:$lhs, imm8_255:$rhs)>; 582def : T1Pat<(addc tGPR:$lhs, tGPR:$rhs), 583 (tADDrr tGPR:$lhs, tGPR:$rhs)>; 584 585// Subtract with carry 586def : T1Pat<(addc tGPR:$lhs, imm0_7_neg:$rhs), 587 (tSUBi3 tGPR:$lhs, imm0_7_neg:$rhs)>; 588def : T1Pat<(addc tGPR:$lhs, imm8_255_neg:$rhs), 589 (tSUBi8 tGPR:$lhs, imm8_255_neg:$rhs)>; 590def : T1Pat<(subc tGPR:$lhs, tGPR:$rhs), 591 (tSUBrr tGPR:$lhs, tGPR:$rhs)>; 592 593// ConstantPool, GlobalAddress 594def : T1Pat<(ARMWrapper tglobaladdr :$dst), (tLEApcrel tglobaladdr :$dst)>; 595def : T1Pat<(ARMWrapper tconstpool :$dst), (tLEApcrel tconstpool :$dst)>; 596 597// JumpTable 598def : T1Pat<(ARMWrapperJT tjumptable:$dst, imm:$id), 599 (tLEApcrelJT tjumptable:$dst, imm:$id)>; 600 601// Direct calls 602def : T1Pat<(ARMtcall texternalsym:$func), (tBL texternalsym:$func)>; 603def : Tv5Pat<(ARMcall texternalsym:$func), (tBLXi texternalsym:$func)>; 604 605// Indirect calls to ARM routines 606def : Tv5Pat<(ARMcall tGPR:$dst), (tBLXr tGPR:$dst)>; 607 608// zextload i1 -> zextload i8 609def : T1Pat<(zextloadi1 t_addrmode_s1:$addr), 610 (tLDRB t_addrmode_s1:$addr)>; 611 612// extload -> zextload 613def : T1Pat<(extloadi1 t_addrmode_s1:$addr), (tLDRB t_addrmode_s1:$addr)>; 614def : T1Pat<(extloadi8 t_addrmode_s1:$addr), (tLDRB t_addrmode_s1:$addr)>; 615def : T1Pat<(extloadi16 t_addrmode_s2:$addr), (tLDRH t_addrmode_s2:$addr)>; 616 617// If it's possible to use [r,r] address mode for sextload, select to 618// ldr{b|h} + sxt{b|h} instead. 619def : T1Pat<(sextloadi8 t_addrmode_s1:$addr), 620 (tSXTB (tLDRB t_addrmode_s1:$addr))>; 621def : T1Pat<(sextloadi16 t_addrmode_s2:$addr), 622 (tSXTH (tLDRH t_addrmode_s2:$addr))>; 623 624 625// Large immediate handling. 626 627// Two piece imms. 628def : T1Pat<(i32 thumb_immshifted:$src), 629 (tLSLri (tMOVi8 (thumb_immshifted_val imm:$src)), 630 (thumb_immshifted_shamt imm:$src))>; 631 632def : T1Pat<(i32 imm0_255_comp:$src), 633 (tMVN (tMOVi8 (imm_comp_XFORM imm:$src)))>; 634