ARMInstrThumb.td revision 199989
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// Scaled 4 immediate. 70def t_imm_s4 : Operand<i32> { 71 let PrintMethod = "printThumbS4ImmOperand"; 72} 73 74// Define Thumb specific addressing modes. 75 76// t_addrmode_rr := reg + reg 77// 78def t_addrmode_rr : Operand<i32>, 79 ComplexPattern<i32, 2, "SelectThumbAddrModeRR", []> { 80 let PrintMethod = "printThumbAddrModeRROperand"; 81 let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); 82} 83 84// t_addrmode_s4 := reg + reg 85// reg + imm5 * 4 86// 87def t_addrmode_s4 : Operand<i32>, 88 ComplexPattern<i32, 3, "SelectThumbAddrModeS4", []> { 89 let PrintMethod = "printThumbAddrModeS4Operand"; 90 let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg); 91} 92 93// t_addrmode_s2 := reg + reg 94// reg + imm5 * 2 95// 96def t_addrmode_s2 : Operand<i32>, 97 ComplexPattern<i32, 3, "SelectThumbAddrModeS2", []> { 98 let PrintMethod = "printThumbAddrModeS2Operand"; 99 let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg); 100} 101 102// t_addrmode_s1 := reg + reg 103// reg + imm5 104// 105def t_addrmode_s1 : Operand<i32>, 106 ComplexPattern<i32, 3, "SelectThumbAddrModeS1", []> { 107 let PrintMethod = "printThumbAddrModeS1Operand"; 108 let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg); 109} 110 111// t_addrmode_sp := sp + imm8 * 4 112// 113def t_addrmode_sp : Operand<i32>, 114 ComplexPattern<i32, 2, "SelectThumbAddrModeSP", []> { 115 let PrintMethod = "printThumbAddrModeSPOperand"; 116 let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm); 117} 118 119//===----------------------------------------------------------------------===// 120// Miscellaneous Instructions. 121// 122 123let Defs = [SP], Uses = [SP] in { 124def tADJCALLSTACKUP : 125PseudoInst<(outs), (ins i32imm:$amt1, i32imm:$amt2), NoItinerary, 126 "@ tADJCALLSTACKUP $amt1", 127 [(ARMcallseq_end imm:$amt1, imm:$amt2)]>, Requires<[IsThumb1Only]>; 128 129def tADJCALLSTACKDOWN : 130PseudoInst<(outs), (ins i32imm:$amt), NoItinerary, 131 "@ tADJCALLSTACKDOWN $amt", 132 [(ARMcallseq_start imm:$amt)]>, Requires<[IsThumb1Only]>; 133} 134 135// For both thumb1 and thumb2. 136let isNotDuplicable = 1 in 137def tPICADD : TIt<(outs GPR:$dst), (ins GPR:$lhs, pclabel:$cp), IIC_iALUr, 138 "\n$cp:\n\tadd\t$dst, pc", 139 [(set GPR:$dst, (ARMpic_add GPR:$lhs, imm:$cp))]>; 140 141// PC relative add. 142def tADDrPCi : T1I<(outs tGPR:$dst), (ins t_imm_s4:$rhs), IIC_iALUi, 143 "add\t$dst, pc, $rhs", []>; 144 145// ADD rd, sp, #imm8 146def tADDrSPi : T1I<(outs tGPR:$dst), (ins GPR:$sp, t_imm_s4:$rhs), IIC_iALUi, 147 "add\t$dst, $sp, $rhs", []>; 148 149// ADD sp, sp, #imm7 150def tADDspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), IIC_iALUi, 151 "add\t$dst, $rhs", []>; 152 153// SUB sp, sp, #imm7 154def tSUBspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), IIC_iALUi, 155 "sub\t$dst, $rhs", []>; 156 157// ADD rm, sp 158def tADDrSP : TIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, 159 "add\t$dst, $rhs", []>; 160 161// ADD sp, rm 162def tADDspr : TIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, 163 "add\t$dst, $rhs", []>; 164 165// Pseudo instruction that will expand into a tSUBspi + a copy. 166let usesCustomInserter = 1 in { // Expanded after instruction selection. 167def tSUBspi_ : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), 168 NoItinerary, "@ sub\t$dst, $rhs", []>; 169 170def tADDspr_ : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), 171 NoItinerary, "@ add\t$dst, $rhs", []>; 172 173let Defs = [CPSR] in 174def tANDsp : PseudoInst<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), 175 NoItinerary, "@ and\t$dst, $rhs", []>; 176} // usesCustomInserter 177 178//===----------------------------------------------------------------------===// 179// Control Flow Instructions. 180// 181 182let isReturn = 1, isTerminator = 1, isBarrier = 1 in { 183 def tBX_RET : TI<(outs), (ins), IIC_Br, "bx\tlr", [(ARMretflag)]>; 184 // Alternative return instruction used by vararg functions. 185 def tBX_RET_vararg : TI<(outs), (ins tGPR:$target), IIC_Br, "bx\t$target", []>; 186} 187 188// Indirect branches 189let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { 190 def tBRIND : TI<(outs), (ins GPR:$dst), IIC_Br, "mov\tpc, $dst", 191 [(brind GPR:$dst)]>; 192} 193 194// FIXME: remove when we have a way to marking a MI with these properties. 195let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1, 196 hasExtraDefRegAllocReq = 1 in 197def tPOP_RET : T1I<(outs), (ins pred:$p, reglist:$wb, variable_ops), IIC_Br, 198 "pop${p}\t$wb", []>; 199 200let isCall = 1, 201 Defs = [R0, R1, R2, R3, R12, LR, 202 D0, D1, D2, D3, D4, D5, D6, D7, 203 D16, D17, D18, D19, D20, D21, D22, D23, 204 D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR] in { 205 // Also used for Thumb2 206 def tBL : TIx2<(outs), (ins i32imm:$func, variable_ops), IIC_Br, 207 "bl\t${func:call}", 208 [(ARMtcall tglobaladdr:$func)]>, 209 Requires<[IsThumb, IsNotDarwin]>; 210 211 // ARMv5T and above, also used for Thumb2 212 def tBLXi : TIx2<(outs), (ins i32imm:$func, variable_ops), IIC_Br, 213 "blx\t${func:call}", 214 [(ARMcall tglobaladdr:$func)]>, 215 Requires<[IsThumb, HasV5T, IsNotDarwin]>; 216 217 // Also used for Thumb2 218 def tBLXr : TI<(outs), (ins GPR:$func, variable_ops), IIC_Br, 219 "blx\t$func", 220 [(ARMtcall GPR:$func)]>, 221 Requires<[IsThumb, HasV5T, IsNotDarwin]>; 222 223 // ARMv4T 224 def tBX : TIx2<(outs), (ins tGPR:$func, variable_ops), IIC_Br, 225 "mov\tlr, pc\n\tbx\t$func", 226 [(ARMcall_nolink tGPR:$func)]>, 227 Requires<[IsThumb1Only, IsNotDarwin]>; 228} 229 230// On Darwin R9 is call-clobbered. 231let isCall = 1, 232 Defs = [R0, R1, R2, R3, R9, R12, LR, 233 D0, D1, D2, D3, D4, D5, D6, D7, 234 D16, D17, D18, D19, D20, D21, D22, D23, 235 D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR] in { 236 // Also used for Thumb2 237 def tBLr9 : TIx2<(outs), (ins i32imm:$func, variable_ops), IIC_Br, 238 "bl\t${func:call}", 239 [(ARMtcall tglobaladdr:$func)]>, 240 Requires<[IsThumb, IsDarwin]>; 241 242 // ARMv5T and above, also used for Thumb2 243 def tBLXi_r9 : TIx2<(outs), (ins i32imm:$func, variable_ops), IIC_Br, 244 "blx\t${func:call}", 245 [(ARMcall tglobaladdr:$func)]>, 246 Requires<[IsThumb, HasV5T, IsDarwin]>; 247 248 // Also used for Thumb2 249 def tBLXr_r9 : TI<(outs), (ins GPR:$func, variable_ops), IIC_Br, 250 "blx\t$func", 251 [(ARMtcall GPR:$func)]>, 252 Requires<[IsThumb, HasV5T, IsDarwin]>; 253 254 // ARMv4T 255 def tBXr9 : TIx2<(outs), (ins tGPR:$func, variable_ops), IIC_Br, 256 "mov\tlr, pc\n\tbx\t$func", 257 [(ARMcall_nolink tGPR:$func)]>, 258 Requires<[IsThumb1Only, IsDarwin]>; 259} 260 261let isBranch = 1, isTerminator = 1 in { 262 let isBarrier = 1 in { 263 let isPredicable = 1 in 264 def tB : T1I<(outs), (ins brtarget:$target), IIC_Br, 265 "b\t$target", [(br bb:$target)]>; 266 267 // Far jump 268 let Defs = [LR] in 269 def tBfar : TIx2<(outs), (ins brtarget:$target), IIC_Br, 270 "bl\t$target\t@ far jump",[]>; 271 272 def tBR_JTr : T1JTI<(outs), 273 (ins tGPR:$target, jtblock_operand:$jt, i32imm:$id), 274 IIC_Br, "mov\tpc, $target\n\t.align\t2\n$jt", 275 [(ARMbrjt tGPR:$target, tjumptable:$jt, imm:$id)]>; 276 } 277} 278 279// FIXME: should be able to write a pattern for ARMBrcond, but can't use 280// a two-value operand where a dag node expects two operands. :( 281let isBranch = 1, isTerminator = 1 in 282 def tBcc : T1I<(outs), (ins brtarget:$target, pred:$cc), IIC_Br, 283 "b$cc\t$target", 284 [/*(ARMbrcond bb:$target, imm:$cc)*/]>; 285 286// Compare and branch on zero / non-zero 287let isBranch = 1, isTerminator = 1 in { 288 def tCBZ : T1I<(outs), (ins tGPR:$cmp, brtarget:$target), IIC_Br, 289 "cbz\t$cmp, $target", []>; 290 291 def tCBNZ : T1I<(outs), (ins tGPR:$cmp, brtarget:$target), IIC_Br, 292 "cbnz\t$cmp, $target", []>; 293} 294 295//===----------------------------------------------------------------------===// 296// Load Store Instructions. 297// 298 299let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in 300def tLDR : T1pI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr), IIC_iLoadr, 301 "ldr", "\t$dst, $addr", 302 [(set tGPR:$dst, (load t_addrmode_s4:$addr))]>; 303 304def tLDRB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr), IIC_iLoadr, 305 "ldrb", "\t$dst, $addr", 306 [(set tGPR:$dst, (zextloadi8 t_addrmode_s1:$addr))]>; 307 308def tLDRH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr), IIC_iLoadr, 309 "ldrh", "\t$dst, $addr", 310 [(set tGPR:$dst, (zextloadi16 t_addrmode_s2:$addr))]>; 311 312let AddedComplexity = 10 in 313def tLDRSB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), IIC_iLoadr, 314 "ldrsb", "\t$dst, $addr", 315 [(set tGPR:$dst, (sextloadi8 t_addrmode_rr:$addr))]>; 316 317let AddedComplexity = 10 in 318def tLDRSH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), IIC_iLoadr, 319 "ldrsh", "\t$dst, $addr", 320 [(set tGPR:$dst, (sextloadi16 t_addrmode_rr:$addr))]>; 321 322let canFoldAsLoad = 1 in 323def tLDRspi : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), IIC_iLoadi, 324 "ldr", "\t$dst, $addr", 325 [(set tGPR:$dst, (load t_addrmode_sp:$addr))]>; 326 327// Special instruction for restore. It cannot clobber condition register 328// when it's expanded by eliminateCallFramePseudoInstr(). 329let canFoldAsLoad = 1, mayLoad = 1 in 330def tRestore : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), IIC_iLoadi, 331 "ldr", "\t$dst, $addr", []>; 332 333// Load tconstpool 334// FIXME: Use ldr.n to work around a Darwin assembler bug. 335let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in 336def tLDRpci : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr), IIC_iLoadi, 337 "ldr", ".n\t$dst, $addr", 338 [(set tGPR:$dst, (load (ARMWrapper tconstpool:$addr)))]>; 339 340// Special LDR for loads from non-pc-relative constpools. 341let canFoldAsLoad = 1, mayLoad = 1, isReMaterializable = 1, 342 mayHaveSideEffects = 1 in 343def tLDRcp : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr), IIC_iLoadi, 344 "ldr", "\t$dst, $addr", []>; 345 346def tSTR : T1pI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr), IIC_iStorer, 347 "str", "\t$src, $addr", 348 [(store tGPR:$src, t_addrmode_s4:$addr)]>; 349 350def tSTRB : T1pI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr), IIC_iStorer, 351 "strb", "\t$src, $addr", 352 [(truncstorei8 tGPR:$src, t_addrmode_s1:$addr)]>; 353 354def tSTRH : T1pI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr), IIC_iStorer, 355 "strh", "\t$src, $addr", 356 [(truncstorei16 tGPR:$src, t_addrmode_s2:$addr)]>; 357 358def tSTRspi : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStorei, 359 "str", "\t$src, $addr", 360 [(store tGPR:$src, t_addrmode_sp:$addr)]>; 361 362let mayStore = 1 in { 363// Special instruction for spill. It cannot clobber condition register 364// when it's expanded by eliminateCallFramePseudoInstr(). 365def tSpill : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStorei, 366 "str", "\t$src, $addr", []>; 367} 368 369//===----------------------------------------------------------------------===// 370// Load / store multiple Instructions. 371// 372 373// These requires base address to be written back or one of the loaded regs. 374let mayLoad = 1, hasExtraDefRegAllocReq = 1 in 375def tLDM : T1I<(outs), 376 (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops), 377 IIC_iLoadm, 378 "ldm${addr:submode}${p}\t$addr, $wb", []>; 379 380let mayStore = 1, hasExtraSrcRegAllocReq = 1 in 381def tSTM : T1I<(outs), 382 (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops), 383 IIC_iStorem, 384 "stm${addr:submode}${p}\t$addr, $wb", []>; 385 386let mayLoad = 1, Uses = [SP], Defs = [SP], hasExtraDefRegAllocReq = 1 in 387def tPOP : T1I<(outs), (ins pred:$p, reglist:$wb, variable_ops), IIC_Br, 388 "pop${p}\t$wb", []>; 389 390let mayStore = 1, Uses = [SP], Defs = [SP], hasExtraSrcRegAllocReq = 1 in 391def tPUSH : T1I<(outs), (ins pred:$p, reglist:$wb, variable_ops), IIC_Br, 392 "push${p}\t$wb", []>; 393 394//===----------------------------------------------------------------------===// 395// Arithmetic Instructions. 396// 397 398// Add with carry register 399let isCommutable = 1, Uses = [CPSR] in 400def tADC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 401 "adc", "\t$dst, $rhs", 402 [(set tGPR:$dst, (adde tGPR:$lhs, tGPR:$rhs))]>; 403 404// Add immediate 405def tADDi3 : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi, 406 "add", "\t$dst, $lhs, $rhs", 407 [(set tGPR:$dst, (add tGPR:$lhs, imm0_7:$rhs))]>; 408 409def tADDi8 : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi, 410 "add", "\t$dst, $rhs", 411 [(set tGPR:$dst, (add tGPR:$lhs, imm8_255:$rhs))]>; 412 413// Add register 414let isCommutable = 1 in 415def tADDrr : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 416 "add", "\t$dst, $lhs, $rhs", 417 [(set tGPR:$dst, (add tGPR:$lhs, tGPR:$rhs))]>; 418 419let neverHasSideEffects = 1 in 420def tADDhirr : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, 421 "add", "\t$dst, $rhs", []>; 422 423// And register 424let isCommutable = 1 in 425def tAND : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 426 "and", "\t$dst, $rhs", 427 [(set tGPR:$dst, (and tGPR:$lhs, tGPR:$rhs))]>; 428 429// ASR immediate 430def tASRri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iMOVsi, 431 "asr", "\t$dst, $lhs, $rhs", 432 [(set tGPR:$dst, (sra tGPR:$lhs, (i32 imm:$rhs)))]>; 433 434// ASR register 435def tASRrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, 436 "asr", "\t$dst, $rhs", 437 [(set tGPR:$dst, (sra tGPR:$lhs, tGPR:$rhs))]>; 438 439// BIC register 440def tBIC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 441 "bic", "\t$dst, $rhs", 442 [(set tGPR:$dst, (and tGPR:$lhs, (not tGPR:$rhs)))]>; 443 444// CMN register 445let Defs = [CPSR] in { 446def tCMN : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, 447 "cmn", "\t$lhs, $rhs", 448 [(ARMcmp tGPR:$lhs, (ineg tGPR:$rhs))]>; 449def tCMNZ : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, 450 "cmn", "\t$lhs, $rhs", 451 [(ARMcmpZ tGPR:$lhs, (ineg tGPR:$rhs))]>; 452} 453 454// CMP immediate 455let Defs = [CPSR] in { 456def tCMPi8 : T1pI<(outs), (ins tGPR:$lhs, i32imm:$rhs), IIC_iCMPi, 457 "cmp", "\t$lhs, $rhs", 458 [(ARMcmp tGPR:$lhs, imm0_255:$rhs)]>; 459def tCMPzi8 : T1pI<(outs), (ins tGPR:$lhs, i32imm:$rhs), IIC_iCMPi, 460 "cmp", "\t$lhs, $rhs", 461 [(ARMcmpZ tGPR:$lhs, imm0_255:$rhs)]>; 462 463} 464 465// CMP register 466let Defs = [CPSR] in { 467def tCMPr : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, 468 "cmp", "\t$lhs, $rhs", 469 [(ARMcmp tGPR:$lhs, tGPR:$rhs)]>; 470def tCMPzr : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, 471 "cmp", "\t$lhs, $rhs", 472 [(ARMcmpZ tGPR:$lhs, tGPR:$rhs)]>; 473 474def tCMPhir : T1pI<(outs), (ins GPR:$lhs, GPR:$rhs), IIC_iCMPr, 475 "cmp", "\t$lhs, $rhs", []>; 476def tCMPzhir : T1pI<(outs), (ins GPR:$lhs, GPR:$rhs), IIC_iCMPr, 477 "cmp", "\t$lhs, $rhs", []>; 478} 479 480 481// XOR register 482let isCommutable = 1 in 483def tEOR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 484 "eor", "\t$dst, $rhs", 485 [(set tGPR:$dst, (xor tGPR:$lhs, tGPR:$rhs))]>; 486 487// LSL immediate 488def tLSLri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iMOVsi, 489 "lsl", "\t$dst, $lhs, $rhs", 490 [(set tGPR:$dst, (shl tGPR:$lhs, (i32 imm:$rhs)))]>; 491 492// LSL register 493def tLSLrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, 494 "lsl", "\t$dst, $rhs", 495 [(set tGPR:$dst, (shl tGPR:$lhs, tGPR:$rhs))]>; 496 497// LSR immediate 498def tLSRri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iMOVsi, 499 "lsr", "\t$dst, $lhs, $rhs", 500 [(set tGPR:$dst, (srl tGPR:$lhs, (i32 imm:$rhs)))]>; 501 502// LSR register 503def tLSRrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, 504 "lsr", "\t$dst, $rhs", 505 [(set tGPR:$dst, (srl tGPR:$lhs, tGPR:$rhs))]>; 506 507// move register 508def tMOVi8 : T1sI<(outs tGPR:$dst), (ins i32imm:$src), IIC_iMOVi, 509 "mov", "\t$dst, $src", 510 [(set tGPR:$dst, imm0_255:$src)]>; 511 512// TODO: A7-73: MOV(2) - mov setting flag. 513 514 515let neverHasSideEffects = 1 in { 516// FIXME: Make this predicable. 517def tMOVr : T1I<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr, 518 "mov\t$dst, $src", []>; 519let Defs = [CPSR] in 520def tMOVSr : T1I<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr, 521 "movs\t$dst, $src", []>; 522 523// FIXME: Make these predicable. 524def tMOVgpr2tgpr : T1I<(outs tGPR:$dst), (ins GPR:$src), IIC_iMOVr, 525 "mov\t$dst, $src", []>; 526def tMOVtgpr2gpr : T1I<(outs GPR:$dst), (ins tGPR:$src), IIC_iMOVr, 527 "mov\t$dst, $src", []>; 528def tMOVgpr2gpr : T1I<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVr, 529 "mov\t$dst, $src", []>; 530} // neverHasSideEffects 531 532// multiply register 533let isCommutable = 1 in 534def tMUL : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMUL32, 535 "mul", "\t$dst, $rhs", 536 [(set tGPR:$dst, (mul tGPR:$lhs, tGPR:$rhs))]>; 537 538// move inverse register 539def tMVN : T1sI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr, 540 "mvn", "\t$dst, $src", 541 [(set tGPR:$dst, (not tGPR:$src))]>; 542 543// bitwise or register 544let isCommutable = 1 in 545def tORR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 546 "orr", "\t$dst, $rhs", 547 [(set tGPR:$dst, (or tGPR:$lhs, tGPR:$rhs))]>; 548 549// swaps 550def tREV : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 551 "rev", "\t$dst, $src", 552 [(set tGPR:$dst, (bswap tGPR:$src))]>, 553 Requires<[IsThumb1Only, HasV6]>; 554 555def tREV16 : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 556 "rev16", "\t$dst, $src", 557 [(set tGPR:$dst, 558 (or (and (srl tGPR:$src, (i32 8)), 0xFF), 559 (or (and (shl tGPR:$src, (i32 8)), 0xFF00), 560 (or (and (srl tGPR:$src, (i32 8)), 0xFF0000), 561 (and (shl tGPR:$src, (i32 8)), 0xFF000000)))))]>, 562 Requires<[IsThumb1Only, HasV6]>; 563 564def tREVSH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 565 "revsh", "\t$dst, $src", 566 [(set tGPR:$dst, 567 (sext_inreg 568 (or (srl (and tGPR:$src, 0xFF00), (i32 8)), 569 (shl tGPR:$src, (i32 8))), i16))]>, 570 Requires<[IsThumb1Only, HasV6]>; 571 572// rotate right register 573def tROR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, 574 "ror", "\t$dst, $rhs", 575 [(set tGPR:$dst, (rotr tGPR:$lhs, tGPR:$rhs))]>; 576 577// negate register 578def tRSB : T1sI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iALUi, 579 "rsb", "\t$dst, $src, #0", 580 [(set tGPR:$dst, (ineg tGPR:$src))]>; 581 582// Subtract with carry register 583let Uses = [CPSR] in 584def tSBC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 585 "sbc", "\t$dst, $rhs", 586 [(set tGPR:$dst, (sube tGPR:$lhs, tGPR:$rhs))]>; 587 588// Subtract immediate 589def tSUBi3 : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi, 590 "sub", "\t$dst, $lhs, $rhs", 591 [(set tGPR:$dst, (add tGPR:$lhs, imm0_7_neg:$rhs))]>; 592 593def tSUBi8 : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi, 594 "sub", "\t$dst, $rhs", 595 [(set tGPR:$dst, (add tGPR:$lhs, imm8_255_neg:$rhs))]>; 596 597// subtract register 598def tSUBrr : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 599 "sub", "\t$dst, $lhs, $rhs", 600 [(set tGPR:$dst, (sub tGPR:$lhs, tGPR:$rhs))]>; 601 602// TODO: A7-96: STMIA - store multiple. 603 604// sign-extend byte 605def tSXTB : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 606 "sxtb", "\t$dst, $src", 607 [(set tGPR:$dst, (sext_inreg tGPR:$src, i8))]>, 608 Requires<[IsThumb1Only, HasV6]>; 609 610// sign-extend short 611def tSXTH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 612 "sxth", "\t$dst, $src", 613 [(set tGPR:$dst, (sext_inreg tGPR:$src, i16))]>, 614 Requires<[IsThumb1Only, HasV6]>; 615 616// test 617let isCommutable = 1, Defs = [CPSR] in 618def tTST : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, 619 "tst", "\t$lhs, $rhs", 620 [(ARMcmpZ (and tGPR:$lhs, tGPR:$rhs), 0)]>; 621 622// zero-extend byte 623def tUXTB : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 624 "uxtb", "\t$dst, $src", 625 [(set tGPR:$dst, (and tGPR:$src, 0xFF))]>, 626 Requires<[IsThumb1Only, HasV6]>; 627 628// zero-extend short 629def tUXTH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 630 "uxth", "\t$dst, $src", 631 [(set tGPR:$dst, (and tGPR:$src, 0xFFFF))]>, 632 Requires<[IsThumb1Only, HasV6]>; 633 634 635// Conditional move tMOVCCr - Used to implement the Thumb SELECT_CC DAG operation. 636// Expanded after instruction selection into a branch sequence. 637let usesCustomInserter = 1 in // Expanded after instruction selection. 638 def tMOVCCr_pseudo : 639 PseudoInst<(outs tGPR:$dst), (ins tGPR:$false, tGPR:$true, pred:$cc), 640 NoItinerary, "@ tMOVCCr $cc", 641 [/*(set tGPR:$dst, (ARMcmov tGPR:$false, tGPR:$true, imm:$cc))*/]>; 642 643 644// 16-bit movcc in IT blocks for Thumb2. 645def tMOVCCr : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iCMOVr, 646 "mov", "\t$dst, $rhs", []>; 647 648def tMOVCCi : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs), IIC_iCMOVi, 649 "mov", "\t$dst, $rhs", []>; 650 651// tLEApcrel - Load a pc-relative address into a register without offending the 652// assembler. 653def tLEApcrel : T1I<(outs tGPR:$dst), (ins i32imm:$label, pred:$p), IIC_iALUi, 654 "adr$p\t$dst, #$label", []>; 655 656def tLEApcrelJT : T1I<(outs tGPR:$dst), 657 (ins i32imm:$label, nohash_imm:$id, pred:$p), 658 IIC_iALUi, "adr$p\t$dst, #${label}_${id}", []>; 659 660//===----------------------------------------------------------------------===// 661// TLS Instructions 662// 663 664// __aeabi_read_tp preserves the registers r1-r3. 665let isCall = 1, 666 Defs = [R0, LR] in { 667 def tTPsoft : TIx2<(outs), (ins), IIC_Br, 668 "bl\t__aeabi_read_tp", 669 [(set R0, ARMthread_pointer)]>; 670} 671 672//===----------------------------------------------------------------------===// 673// Non-Instruction Patterns 674// 675 676// Add with carry 677def : T1Pat<(addc tGPR:$lhs, imm0_7:$rhs), 678 (tADDi3 tGPR:$lhs, imm0_7:$rhs)>; 679def : T1Pat<(addc tGPR:$lhs, imm8_255:$rhs), 680 (tADDi8 tGPR:$lhs, imm8_255:$rhs)>; 681def : T1Pat<(addc tGPR:$lhs, tGPR:$rhs), 682 (tADDrr tGPR:$lhs, tGPR:$rhs)>; 683 684// Subtract with carry 685def : T1Pat<(addc tGPR:$lhs, imm0_7_neg:$rhs), 686 (tSUBi3 tGPR:$lhs, imm0_7_neg:$rhs)>; 687def : T1Pat<(addc tGPR:$lhs, imm8_255_neg:$rhs), 688 (tSUBi8 tGPR:$lhs, imm8_255_neg:$rhs)>; 689def : T1Pat<(subc tGPR:$lhs, tGPR:$rhs), 690 (tSUBrr tGPR:$lhs, tGPR:$rhs)>; 691 692// ConstantPool, GlobalAddress 693def : T1Pat<(ARMWrapper tglobaladdr :$dst), (tLEApcrel tglobaladdr :$dst)>; 694def : T1Pat<(ARMWrapper tconstpool :$dst), (tLEApcrel tconstpool :$dst)>; 695 696// JumpTable 697def : T1Pat<(ARMWrapperJT tjumptable:$dst, imm:$id), 698 (tLEApcrelJT tjumptable:$dst, imm:$id)>; 699 700// Direct calls 701def : T1Pat<(ARMtcall texternalsym:$func), (tBL texternalsym:$func)>, 702 Requires<[IsThumb, IsNotDarwin]>; 703def : T1Pat<(ARMtcall texternalsym:$func), (tBLr9 texternalsym:$func)>, 704 Requires<[IsThumb, IsDarwin]>; 705 706def : Tv5Pat<(ARMcall texternalsym:$func), (tBLXi texternalsym:$func)>, 707 Requires<[IsThumb, HasV5T, IsNotDarwin]>; 708def : Tv5Pat<(ARMcall texternalsym:$func), (tBLXi_r9 texternalsym:$func)>, 709 Requires<[IsThumb, HasV5T, IsDarwin]>; 710 711// Indirect calls to ARM routines 712def : Tv5Pat<(ARMcall GPR:$dst), (tBLXr GPR:$dst)>, 713 Requires<[IsThumb, HasV5T, IsNotDarwin]>; 714def : Tv5Pat<(ARMcall GPR:$dst), (tBLXr_r9 GPR:$dst)>, 715 Requires<[IsThumb, HasV5T, IsDarwin]>; 716 717// zextload i1 -> zextload i8 718def : T1Pat<(zextloadi1 t_addrmode_s1:$addr), 719 (tLDRB t_addrmode_s1:$addr)>; 720 721// extload -> zextload 722def : T1Pat<(extloadi1 t_addrmode_s1:$addr), (tLDRB t_addrmode_s1:$addr)>; 723def : T1Pat<(extloadi8 t_addrmode_s1:$addr), (tLDRB t_addrmode_s1:$addr)>; 724def : T1Pat<(extloadi16 t_addrmode_s2:$addr), (tLDRH t_addrmode_s2:$addr)>; 725 726// If it's impossible to use [r,r] address mode for sextload, select to 727// ldr{b|h} + sxt{b|h} instead. 728def : T1Pat<(sextloadi8 t_addrmode_s1:$addr), 729 (tSXTB (tLDRB t_addrmode_s1:$addr))>, 730 Requires<[IsThumb1Only, HasV6]>; 731def : T1Pat<(sextloadi16 t_addrmode_s2:$addr), 732 (tSXTH (tLDRH t_addrmode_s2:$addr))>, 733 Requires<[IsThumb1Only, HasV6]>; 734 735def : T1Pat<(sextloadi8 t_addrmode_s1:$addr), 736 (tASRri (tLSLri (tLDRB t_addrmode_s1:$addr), 24), 24)>; 737def : T1Pat<(sextloadi16 t_addrmode_s1:$addr), 738 (tASRri (tLSLri (tLDRH t_addrmode_s1:$addr), 16), 16)>; 739 740// Large immediate handling. 741 742// Two piece imms. 743def : T1Pat<(i32 thumb_immshifted:$src), 744 (tLSLri (tMOVi8 (thumb_immshifted_val imm:$src)), 745 (thumb_immshifted_shamt imm:$src))>; 746 747def : T1Pat<(i32 imm0_255_comp:$src), 748 (tMVN (tMOVi8 (imm_comp_XFORM imm:$src)))>; 749 750// Pseudo instruction that combines ldr from constpool and add pc. This should 751// be expanded into two instructions late to allow if-conversion and 752// scheduling. 753let isReMaterializable = 1 in 754def tLDRpci_pic : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr, pclabel:$cp), 755 NoItinerary, "@ ldr.n\t$dst, $addr\n$cp:\n\tadd\t$dst, pc", 756 [(set GPR:$dst, (ARMpic_add (load (ARMWrapper tconstpool:$addr)), 757 imm:$cp))]>, 758 Requires<[IsThumb1Only]>; 759