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