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