1//===-- ARMInstrThumb.td - Thumb support for ARM -----------*- tablegen -*-===// 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 imm_sr_XFORM: SDNodeXForm<imm, [{ 19 unsigned Imm = N->getZExtValue(); 20 return CurDAG->getTargetConstant((Imm == 32 ? 0 : Imm), SDLoc(N), MVT::i32); 21}]>; 22def ThumbSRImmAsmOperand: ImmAsmOperand<1,32> { let Name = "ImmThumbSR"; } 23def imm_sr : Operand<i32>, PatLeaf<(imm), [{ 24 uint64_t Imm = N->getZExtValue(); 25 return Imm > 0 && Imm <= 32; 26}], imm_sr_XFORM> { 27 let PrintMethod = "printThumbSRImm"; 28 let ParserMatchClass = ThumbSRImmAsmOperand; 29} 30 31def imm0_7_neg : PatLeaf<(i32 imm), [{ 32 return (uint32_t)-N->getZExtValue() < 8; 33}], imm_neg_XFORM>; 34 35def ThumbModImmNeg1_7AsmOperand : AsmOperandClass { let Name = "ThumbModImmNeg1_7"; } 36def mod_imm1_7_neg : Operand<i32>, PatLeaf<(imm), [{ 37 unsigned Value = -(unsigned)N->getZExtValue(); 38 return 0 < Value && Value < 8; 39 }], imm_neg_XFORM> { 40 let ParserMatchClass = ThumbModImmNeg1_7AsmOperand; 41} 42 43def ThumbModImmNeg8_255AsmOperand : AsmOperandClass { let Name = "ThumbModImmNeg8_255"; } 44def mod_imm8_255_neg : Operand<i32>, PatLeaf<(imm), [{ 45 unsigned Value = -(unsigned)N->getZExtValue(); 46 return 7 < Value && Value < 256; 47 }], imm_neg_XFORM> { 48 let ParserMatchClass = ThumbModImmNeg8_255AsmOperand; 49} 50 51 52def imm0_255_comp : PatLeaf<(i32 imm), [{ 53 return ~((uint32_t)N->getZExtValue()) < 256; 54}]>; 55 56def imm8_255_neg : PatLeaf<(i32 imm), [{ 57 unsigned Val = -N->getZExtValue(); 58 return Val >= 8 && Val < 256; 59}], imm_neg_XFORM>; 60 61// Break imm's up into two pieces: an immediate + a left shift. This uses 62// thumb_immshifted to match and thumb_immshifted_val and thumb_immshifted_shamt 63// to get the val/shift pieces. 64def thumb_immshifted : PatLeaf<(imm), [{ 65 return ARM_AM::isThumbImmShiftedVal((unsigned)N->getZExtValue()); 66}]>; 67 68def thumb_immshifted_val : SDNodeXForm<imm, [{ 69 unsigned V = ARM_AM::getThumbImmNonShiftedVal((unsigned)N->getZExtValue()); 70 return CurDAG->getTargetConstant(V, SDLoc(N), MVT::i32); 71}]>; 72 73def thumb_immshifted_shamt : SDNodeXForm<imm, [{ 74 unsigned V = ARM_AM::getThumbImmValShift((unsigned)N->getZExtValue()); 75 return CurDAG->getTargetConstant(V, SDLoc(N), MVT::i32); 76}]>; 77 78def imm256_510 : ImmLeaf<i32, [{ 79 return Imm >= 256 && Imm < 511; 80}]>; 81 82def thumb_imm256_510_addend : SDNodeXForm<imm, [{ 83 return CurDAG->getTargetConstant(N->getZExtValue() - 255, SDLoc(N), MVT::i32); 84}]>; 85 86// Scaled 4 immediate. 87def t_imm0_1020s4_asmoperand: AsmOperandClass { let Name = "Imm0_1020s4"; } 88def t_imm0_1020s4 : Operand<i32> { 89 let PrintMethod = "printThumbS4ImmOperand"; 90 let ParserMatchClass = t_imm0_1020s4_asmoperand; 91 let OperandType = "OPERAND_IMMEDIATE"; 92} 93 94def t_imm0_508s4_asmoperand: AsmOperandClass { let Name = "Imm0_508s4"; } 95def t_imm0_508s4 : Operand<i32> { 96 let PrintMethod = "printThumbS4ImmOperand"; 97 let ParserMatchClass = t_imm0_508s4_asmoperand; 98 let OperandType = "OPERAND_IMMEDIATE"; 99} 100// Alias use only, so no printer is necessary. 101def t_imm0_508s4_neg_asmoperand: AsmOperandClass { let Name = "Imm0_508s4Neg"; } 102def t_imm0_508s4_neg : Operand<i32> { 103 let ParserMatchClass = t_imm0_508s4_neg_asmoperand; 104 let OperandType = "OPERAND_IMMEDIATE"; 105} 106 107// Define Thumb specific addressing modes. 108 109// unsigned 8-bit, 2-scaled memory offset 110class OperandUnsignedOffset_b8s2 : AsmOperandClass { 111 let Name = "UnsignedOffset_b8s2"; 112 let PredicateMethod = "isUnsignedOffset<8, 2>"; 113} 114 115def UnsignedOffset_b8s2 : OperandUnsignedOffset_b8s2; 116 117// thumb style PC relative operand. signed, 8 bits magnitude, 118// two bits shift. can be represented as either [pc, #imm], #imm, 119// or relocatable expression... 120def ThumbMemPC : AsmOperandClass { 121 let Name = "ThumbMemPC"; 122} 123 124let OperandType = "OPERAND_PCREL" in { 125def t_brtarget : Operand<OtherVT> { 126 let EncoderMethod = "getThumbBRTargetOpValue"; 127 let DecoderMethod = "DecodeThumbBROperand"; 128} 129 130// ADR instruction labels. 131def t_adrlabel : Operand<i32> { 132 let EncoderMethod = "getThumbAdrLabelOpValue"; 133 let PrintMethod = "printAdrLabelOperand<2>"; 134 let ParserMatchClass = UnsignedOffset_b8s2; 135} 136 137 138def thumb_br_target : Operand<OtherVT> { 139 let ParserMatchClass = ThumbBranchTarget; 140 let EncoderMethod = "getThumbBranchTargetOpValue"; 141 let OperandType = "OPERAND_PCREL"; 142} 143 144def thumb_bl_target : Operand<i32> { 145 let ParserMatchClass = ThumbBranchTarget; 146 let EncoderMethod = "getThumbBLTargetOpValue"; 147 let DecoderMethod = "DecodeThumbBLTargetOperand"; 148} 149 150// Target for BLX *from* thumb mode. 151def thumb_blx_target : Operand<i32> { 152 let ParserMatchClass = ARMBranchTarget; 153 let EncoderMethod = "getThumbBLXTargetOpValue"; 154 let DecoderMethod = "DecodeThumbBLXOffset"; 155} 156 157def thumb_bcc_target : Operand<OtherVT> { 158 let ParserMatchClass = ThumbBranchTarget; 159 let EncoderMethod = "getThumbBCCTargetOpValue"; 160 let DecoderMethod = "DecodeThumbBCCTargetOperand"; 161} 162 163def thumb_cb_target : Operand<OtherVT> { 164 let ParserMatchClass = ThumbBranchTarget; 165 let EncoderMethod = "getThumbCBTargetOpValue"; 166 let DecoderMethod = "DecodeThumbCmpBROperand"; 167} 168 169// t_addrmode_pc := <label> => pc + imm8 * 4 170// 171def t_addrmode_pc : MemOperand { 172 let EncoderMethod = "getAddrModePCOpValue"; 173 let DecoderMethod = "DecodeThumbAddrModePC"; 174 let PrintMethod = "printThumbLdrLabelOperand"; 175 let ParserMatchClass = ThumbMemPC; 176} 177} 178 179// t_addrmode_rr := reg + reg 180// 181def t_addrmode_rr_asm_operand : AsmOperandClass { let Name = "MemThumbRR"; } 182def t_addrmode_rr : MemOperand, 183 ComplexPattern<i32, 2, "SelectThumbAddrModeRR", []> { 184 let EncoderMethod = "getThumbAddrModeRegRegOpValue"; 185 let PrintMethod = "printThumbAddrModeRROperand"; 186 let DecoderMethod = "DecodeThumbAddrModeRR"; 187 let ParserMatchClass = t_addrmode_rr_asm_operand; 188 let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); 189} 190 191// t_addrmode_rrs := reg + reg 192// 193// We use separate scaled versions because the Select* functions need 194// to explicitly check for a matching constant and return false here so that 195// the reg+imm forms will match instead. This is a horrible way to do that, 196// as it forces tight coupling between the methods, but it's how selectiondag 197// currently works. 198def t_addrmode_rrs1 : MemOperand, 199 ComplexPattern<i32, 2, "SelectThumbAddrModeRI5S1", []> { 200 let EncoderMethod = "getThumbAddrModeRegRegOpValue"; 201 let PrintMethod = "printThumbAddrModeRROperand"; 202 let DecoderMethod = "DecodeThumbAddrModeRR"; 203 let ParserMatchClass = t_addrmode_rr_asm_operand; 204 let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); 205} 206def t_addrmode_rrs2 : MemOperand, 207 ComplexPattern<i32, 2, "SelectThumbAddrModeRI5S2", []> { 208 let EncoderMethod = "getThumbAddrModeRegRegOpValue"; 209 let DecoderMethod = "DecodeThumbAddrModeRR"; 210 let PrintMethod = "printThumbAddrModeRROperand"; 211 let ParserMatchClass = t_addrmode_rr_asm_operand; 212 let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); 213} 214def t_addrmode_rrs4 : MemOperand, 215 ComplexPattern<i32, 2, "SelectThumbAddrModeRI5S4", []> { 216 let EncoderMethod = "getThumbAddrModeRegRegOpValue"; 217 let DecoderMethod = "DecodeThumbAddrModeRR"; 218 let PrintMethod = "printThumbAddrModeRROperand"; 219 let ParserMatchClass = t_addrmode_rr_asm_operand; 220 let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); 221} 222 223// t_addrmode_is4 := reg + imm5 * 4 224// 225def t_addrmode_is4_asm_operand : AsmOperandClass { let Name = "MemThumbRIs4"; } 226def t_addrmode_is4 : MemOperand, 227 ComplexPattern<i32, 2, "SelectThumbAddrModeImm5S4", []> { 228 let EncoderMethod = "getAddrModeISOpValue"; 229 let DecoderMethod = "DecodeThumbAddrModeIS"; 230 let PrintMethod = "printThumbAddrModeImm5S4Operand"; 231 let ParserMatchClass = t_addrmode_is4_asm_operand; 232 let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm); 233} 234 235// t_addrmode_is2 := reg + imm5 * 2 236// 237def t_addrmode_is2_asm_operand : AsmOperandClass { let Name = "MemThumbRIs2"; } 238def t_addrmode_is2 : MemOperand, 239 ComplexPattern<i32, 2, "SelectThumbAddrModeImm5S2", []> { 240 let EncoderMethod = "getAddrModeISOpValue"; 241 let DecoderMethod = "DecodeThumbAddrModeIS"; 242 let PrintMethod = "printThumbAddrModeImm5S2Operand"; 243 let ParserMatchClass = t_addrmode_is2_asm_operand; 244 let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm); 245} 246 247// t_addrmode_is1 := reg + imm5 248// 249def t_addrmode_is1_asm_operand : AsmOperandClass { let Name = "MemThumbRIs1"; } 250def t_addrmode_is1 : MemOperand, 251 ComplexPattern<i32, 2, "SelectThumbAddrModeImm5S1", []> { 252 let EncoderMethod = "getAddrModeISOpValue"; 253 let DecoderMethod = "DecodeThumbAddrModeIS"; 254 let PrintMethod = "printThumbAddrModeImm5S1Operand"; 255 let ParserMatchClass = t_addrmode_is1_asm_operand; 256 let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm); 257} 258 259// t_addrmode_sp := sp + imm8 * 4 260// 261// FIXME: This really shouldn't have an explicit SP operand at all. It should 262// be implicit, just like in the instruction encoding itself. 263def t_addrmode_sp_asm_operand : AsmOperandClass { let Name = "MemThumbSPI"; } 264def t_addrmode_sp : MemOperand, 265 ComplexPattern<i32, 2, "SelectThumbAddrModeSP", []> { 266 let EncoderMethod = "getAddrModeThumbSPOpValue"; 267 let DecoderMethod = "DecodeThumbAddrModeSP"; 268 let PrintMethod = "printThumbAddrModeSPOperand"; 269 let ParserMatchClass = t_addrmode_sp_asm_operand; 270 let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); 271} 272 273// Inspects parent to determine whether an or instruction can be implemented as 274// an add (i.e. whether we know overflow won't occur in the add). 275def AddLikeOrOp : ComplexPattern<i32, 1, "SelectAddLikeOr", [], 276 [SDNPWantParent]>; 277 278// Pattern to exclude immediates from matching 279def non_imm32 : PatLeaf<(i32 GPR), [{ return !isa<ConstantSDNode>(N); }]>; 280 281//===----------------------------------------------------------------------===// 282// Miscellaneous Instructions. 283// 284 285// FIXME: Marking these as hasSideEffects is necessary to prevent machine DCE 286// from removing one half of the matched pairs. That breaks PEI, which assumes 287// these will always be in pairs, and asserts if it finds otherwise. Better way? 288let Defs = [SP], Uses = [SP], hasSideEffects = 1 in { 289def tADJCALLSTACKUP : 290 PseudoInst<(outs), (ins i32imm:$amt1, i32imm:$amt2), NoItinerary, 291 [(ARMcallseq_end imm:$amt1, imm:$amt2)]>, 292 Requires<[IsThumb, IsThumb1Only]>; 293 294def tADJCALLSTACKDOWN : 295 PseudoInst<(outs), (ins i32imm:$amt, i32imm:$amt2), NoItinerary, 296 [(ARMcallseq_start imm:$amt, imm:$amt2)]>, 297 Requires<[IsThumb, IsThumb1Only]>; 298} 299 300class T1SystemEncoding<bits<8> opc> 301 : T1Encoding<0b101111> { 302 let Inst{9-8} = 0b11; 303 let Inst{7-0} = opc; 304} 305 306def tHINT : T1pI<(outs), (ins imm0_15:$imm), NoItinerary, "hint", "\t$imm", 307 [(int_arm_hint imm0_15:$imm)]>, 308 T1SystemEncoding<0x00>, 309 Requires<[IsThumb, HasV6M]> { 310 bits<4> imm; 311 let Inst{7-4} = imm; 312} 313 314// Note: When EmitPriority == 1, the alias will be used for printing 315class tHintAlias<string Asm, dag Result, bit EmitPriority = 0> : tInstAlias<Asm, Result, EmitPriority> { 316 let Predicates = [IsThumb, HasV6M]; 317} 318 319def : tHintAlias<"nop$p", (tHINT 0, pred:$p), 1>; // A8.6.110 320def : tHintAlias<"yield$p", (tHINT 1, pred:$p), 1>; // A8.6.410 321def : tHintAlias<"wfe$p", (tHINT 2, pred:$p), 1>; // A8.6.408 322def : tHintAlias<"wfi$p", (tHINT 3, pred:$p), 1>; // A8.6.409 323def : tHintAlias<"sev$p", (tHINT 4, pred:$p), 1>; // A8.6.157 324def : tInstAlias<"sevl$p", (tHINT 5, pred:$p), 1> { 325 let Predicates = [IsThumb2, HasV8]; 326} 327 328// The imm operand $val can be used by a debugger to store more information 329// about the breakpoint. 330def tBKPT : T1I<(outs), (ins imm0_255:$val), NoItinerary, "bkpt\t$val", 331 []>, 332 T1Encoding<0b101111> { 333 let Inst{9-8} = 0b10; 334 // A8.6.22 335 bits<8> val; 336 let Inst{7-0} = val; 337} 338// default immediate for breakpoint mnemonic 339def : InstAlias<"bkpt", (tBKPT 0), 0>, Requires<[IsThumb]>; 340 341def tHLT : T1I<(outs), (ins imm0_63:$val), NoItinerary, "hlt\t$val", 342 []>, T1Encoding<0b101110>, Requires<[IsThumb, HasV8]> { 343 let Inst{9-6} = 0b1010; 344 bits<6> val; 345 let Inst{5-0} = val; 346} 347 348def tSETEND : T1I<(outs), (ins setend_op:$end), NoItinerary, "setend\t$end", 349 []>, T1Encoding<0b101101>, Requires<[IsThumb, IsNotMClass]>, Deprecated<HasV8Ops> { 350 bits<1> end; 351 // A8.6.156 352 let Inst{9-5} = 0b10010; 353 let Inst{4} = 1; 354 let Inst{3} = end; 355 let Inst{2-0} = 0b000; 356} 357 358// Change Processor State is a system instruction -- for disassembly only. 359def tCPS : T1I<(outs), (ins imod_op:$imod, iflags_op:$iflags), 360 NoItinerary, "cps$imod $iflags", []>, 361 T1Misc<0b0110011> { 362 // A8.6.38 & B6.1.1 363 bit imod; 364 bits<3> iflags; 365 366 let Inst{4} = imod; 367 let Inst{3} = 0; 368 let Inst{2-0} = iflags; 369 let DecoderMethod = "DecodeThumbCPS"; 370} 371 372// For both thumb1 and thumb2. 373let isNotDuplicable = 1, isCodeGenOnly = 1 in 374def tPICADD : TIt<(outs GPR:$dst), (ins GPR:$lhs, pclabel:$cp), IIC_iALUr, "", 375 [(set GPR:$dst, (ARMpic_add GPR:$lhs, imm:$cp))]>, 376 T1Special<{0,0,?,?}>, Sched<[WriteALU]> { 377 // A8.6.6 378 bits<3> dst; 379 let Inst{6-3} = 0b1111; // Rm = pc 380 let Inst{2-0} = dst; 381} 382 383// ADD <Rd>, sp, #<imm8> 384// FIXME: This should not be marked as having side effects, and it should be 385// rematerializable. Clearing the side effect bit causes miscompilations, 386// probably because the instruction can be moved around. 387def tADDrSPi : T1pI<(outs tGPR:$dst), (ins GPRsp:$sp, t_imm0_1020s4:$imm), 388 IIC_iALUi, "add", "\t$dst, $sp, $imm", []>, 389 T1Encoding<{1,0,1,0,1,?}>, Sched<[WriteALU]> { 390 // A6.2 & A8.6.8 391 bits<3> dst; 392 bits<8> imm; 393 let Inst{10-8} = dst; 394 let Inst{7-0} = imm; 395 let DecoderMethod = "DecodeThumbAddSpecialReg"; 396} 397 398// Thumb1 frame lowering is rather fragile, we hope to be able to use 399// tADDrSPi, but we may need to insert a sequence that clobbers CPSR. 400def tADDframe : PseudoInst<(outs tGPR:$dst), (ins i32imm:$base, i32imm:$offset), 401 NoItinerary, []>, 402 Requires<[IsThumb, IsThumb1Only]> { 403 let Defs = [CPSR]; 404} 405 406// ADD sp, sp, #<imm7> 407def tADDspi : T1pIt<(outs GPRsp:$Rdn), (ins GPRsp:$Rn, t_imm0_508s4:$imm), 408 IIC_iALUi, "add", "\t$Rdn, $imm", []>, 409 T1Misc<{0,0,0,0,0,?,?}>, Sched<[WriteALU]> { 410 // A6.2.5 & A8.6.8 411 bits<7> imm; 412 let Inst{6-0} = imm; 413 let DecoderMethod = "DecodeThumbAddSPImm"; 414} 415 416// SUB sp, sp, #<imm7> 417// FIXME: The encoding and the ASM string don't match up. 418def tSUBspi : T1pIt<(outs GPRsp:$Rdn), (ins GPRsp:$Rn, t_imm0_508s4:$imm), 419 IIC_iALUi, "sub", "\t$Rdn, $imm", []>, 420 T1Misc<{0,0,0,0,1,?,?}>, Sched<[WriteALU]> { 421 // A6.2.5 & A8.6.214 422 bits<7> imm; 423 let Inst{6-0} = imm; 424 let DecoderMethod = "DecodeThumbAddSPImm"; 425} 426 427def : tInstSubst<"add${p} sp, $imm", 428 (tSUBspi SP, t_imm0_508s4_neg:$imm, pred:$p)>; 429def : tInstSubst<"add${p} sp, sp, $imm", 430 (tSUBspi SP, t_imm0_508s4_neg:$imm, pred:$p)>; 431 432// Can optionally specify SP as a three operand instruction. 433def : tInstAlias<"add${p} sp, sp, $imm", 434 (tADDspi SP, t_imm0_508s4:$imm, pred:$p)>; 435def : tInstAlias<"sub${p} sp, sp, $imm", 436 (tSUBspi SP, t_imm0_508s4:$imm, pred:$p)>; 437 438// ADD <Rm>, sp 439def tADDrSP : T1pI<(outs GPR:$Rdn), (ins GPRsp:$sp, GPR:$Rn), IIC_iALUr, 440 "add", "\t$Rdn, $sp, $Rn", []>, 441 T1Special<{0,0,?,?}>, Sched<[WriteALU]> { 442 // A8.6.9 Encoding T1 443 bits<4> Rdn; 444 let Inst{7} = Rdn{3}; 445 let Inst{6-3} = 0b1101; 446 let Inst{2-0} = Rdn{2-0}; 447 let DecoderMethod = "DecodeThumbAddSPReg"; 448} 449 450// ADD sp, <Rm> 451def tADDspr : T1pIt<(outs GPRsp:$Rdn), (ins GPRsp:$Rn, GPR:$Rm), IIC_iALUr, 452 "add", "\t$Rdn, $Rm", []>, 453 T1Special<{0,0,?,?}>, Sched<[WriteALU]> { 454 // A8.6.9 Encoding T2 455 bits<4> Rm; 456 let Inst{7} = 1; 457 let Inst{6-3} = Rm; 458 let Inst{2-0} = 0b101; 459 let DecoderMethod = "DecodeThumbAddSPReg"; 460} 461 462//===----------------------------------------------------------------------===// 463// Control Flow Instructions. 464// 465 466// Indirect branches 467let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { 468 def tBX : TI<(outs), (ins GPR:$Rm, pred:$p), IIC_Br, "bx${p}\t$Rm", []>, 469 T1Special<{1,1,0,?}>, Sched<[WriteBr]> { 470 // A6.2.3 & A8.6.25 471 bits<4> Rm; 472 let Inst{6-3} = Rm; 473 let Inst{2-0} = 0b000; 474 let Unpredictable{2-0} = 0b111; 475 } 476 def tBXNS : TI<(outs), (ins GPR:$Rm, pred:$p), IIC_Br, "bxns${p}\t$Rm", []>, 477 Requires<[IsThumb, Has8MSecExt]>, 478 T1Special<{1,1,0,?}>, Sched<[WriteBr]> { 479 bits<4> Rm; 480 let Inst{6-3} = Rm; 481 let Inst{2-0} = 0b100; 482 let Unpredictable{1-0} = 0b11; 483 } 484} 485 486let isReturn = 1, isTerminator = 1, isBarrier = 1 in { 487 def tBX_RET : tPseudoExpand<(outs), (ins pred:$p), 2, IIC_Br, 488 [(ARMretflag)], (tBX LR, pred:$p)>, Sched<[WriteBr]>; 489 490 // Alternative return instruction used by vararg functions. 491 def tBX_RET_vararg : tPseudoExpand<(outs), (ins tGPR:$Rm, pred:$p), 492 2, IIC_Br, [], 493 (tBX GPR:$Rm, pred:$p)>, Sched<[WriteBr]>; 494} 495 496// All calls clobber the non-callee saved registers. SP is marked as a use to 497// prevent stack-pointer assignments that appear immediately before calls from 498// potentially appearing dead. 499let isCall = 1, 500 Defs = [LR], Uses = [SP] in { 501 // Also used for Thumb2 502 def tBL : TIx2<0b11110, 0b11, 1, 503 (outs), (ins pred:$p, thumb_bl_target:$func), IIC_Br, 504 "bl${p}\t$func", 505 [(ARMcall tglobaladdr:$func)]>, 506 Requires<[IsThumb]>, Sched<[WriteBrL]> { 507 bits<24> func; 508 let Inst{26} = func{23}; 509 let Inst{25-16} = func{20-11}; 510 let Inst{13} = func{22}; 511 let Inst{11} = func{21}; 512 let Inst{10-0} = func{10-0}; 513 } 514 515 // ARMv5T and above, also used for Thumb2 516 def tBLXi : TIx2<0b11110, 0b11, 0, 517 (outs), (ins pred:$p, thumb_blx_target:$func), IIC_Br, 518 "blx${p}\t$func", []>, 519 Requires<[IsThumb, HasV5T, IsNotMClass]>, Sched<[WriteBrL]> { 520 bits<24> func; 521 let Inst{26} = func{23}; 522 let Inst{25-16} = func{20-11}; 523 let Inst{13} = func{22}; 524 let Inst{11} = func{21}; 525 let Inst{10-1} = func{10-1}; 526 let Inst{0} = 0; // func{0} is assumed zero 527 } 528 529 // Also used for Thumb2 530 def tBLXr : TI<(outs), (ins pred:$p, GPR:$func), IIC_Br, 531 "blx${p}\t$func", 532 [(ARMcall GPR:$func)]>, 533 Requires<[IsThumb, HasV5T]>, 534 T1Special<{1,1,1,?}>, Sched<[WriteBrL]> { // A6.2.3 & A8.6.24; 535 bits<4> func; 536 let Inst{6-3} = func; 537 let Inst{2-0} = 0b000; 538 } 539 540 // ARMv8-M Security Extensions 541 def tBLXNSr : TI<(outs), (ins pred:$p, GPRnopc:$func), IIC_Br, 542 "blxns${p}\t$func", []>, 543 Requires<[IsThumb, Has8MSecExt]>, 544 T1Special<{1,1,1,?}>, Sched<[WriteBrL]> { 545 bits<4> func; 546 let Inst{6-3} = func; 547 let Inst{2-0} = 0b100; 548 let Unpredictable{1-0} = 0b11; 549 } 550 551 // ARMv4T 552 def tBX_CALL : tPseudoInst<(outs), (ins tGPR:$func), 553 4, IIC_Br, 554 [(ARMcall_nolink tGPR:$func)]>, 555 Requires<[IsThumb, IsThumb1Only]>, Sched<[WriteBr]>; 556} 557 558let isBranch = 1, isTerminator = 1, isBarrier = 1 in { 559 let isPredicable = 1 in 560 def tB : T1pI<(outs), (ins t_brtarget:$target), IIC_Br, 561 "b", "\t$target", [(br bb:$target)]>, 562 T1Encoding<{1,1,1,0,0,?}>, Sched<[WriteBr]> { 563 bits<11> target; 564 let Inst{10-0} = target; 565 let AsmMatchConverter = "cvtThumbBranches"; 566 } 567 568 // Far jump 569 // Just a pseudo for a tBL instruction. Needed to let regalloc know about 570 // the clobber of LR. 571 let Defs = [LR] in 572 def tBfar : tPseudoExpand<(outs), (ins thumb_bl_target:$target, pred:$p), 573 4, IIC_Br, [], 574 (tBL pred:$p, thumb_bl_target:$target)>, 575 Sched<[WriteBrTbl]>; 576 577 def tBR_JTr : tPseudoInst<(outs), 578 (ins tGPR:$target, i32imm:$jt), 579 0, IIC_Br, 580 [(ARMbrjt tGPR:$target, tjumptable:$jt)]>, 581 Sched<[WriteBrTbl]> { 582 let Size = 2; 583 list<Predicate> Predicates = [IsThumb, IsThumb1Only]; 584 } 585} 586 587// FIXME: should be able to write a pattern for ARMBrcond, but can't use 588// a two-value operand where a dag node expects two operands. :( 589let isBranch = 1, isTerminator = 1 in 590 def tBcc : T1I<(outs), (ins thumb_bcc_target:$target, pred:$p), IIC_Br, 591 "b${p}\t$target", 592 [/*(ARMbrcond bb:$target, imm:$cc)*/]>, 593 T1BranchCond<{1,1,0,1}>, Sched<[WriteBr]> { 594 bits<4> p; 595 bits<8> target; 596 let Inst{11-8} = p; 597 let Inst{7-0} = target; 598 let AsmMatchConverter = "cvtThumbBranches"; 599} 600 601 602// Tail calls 603let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in { 604 // IOS versions. 605 let Uses = [SP] in { 606 def tTAILJMPr : tPseudoExpand<(outs), (ins tcGPR:$dst), 607 4, IIC_Br, [], 608 (tBX GPR:$dst, (ops 14, zero_reg))>, 609 Requires<[IsThumb]>, Sched<[WriteBr]>; 610 } 611 // tTAILJMPd: MachO version uses a Thumb2 branch (no Thumb1 tail calls 612 // on MachO), so it's in ARMInstrThumb2.td. 613 // Non-MachO version: 614 let Uses = [SP] in { 615 def tTAILJMPdND : tPseudoExpand<(outs), 616 (ins t_brtarget:$dst, pred:$p), 617 4, IIC_Br, [], 618 (tB t_brtarget:$dst, pred:$p)>, 619 Requires<[IsThumb, IsNotMachO]>, Sched<[WriteBr]>; 620 } 621} 622 623 624// A8.6.218 Supervisor Call (Software Interrupt) 625// A8.6.16 B: Encoding T1 626// If Inst{11-8} == 0b1111 then SEE SVC 627let isCall = 1, Uses = [SP] in 628def tSVC : T1pI<(outs), (ins imm0_255:$imm), IIC_Br, 629 "svc", "\t$imm", []>, Encoding16, Sched<[WriteBr]> { 630 bits<8> imm; 631 let Inst{15-12} = 0b1101; 632 let Inst{11-8} = 0b1111; 633 let Inst{7-0} = imm; 634} 635 636// The assembler uses 0xDEFE for a trap instruction. 637let isBarrier = 1, isTerminator = 1 in 638def tTRAP : TI<(outs), (ins), IIC_Br, 639 "trap", [(trap)]>, Encoding16, Sched<[WriteBr]> { 640 let Inst = 0xdefe; 641} 642 643//===----------------------------------------------------------------------===// 644// Load Store Instructions. 645// 646 647// PC-relative loads need to be matched first as constant pool accesses need to 648// always be PC-relative. We do this using AddedComplexity, as the pattern is 649// simpler than the patterns of the other load instructions. 650let canFoldAsLoad = 1, isReMaterializable = 1, AddedComplexity = 10 in 651def tLDRpci : T1pIs<(outs tGPR:$Rt), (ins t_addrmode_pc:$addr), IIC_iLoad_i, 652 "ldr", "\t$Rt, $addr", 653 [(set tGPR:$Rt, (load (ARMWrapper tconstpool:$addr)))]>, 654 T1Encoding<{0,1,0,0,1,?}> { 655 // A6.2 & A8.6.59 656 bits<3> Rt; 657 bits<8> addr; 658 let Inst{10-8} = Rt; 659 let Inst{7-0} = addr; 660} 661 662// SP-relative loads should be matched before standard immediate-offset loads as 663// it means we avoid having to move SP to another register. 664let canFoldAsLoad = 1 in 665def tLDRspi : T1pIs<(outs tGPR:$Rt), (ins t_addrmode_sp:$addr), IIC_iLoad_i, 666 "ldr", "\t$Rt, $addr", 667 [(set tGPR:$Rt, (load t_addrmode_sp:$addr))]>, 668 T1LdStSP<{1,?,?}> { 669 bits<3> Rt; 670 bits<8> addr; 671 let Inst{10-8} = Rt; 672 let Inst{7-0} = addr; 673} 674 675// Loads: reg/reg and reg/imm5 676let canFoldAsLoad = 1, isReMaterializable = 1 in 677multiclass thumb_ld_rr_ri_enc<bits<3> reg_opc, bits<4> imm_opc, 678 Operand AddrMode_r, Operand AddrMode_i, 679 AddrMode am, InstrItinClass itin_r, 680 InstrItinClass itin_i, string asm, 681 PatFrag opnode> { 682 // Immediate-offset loads should be matched before register-offset loads as 683 // when the offset is a constant it's simpler to first check if it fits in the 684 // immediate offset field then fall back to register-offset if it doesn't. 685 def i : // reg/imm5 686 T1pILdStEncodeImm<imm_opc, 1 /* Load */, 687 (outs tGPR:$Rt), (ins AddrMode_i:$addr), 688 am, itin_i, asm, "\t$Rt, $addr", 689 [(set tGPR:$Rt, (opnode AddrMode_i:$addr))]>; 690 // Register-offset loads are matched last. 691 def r : // reg/reg 692 T1pILdStEncode<reg_opc, 693 (outs tGPR:$Rt), (ins AddrMode_r:$addr), 694 am, itin_r, asm, "\t$Rt, $addr", 695 [(set tGPR:$Rt, (opnode AddrMode_r:$addr))]>; 696} 697// Stores: reg/reg and reg/imm5 698multiclass thumb_st_rr_ri_enc<bits<3> reg_opc, bits<4> imm_opc, 699 Operand AddrMode_r, Operand AddrMode_i, 700 AddrMode am, InstrItinClass itin_r, 701 InstrItinClass itin_i, string asm, 702 PatFrag opnode> { 703 def i : // reg/imm5 704 T1pILdStEncodeImm<imm_opc, 0 /* Store */, 705 (outs), (ins tGPR:$Rt, AddrMode_i:$addr), 706 am, itin_i, asm, "\t$Rt, $addr", 707 [(opnode tGPR:$Rt, AddrMode_i:$addr)]>; 708 def r : // reg/reg 709 T1pILdStEncode<reg_opc, 710 (outs), (ins tGPR:$Rt, AddrMode_r:$addr), 711 am, itin_r, asm, "\t$Rt, $addr", 712 [(opnode tGPR:$Rt, AddrMode_r:$addr)]>; 713} 714 715// A8.6.57 & A8.6.60 716defm tLDR : thumb_ld_rr_ri_enc<0b100, 0b0110, t_addrmode_rr, 717 t_addrmode_is4, AddrModeT1_4, 718 IIC_iLoad_r, IIC_iLoad_i, "ldr", 719 load>; 720 721// A8.6.64 & A8.6.61 722defm tLDRB : thumb_ld_rr_ri_enc<0b110, 0b0111, t_addrmode_rr, 723 t_addrmode_is1, AddrModeT1_1, 724 IIC_iLoad_bh_r, IIC_iLoad_bh_i, "ldrb", 725 zextloadi8>; 726 727// A8.6.76 & A8.6.73 728defm tLDRH : thumb_ld_rr_ri_enc<0b101, 0b1000, t_addrmode_rr, 729 t_addrmode_is2, AddrModeT1_2, 730 IIC_iLoad_bh_r, IIC_iLoad_bh_i, "ldrh", 731 zextloadi16>; 732 733let AddedComplexity = 10 in 734def tLDRSB : // A8.6.80 735 T1pILdStEncode<0b011, (outs tGPR:$Rt), (ins t_addrmode_rr:$addr), 736 AddrModeT1_1, IIC_iLoad_bh_r, 737 "ldrsb", "\t$Rt, $addr", 738 [(set tGPR:$Rt, (sextloadi8 t_addrmode_rr:$addr))]>; 739 740let AddedComplexity = 10 in 741def tLDRSH : // A8.6.84 742 T1pILdStEncode<0b111, (outs tGPR:$Rt), (ins t_addrmode_rr:$addr), 743 AddrModeT1_2, IIC_iLoad_bh_r, 744 "ldrsh", "\t$Rt, $addr", 745 [(set tGPR:$Rt, (sextloadi16 t_addrmode_rr:$addr))]>; 746 747 748def tSTRspi : T1pIs<(outs), (ins tGPR:$Rt, t_addrmode_sp:$addr), IIC_iStore_i, 749 "str", "\t$Rt, $addr", 750 [(store tGPR:$Rt, t_addrmode_sp:$addr)]>, 751 T1LdStSP<{0,?,?}> { 752 bits<3> Rt; 753 bits<8> addr; 754 let Inst{10-8} = Rt; 755 let Inst{7-0} = addr; 756} 757 758// A8.6.194 & A8.6.192 759defm tSTR : thumb_st_rr_ri_enc<0b000, 0b0110, t_addrmode_rr, 760 t_addrmode_is4, AddrModeT1_4, 761 IIC_iStore_r, IIC_iStore_i, "str", 762 store>; 763 764// A8.6.197 & A8.6.195 765defm tSTRB : thumb_st_rr_ri_enc<0b010, 0b0111, t_addrmode_rr, 766 t_addrmode_is1, AddrModeT1_1, 767 IIC_iStore_bh_r, IIC_iStore_bh_i, "strb", 768 truncstorei8>; 769 770// A8.6.207 & A8.6.205 771defm tSTRH : thumb_st_rr_ri_enc<0b001, 0b1000, t_addrmode_rr, 772 t_addrmode_is2, AddrModeT1_2, 773 IIC_iStore_bh_r, IIC_iStore_bh_i, "strh", 774 truncstorei16>; 775 776 777//===----------------------------------------------------------------------===// 778// Load / store multiple Instructions. 779// 780 781// These require base address to be written back or one of the loaded regs. 782let hasSideEffects = 0 in { 783 784let mayLoad = 1, hasExtraDefRegAllocReq = 1 in 785def tLDMIA : T1I<(outs), (ins tGPR:$Rn, pred:$p, reglist:$regs, variable_ops), 786 IIC_iLoad_m, "ldm${p}\t$Rn, $regs", []>, T1Encoding<{1,1,0,0,1,?}> { 787 bits<3> Rn; 788 bits<8> regs; 789 let Inst{10-8} = Rn; 790 let Inst{7-0} = regs; 791} 792 793// Writeback version is just a pseudo, as there's no encoding difference. 794// Writeback happens iff the base register is not in the destination register 795// list. 796let mayLoad = 1, hasExtraDefRegAllocReq = 1 in 797def tLDMIA_UPD : 798 InstTemplate<AddrModeNone, 0, IndexModeNone, Pseudo, GenericDomain, 799 "$Rn = $wb", IIC_iLoad_mu>, 800 PseudoInstExpansion<(tLDMIA tGPR:$Rn, pred:$p, reglist:$regs)> { 801 let Size = 2; 802 let OutOperandList = (outs GPR:$wb); 803 let InOperandList = (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops); 804 let Pattern = []; 805 let isCodeGenOnly = 1; 806 let isPseudo = 1; 807 list<Predicate> Predicates = [IsThumb]; 808} 809 810// There is no non-writeback version of STM for Thumb. 811let mayStore = 1, hasExtraSrcRegAllocReq = 1 in 812def tSTMIA_UPD : Thumb1I<(outs GPR:$wb), 813 (ins tGPR:$Rn, pred:$p, reglist:$regs, variable_ops), 814 AddrModeNone, 2, IIC_iStore_mu, 815 "stm${p}\t$Rn!, $regs", "$Rn = $wb", []>, 816 T1Encoding<{1,1,0,0,0,?}> { 817 bits<3> Rn; 818 bits<8> regs; 819 let Inst{10-8} = Rn; 820 let Inst{7-0} = regs; 821} 822 823} // hasSideEffects 824 825def : InstAlias<"ldm${p} $Rn!, $regs", 826 (tLDMIA tGPR:$Rn, pred:$p, reglist:$regs), 0>, 827 Requires<[IsThumb, IsThumb1Only]>; 828 829let mayLoad = 1, Uses = [SP], Defs = [SP], hasExtraDefRegAllocReq = 1 in 830def tPOP : T1I<(outs), (ins pred:$p, reglist:$regs, variable_ops), 831 IIC_iPop, 832 "pop${p}\t$regs", []>, 833 T1Misc<{1,1,0,?,?,?,?}> { 834 bits<16> regs; 835 let Inst{8} = regs{15}; 836 let Inst{7-0} = regs{7-0}; 837} 838 839let mayStore = 1, Uses = [SP], Defs = [SP], hasExtraSrcRegAllocReq = 1 in 840def tPUSH : T1I<(outs), (ins pred:$p, reglist:$regs, variable_ops), 841 IIC_iStore_m, 842 "push${p}\t$regs", []>, 843 T1Misc<{0,1,0,?,?,?,?}> { 844 bits<16> regs; 845 let Inst{8} = regs{14}; 846 let Inst{7-0} = regs{7-0}; 847} 848 849//===----------------------------------------------------------------------===// 850// Arithmetic Instructions. 851// 852 853// Helper classes for encoding T1pI patterns: 854class T1pIDPEncode<bits<4> opA, dag oops, dag iops, InstrItinClass itin, 855 string opc, string asm, list<dag> pattern> 856 : T1pI<oops, iops, itin, opc, asm, pattern>, 857 T1DataProcessing<opA> { 858 bits<3> Rm; 859 bits<3> Rn; 860 let Inst{5-3} = Rm; 861 let Inst{2-0} = Rn; 862} 863class T1pIMiscEncode<bits<7> opA, dag oops, dag iops, InstrItinClass itin, 864 string opc, string asm, list<dag> pattern> 865 : T1pI<oops, iops, itin, opc, asm, pattern>, 866 T1Misc<opA> { 867 bits<3> Rm; 868 bits<3> Rd; 869 let Inst{5-3} = Rm; 870 let Inst{2-0} = Rd; 871} 872 873// Helper classes for encoding T1sI patterns: 874class T1sIDPEncode<bits<4> opA, dag oops, dag iops, InstrItinClass itin, 875 string opc, string asm, list<dag> pattern> 876 : T1sI<oops, iops, itin, opc, asm, pattern>, 877 T1DataProcessing<opA> { 878 bits<3> Rd; 879 bits<3> Rn; 880 let Inst{5-3} = Rn; 881 let Inst{2-0} = Rd; 882} 883class T1sIGenEncode<bits<5> opA, dag oops, dag iops, InstrItinClass itin, 884 string opc, string asm, list<dag> pattern> 885 : T1sI<oops, iops, itin, opc, asm, pattern>, 886 T1General<opA> { 887 bits<3> Rm; 888 bits<3> Rn; 889 bits<3> Rd; 890 let Inst{8-6} = Rm; 891 let Inst{5-3} = Rn; 892 let Inst{2-0} = Rd; 893} 894class T1sIGenEncodeImm<bits<5> opA, dag oops, dag iops, InstrItinClass itin, 895 string opc, string asm, list<dag> pattern> 896 : T1sI<oops, iops, itin, opc, asm, pattern>, 897 T1General<opA> { 898 bits<3> Rd; 899 bits<3> Rm; 900 let Inst{5-3} = Rm; 901 let Inst{2-0} = Rd; 902} 903 904// Helper classes for encoding T1sIt patterns: 905class T1sItDPEncode<bits<4> opA, dag oops, dag iops, InstrItinClass itin, 906 string opc, string asm, list<dag> pattern> 907 : T1sIt<oops, iops, itin, opc, asm, pattern>, 908 T1DataProcessing<opA> { 909 bits<3> Rdn; 910 bits<3> Rm; 911 let Inst{5-3} = Rm; 912 let Inst{2-0} = Rdn; 913} 914class T1sItGenEncodeImm<bits<5> opA, dag oops, dag iops, InstrItinClass itin, 915 string opc, string asm, list<dag> pattern> 916 : T1sIt<oops, iops, itin, opc, asm, pattern>, 917 T1General<opA> { 918 bits<3> Rdn; 919 bits<8> imm8; 920 let Inst{10-8} = Rdn; 921 let Inst{7-0} = imm8; 922} 923 924let isAdd = 1 in { 925 // Add with carry register 926 let isCommutable = 1, Uses = [CPSR] in 927 def tADC : // A8.6.2 928 T1sItDPEncode<0b0101, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), IIC_iALUr, 929 "adc", "\t$Rdn, $Rm", 930 []>, Sched<[WriteALU]>; 931 932 // Add immediate 933 def tADDi3 : // A8.6.4 T1 934 T1sIGenEncodeImm<0b01110, (outs tGPR:$Rd), (ins tGPR:$Rm, imm0_7:$imm3), 935 IIC_iALUi, 936 "add", "\t$Rd, $Rm, $imm3", 937 [(set tGPR:$Rd, (add tGPR:$Rm, imm0_7:$imm3))]>, 938 Sched<[WriteALU]> { 939 bits<3> imm3; 940 let Inst{8-6} = imm3; 941 } 942 943 def tADDi8 : // A8.6.4 T2 944 T1sItGenEncodeImm<{1,1,0,?,?}, (outs tGPR:$Rdn), 945 (ins tGPR:$Rn, imm0_255:$imm8), IIC_iALUi, 946 "add", "\t$Rdn, $imm8", 947 [(set tGPR:$Rdn, (add tGPR:$Rn, imm8_255:$imm8))]>, 948 Sched<[WriteALU]>; 949 950 // Add register 951 let isCommutable = 1 in 952 def tADDrr : // A8.6.6 T1 953 T1sIGenEncode<0b01100, (outs tGPR:$Rd), (ins tGPR:$Rn, tGPR:$Rm), 954 IIC_iALUr, 955 "add", "\t$Rd, $Rn, $Rm", 956 [(set tGPR:$Rd, (add tGPR:$Rn, tGPR:$Rm))]>, Sched<[WriteALU]>; 957 958 /// Similar to the above except these set the 's' bit so the 959 /// instruction modifies the CPSR register. 960 /// 961 /// These opcodes will be converted to the real non-S opcodes by 962 /// AdjustInstrPostInstrSelection after giving then an optional CPSR operand. 963 let hasPostISelHook = 1, Defs = [CPSR] in { 964 let isCommutable = 1, Uses = [CPSR] in 965 def tADCS : tPseudoInst<(outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 966 2, IIC_iALUr, 967 [(set tGPR:$Rdn, CPSR, (ARMadde tGPR:$Rn, tGPR:$Rm, 968 CPSR))]>, 969 Requires<[IsThumb1Only]>, 970 Sched<[WriteALU]>; 971 972 def tADDSi3 : tPseudoInst<(outs tGPR:$Rd), (ins tGPR:$Rm, imm0_7:$imm3), 973 2, IIC_iALUi, 974 [(set tGPR:$Rd, CPSR, (ARMaddc tGPR:$Rm, 975 imm0_7:$imm3))]>, 976 Requires<[IsThumb1Only]>, 977 Sched<[WriteALU]>; 978 979 def tADDSi8 : tPseudoInst<(outs tGPR:$Rdn), (ins tGPR:$Rn, imm0_255:$imm8), 980 2, IIC_iALUi, 981 [(set tGPR:$Rdn, CPSR, (ARMaddc tGPR:$Rn, 982 imm8_255:$imm8))]>, 983 Requires<[IsThumb1Only]>, 984 Sched<[WriteALU]>; 985 986 let isCommutable = 1 in 987 def tADDSrr : tPseudoInst<(outs tGPR:$Rd), (ins tGPR:$Rn, tGPR:$Rm), 988 2, IIC_iALUr, 989 [(set tGPR:$Rd, CPSR, (ARMaddc tGPR:$Rn, 990 tGPR:$Rm))]>, 991 Requires<[IsThumb1Only]>, 992 Sched<[WriteALU]>; 993 } 994 995 let hasSideEffects = 0 in 996 def tADDhirr : T1pIt<(outs GPR:$Rdn), (ins GPR:$Rn, GPR:$Rm), IIC_iALUr, 997 "add", "\t$Rdn, $Rm", []>, 998 T1Special<{0,0,?,?}>, Sched<[WriteALU]> { 999 // A8.6.6 T2 1000 bits<4> Rdn; 1001 bits<4> Rm; 1002 let Inst{7} = Rdn{3}; 1003 let Inst{6-3} = Rm; 1004 let Inst{2-0} = Rdn{2-0}; 1005 } 1006} 1007 1008// Thumb has more flexible short encodings for ADD than ORR, so use those where 1009// possible. 1010def : T1Pat<(or AddLikeOrOp:$Rn, imm0_7:$imm), (tADDi3 $Rn, imm0_7:$imm)>; 1011 1012def : T1Pat<(or AddLikeOrOp:$Rn, imm8_255:$imm), (tADDi8 $Rn, imm8_255:$imm)>; 1013 1014def : T1Pat<(or AddLikeOrOp:$Rn, tGPR:$Rm), (tADDrr $Rn, $Rm)>; 1015 1016 1017def : tInstAlias <"add${s}${p} $Rdn, $Rm", 1018 (tADDrr tGPR:$Rdn,s_cc_out:$s, tGPR:$Rdn, tGPR:$Rm, pred:$p)>; 1019 1020def : tInstSubst<"sub${s}${p} $rd, $rn, $imm", 1021 (tADDi3 tGPR:$rd, s_cc_out:$s, tGPR:$rn, mod_imm1_7_neg:$imm, pred:$p)>; 1022def : tInstSubst<"sub${s}${p} $rdn, $imm", 1023 (tADDi8 tGPR:$rdn, s_cc_out:$s, mod_imm8_255_neg:$imm, pred:$p)>; 1024 1025 1026// AND register 1027let isCommutable = 1 in 1028def tAND : // A8.6.12 1029 T1sItDPEncode<0b0000, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 1030 IIC_iBITr, 1031 "and", "\t$Rdn, $Rm", 1032 [(set tGPR:$Rdn, (and tGPR:$Rn, tGPR:$Rm))]>, Sched<[WriteALU]>; 1033 1034// ASR immediate 1035def tASRri : // A8.6.14 1036 T1sIGenEncodeImm<{0,1,0,?,?}, (outs tGPR:$Rd), (ins tGPR:$Rm, imm_sr:$imm5), 1037 IIC_iMOVsi, 1038 "asr", "\t$Rd, $Rm, $imm5", 1039 [(set tGPR:$Rd, (sra tGPR:$Rm, (i32 imm_sr:$imm5)))]>, 1040 Sched<[WriteALU]> { 1041 bits<5> imm5; 1042 let Inst{10-6} = imm5; 1043} 1044 1045// ASR register 1046def tASRrr : // A8.6.15 1047 T1sItDPEncode<0b0100, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 1048 IIC_iMOVsr, 1049 "asr", "\t$Rdn, $Rm", 1050 [(set tGPR:$Rdn, (sra tGPR:$Rn, tGPR:$Rm))]>, Sched<[WriteALU]>; 1051 1052// BIC register 1053def tBIC : // A8.6.20 1054 T1sItDPEncode<0b1110, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 1055 IIC_iBITr, 1056 "bic", "\t$Rdn, $Rm", 1057 [(set tGPR:$Rdn, (and tGPR:$Rn, (not tGPR:$Rm)))]>, 1058 Sched<[WriteALU]>; 1059 1060// CMN register 1061let isCompare = 1, Defs = [CPSR] in { 1062//FIXME: Disable CMN, as CCodes are backwards from compare expectations 1063// Compare-to-zero still works out, just not the relationals 1064//def tCMN : // A8.6.33 1065// T1pIDPEncode<0b1011, (outs), (ins tGPR:$lhs, tGPR:$rhs), 1066// IIC_iCMPr, 1067// "cmn", "\t$lhs, $rhs", 1068// [(ARMcmp tGPR:$lhs, (ineg tGPR:$rhs))]>; 1069 1070def tCMNz : // A8.6.33 1071 T1pIDPEncode<0b1011, (outs), (ins tGPR:$Rn, tGPR:$Rm), 1072 IIC_iCMPr, 1073 "cmn", "\t$Rn, $Rm", 1074 [(ARMcmpZ tGPR:$Rn, (ineg tGPR:$Rm))]>, Sched<[WriteCMP]>; 1075 1076} // isCompare = 1, Defs = [CPSR] 1077 1078// CMP immediate 1079let isCompare = 1, Defs = [CPSR] in { 1080def tCMPi8 : T1pI<(outs), (ins tGPR:$Rn, imm0_255:$imm8), IIC_iCMPi, 1081 "cmp", "\t$Rn, $imm8", 1082 [(ARMcmp tGPR:$Rn, imm0_255:$imm8)]>, 1083 T1General<{1,0,1,?,?}>, Sched<[WriteCMP]> { 1084 // A8.6.35 1085 bits<3> Rn; 1086 bits<8> imm8; 1087 let Inst{10-8} = Rn; 1088 let Inst{7-0} = imm8; 1089} 1090 1091// CMP register 1092def tCMPr : // A8.6.36 T1 1093 T1pIDPEncode<0b1010, (outs), (ins tGPR:$Rn, tGPR:$Rm), 1094 IIC_iCMPr, 1095 "cmp", "\t$Rn, $Rm", 1096 [(ARMcmp tGPR:$Rn, tGPR:$Rm)]>, Sched<[WriteCMP]>; 1097 1098def tCMPhir : T1pI<(outs), (ins GPR:$Rn, GPR:$Rm), IIC_iCMPr, 1099 "cmp", "\t$Rn, $Rm", []>, 1100 T1Special<{0,1,?,?}>, Sched<[WriteCMP]> { 1101 // A8.6.36 T2 1102 bits<4> Rm; 1103 bits<4> Rn; 1104 let Inst{7} = Rn{3}; 1105 let Inst{6-3} = Rm; 1106 let Inst{2-0} = Rn{2-0}; 1107} 1108} // isCompare = 1, Defs = [CPSR] 1109 1110 1111// XOR register 1112let isCommutable = 1 in 1113def tEOR : // A8.6.45 1114 T1sItDPEncode<0b0001, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 1115 IIC_iBITr, 1116 "eor", "\t$Rdn, $Rm", 1117 [(set tGPR:$Rdn, (xor tGPR:$Rn, tGPR:$Rm))]>, Sched<[WriteALU]>; 1118 1119// LSL immediate 1120def tLSLri : // A8.6.88 1121 T1sIGenEncodeImm<{0,0,0,?,?}, (outs tGPR:$Rd), (ins tGPR:$Rm, imm0_31:$imm5), 1122 IIC_iMOVsi, 1123 "lsl", "\t$Rd, $Rm, $imm5", 1124 [(set tGPR:$Rd, (shl tGPR:$Rm, (i32 imm:$imm5)))]>, 1125 Sched<[WriteALU]> { 1126 bits<5> imm5; 1127 let Inst{10-6} = imm5; 1128} 1129 1130// LSL register 1131def tLSLrr : // A8.6.89 1132 T1sItDPEncode<0b0010, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 1133 IIC_iMOVsr, 1134 "lsl", "\t$Rdn, $Rm", 1135 [(set tGPR:$Rdn, (shl tGPR:$Rn, tGPR:$Rm))]>, Sched<[WriteALU]>; 1136 1137// LSR immediate 1138def tLSRri : // A8.6.90 1139 T1sIGenEncodeImm<{0,0,1,?,?}, (outs tGPR:$Rd), (ins tGPR:$Rm, imm_sr:$imm5), 1140 IIC_iMOVsi, 1141 "lsr", "\t$Rd, $Rm, $imm5", 1142 [(set tGPR:$Rd, (srl tGPR:$Rm, (i32 imm_sr:$imm5)))]>, 1143 Sched<[WriteALU]> { 1144 bits<5> imm5; 1145 let Inst{10-6} = imm5; 1146} 1147 1148// LSR register 1149def tLSRrr : // A8.6.91 1150 T1sItDPEncode<0b0011, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 1151 IIC_iMOVsr, 1152 "lsr", "\t$Rdn, $Rm", 1153 [(set tGPR:$Rdn, (srl tGPR:$Rn, tGPR:$Rm))]>, Sched<[WriteALU]>; 1154 1155// Move register 1156let isMoveImm = 1 in 1157def tMOVi8 : T1sI<(outs tGPR:$Rd), (ins imm0_255:$imm8), IIC_iMOVi, 1158 "mov", "\t$Rd, $imm8", 1159 [(set tGPR:$Rd, imm0_255:$imm8)]>, 1160 T1General<{1,0,0,?,?}>, Sched<[WriteALU]> { 1161 // A8.6.96 1162 bits<3> Rd; 1163 bits<8> imm8; 1164 let Inst{10-8} = Rd; 1165 let Inst{7-0} = imm8; 1166} 1167// Because we have an explicit tMOVSr below, we need an alias to handle 1168// the immediate "movs" form here. Blech. 1169def : tInstAlias <"movs $Rdn, $imm", 1170 (tMOVi8 tGPR:$Rdn, CPSR, imm0_255:$imm, 14, 0)>; 1171 1172// A7-73: MOV(2) - mov setting flag. 1173 1174let hasSideEffects = 0, isMoveReg = 1 in { 1175def tMOVr : Thumb1pI<(outs GPR:$Rd), (ins GPR:$Rm), AddrModeNone, 1176 2, IIC_iMOVr, 1177 "mov", "\t$Rd, $Rm", "", []>, 1178 T1Special<{1,0,?,?}>, Sched<[WriteALU]> { 1179 // A8.6.97 1180 bits<4> Rd; 1181 bits<4> Rm; 1182 let Inst{7} = Rd{3}; 1183 let Inst{6-3} = Rm; 1184 let Inst{2-0} = Rd{2-0}; 1185} 1186let Defs = [CPSR] in 1187def tMOVSr : T1I<(outs tGPR:$Rd), (ins tGPR:$Rm), IIC_iMOVr, 1188 "movs\t$Rd, $Rm", []>, Encoding16, Sched<[WriteALU]> { 1189 // A8.6.97 1190 bits<3> Rd; 1191 bits<3> Rm; 1192 let Inst{15-6} = 0b0000000000; 1193 let Inst{5-3} = Rm; 1194 let Inst{2-0} = Rd; 1195} 1196} // hasSideEffects 1197 1198// Multiply register 1199let isCommutable = 1 in 1200def tMUL : // A8.6.105 T1 1201 Thumb1sI<(outs tGPR:$Rd), (ins tGPR:$Rn, tGPR:$Rm), AddrModeNone, 2, 1202 IIC_iMUL32, "mul", "\t$Rd, $Rn, $Rm", "$Rm = $Rd", 1203 [(set tGPR:$Rd, (mul tGPR:$Rn, tGPR:$Rm))]>, 1204 T1DataProcessing<0b1101> { 1205 bits<3> Rd; 1206 bits<3> Rn; 1207 let Inst{5-3} = Rn; 1208 let Inst{2-0} = Rd; 1209 let AsmMatchConverter = "cvtThumbMultiply"; 1210} 1211 1212def :tInstAlias<"mul${s}${p} $Rdm, $Rn", (tMUL tGPR:$Rdm, s_cc_out:$s, tGPR:$Rn, 1213 pred:$p)>; 1214 1215// Move inverse register 1216def tMVN : // A8.6.107 1217 T1sIDPEncode<0b1111, (outs tGPR:$Rd), (ins tGPR:$Rn), IIC_iMVNr, 1218 "mvn", "\t$Rd, $Rn", 1219 [(set tGPR:$Rd, (not tGPR:$Rn))]>, Sched<[WriteALU]>; 1220 1221// Bitwise or register 1222let isCommutable = 1 in 1223def tORR : // A8.6.114 1224 T1sItDPEncode<0b1100, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 1225 IIC_iBITr, 1226 "orr", "\t$Rdn, $Rm", 1227 [(set tGPR:$Rdn, (or tGPR:$Rn, tGPR:$Rm))]>, Sched<[WriteALU]>; 1228 1229// Swaps 1230def tREV : // A8.6.134 1231 T1pIMiscEncode<{1,0,1,0,0,0,?}, (outs tGPR:$Rd), (ins tGPR:$Rm), 1232 IIC_iUNAr, 1233 "rev", "\t$Rd, $Rm", 1234 [(set tGPR:$Rd, (bswap tGPR:$Rm))]>, 1235 Requires<[IsThumb, IsThumb1Only, HasV6]>, Sched<[WriteALU]>; 1236 1237def tREV16 : // A8.6.135 1238 T1pIMiscEncode<{1,0,1,0,0,1,?}, (outs tGPR:$Rd), (ins tGPR:$Rm), 1239 IIC_iUNAr, 1240 "rev16", "\t$Rd, $Rm", 1241 [(set tGPR:$Rd, (rotr (bswap tGPR:$Rm), (i32 16)))]>, 1242 Requires<[IsThumb, IsThumb1Only, HasV6]>, Sched<[WriteALU]>; 1243 1244def tREVSH : // A8.6.136 1245 T1pIMiscEncode<{1,0,1,0,1,1,?}, (outs tGPR:$Rd), (ins tGPR:$Rm), 1246 IIC_iUNAr, 1247 "revsh", "\t$Rd, $Rm", 1248 [(set tGPR:$Rd, (sra (bswap tGPR:$Rm), (i32 16)))]>, 1249 Requires<[IsThumb, IsThumb1Only, HasV6]>, Sched<[WriteALU]>; 1250 1251// Rotate right register 1252def tROR : // A8.6.139 1253 T1sItDPEncode<0b0111, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 1254 IIC_iMOVsr, 1255 "ror", "\t$Rdn, $Rm", 1256 [(set tGPR:$Rdn, (rotr tGPR:$Rn, tGPR:$Rm))]>, 1257 Sched<[WriteALU]>; 1258 1259// Negate register 1260def tRSB : // A8.6.141 1261 T1sIDPEncode<0b1001, (outs tGPR:$Rd), (ins tGPR:$Rn), 1262 IIC_iALUi, 1263 "rsb", "\t$Rd, $Rn, #0", 1264 [(set tGPR:$Rd, (ineg tGPR:$Rn))]>, Sched<[WriteALU]>; 1265 1266// Subtract with carry register 1267let Uses = [CPSR] in 1268def tSBC : // A8.6.151 1269 T1sItDPEncode<0b0110, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 1270 IIC_iALUr, 1271 "sbc", "\t$Rdn, $Rm", 1272 []>, 1273 Sched<[WriteALU]>; 1274 1275// Subtract immediate 1276def tSUBi3 : // A8.6.210 T1 1277 T1sIGenEncodeImm<0b01111, (outs tGPR:$Rd), (ins tGPR:$Rm, imm0_7:$imm3), 1278 IIC_iALUi, 1279 "sub", "\t$Rd, $Rm, $imm3", 1280 [(set tGPR:$Rd, (add tGPR:$Rm, imm0_7_neg:$imm3))]>, 1281 Sched<[WriteALU]> { 1282 bits<3> imm3; 1283 let Inst{8-6} = imm3; 1284} 1285 1286def tSUBi8 : // A8.6.210 T2 1287 T1sItGenEncodeImm<{1,1,1,?,?}, (outs tGPR:$Rdn), 1288 (ins tGPR:$Rn, imm0_255:$imm8), IIC_iALUi, 1289 "sub", "\t$Rdn, $imm8", 1290 [(set tGPR:$Rdn, (add tGPR:$Rn, imm8_255_neg:$imm8))]>, 1291 Sched<[WriteALU]>; 1292 1293def : tInstSubst<"add${s}${p} $rd, $rn, $imm", 1294 (tSUBi3 tGPR:$rd, s_cc_out:$s, tGPR:$rn, mod_imm1_7_neg:$imm, pred:$p)>; 1295 1296 1297def : tInstSubst<"add${s}${p} $rdn, $imm", 1298 (tSUBi8 tGPR:$rdn, s_cc_out:$s, mod_imm8_255_neg:$imm, pred:$p)>; 1299 1300 1301// Subtract register 1302def tSUBrr : // A8.6.212 1303 T1sIGenEncode<0b01101, (outs tGPR:$Rd), (ins tGPR:$Rn, tGPR:$Rm), 1304 IIC_iALUr, 1305 "sub", "\t$Rd, $Rn, $Rm", 1306 [(set tGPR:$Rd, (sub tGPR:$Rn, tGPR:$Rm))]>, 1307 Sched<[WriteALU]>; 1308 1309def : tInstAlias <"sub${s}${p} $Rdn, $Rm", 1310 (tSUBrr tGPR:$Rdn,s_cc_out:$s, tGPR:$Rdn, tGPR:$Rm, pred:$p)>; 1311 1312/// Similar to the above except these set the 's' bit so the 1313/// instruction modifies the CPSR register. 1314/// 1315/// These opcodes will be converted to the real non-S opcodes by 1316/// AdjustInstrPostInstrSelection after giving then an optional CPSR operand. 1317let hasPostISelHook = 1, Defs = [CPSR] in { 1318 let Uses = [CPSR] in 1319 def tSBCS : tPseudoInst<(outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 1320 2, IIC_iALUr, 1321 [(set tGPR:$Rdn, CPSR, (ARMsube tGPR:$Rn, tGPR:$Rm, 1322 CPSR))]>, 1323 Requires<[IsThumb1Only]>, 1324 Sched<[WriteALU]>; 1325 1326 def tSUBSi3 : tPseudoInst<(outs tGPR:$Rd), (ins tGPR:$Rm, imm0_7:$imm3), 1327 2, IIC_iALUi, 1328 [(set tGPR:$Rd, CPSR, (ARMsubc tGPR:$Rm, 1329 imm0_7:$imm3))]>, 1330 Requires<[IsThumb1Only]>, 1331 Sched<[WriteALU]>; 1332 1333 def tSUBSi8 : tPseudoInst<(outs tGPR:$Rdn), (ins tGPR:$Rn, imm0_255:$imm8), 1334 2, IIC_iALUi, 1335 [(set tGPR:$Rdn, CPSR, (ARMsubc tGPR:$Rn, 1336 imm8_255:$imm8))]>, 1337 Requires<[IsThumb1Only]>, 1338 Sched<[WriteALU]>; 1339 1340 def tSUBSrr : tPseudoInst<(outs tGPR:$Rd), (ins tGPR:$Rn, tGPR:$Rm), 1341 2, IIC_iALUr, 1342 [(set tGPR:$Rd, CPSR, (ARMsubc tGPR:$Rn, 1343 tGPR:$Rm))]>, 1344 Requires<[IsThumb1Only]>, 1345 Sched<[WriteALU]>; 1346} 1347 1348// Sign-extend byte 1349def tSXTB : // A8.6.222 1350 T1pIMiscEncode<{0,0,1,0,0,1,?}, (outs tGPR:$Rd), (ins tGPR:$Rm), 1351 IIC_iUNAr, 1352 "sxtb", "\t$Rd, $Rm", 1353 [(set tGPR:$Rd, (sext_inreg tGPR:$Rm, i8))]>, 1354 Requires<[IsThumb, IsThumb1Only, HasV6]>, 1355 Sched<[WriteALU]>; 1356 1357// Sign-extend short 1358def tSXTH : // A8.6.224 1359 T1pIMiscEncode<{0,0,1,0,0,0,?}, (outs tGPR:$Rd), (ins tGPR:$Rm), 1360 IIC_iUNAr, 1361 "sxth", "\t$Rd, $Rm", 1362 [(set tGPR:$Rd, (sext_inreg tGPR:$Rm, i16))]>, 1363 Requires<[IsThumb, IsThumb1Only, HasV6]>, 1364 Sched<[WriteALU]>; 1365 1366// Test 1367let isCompare = 1, isCommutable = 1, Defs = [CPSR] in 1368def tTST : // A8.6.230 1369 T1pIDPEncode<0b1000, (outs), (ins tGPR:$Rn, tGPR:$Rm), IIC_iTSTr, 1370 "tst", "\t$Rn, $Rm", 1371 [(ARMcmpZ (and_su tGPR:$Rn, tGPR:$Rm), 0)]>, 1372 Sched<[WriteALU]>; 1373 1374// A8.8.247 UDF - Undefined (Encoding T1) 1375def tUDF : TI<(outs), (ins imm0_255:$imm8), IIC_Br, "udf\t$imm8", 1376 [(int_arm_undefined imm0_255:$imm8)]>, Encoding16 { 1377 bits<8> imm8; 1378 let Inst{15-12} = 0b1101; 1379 let Inst{11-8} = 0b1110; 1380 let Inst{7-0} = imm8; 1381} 1382 1383def t__brkdiv0 : TI<(outs), (ins), IIC_Br, "__brkdiv0", 1384 [(int_arm_undefined 249)]>, Encoding16, 1385 Requires<[IsThumb, IsWindows]> { 1386 let Inst = 0xdef9; 1387 let isTerminator = 1; 1388} 1389 1390// Zero-extend byte 1391def tUXTB : // A8.6.262 1392 T1pIMiscEncode<{0,0,1,0,1,1,?}, (outs tGPR:$Rd), (ins tGPR:$Rm), 1393 IIC_iUNAr, 1394 "uxtb", "\t$Rd, $Rm", 1395 [(set tGPR:$Rd, (and tGPR:$Rm, 0xFF))]>, 1396 Requires<[IsThumb, IsThumb1Only, HasV6]>, 1397 Sched<[WriteALU]>; 1398 1399// Zero-extend short 1400def tUXTH : // A8.6.264 1401 T1pIMiscEncode<{0,0,1,0,1,0,?}, (outs tGPR:$Rd), (ins tGPR:$Rm), 1402 IIC_iUNAr, 1403 "uxth", "\t$Rd, $Rm", 1404 [(set tGPR:$Rd, (and tGPR:$Rm, 0xFFFF))]>, 1405 Requires<[IsThumb, IsThumb1Only, HasV6]>, Sched<[WriteALU]>; 1406 1407// Conditional move tMOVCCr - Used to implement the Thumb SELECT_CC operation. 1408// Expanded after instruction selection into a branch sequence. 1409let usesCustomInserter = 1 in // Expanded after instruction selection. 1410 def tMOVCCr_pseudo : 1411 PseudoInst<(outs tGPR:$dst), (ins tGPR:$false, tGPR:$true, cmovpred:$p), 1412 NoItinerary, 1413 [(set tGPR:$dst, (ARMcmov tGPR:$false, tGPR:$true, cmovpred:$p))]>; 1414 1415// tLEApcrel - Load a pc-relative address into a register without offending the 1416// assembler. 1417 1418def tADR : T1I<(outs tGPR:$Rd), (ins t_adrlabel:$addr, pred:$p), 1419 IIC_iALUi, "adr{$p}\t$Rd, $addr", []>, 1420 T1Encoding<{1,0,1,0,0,?}>, Sched<[WriteALU]> { 1421 bits<3> Rd; 1422 bits<8> addr; 1423 let Inst{10-8} = Rd; 1424 let Inst{7-0} = addr; 1425 let DecoderMethod = "DecodeThumbAddSpecialReg"; 1426} 1427 1428let hasSideEffects = 0, isReMaterializable = 1 in 1429def tLEApcrel : tPseudoInst<(outs tGPR:$Rd), (ins i32imm:$label, pred:$p), 1430 2, IIC_iALUi, []>, Sched<[WriteALU]>; 1431 1432let hasSideEffects = 1 in 1433def tLEApcrelJT : tPseudoInst<(outs tGPR:$Rd), 1434 (ins i32imm:$label, pred:$p), 1435 2, IIC_iALUi, []>, Sched<[WriteALU]>; 1436 1437// Thumb-1 doesn't have the TBB or TBH instructions, but we can synthesize them 1438// and make use of the same compressed jump table format as Thumb-2. 1439let Size = 2, isBranch = 1, isTerminator = 1, isBarrier = 1, 1440 isIndirectBranch = 1 in { 1441def tTBB_JT : tPseudoInst<(outs), 1442 (ins tGPRwithpc:$base, tGPR:$index, i32imm:$jt, i32imm:$pclbl), 0, 1443 IIC_Br, []>, Sched<[WriteBr]>; 1444 1445def tTBH_JT : tPseudoInst<(outs), 1446 (ins tGPRwithpc:$base, tGPR:$index, i32imm:$jt, i32imm:$pclbl), 0, 1447 IIC_Br, []>, Sched<[WriteBr]>; 1448} 1449 1450//===----------------------------------------------------------------------===// 1451// TLS Instructions 1452// 1453 1454// __aeabi_read_tp preserves the registers r1-r3. 1455// This is a pseudo inst so that we can get the encoding right, 1456// complete with fixup for the aeabi_read_tp function. 1457let isCall = 1, Defs = [R0, R12, LR, CPSR], Uses = [SP] in 1458def tTPsoft : tPseudoInst<(outs), (ins), 4, IIC_Br, 1459 [(set R0, ARMthread_pointer)]>, 1460 Sched<[WriteBr]>; 1461 1462//===----------------------------------------------------------------------===// 1463// SJLJ Exception handling intrinsics 1464// 1465 1466// eh_sjlj_setjmp() is an instruction sequence to store the return address and 1467// save #0 in R0 for the non-longjmp case. Since by its nature we may be coming 1468// from some other function to get here, and we're using the stack frame for the 1469// containing function to save/restore registers, we can't keep anything live in 1470// regs across the eh_sjlj_setjmp(), else it will almost certainly have been 1471// tromped upon when we get here from a longjmp(). We force everything out of 1472// registers except for our own input by listing the relevant registers in 1473// Defs. By doing so, we also cause the prologue/epilogue code to actively 1474// preserve all of the callee-saved resgisters, which is exactly what we want. 1475// $val is a scratch register for our use. 1476let Defs = [ R0, R1, R2, R3, R4, R5, R6, R7, R12, CPSR ], 1477 hasSideEffects = 1, isBarrier = 1, isCodeGenOnly = 1, 1478 usesCustomInserter = 1 in 1479def tInt_eh_sjlj_setjmp : ThumbXI<(outs),(ins tGPR:$src, tGPR:$val), 1480 AddrModeNone, 0, NoItinerary, "","", 1481 [(set R0, (ARMeh_sjlj_setjmp tGPR:$src, tGPR:$val))]>; 1482 1483// FIXME: Non-IOS version(s) 1484let isBarrier = 1, hasSideEffects = 1, isTerminator = 1, isCodeGenOnly = 1, 1485 Defs = [ R7, LR, SP ] in 1486def tInt_eh_sjlj_longjmp : XI<(outs), (ins GPR:$src, GPR:$scratch), 1487 AddrModeNone, 0, IndexModeNone, 1488 Pseudo, NoItinerary, "", "", 1489 [(ARMeh_sjlj_longjmp GPR:$src, GPR:$scratch)]>, 1490 Requires<[IsThumb,IsNotWindows]>; 1491 1492let isBarrier = 1, hasSideEffects = 1, isTerminator = 1, isCodeGenOnly = 1, 1493 Defs = [ R11, LR, SP ] in 1494def tInt_WIN_eh_sjlj_longjmp 1495 : XI<(outs), (ins GPR:$src, GPR:$scratch), AddrModeNone, 0, IndexModeNone, 1496 Pseudo, NoItinerary, "", "", [(ARMeh_sjlj_longjmp GPR:$src, GPR:$scratch)]>, 1497 Requires<[IsThumb,IsWindows]>; 1498 1499//===----------------------------------------------------------------------===// 1500// Non-Instruction Patterns 1501// 1502 1503// Comparisons 1504def : T1Pat<(ARMcmpZ tGPR:$Rn, imm0_255:$imm8), 1505 (tCMPi8 tGPR:$Rn, imm0_255:$imm8)>; 1506def : T1Pat<(ARMcmpZ tGPR:$Rn, tGPR:$Rm), 1507 (tCMPr tGPR:$Rn, tGPR:$Rm)>; 1508 1509// Bswap 16 with load/store 1510def : T1Pat<(srl (bswap (extloadi16 t_addrmode_is2:$addr)), (i32 16)), 1511 (tREV16 (tLDRHi t_addrmode_is2:$addr))>; 1512def : T1Pat<(srl (bswap (extloadi16 t_addrmode_rr:$addr)), (i32 16)), 1513 (tREV16 (tLDRHr t_addrmode_rr:$addr))>; 1514def : T1Pat<(truncstorei16 (srl (bswap tGPR:$Rn), (i32 16)), 1515 t_addrmode_is2:$addr), 1516 (tSTRHi(tREV16 tGPR:$Rn), t_addrmode_is2:$addr)>; 1517def : T1Pat<(truncstorei16 (srl (bswap tGPR:$Rn), (i32 16)), 1518 t_addrmode_rr:$addr), 1519 (tSTRHr (tREV16 tGPR:$Rn), t_addrmode_rr:$addr)>; 1520 1521// ConstantPool 1522def : T1Pat<(ARMWrapper tconstpool :$dst), (tLEApcrel tconstpool :$dst)>; 1523 1524// GlobalAddress 1525def tLDRLIT_ga_pcrel : PseudoInst<(outs tGPR:$dst), (ins i32imm:$addr), 1526 IIC_iLoadiALU, 1527 [(set tGPR:$dst, 1528 (ARMWrapperPIC tglobaladdr:$addr))]>, 1529 Requires<[IsThumb, DontUseMovtInPic]>; 1530 1531def tLDRLIT_ga_abs : PseudoInst<(outs tGPR:$dst), (ins i32imm:$src), 1532 IIC_iLoad_i, 1533 [(set tGPR:$dst, 1534 (ARMWrapper tglobaladdr:$src))]>, 1535 Requires<[IsThumb, DontUseMovt]>; 1536 1537// TLS globals 1538def : Pat<(ARMWrapperPIC tglobaltlsaddr:$addr), 1539 (tLDRLIT_ga_pcrel tglobaltlsaddr:$addr)>, 1540 Requires<[IsThumb, DontUseMovtInPic]>; 1541def : Pat<(ARMWrapper tglobaltlsaddr:$addr), 1542 (tLDRLIT_ga_abs tglobaltlsaddr:$addr)>, 1543 Requires<[IsThumb, DontUseMovt]>; 1544 1545 1546// JumpTable 1547def : T1Pat<(ARMWrapperJT tjumptable:$dst), 1548 (tLEApcrelJT tjumptable:$dst)>; 1549 1550// Direct calls 1551def : T1Pat<(ARMcall texternalsym:$func), (tBL texternalsym:$func)>, 1552 Requires<[IsThumb]>; 1553 1554// zextload i1 -> zextload i8 1555def : T1Pat<(zextloadi1 t_addrmode_is1:$addr), 1556 (tLDRBi t_addrmode_is1:$addr)>; 1557def : T1Pat<(zextloadi1 t_addrmode_rr:$addr), 1558 (tLDRBr t_addrmode_rr:$addr)>; 1559 1560// extload from the stack -> word load from the stack, as it avoids having to 1561// materialize the base in a separate register. This only works when a word 1562// load puts the byte/halfword value in the same place in the register that the 1563// byte/halfword load would, i.e. when little-endian. 1564def : T1Pat<(extloadi1 t_addrmode_sp:$addr), (tLDRspi t_addrmode_sp:$addr)>, 1565 Requires<[IsThumb, IsThumb1Only, IsLE]>; 1566def : T1Pat<(extloadi8 t_addrmode_sp:$addr), (tLDRspi t_addrmode_sp:$addr)>, 1567 Requires<[IsThumb, IsThumb1Only, IsLE]>; 1568def : T1Pat<(extloadi16 t_addrmode_sp:$addr), (tLDRspi t_addrmode_sp:$addr)>, 1569 Requires<[IsThumb, IsThumb1Only, IsLE]>; 1570 1571// extload -> zextload 1572def : T1Pat<(extloadi1 t_addrmode_is1:$addr), (tLDRBi t_addrmode_is1:$addr)>; 1573def : T1Pat<(extloadi1 t_addrmode_rr:$addr), (tLDRBr t_addrmode_rr:$addr)>; 1574def : T1Pat<(extloadi8 t_addrmode_is1:$addr), (tLDRBi t_addrmode_is1:$addr)>; 1575def : T1Pat<(extloadi8 t_addrmode_rr:$addr), (tLDRBr t_addrmode_rr:$addr)>; 1576def : T1Pat<(extloadi16 t_addrmode_is2:$addr), (tLDRHi t_addrmode_is2:$addr)>; 1577def : T1Pat<(extloadi16 t_addrmode_rr:$addr), (tLDRHr t_addrmode_rr:$addr)>; 1578 1579// post-inc loads and stores 1580 1581// post-inc LDR -> LDM r0!, {r1}. The way operands are layed out in LDMs is 1582// different to how ISel expects them for a post-inc load, so use a pseudo 1583// and expand it just after ISel. 1584let usesCustomInserter = 1, mayLoad =1, 1585 Constraints = "$Rn = $Rn_wb,@earlyclobber $Rn_wb" in 1586 def tLDR_postidx: tPseudoInst<(outs rGPR:$Rt, rGPR:$Rn_wb), 1587 (ins rGPR:$Rn, pred:$p), 1588 4, IIC_iStore_ru, 1589 []>; 1590 1591// post-inc STR -> STM r0!, {r1}. The layout of this (because it doesn't def 1592// multiple registers) is the same in ISel as MachineInstr, so there's no need 1593// for a pseudo. 1594def : T1Pat<(post_store rGPR:$Rt, rGPR:$Rn, 4), 1595 (tSTMIA_UPD rGPR:$Rn, rGPR:$Rt)>; 1596 1597// If it's impossible to use [r,r] address mode for sextload, select to 1598// ldr{b|h} + sxt{b|h} instead. 1599def : T1Pat<(sextloadi8 t_addrmode_is1:$addr), 1600 (tSXTB (tLDRBi t_addrmode_is1:$addr))>, 1601 Requires<[IsThumb, IsThumb1Only, HasV6]>; 1602def : T1Pat<(sextloadi8 t_addrmode_rr:$addr), 1603 (tSXTB (tLDRBr t_addrmode_rr:$addr))>, 1604 Requires<[IsThumb, IsThumb1Only, HasV6]>; 1605def : T1Pat<(sextloadi16 t_addrmode_is2:$addr), 1606 (tSXTH (tLDRHi t_addrmode_is2:$addr))>, 1607 Requires<[IsThumb, IsThumb1Only, HasV6]>; 1608def : T1Pat<(sextloadi16 t_addrmode_rr:$addr), 1609 (tSXTH (tLDRHr t_addrmode_rr:$addr))>, 1610 Requires<[IsThumb, IsThumb1Only, HasV6]>; 1611 1612def : T1Pat<(sextloadi8 t_addrmode_is1:$addr), 1613 (tASRri (tLSLri (tLDRBi t_addrmode_is1:$addr), 24), 24)>; 1614def : T1Pat<(sextloadi8 t_addrmode_rr:$addr), 1615 (tASRri (tLSLri (tLDRBr t_addrmode_rr:$addr), 24), 24)>; 1616def : T1Pat<(sextloadi16 t_addrmode_is2:$addr), 1617 (tASRri (tLSLri (tLDRHi t_addrmode_is2:$addr), 16), 16)>; 1618def : T1Pat<(sextloadi16 t_addrmode_rr:$addr), 1619 (tASRri (tLSLri (tLDRHr t_addrmode_rr:$addr), 16), 16)>; 1620 1621def : T1Pat<(atomic_load_8 t_addrmode_is1:$src), 1622 (tLDRBi t_addrmode_is1:$src)>; 1623def : T1Pat<(atomic_load_8 t_addrmode_rr:$src), 1624 (tLDRBr t_addrmode_rr:$src)>; 1625def : T1Pat<(atomic_load_16 t_addrmode_is2:$src), 1626 (tLDRHi t_addrmode_is2:$src)>; 1627def : T1Pat<(atomic_load_16 t_addrmode_rr:$src), 1628 (tLDRHr t_addrmode_rr:$src)>; 1629def : T1Pat<(atomic_load_32 t_addrmode_is4:$src), 1630 (tLDRi t_addrmode_is4:$src)>; 1631def : T1Pat<(atomic_load_32 t_addrmode_rr:$src), 1632 (tLDRr t_addrmode_rr:$src)>; 1633def : T1Pat<(atomic_store_8 t_addrmode_is1:$ptr, tGPR:$val), 1634 (tSTRBi tGPR:$val, t_addrmode_is1:$ptr)>; 1635def : T1Pat<(atomic_store_8 t_addrmode_rr:$ptr, tGPR:$val), 1636 (tSTRBr tGPR:$val, t_addrmode_rr:$ptr)>; 1637def : T1Pat<(atomic_store_16 t_addrmode_is2:$ptr, tGPR:$val), 1638 (tSTRHi tGPR:$val, t_addrmode_is2:$ptr)>; 1639def : T1Pat<(atomic_store_16 t_addrmode_rr:$ptr, tGPR:$val), 1640 (tSTRHr tGPR:$val, t_addrmode_rr:$ptr)>; 1641def : T1Pat<(atomic_store_32 t_addrmode_is4:$ptr, tGPR:$val), 1642 (tSTRi tGPR:$val, t_addrmode_is4:$ptr)>; 1643def : T1Pat<(atomic_store_32 t_addrmode_rr:$ptr, tGPR:$val), 1644 (tSTRr tGPR:$val, t_addrmode_rr:$ptr)>; 1645 1646// Large immediate handling. 1647 1648// Two piece imms. 1649def : T1Pat<(i32 thumb_immshifted:$src), 1650 (tLSLri (tMOVi8 (thumb_immshifted_val imm:$src)), 1651 (thumb_immshifted_shamt imm:$src))>; 1652 1653def : T1Pat<(i32 imm0_255_comp:$src), 1654 (tMVN (tMOVi8 (imm_not_XFORM imm:$src)))>; 1655 1656def : T1Pat<(i32 imm256_510:$src), 1657 (tADDi8 (tMOVi8 255), 1658 (thumb_imm256_510_addend imm:$src))>; 1659 1660// Pseudo instruction that combines ldr from constpool and add pc. This should 1661// be expanded into two instructions late to allow if-conversion and 1662// scheduling. 1663let isReMaterializable = 1 in 1664def tLDRpci_pic : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr, pclabel:$cp), 1665 NoItinerary, 1666 [(set GPR:$dst, (ARMpic_add (load (ARMWrapper tconstpool:$addr)), 1667 imm:$cp))]>, 1668 Requires<[IsThumb, IsThumb1Only]>; 1669 1670// Pseudo-instruction for merged POP and return. 1671// FIXME: remove when we have a way to marking a MI with these properties. 1672let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1, 1673 hasExtraDefRegAllocReq = 1 in 1674def tPOP_RET : tPseudoExpand<(outs), (ins pred:$p, reglist:$regs, variable_ops), 1675 2, IIC_iPop_Br, [], 1676 (tPOP pred:$p, reglist:$regs)>, Sched<[WriteBrL]>; 1677 1678// Indirect branch using "mov pc, $Rm" 1679let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { 1680 def tBRIND : tPseudoExpand<(outs), (ins GPR:$Rm, pred:$p), 1681 2, IIC_Br, [(brind GPR:$Rm)], 1682 (tMOVr PC, GPR:$Rm, pred:$p)>, Sched<[WriteBr]>; 1683} 1684 1685 1686// In Thumb1, "nop" is encoded as a "mov r8, r8". Technically, the bf00 1687// encoding is available on ARMv6K, but we don't differentiate that finely. 1688def : InstAlias<"nop", (tMOVr R8, R8, 14, 0), 0>, Requires<[IsThumb, IsThumb1Only]>; 1689 1690 1691// "neg" is and alias for "rsb rd, rn, #0" 1692def : tInstAlias<"neg${s}${p} $Rd, $Rm", 1693 (tRSB tGPR:$Rd, s_cc_out:$s, tGPR:$Rm, pred:$p)>; 1694 1695 1696// Implied destination operand forms for shifts. 1697def : tInstAlias<"lsl${s}${p} $Rdm, $imm", 1698 (tLSLri tGPR:$Rdm, cc_out:$s, tGPR:$Rdm, imm0_31:$imm, pred:$p)>; 1699def : tInstAlias<"lsr${s}${p} $Rdm, $imm", 1700 (tLSRri tGPR:$Rdm, cc_out:$s, tGPR:$Rdm, imm_sr:$imm, pred:$p)>; 1701def : tInstAlias<"asr${s}${p} $Rdm, $imm", 1702 (tASRri tGPR:$Rdm, cc_out:$s, tGPR:$Rdm, imm_sr:$imm, pred:$p)>; 1703 1704// Pseudo instruction ldr Rt, =immediate 1705def tLDRConstPool 1706 : tAsmPseudo<"ldr${p} $Rt, $immediate", 1707 (ins tGPR:$Rt, const_pool_asm_imm:$immediate, pred:$p)>; 1708