ARMInstrThumb.td revision 38466309d5c8ce408f05567fa47aeaa3b5826080
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 ARMtcall : SDNode<"ARMISD::tCALL", SDT_ARMcall, 19 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, 20 SDNPVariadic]>; 21 22def imm_sr_XFORM: SDNodeXForm<imm, [{ 23 unsigned Imm = N->getZExtValue(); 24 return CurDAG->getTargetConstant((Imm == 32 ? 0 : Imm), MVT::i32); 25}]>; 26def ThumbSRImmAsmOperand: AsmOperandClass { let Name = "ImmThumbSR"; } 27def imm_sr : Operand<i32>, PatLeaf<(imm), [{ 28 uint64_t Imm = N->getZExtValue(); 29 return Imm > 0 && Imm <= 32; 30}], imm_sr_XFORM> { 31 let PrintMethod = "printThumbSRImm"; 32 let ParserMatchClass = ThumbSRImmAsmOperand; 33} 34 35def imm_neg_XFORM : SDNodeXForm<imm, [{ 36 return CurDAG->getTargetConstant(-(int)N->getZExtValue(), MVT::i32); 37}]>; 38def imm_comp_XFORM : SDNodeXForm<imm, [{ 39 return CurDAG->getTargetConstant(~((uint32_t)N->getZExtValue()), MVT::i32); 40}]>; 41 42def imm0_7_neg : PatLeaf<(i32 imm), [{ 43 return (uint32_t)-N->getZExtValue() < 8; 44}], imm_neg_XFORM>; 45 46def imm0_255_comp : PatLeaf<(i32 imm), [{ 47 return ~((uint32_t)N->getZExtValue()) < 256; 48}]>; 49 50def imm8_255 : ImmLeaf<i32, [{ 51 return Imm >= 8 && Imm < 256; 52}]>; 53def imm8_255_neg : PatLeaf<(i32 imm), [{ 54 unsigned Val = -N->getZExtValue(); 55 return Val >= 8 && Val < 256; 56}], imm_neg_XFORM>; 57 58// Break imm's up into two pieces: an immediate + a left shift. This uses 59// thumb_immshifted to match and thumb_immshifted_val and thumb_immshifted_shamt 60// to get the val/shift pieces. 61def thumb_immshifted : PatLeaf<(imm), [{ 62 return ARM_AM::isThumbImmShiftedVal((unsigned)N->getZExtValue()); 63}]>; 64 65def thumb_immshifted_val : SDNodeXForm<imm, [{ 66 unsigned V = ARM_AM::getThumbImmNonShiftedVal((unsigned)N->getZExtValue()); 67 return CurDAG->getTargetConstant(V, MVT::i32); 68}]>; 69 70def thumb_immshifted_shamt : SDNodeXForm<imm, [{ 71 unsigned V = ARM_AM::getThumbImmValShift((unsigned)N->getZExtValue()); 72 return CurDAG->getTargetConstant(V, MVT::i32); 73}]>; 74 75// ADR instruction labels. 76def t_adrlabel : Operand<i32> { 77 let EncoderMethod = "getThumbAdrLabelOpValue"; 78} 79 80// Scaled 4 immediate. 81def t_imm_s4 : Operand<i32> { 82 let PrintMethod = "printThumbS4ImmOperand"; 83 let OperandType = "OPERAND_IMMEDIATE"; 84} 85 86// Define Thumb specific addressing modes. 87 88let OperandType = "OPERAND_PCREL" in { 89def t_brtarget : Operand<OtherVT> { 90 let EncoderMethod = "getThumbBRTargetOpValue"; 91 let DecoderMethod = "DecodeThumbBROperand"; 92} 93 94def t_bcctarget : Operand<i32> { 95 let EncoderMethod = "getThumbBCCTargetOpValue"; 96 let DecoderMethod = "DecodeThumbBCCTargetOperand"; 97} 98 99def t_cbtarget : Operand<i32> { 100 let EncoderMethod = "getThumbCBTargetOpValue"; 101 let DecoderMethod = "DecodeThumbCmpBROperand"; 102} 103 104def t_bltarget : Operand<i32> { 105 let EncoderMethod = "getThumbBLTargetOpValue"; 106 let DecoderMethod = "DecodeThumbBLTargetOperand"; 107} 108 109def t_blxtarget : Operand<i32> { 110 let EncoderMethod = "getThumbBLXTargetOpValue"; 111 let DecoderMethod = "DecodeThumbBLXOffset"; 112} 113} 114 115// t_addrmode_rr := reg + reg 116// 117def t_addrmode_rr_asm_operand : AsmOperandClass { let Name = "MemThumbRR"; } 118def t_addrmode_rr : Operand<i32>, 119 ComplexPattern<i32, 2, "SelectThumbAddrModeRR", []> { 120 let EncoderMethod = "getThumbAddrModeRegRegOpValue"; 121 let PrintMethod = "printThumbAddrModeRROperand"; 122 let DecoderMethod = "DecodeThumbAddrModeRR"; 123 let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); 124} 125 126// t_addrmode_rrs := reg + reg 127// 128// We use separate scaled versions because the Select* functions need 129// to explicitly check for a matching constant and return false here so that 130// the reg+imm forms will match instead. This is a horrible way to do that, 131// as it forces tight coupling between the methods, but it's how selectiondag 132// currently works. 133def t_addrmode_rrs1 : Operand<i32>, 134 ComplexPattern<i32, 2, "SelectThumbAddrModeRI5S1", []> { 135 let EncoderMethod = "getThumbAddrModeRegRegOpValue"; 136 let PrintMethod = "printThumbAddrModeRROperand"; 137 let DecoderMethod = "DecodeThumbAddrModeRR"; 138 let ParserMatchClass = t_addrmode_rr_asm_operand; 139 let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); 140} 141def t_addrmode_rrs2 : Operand<i32>, 142 ComplexPattern<i32, 2, "SelectThumbAddrModeRI5S2", []> { 143 let EncoderMethod = "getThumbAddrModeRegRegOpValue"; 144 let DecoderMethod = "DecodeThumbAddrModeRR"; 145 let PrintMethod = "printThumbAddrModeRROperand"; 146 let ParserMatchClass = t_addrmode_rr_asm_operand; 147 let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); 148} 149def t_addrmode_rrs4 : Operand<i32>, 150 ComplexPattern<i32, 2, "SelectThumbAddrModeRI5S4", []> { 151 let EncoderMethod = "getThumbAddrModeRegRegOpValue"; 152 let DecoderMethod = "DecodeThumbAddrModeRR"; 153 let PrintMethod = "printThumbAddrModeRROperand"; 154 let ParserMatchClass = t_addrmode_rr_asm_operand; 155 let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); 156} 157 158// t_addrmode_is4 := reg + imm5 * 4 159// 160def t_addrmode_is4_asm_operand : AsmOperandClass { let Name = "MemThumbRIs4"; } 161def t_addrmode_is4 : Operand<i32>, 162 ComplexPattern<i32, 2, "SelectThumbAddrModeImm5S4", []> { 163 let EncoderMethod = "getAddrModeISOpValue"; 164 let DecoderMethod = "DecodeThumbAddrModeIS"; 165 let PrintMethod = "printThumbAddrModeImm5S4Operand"; 166 let ParserMatchClass = t_addrmode_is4_asm_operand; 167 let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm); 168} 169 170// t_addrmode_is2 := reg + imm5 * 2 171// 172def t_addrmode_is2_asm_operand : AsmOperandClass { let Name = "MemThumbRIs2"; } 173def t_addrmode_is2 : Operand<i32>, 174 ComplexPattern<i32, 2, "SelectThumbAddrModeImm5S2", []> { 175 let EncoderMethod = "getAddrModeISOpValue"; 176 let DecoderMethod = "DecodeThumbAddrModeIS"; 177 let PrintMethod = "printThumbAddrModeImm5S2Operand"; 178 let ParserMatchClass = t_addrmode_is2_asm_operand; 179 let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm); 180} 181 182// t_addrmode_is1 := reg + imm5 183// 184def t_addrmode_is1_asm_operand : AsmOperandClass { let Name = "MemThumbRIs1"; } 185def t_addrmode_is1 : Operand<i32>, 186 ComplexPattern<i32, 2, "SelectThumbAddrModeImm5S1", []> { 187 let EncoderMethod = "getAddrModeISOpValue"; 188 let DecoderMethod = "DecodeThumbAddrModeIS"; 189 let PrintMethod = "printThumbAddrModeImm5S1Operand"; 190 let ParserMatchClass = t_addrmode_is1_asm_operand; 191 let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm); 192} 193 194// t_addrmode_sp := sp + imm8 * 4 195// 196def t_addrmode_sp_asm_operand : AsmOperandClass { let Name = "MemThumbSPI"; } 197def t_addrmode_sp : Operand<i32>, 198 ComplexPattern<i32, 2, "SelectThumbAddrModeSP", []> { 199 let EncoderMethod = "getAddrModeThumbSPOpValue"; 200 let DecoderMethod = "DecodeThumbAddrModeSP"; 201 let PrintMethod = "printThumbAddrModeSPOperand"; 202 let ParserMatchClass = t_addrmode_sp_asm_operand; 203 let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); 204} 205 206// t_addrmode_pc := <label> => pc + imm8 * 4 207// 208def t_addrmode_pc : Operand<i32> { 209 let EncoderMethod = "getAddrModePCOpValue"; 210 let DecoderMethod = "DecodeThumbAddrModePC"; 211} 212 213//===----------------------------------------------------------------------===// 214// Miscellaneous Instructions. 215// 216 217// FIXME: Marking these as hasSideEffects is necessary to prevent machine DCE 218// from removing one half of the matched pairs. That breaks PEI, which assumes 219// these will always be in pairs, and asserts if it finds otherwise. Better way? 220let Defs = [SP], Uses = [SP], hasSideEffects = 1 in { 221def tADJCALLSTACKUP : 222 PseudoInst<(outs), (ins i32imm:$amt1, i32imm:$amt2), NoItinerary, 223 [(ARMcallseq_end imm:$amt1, imm:$amt2)]>, 224 Requires<[IsThumb, IsThumb1Only]>; 225 226def tADJCALLSTACKDOWN : 227 PseudoInst<(outs), (ins i32imm:$amt), NoItinerary, 228 [(ARMcallseq_start imm:$amt)]>, 229 Requires<[IsThumb, IsThumb1Only]>; 230} 231 232class T1SystemEncoding<bits<8> opc> 233 : T1Encoding<0b101111> { 234 let Inst{9-8} = 0b11; 235 let Inst{7-0} = opc; 236} 237 238def tNOP : T1pI<(outs), (ins), NoItinerary, "nop", "", []>, 239 T1SystemEncoding<0x00>; // A8.6.110 240 241def tYIELD : T1pI<(outs), (ins), NoItinerary, "yield", "", []>, 242 T1SystemEncoding<0x10>; // A8.6.410 243 244def tWFE : T1pI<(outs), (ins), NoItinerary, "wfe", "", []>, 245 T1SystemEncoding<0x20>; // A8.6.408 246 247def tWFI : T1pI<(outs), (ins), NoItinerary, "wfi", "", []>, 248 T1SystemEncoding<0x30>; // A8.6.409 249 250def tSEV : T1pI<(outs), (ins), NoItinerary, "sev", "", []>, 251 T1SystemEncoding<0x40>; // A8.6.157 252 253// The imm operand $val can be used by a debugger to store more information 254// about the breakpoint. 255def tBKPT : T1I<(outs), (ins imm0_255:$val), NoItinerary, "bkpt\t$val", 256 []>, 257 T1Encoding<0b101111> { 258 let Inst{9-8} = 0b10; 259 // A8.6.22 260 bits<8> val; 261 let Inst{7-0} = val; 262} 263 264def tSETEND : T1I<(outs), (ins setend_op:$end), NoItinerary, "setend\t$end", 265 []>, T1Encoding<0b101101> { 266 bits<1> end; 267 // A8.6.156 268 let Inst{9-5} = 0b10010; 269 let Inst{4} = 1; 270 let Inst{3} = end; 271 let Inst{2-0} = 0b000; 272} 273 274// Change Processor State is a system instruction -- for disassembly only. 275def tCPS : T1I<(outs), (ins imod_op:$imod, iflags_op:$iflags), 276 NoItinerary, "cps$imod $iflags", 277 [/* For disassembly only; pattern left blank */]>, 278 T1Misc<0b0110011> { 279 // A8.6.38 & B6.1.1 280 bit imod; 281 bits<3> iflags; 282 283 let Inst{4} = imod; 284 let Inst{3} = 0; 285 let Inst{2-0} = iflags; 286 let DecoderMethod = "DecodeThumbCPS"; 287} 288 289// For both thumb1 and thumb2. 290let isNotDuplicable = 1, isCodeGenOnly = 1 in 291def tPICADD : TIt<(outs GPR:$dst), (ins GPR:$lhs, pclabel:$cp), IIC_iALUr, "", 292 [(set GPR:$dst, (ARMpic_add GPR:$lhs, imm:$cp))]>, 293 T1Special<{0,0,?,?}> { 294 // A8.6.6 295 bits<3> dst; 296 let Inst{6-3} = 0b1111; // Rm = pc 297 let Inst{2-0} = dst; 298} 299 300// ADD <Rd>, sp, #<imm8> 301// This is rematerializable, which is particularly useful for taking the 302// address of locals. 303let isReMaterializable = 1 in 304def tADDrSPi : T1I<(outs tGPR:$dst), (ins GPR:$sp, t_imm_s4:$rhs), IIC_iALUi, 305 "add\t$dst, $sp, $rhs", []>, 306 T1Encoding<{1,0,1,0,1,?}> { 307 // A6.2 & A8.6.8 308 bits<3> dst; 309 bits<8> rhs; 310 let Inst{10-8} = dst; 311 let Inst{7-0} = rhs; 312 let DecoderMethod = "DecodeThumbAddSpecialReg"; 313} 314 315// ADD sp, sp, #<imm7> 316def tADDspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), IIC_iALUi, 317 "add\t$dst, $rhs", []>, 318 T1Misc<{0,0,0,0,0,?,?}> { 319 // A6.2.5 & A8.6.8 320 bits<7> rhs; 321 let Inst{6-0} = rhs; 322 let DecoderMethod = "DecodeThumbAddSPImm"; 323} 324 325// SUB sp, sp, #<imm7> 326// FIXME: The encoding and the ASM string don't match up. 327def tSUBspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), IIC_iALUi, 328 "sub\t$dst, $rhs", []>, 329 T1Misc<{0,0,0,0,1,?,?}> { 330 // A6.2.5 & A8.6.214 331 bits<7> rhs; 332 let Inst{6-0} = rhs; 333 let DecoderMethod = "DecodeThumbAddSPImm"; 334} 335 336// ADD <Rm>, sp 337def tADDrSP : TIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, 338 "add\t$dst, $rhs", []>, 339 T1Special<{0,0,?,?}> { 340 // A8.6.9 Encoding T1 341 bits<4> dst; 342 let Inst{7} = dst{3}; 343 let Inst{6-3} = 0b1101; 344 let Inst{2-0} = dst{2-0}; 345 let DecoderMethod = "DecodeThumbAddSPReg"; 346} 347 348// ADD sp, <Rm> 349def tADDspr : TIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, 350 "add\t$dst, $rhs", []>, 351 T1Special<{0,0,?,?}> { 352 // A8.6.9 Encoding T2 353 bits<4> dst; 354 let Inst{7} = 1; 355 let Inst{6-3} = dst; 356 let Inst{2-0} = 0b101; 357 let DecoderMethod = "DecodeThumbAddSPReg"; 358} 359 360//===----------------------------------------------------------------------===// 361// Control Flow Instructions. 362// 363 364// Indirect branches 365let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { 366 def tBX : TI<(outs), (ins GPR:$Rm, pred:$p), IIC_Br, "bx${p}\t$Rm", []>, 367 T1Special<{1,1,0,?}> { 368 // A6.2.3 & A8.6.25 369 bits<4> Rm; 370 let Inst{6-3} = Rm; 371 let Inst{2-0} = 0b000; 372 } 373} 374 375let isReturn = 1, isTerminator = 1, isBarrier = 1 in { 376 def tBX_RET : tPseudoExpand<(outs), (ins pred:$p), 2, IIC_Br, 377 [(ARMretflag)], (tBX LR, pred:$p)>; 378 379 // Alternative return instruction used by vararg functions. 380 def tBX_RET_vararg : tPseudoExpand<(outs), (ins tGPR:$Rm, pred:$p), 381 2, IIC_Br, [], 382 (tBX GPR:$Rm, pred:$p)>; 383} 384 385// All calls clobber the non-callee saved registers. SP is marked as a use to 386// prevent stack-pointer assignments that appear immediately before calls from 387// potentially appearing dead. 388let isCall = 1, 389 // On non-Darwin platforms R9 is callee-saved. 390 Defs = [R0, R1, R2, R3, R12, LR, QQQQ0, QQQQ2, QQQQ3, CPSR, FPSCR], 391 Uses = [SP] in { 392 // Also used for Thumb2 393 def tBL : TIx2<0b11110, 0b11, 1, 394 (outs), (ins pred:$p, t_bltarget:$func, variable_ops), IIC_Br, 395 "bl${p}\t$func", 396 [(ARMtcall tglobaladdr:$func)]>, 397 Requires<[IsThumb, IsNotDarwin]> { 398 bits<22> func; 399 let Inst{26} = func{21}; 400 let Inst{25-16} = func{20-11}; 401 let Inst{13} = 1; 402 let Inst{11} = 1; 403 let Inst{10-0} = func{10-0}; 404 } 405 406 // ARMv5T and above, also used for Thumb2 407 def tBLXi : TIx2<0b11110, 0b11, 0, 408 (outs), (ins pred:$p, t_blxtarget:$func, variable_ops), IIC_Br, 409 "blx${p}\t$func", 410 [(ARMcall tglobaladdr:$func)]>, 411 Requires<[IsThumb, HasV5T, IsNotDarwin]> { 412 bits<21> func; 413 let Inst{25-16} = func{20-11}; 414 let Inst{13} = 1; 415 let Inst{11} = 1; 416 let Inst{10-1} = func{10-1}; 417 let Inst{0} = 0; // func{0} is assumed zero 418 } 419 420 // Also used for Thumb2 421 def tBLXr : TI<(outs), (ins pred:$p, GPR:$func, variable_ops), IIC_Br, 422 "blx${p}\t$func", 423 [(ARMtcall GPR:$func)]>, 424 Requires<[IsThumb, HasV5T, IsNotDarwin]>, 425 T1Special<{1,1,1,?}> { // A6.2.3 & A8.6.24; 426 bits<4> func; 427 let Inst{6-3} = func; 428 let Inst{2-0} = 0b000; 429 } 430 431 // ARMv4T 432 def tBX_CALL : tPseudoInst<(outs), (ins tGPR:$func, variable_ops), 433 4, IIC_Br, 434 [(ARMcall_nolink tGPR:$func)]>, 435 Requires<[IsThumb, IsThumb1Only, IsNotDarwin]>; 436} 437 438let isCall = 1, 439 // On Darwin R9 is call-clobbered. 440 // R7 is marked as a use to prevent frame-pointer assignments from being 441 // moved above / below calls. 442 Defs = [R0, R1, R2, R3, R9, R12, LR, QQQQ0, QQQQ2, QQQQ3, CPSR, FPSCR], 443 Uses = [R7, SP] in { 444 // Also used for Thumb2 445 def tBLr9 : tPseudoExpand<(outs), (ins pred:$p, t_bltarget:$func, variable_ops), 446 4, IIC_Br, [(ARMtcall tglobaladdr:$func)], 447 (tBL pred:$p, t_bltarget:$func)>, 448 Requires<[IsThumb, IsDarwin]>; 449 450 // ARMv5T and above, also used for Thumb2 451 def tBLXi_r9 : tPseudoExpand<(outs), (ins pred:$p, t_blxtarget:$func, variable_ops), 452 4, IIC_Br, [(ARMcall tglobaladdr:$func)], 453 (tBLXi pred:$p, t_blxtarget:$func)>, 454 Requires<[IsThumb, HasV5T, IsDarwin]>; 455 456 // Also used for Thumb2 457 def tBLXr_r9 : tPseudoExpand<(outs), (ins pred:$p, GPR:$func, variable_ops), 458 2, IIC_Br, [(ARMtcall GPR:$func)], 459 (tBLXr pred:$p, GPR:$func)>, 460 Requires<[IsThumb, HasV5T, IsDarwin]>; 461 462 // ARMv4T 463 def tBXr9_CALL : tPseudoInst<(outs), (ins tGPR:$func, variable_ops), 464 4, IIC_Br, 465 [(ARMcall_nolink tGPR:$func)]>, 466 Requires<[IsThumb, IsThumb1Only, IsDarwin]>; 467} 468 469let isBranch = 1, isTerminator = 1, isBarrier = 1 in { 470 let isPredicable = 1 in 471 def tB : T1I<(outs), (ins t_brtarget:$target), IIC_Br, 472 "b\t$target", [(br bb:$target)]>, 473 T1Encoding<{1,1,1,0,0,?}> { 474 bits<11> target; 475 let Inst{10-0} = target; 476 } 477 478 // Far jump 479 // Just a pseudo for a tBL instruction. Needed to let regalloc know about 480 // the clobber of LR. 481 let Defs = [LR] in 482 def tBfar : tPseudoExpand<(outs), (ins t_bltarget:$target, pred:$p), 483 4, IIC_Br, [], (tBL pred:$p, t_bltarget:$target)>; 484 485 def tBR_JTr : tPseudoInst<(outs), 486 (ins tGPR:$target, i32imm:$jt, i32imm:$id), 487 0, IIC_Br, 488 [(ARMbrjt tGPR:$target, tjumptable:$jt, imm:$id)]> { 489 list<Predicate> Predicates = [IsThumb, IsThumb1Only]; 490 } 491} 492 493// FIXME: should be able to write a pattern for ARMBrcond, but can't use 494// a two-value operand where a dag node expects two operands. :( 495let isBranch = 1, isTerminator = 1 in 496 def tBcc : T1I<(outs), (ins t_bcctarget:$target, pred:$p), IIC_Br, 497 "b${p}\t$target", 498 [/*(ARMbrcond bb:$target, imm:$cc)*/]>, 499 T1BranchCond<{1,1,0,1}> { 500 bits<4> p; 501 bits<8> target; 502 let Inst{11-8} = p; 503 let Inst{7-0} = target; 504} 505 506// Tail calls 507let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in { 508 // Darwin versions. 509 let Defs = [R0, R1, R2, R3, R9, R12, QQQQ0, QQQQ2, QQQQ3, PC], 510 Uses = [SP] in { 511 // tTAILJMPd: Darwin version uses a Thumb2 branch (no Thumb1 tail calls 512 // on Darwin), so it's in ARMInstrThumb2.td. 513 def tTAILJMPr : tPseudoExpand<(outs), (ins tcGPR:$dst, variable_ops), 514 4, IIC_Br, [], 515 (tBX GPR:$dst, (ops 14, zero_reg))>, 516 Requires<[IsThumb, IsDarwin]>; 517 } 518 // Non-Darwin versions (the difference is R9). 519 let Defs = [R0, R1, R2, R3, R12, QQQQ0, QQQQ2, QQQQ3, PC], 520 Uses = [SP] in { 521 def tTAILJMPdND : tPseudoExpand<(outs), (ins t_brtarget:$dst, variable_ops), 522 4, IIC_Br, [], 523 (tB t_brtarget:$dst)>, 524 Requires<[IsThumb, IsNotDarwin]>; 525 def tTAILJMPrND : tPseudoExpand<(outs), (ins tcGPR:$dst, variable_ops), 526 4, IIC_Br, [], 527 (tBX GPR:$dst, (ops 14, zero_reg))>, 528 Requires<[IsThumb, IsNotDarwin]>; 529 } 530} 531 532 533// A8.6.218 Supervisor Call (Software Interrupt) -- for disassembly only 534// A8.6.16 B: Encoding T1 535// If Inst{11-8} == 0b1111 then SEE SVC 536let isCall = 1, Uses = [SP] in 537def tSVC : T1pI<(outs), (ins imm0_255:$imm), IIC_Br, 538 "svc", "\t$imm", []>, Encoding16 { 539 bits<8> imm; 540 let Inst{15-12} = 0b1101; 541 let Inst{11-8} = 0b1111; 542 let Inst{7-0} = imm; 543} 544 545// The assembler uses 0xDEFE for a trap instruction. 546let isBarrier = 1, isTerminator = 1 in 547def tTRAP : TI<(outs), (ins), IIC_Br, 548 "trap", [(trap)]>, Encoding16 { 549 let Inst = 0xdefe; 550} 551 552//===----------------------------------------------------------------------===// 553// Load Store Instructions. 554// 555 556// Loads: reg/reg and reg/imm5 557let canFoldAsLoad = 1, isReMaterializable = 1 in 558multiclass thumb_ld_rr_ri_enc<bits<3> reg_opc, bits<4> imm_opc, 559 Operand AddrMode_r, Operand AddrMode_i, 560 AddrMode am, InstrItinClass itin_r, 561 InstrItinClass itin_i, string asm, 562 PatFrag opnode> { 563 def r : // reg/reg 564 T1pILdStEncode<reg_opc, 565 (outs tGPR:$Rt), (ins AddrMode_r:$addr), 566 am, itin_r, asm, "\t$Rt, $addr", 567 [(set tGPR:$Rt, (opnode AddrMode_r:$addr))]>; 568 def i : // reg/imm5 569 T1pILdStEncodeImm<imm_opc, 1 /* Load */, 570 (outs tGPR:$Rt), (ins AddrMode_i:$addr), 571 am, itin_i, asm, "\t$Rt, $addr", 572 [(set tGPR:$Rt, (opnode AddrMode_i:$addr))]>; 573} 574// Stores: reg/reg and reg/imm5 575multiclass thumb_st_rr_ri_enc<bits<3> reg_opc, bits<4> imm_opc, 576 Operand AddrMode_r, Operand AddrMode_i, 577 AddrMode am, InstrItinClass itin_r, 578 InstrItinClass itin_i, string asm, 579 PatFrag opnode> { 580 def r : // reg/reg 581 T1pILdStEncode<reg_opc, 582 (outs), (ins tGPR:$Rt, AddrMode_r:$addr), 583 am, itin_r, asm, "\t$Rt, $addr", 584 [(opnode tGPR:$Rt, AddrMode_r:$addr)]>; 585 def i : // reg/imm5 586 T1pILdStEncodeImm<imm_opc, 0 /* Store */, 587 (outs), (ins tGPR:$Rt, AddrMode_i:$addr), 588 am, itin_i, asm, "\t$Rt, $addr", 589 [(opnode tGPR:$Rt, AddrMode_i:$addr)]>; 590} 591 592// A8.6.57 & A8.6.60 593defm tLDR : thumb_ld_rr_ri_enc<0b100, 0b0110, t_addrmode_rrs4, 594 t_addrmode_is4, AddrModeT1_4, 595 IIC_iLoad_r, IIC_iLoad_i, "ldr", 596 UnOpFrag<(load node:$Src)>>; 597 598// A8.6.64 & A8.6.61 599defm tLDRB : thumb_ld_rr_ri_enc<0b110, 0b0111, t_addrmode_rrs1, 600 t_addrmode_is1, AddrModeT1_1, 601 IIC_iLoad_bh_r, IIC_iLoad_bh_i, "ldrb", 602 UnOpFrag<(zextloadi8 node:$Src)>>; 603 604// A8.6.76 & A8.6.73 605defm tLDRH : thumb_ld_rr_ri_enc<0b101, 0b1000, t_addrmode_rrs2, 606 t_addrmode_is2, AddrModeT1_2, 607 IIC_iLoad_bh_r, IIC_iLoad_bh_i, "ldrh", 608 UnOpFrag<(zextloadi16 node:$Src)>>; 609 610let AddedComplexity = 10 in 611def tLDRSB : // A8.6.80 612 T1pILdStEncode<0b011, (outs tGPR:$Rt), (ins t_addrmode_rr:$addr), 613 AddrModeT1_1, IIC_iLoad_bh_r, 614 "ldrsb", "\t$Rt, $addr", 615 [(set tGPR:$Rt, (sextloadi8 t_addrmode_rr:$addr))]>; 616 617let AddedComplexity = 10 in 618def tLDRSH : // A8.6.84 619 T1pILdStEncode<0b111, (outs tGPR:$Rt), (ins t_addrmode_rr:$addr), 620 AddrModeT1_2, IIC_iLoad_bh_r, 621 "ldrsh", "\t$Rt, $addr", 622 [(set tGPR:$Rt, (sextloadi16 t_addrmode_rr:$addr))]>; 623 624let canFoldAsLoad = 1 in 625def tLDRspi : T1pIs<(outs tGPR:$Rt), (ins t_addrmode_sp:$addr), IIC_iLoad_i, 626 "ldr", "\t$Rt, $addr", 627 [(set tGPR:$Rt, (load t_addrmode_sp:$addr))]>, 628 T1LdStSP<{1,?,?}> { 629 bits<3> Rt; 630 bits<8> addr; 631 let Inst{10-8} = Rt; 632 let Inst{7-0} = addr; 633} 634 635// Load tconstpool 636// FIXME: Use ldr.n to work around a Darwin assembler bug. 637let canFoldAsLoad = 1, isReMaterializable = 1, isCodeGenOnly = 1 in 638def tLDRpci : T1pIs<(outs tGPR:$Rt), (ins t_addrmode_pc:$addr), IIC_iLoad_i, 639 "ldr", ".n\t$Rt, $addr", 640 [(set tGPR:$Rt, (load (ARMWrapper tconstpool:$addr)))]>, 641 T1Encoding<{0,1,0,0,1,?}> { 642 // A6.2 & A8.6.59 643 bits<3> Rt; 644 bits<8> addr; 645 let Inst{10-8} = Rt; 646 let Inst{7-0} = addr; 647} 648 649// FIXME: Remove this entry when the above ldr.n workaround is fixed. 650// For disassembly use only. 651def tLDRpciDIS : T1pIs<(outs tGPR:$Rt), (ins t_addrmode_pc:$addr), IIC_iLoad_i, 652 "ldr", "\t$Rt, $addr", 653 [/* disassembly only */]>, 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// A8.6.194 & A8.6.192 663defm tSTR : thumb_st_rr_ri_enc<0b000, 0b0110, t_addrmode_rrs4, 664 t_addrmode_is4, AddrModeT1_4, 665 IIC_iStore_r, IIC_iStore_i, "str", 666 BinOpFrag<(store node:$LHS, node:$RHS)>>; 667 668// A8.6.197 & A8.6.195 669defm tSTRB : thumb_st_rr_ri_enc<0b010, 0b0111, t_addrmode_rrs1, 670 t_addrmode_is1, AddrModeT1_1, 671 IIC_iStore_bh_r, IIC_iStore_bh_i, "strb", 672 BinOpFrag<(truncstorei8 node:$LHS, node:$RHS)>>; 673 674// A8.6.207 & A8.6.205 675defm tSTRH : thumb_st_rr_ri_enc<0b001, 0b1000, t_addrmode_rrs2, 676 t_addrmode_is2, AddrModeT1_2, 677 IIC_iStore_bh_r, IIC_iStore_bh_i, "strh", 678 BinOpFrag<(truncstorei16 node:$LHS, node:$RHS)>>; 679 680 681def tSTRspi : T1pIs<(outs), (ins tGPR:$Rt, t_addrmode_sp:$addr), IIC_iStore_i, 682 "str", "\t$Rt, $addr", 683 [(store tGPR:$Rt, t_addrmode_sp:$addr)]>, 684 T1LdStSP<{0,?,?}> { 685 bits<3> Rt; 686 bits<8> addr; 687 let Inst{10-8} = Rt; 688 let Inst{7-0} = addr; 689} 690 691//===----------------------------------------------------------------------===// 692// Load / store multiple Instructions. 693// 694 695multiclass thumb_ldst_mult<string asm, InstrItinClass itin, 696 InstrItinClass itin_upd, bits<6> T1Enc, 697 bit L_bit, string baseOpc> { 698 def IA : 699 T1I<(outs), (ins tGPR:$Rn, pred:$p, reglist:$regs, variable_ops), 700 itin, !strconcat(asm, "${p}\t$Rn, $regs"), []>, 701 T1Encoding<T1Enc> { 702 bits<3> Rn; 703 bits<8> regs; 704 let Inst{10-8} = Rn; 705 let Inst{7-0} = regs; 706 } 707 708 def IA_UPD : 709 InstTemplate<AddrModeNone, 0, IndexModeNone, Pseudo, GenericDomain, 710 "$Rn = $wb", itin_upd>, 711 PseudoInstExpansion<(!cast<Instruction>(!strconcat(baseOpc, "IA")) 712 tGPR:$Rn, pred:$p, reglist:$regs)> { 713 let Size = 2; 714 let OutOperandList = (outs GPR:$wb); 715 let InOperandList = (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops); 716 let Pattern = []; 717 let isCodeGenOnly = 1; 718 let isPseudo = 1; 719 list<Predicate> Predicates = [IsThumb]; 720 } 721} 722 723// These require base address to be written back or one of the loaded regs. 724let neverHasSideEffects = 1 in { 725 726let mayLoad = 1, hasExtraDefRegAllocReq = 1 in 727defm tLDM : thumb_ldst_mult<"ldm", IIC_iLoad_m, IIC_iLoad_mu, 728 {1,1,0,0,1,?}, 1, "tLDM">; 729 730let mayStore = 1, hasExtraSrcRegAllocReq = 1 in 731defm tSTM : thumb_ldst_mult<"stm", IIC_iStore_m, IIC_iStore_mu, 732 {1,1,0,0,0,?}, 0, "tSTM">; 733 734} // neverHasSideEffects 735 736def : InstAlias<"ldm${p} $Rn!, $regs", 737 (tLDMIA tGPR:$Rn, pred:$p, reglist:$regs)>, 738 Requires<[IsThumb, IsThumb1Only]>; 739 740 741let mayLoad = 1, Uses = [SP], Defs = [SP], hasExtraDefRegAllocReq = 1 in 742def tPOP : T1I<(outs), (ins pred:$p, reglist:$regs, variable_ops), 743 IIC_iPop, 744 "pop${p}\t$regs", []>, 745 T1Misc<{1,1,0,?,?,?,?}> { 746 bits<16> regs; 747 let Inst{8} = regs{15}; 748 let Inst{7-0} = regs{7-0}; 749} 750 751let mayStore = 1, Uses = [SP], Defs = [SP], hasExtraSrcRegAllocReq = 1 in 752def tPUSH : T1I<(outs), (ins pred:$p, reglist:$regs, variable_ops), 753 IIC_iStore_m, 754 "push${p}\t$regs", []>, 755 T1Misc<{0,1,0,?,?,?,?}> { 756 bits<16> regs; 757 let Inst{8} = regs{14}; 758 let Inst{7-0} = regs{7-0}; 759} 760 761//===----------------------------------------------------------------------===// 762// Arithmetic Instructions. 763// 764 765// Helper classes for encoding T1pI patterns: 766class T1pIDPEncode<bits<4> opA, dag oops, dag iops, InstrItinClass itin, 767 string opc, string asm, list<dag> pattern> 768 : T1pI<oops, iops, itin, opc, asm, pattern>, 769 T1DataProcessing<opA> { 770 bits<3> Rm; 771 bits<3> Rn; 772 let Inst{5-3} = Rm; 773 let Inst{2-0} = Rn; 774} 775class T1pIMiscEncode<bits<7> opA, dag oops, dag iops, InstrItinClass itin, 776 string opc, string asm, list<dag> pattern> 777 : T1pI<oops, iops, itin, opc, asm, pattern>, 778 T1Misc<opA> { 779 bits<3> Rm; 780 bits<3> Rd; 781 let Inst{5-3} = Rm; 782 let Inst{2-0} = Rd; 783} 784 785// Helper classes for encoding T1sI patterns: 786class T1sIDPEncode<bits<4> opA, dag oops, dag iops, InstrItinClass itin, 787 string opc, string asm, list<dag> pattern> 788 : T1sI<oops, iops, itin, opc, asm, pattern>, 789 T1DataProcessing<opA> { 790 bits<3> Rd; 791 bits<3> Rn; 792 let Inst{5-3} = Rn; 793 let Inst{2-0} = Rd; 794} 795class T1sIGenEncode<bits<5> opA, dag oops, dag iops, InstrItinClass itin, 796 string opc, string asm, list<dag> pattern> 797 : T1sI<oops, iops, itin, opc, asm, pattern>, 798 T1General<opA> { 799 bits<3> Rm; 800 bits<3> Rn; 801 bits<3> Rd; 802 let Inst{8-6} = Rm; 803 let Inst{5-3} = Rn; 804 let Inst{2-0} = Rd; 805} 806class T1sIGenEncodeImm<bits<5> opA, dag oops, dag iops, InstrItinClass itin, 807 string opc, string asm, list<dag> pattern> 808 : T1sI<oops, iops, itin, opc, asm, pattern>, 809 T1General<opA> { 810 bits<3> Rd; 811 bits<3> Rm; 812 let Inst{5-3} = Rm; 813 let Inst{2-0} = Rd; 814} 815 816// Helper classes for encoding T1sIt patterns: 817class T1sItDPEncode<bits<4> opA, dag oops, dag iops, InstrItinClass itin, 818 string opc, string asm, list<dag> pattern> 819 : T1sIt<oops, iops, itin, opc, asm, pattern>, 820 T1DataProcessing<opA> { 821 bits<3> Rdn; 822 bits<3> Rm; 823 let Inst{5-3} = Rm; 824 let Inst{2-0} = Rdn; 825} 826class T1sItGenEncodeImm<bits<5> opA, dag oops, dag iops, InstrItinClass itin, 827 string opc, string asm, list<dag> pattern> 828 : T1sIt<oops, iops, itin, opc, asm, pattern>, 829 T1General<opA> { 830 bits<3> Rdn; 831 bits<8> imm8; 832 let Inst{10-8} = Rdn; 833 let Inst{7-0} = imm8; 834} 835 836// Add with carry register 837let isCommutable = 1, Uses = [CPSR] in 838def tADC : // A8.6.2 839 T1sItDPEncode<0b0101, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), IIC_iALUr, 840 "adc", "\t$Rdn, $Rm", 841 [(set tGPR:$Rdn, (adde tGPR:$Rn, tGPR:$Rm))]>; 842 843// Add immediate 844def tADDi3 : // A8.6.4 T1 845 T1sIGenEncodeImm<0b01110, (outs tGPR:$Rd), (ins tGPR:$Rm, imm0_7:$imm3), 846 IIC_iALUi, 847 "add", "\t$Rd, $Rm, $imm3", 848 [(set tGPR:$Rd, (add tGPR:$Rm, imm0_7:$imm3))]> { 849 bits<3> imm3; 850 let Inst{8-6} = imm3; 851} 852 853def tADDi8 : // A8.6.4 T2 854 T1sItGenEncodeImm<{1,1,0,?,?}, (outs tGPR:$Rdn), 855 (ins tGPR:$Rn, imm0_255:$imm8), IIC_iALUi, 856 "add", "\t$Rdn, $imm8", 857 [(set tGPR:$Rdn, (add tGPR:$Rn, imm8_255:$imm8))]>; 858 859// Add register 860let isCommutable = 1 in 861def tADDrr : // A8.6.6 T1 862 T1sIGenEncode<0b01100, (outs tGPR:$Rd), (ins tGPR:$Rn, tGPR:$Rm), 863 IIC_iALUr, 864 "add", "\t$Rd, $Rn, $Rm", 865 [(set tGPR:$Rd, (add tGPR:$Rn, tGPR:$Rm))]>; 866 867let neverHasSideEffects = 1 in 868def tADDhirr : T1pIt<(outs GPR:$Rdn), (ins GPR:$Rn, GPR:$Rm), IIC_iALUr, 869 "add", "\t$Rdn, $Rm", []>, 870 T1Special<{0,0,?,?}> { 871 // A8.6.6 T2 872 bits<4> Rdn; 873 bits<4> Rm; 874 let Inst{7} = Rdn{3}; 875 let Inst{6-3} = Rm; 876 let Inst{2-0} = Rdn{2-0}; 877} 878 879// AND register 880let isCommutable = 1 in 881def tAND : // A8.6.12 882 T1sItDPEncode<0b0000, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 883 IIC_iBITr, 884 "and", "\t$Rdn, $Rm", 885 [(set tGPR:$Rdn, (and tGPR:$Rn, tGPR:$Rm))]>; 886 887// ASR immediate 888def tASRri : // A8.6.14 889 T1sIGenEncodeImm<{0,1,0,?,?}, (outs tGPR:$Rd), (ins tGPR:$Rm, imm_sr:$imm5), 890 IIC_iMOVsi, 891 "asr", "\t$Rd, $Rm, $imm5", 892 [(set tGPR:$Rd, (sra tGPR:$Rm, (i32 imm_sr:$imm5)))]> { 893 bits<5> imm5; 894 let Inst{10-6} = imm5; 895} 896 897// ASR register 898def tASRrr : // A8.6.15 899 T1sItDPEncode<0b0100, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 900 IIC_iMOVsr, 901 "asr", "\t$Rdn, $Rm", 902 [(set tGPR:$Rdn, (sra tGPR:$Rn, tGPR:$Rm))]>; 903 904// BIC register 905def tBIC : // A8.6.20 906 T1sItDPEncode<0b1110, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 907 IIC_iBITr, 908 "bic", "\t$Rdn, $Rm", 909 [(set tGPR:$Rdn, (and tGPR:$Rn, (not tGPR:$Rm)))]>; 910 911// CMN register 912let isCompare = 1, Defs = [CPSR] in { 913//FIXME: Disable CMN, as CCodes are backwards from compare expectations 914// Compare-to-zero still works out, just not the relationals 915//def tCMN : // A8.6.33 916// T1pIDPEncode<0b1011, (outs), (ins tGPR:$lhs, tGPR:$rhs), 917// IIC_iCMPr, 918// "cmn", "\t$lhs, $rhs", 919// [(ARMcmp tGPR:$lhs, (ineg tGPR:$rhs))]>; 920 921def tCMNz : // A8.6.33 922 T1pIDPEncode<0b1011, (outs), (ins tGPR:$Rn, tGPR:$Rm), 923 IIC_iCMPr, 924 "cmn", "\t$Rn, $Rm", 925 [(ARMcmpZ tGPR:$Rn, (ineg tGPR:$Rm))]>; 926 927} // isCompare = 1, Defs = [CPSR] 928 929// CMP immediate 930let isCompare = 1, Defs = [CPSR] in { 931def tCMPi8 : T1pI<(outs), (ins tGPR:$Rn, imm0_255:$imm8), IIC_iCMPi, 932 "cmp", "\t$Rn, $imm8", 933 [(ARMcmp tGPR:$Rn, imm0_255:$imm8)]>, 934 T1General<{1,0,1,?,?}> { 935 // A8.6.35 936 bits<3> Rn; 937 bits<8> imm8; 938 let Inst{10-8} = Rn; 939 let Inst{7-0} = imm8; 940} 941 942// CMP register 943def tCMPr : // A8.6.36 T1 944 T1pIDPEncode<0b1010, (outs), (ins tGPR:$Rn, tGPR:$Rm), 945 IIC_iCMPr, 946 "cmp", "\t$Rn, $Rm", 947 [(ARMcmp tGPR:$Rn, tGPR:$Rm)]>; 948 949def tCMPhir : T1pI<(outs), (ins GPR:$Rn, GPR:$Rm), IIC_iCMPr, 950 "cmp", "\t$Rn, $Rm", []>, 951 T1Special<{0,1,?,?}> { 952 // A8.6.36 T2 953 bits<4> Rm; 954 bits<4> Rn; 955 let Inst{7} = Rn{3}; 956 let Inst{6-3} = Rm; 957 let Inst{2-0} = Rn{2-0}; 958} 959} // isCompare = 1, Defs = [CPSR] 960 961 962// XOR register 963let isCommutable = 1 in 964def tEOR : // A8.6.45 965 T1sItDPEncode<0b0001, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 966 IIC_iBITr, 967 "eor", "\t$Rdn, $Rm", 968 [(set tGPR:$Rdn, (xor tGPR:$Rn, tGPR:$Rm))]>; 969 970// LSL immediate 971def tLSLri : // A8.6.88 972 T1sIGenEncodeImm<{0,0,0,?,?}, (outs tGPR:$Rd), (ins tGPR:$Rm, i32imm:$imm5), 973 IIC_iMOVsi, 974 "lsl", "\t$Rd, $Rm, $imm5", 975 [(set tGPR:$Rd, (shl tGPR:$Rm, (i32 imm:$imm5)))]> { 976 bits<5> imm5; 977 let Inst{10-6} = imm5; 978} 979 980// LSL register 981def tLSLrr : // A8.6.89 982 T1sItDPEncode<0b0010, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 983 IIC_iMOVsr, 984 "lsl", "\t$Rdn, $Rm", 985 [(set tGPR:$Rdn, (shl tGPR:$Rn, tGPR:$Rm))]>; 986 987// LSR immediate 988def tLSRri : // A8.6.90 989 T1sIGenEncodeImm<{0,0,1,?,?}, (outs tGPR:$Rd), (ins tGPR:$Rm, imm_sr:$imm5), 990 IIC_iMOVsi, 991 "lsr", "\t$Rd, $Rm, $imm5", 992 [(set tGPR:$Rd, (srl tGPR:$Rm, (i32 imm_sr:$imm5)))]> { 993 bits<5> imm5; 994 let Inst{10-6} = imm5; 995} 996 997// LSR register 998def tLSRrr : // A8.6.91 999 T1sItDPEncode<0b0011, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 1000 IIC_iMOVsr, 1001 "lsr", "\t$Rdn, $Rm", 1002 [(set tGPR:$Rdn, (srl tGPR:$Rn, tGPR:$Rm))]>; 1003 1004// Move register 1005let isMoveImm = 1 in 1006def tMOVi8 : T1sI<(outs tGPR:$Rd), (ins imm0_255:$imm8), IIC_iMOVi, 1007 "mov", "\t$Rd, $imm8", 1008 [(set tGPR:$Rd, imm0_255:$imm8)]>, 1009 T1General<{1,0,0,?,?}> { 1010 // A8.6.96 1011 bits<3> Rd; 1012 bits<8> imm8; 1013 let Inst{10-8} = Rd; 1014 let Inst{7-0} = imm8; 1015} 1016 1017// A7-73: MOV(2) - mov setting flag. 1018 1019let neverHasSideEffects = 1 in { 1020def tMOVr : Thumb1pI<(outs GPR:$Rd), (ins GPR:$Rm), AddrModeNone, 1021 2, IIC_iMOVr, 1022 "mov", "\t$Rd, $Rm", "", []>, 1023 T1Special<{1,0,?,?}> { 1024 // A8.6.97 1025 bits<4> Rd; 1026 bits<4> Rm; 1027 let Inst{7} = Rd{3}; 1028 let Inst{6-3} = Rm; 1029 let Inst{2-0} = Rd{2-0}; 1030} 1031let Defs = [CPSR] in 1032def tMOVSr : T1I<(outs tGPR:$Rd), (ins tGPR:$Rm), IIC_iMOVr, 1033 "movs\t$Rd, $Rm", []>, Encoding16 { 1034 // A8.6.97 1035 bits<3> Rd; 1036 bits<3> Rm; 1037 let Inst{15-6} = 0b0000000000; 1038 let Inst{5-3} = Rm; 1039 let Inst{2-0} = Rd; 1040} 1041} // neverHasSideEffects 1042 1043// Multiply register 1044let isCommutable = 1 in 1045def tMUL : // A8.6.105 T1 1046 T1sItDPEncode<0b1101, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 1047 IIC_iMUL32, 1048 "mul", "\t$Rdn, $Rm, $Rdn", 1049 [(set tGPR:$Rdn, (mul tGPR:$Rn, tGPR:$Rm))]>; 1050 1051// Move inverse register 1052def tMVN : // A8.6.107 1053 T1sIDPEncode<0b1111, (outs tGPR:$Rd), (ins tGPR:$Rn), IIC_iMVNr, 1054 "mvn", "\t$Rd, $Rn", 1055 [(set tGPR:$Rd, (not tGPR:$Rn))]>; 1056 1057// Bitwise or register 1058let isCommutable = 1 in 1059def tORR : // A8.6.114 1060 T1sItDPEncode<0b1100, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 1061 IIC_iBITr, 1062 "orr", "\t$Rdn, $Rm", 1063 [(set tGPR:$Rdn, (or tGPR:$Rn, tGPR:$Rm))]>; 1064 1065// Swaps 1066def tREV : // A8.6.134 1067 T1pIMiscEncode<{1,0,1,0,0,0,?}, (outs tGPR:$Rd), (ins tGPR:$Rm), 1068 IIC_iUNAr, 1069 "rev", "\t$Rd, $Rm", 1070 [(set tGPR:$Rd, (bswap tGPR:$Rm))]>, 1071 Requires<[IsThumb, IsThumb1Only, HasV6]>; 1072 1073def tREV16 : // A8.6.135 1074 T1pIMiscEncode<{1,0,1,0,0,1,?}, (outs tGPR:$Rd), (ins tGPR:$Rm), 1075 IIC_iUNAr, 1076 "rev16", "\t$Rd, $Rm", 1077 [(set tGPR:$Rd, (rotr (bswap tGPR:$Rm), (i32 16)))]>, 1078 Requires<[IsThumb, IsThumb1Only, HasV6]>; 1079 1080def tREVSH : // A8.6.136 1081 T1pIMiscEncode<{1,0,1,0,1,1,?}, (outs tGPR:$Rd), (ins tGPR:$Rm), 1082 IIC_iUNAr, 1083 "revsh", "\t$Rd, $Rm", 1084 [(set tGPR:$Rd, (sra (bswap tGPR:$Rm), (i32 16)))]>, 1085 Requires<[IsThumb, IsThumb1Only, HasV6]>; 1086 1087// Rotate right register 1088def tROR : // A8.6.139 1089 T1sItDPEncode<0b0111, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 1090 IIC_iMOVsr, 1091 "ror", "\t$Rdn, $Rm", 1092 [(set tGPR:$Rdn, (rotr tGPR:$Rn, tGPR:$Rm))]>; 1093 1094// Negate register 1095def tRSB : // A8.6.141 1096 T1sIDPEncode<0b1001, (outs tGPR:$Rd), (ins tGPR:$Rn), 1097 IIC_iALUi, 1098 "rsb", "\t$Rd, $Rn, #0", 1099 [(set tGPR:$Rd, (ineg tGPR:$Rn))]>; 1100 1101// Subtract with carry register 1102let Uses = [CPSR] in 1103def tSBC : // A8.6.151 1104 T1sItDPEncode<0b0110, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 1105 IIC_iALUr, 1106 "sbc", "\t$Rdn, $Rm", 1107 [(set tGPR:$Rdn, (sube tGPR:$Rn, tGPR:$Rm))]>; 1108 1109// Subtract immediate 1110def tSUBi3 : // A8.6.210 T1 1111 T1sIGenEncodeImm<0b01111, (outs tGPR:$Rd), (ins tGPR:$Rm, i32imm:$imm3), 1112 IIC_iALUi, 1113 "sub", "\t$Rd, $Rm, $imm3", 1114 [(set tGPR:$Rd, (add tGPR:$Rm, imm0_7_neg:$imm3))]> { 1115 bits<3> imm3; 1116 let Inst{8-6} = imm3; 1117} 1118 1119def tSUBi8 : // A8.6.210 T2 1120 T1sItGenEncodeImm<{1,1,1,?,?}, (outs tGPR:$Rdn), (ins tGPR:$Rn, i32imm:$imm8), 1121 IIC_iALUi, 1122 "sub", "\t$Rdn, $imm8", 1123 [(set tGPR:$Rdn, (add tGPR:$Rn, imm8_255_neg:$imm8))]>; 1124 1125// Subtract register 1126def tSUBrr : // A8.6.212 1127 T1sIGenEncode<0b01101, (outs tGPR:$Rd), (ins tGPR:$Rn, tGPR:$Rm), 1128 IIC_iALUr, 1129 "sub", "\t$Rd, $Rn, $Rm", 1130 [(set tGPR:$Rd, (sub tGPR:$Rn, tGPR:$Rm))]>; 1131 1132// TODO: A7-96: STMIA - store multiple. 1133 1134// Sign-extend byte 1135def tSXTB : // A8.6.222 1136 T1pIMiscEncode<{0,0,1,0,0,1,?}, (outs tGPR:$Rd), (ins tGPR:$Rm), 1137 IIC_iUNAr, 1138 "sxtb", "\t$Rd, $Rm", 1139 [(set tGPR:$Rd, (sext_inreg tGPR:$Rm, i8))]>, 1140 Requires<[IsThumb, IsThumb1Only, HasV6]>; 1141 1142// Sign-extend short 1143def tSXTH : // A8.6.224 1144 T1pIMiscEncode<{0,0,1,0,0,0,?}, (outs tGPR:$Rd), (ins tGPR:$Rm), 1145 IIC_iUNAr, 1146 "sxth", "\t$Rd, $Rm", 1147 [(set tGPR:$Rd, (sext_inreg tGPR:$Rm, i16))]>, 1148 Requires<[IsThumb, IsThumb1Only, HasV6]>; 1149 1150// Test 1151let isCompare = 1, isCommutable = 1, Defs = [CPSR] in 1152def tTST : // A8.6.230 1153 T1pIDPEncode<0b1000, (outs), (ins tGPR:$Rn, tGPR:$Rm), IIC_iTSTr, 1154 "tst", "\t$Rn, $Rm", 1155 [(ARMcmpZ (and_su tGPR:$Rn, tGPR:$Rm), 0)]>; 1156 1157// Zero-extend byte 1158def tUXTB : // A8.6.262 1159 T1pIMiscEncode<{0,0,1,0,1,1,?}, (outs tGPR:$Rd), (ins tGPR:$Rm), 1160 IIC_iUNAr, 1161 "uxtb", "\t$Rd, $Rm", 1162 [(set tGPR:$Rd, (and tGPR:$Rm, 0xFF))]>, 1163 Requires<[IsThumb, IsThumb1Only, HasV6]>; 1164 1165// Zero-extend short 1166def tUXTH : // A8.6.264 1167 T1pIMiscEncode<{0,0,1,0,1,0,?}, (outs tGPR:$Rd), (ins tGPR:$Rm), 1168 IIC_iUNAr, 1169 "uxth", "\t$Rd, $Rm", 1170 [(set tGPR:$Rd, (and tGPR:$Rm, 0xFFFF))]>, 1171 Requires<[IsThumb, IsThumb1Only, HasV6]>; 1172 1173// Conditional move tMOVCCr - Used to implement the Thumb SELECT_CC operation. 1174// Expanded after instruction selection into a branch sequence. 1175let usesCustomInserter = 1 in // Expanded after instruction selection. 1176 def tMOVCCr_pseudo : 1177 PseudoInst<(outs tGPR:$dst), (ins tGPR:$false, tGPR:$true, pred:$cc), 1178 NoItinerary, 1179 [/*(set tGPR:$dst, (ARMcmov tGPR:$false, tGPR:$true, imm:$cc))*/]>; 1180 1181// tLEApcrel - Load a pc-relative address into a register without offending the 1182// assembler. 1183 1184def tADR : T1I<(outs tGPR:$Rd), (ins t_adrlabel:$addr, pred:$p), 1185 IIC_iALUi, "adr{$p}\t$Rd, $addr", []>, 1186 T1Encoding<{1,0,1,0,0,?}> { 1187 bits<3> Rd; 1188 bits<8> addr; 1189 let Inst{10-8} = Rd; 1190 let Inst{7-0} = addr; 1191 let DecoderMethod = "DecodeThumbAddSpecialReg"; 1192} 1193 1194let neverHasSideEffects = 1, isReMaterializable = 1 in 1195def tLEApcrel : tPseudoInst<(outs tGPR:$Rd), (ins i32imm:$label, pred:$p), 1196 2, IIC_iALUi, []>; 1197 1198def tLEApcrelJT : tPseudoInst<(outs tGPR:$Rd), 1199 (ins i32imm:$label, nohash_imm:$id, pred:$p), 1200 2, IIC_iALUi, []>; 1201 1202//===----------------------------------------------------------------------===// 1203// TLS Instructions 1204// 1205 1206// __aeabi_read_tp preserves the registers r1-r3. 1207// This is a pseudo inst so that we can get the encoding right, 1208// complete with fixup for the aeabi_read_tp function. 1209let isCall = 1, Defs = [R0, R12, LR, CPSR], Uses = [SP] in 1210def tTPsoft : tPseudoInst<(outs), (ins), 4, IIC_Br, 1211 [(set R0, ARMthread_pointer)]>; 1212 1213//===----------------------------------------------------------------------===// 1214// SJLJ Exception handling intrinsics 1215// 1216 1217// eh_sjlj_setjmp() is an instruction sequence to store the return address and 1218// save #0 in R0 for the non-longjmp case. Since by its nature we may be coming 1219// from some other function to get here, and we're using the stack frame for the 1220// containing function to save/restore registers, we can't keep anything live in 1221// regs across the eh_sjlj_setjmp(), else it will almost certainly have been 1222// tromped upon when we get here from a longjmp(). We force everything out of 1223// registers except for our own input by listing the relevant registers in 1224// Defs. By doing so, we also cause the prologue/epilogue code to actively 1225// preserve all of the callee-saved resgisters, which is exactly what we want. 1226// $val is a scratch register for our use. 1227let Defs = [ R0, R1, R2, R3, R4, R5, R6, R7, R12, CPSR ], 1228 hasSideEffects = 1, isBarrier = 1, isCodeGenOnly = 1 in 1229def tInt_eh_sjlj_setjmp : ThumbXI<(outs),(ins tGPR:$src, tGPR:$val), 1230 AddrModeNone, 0, NoItinerary, "","", 1231 [(set R0, (ARMeh_sjlj_setjmp tGPR:$src, tGPR:$val))]>; 1232 1233// FIXME: Non-Darwin version(s) 1234let isBarrier = 1, hasSideEffects = 1, isTerminator = 1, isCodeGenOnly = 1, 1235 Defs = [ R7, LR, SP ] in 1236def tInt_eh_sjlj_longjmp : XI<(outs), (ins GPR:$src, GPR:$scratch), 1237 AddrModeNone, 0, IndexModeNone, 1238 Pseudo, NoItinerary, "", "", 1239 [(ARMeh_sjlj_longjmp GPR:$src, GPR:$scratch)]>, 1240 Requires<[IsThumb, IsDarwin]>; 1241 1242//===----------------------------------------------------------------------===// 1243// Non-Instruction Patterns 1244// 1245 1246// Comparisons 1247def : T1Pat<(ARMcmpZ tGPR:$Rn, imm0_255:$imm8), 1248 (tCMPi8 tGPR:$Rn, imm0_255:$imm8)>; 1249def : T1Pat<(ARMcmpZ tGPR:$Rn, tGPR:$Rm), 1250 (tCMPr tGPR:$Rn, tGPR:$Rm)>; 1251 1252// Add with carry 1253def : T1Pat<(addc tGPR:$lhs, imm0_7:$rhs), 1254 (tADDi3 tGPR:$lhs, imm0_7:$rhs)>; 1255def : T1Pat<(addc tGPR:$lhs, imm8_255:$rhs), 1256 (tADDi8 tGPR:$lhs, imm8_255:$rhs)>; 1257def : T1Pat<(addc tGPR:$lhs, tGPR:$rhs), 1258 (tADDrr tGPR:$lhs, tGPR:$rhs)>; 1259 1260// Subtract with carry 1261def : T1Pat<(addc tGPR:$lhs, imm0_7_neg:$rhs), 1262 (tSUBi3 tGPR:$lhs, imm0_7_neg:$rhs)>; 1263def : T1Pat<(addc tGPR:$lhs, imm8_255_neg:$rhs), 1264 (tSUBi8 tGPR:$lhs, imm8_255_neg:$rhs)>; 1265def : T1Pat<(subc tGPR:$lhs, tGPR:$rhs), 1266 (tSUBrr tGPR:$lhs, tGPR:$rhs)>; 1267 1268// ConstantPool, GlobalAddress 1269def : T1Pat<(ARMWrapper tglobaladdr :$dst), (tLEApcrel tglobaladdr :$dst)>; 1270def : T1Pat<(ARMWrapper tconstpool :$dst), (tLEApcrel tconstpool :$dst)>; 1271 1272// JumpTable 1273def : T1Pat<(ARMWrapperJT tjumptable:$dst, imm:$id), 1274 (tLEApcrelJT tjumptable:$dst, imm:$id)>; 1275 1276// Direct calls 1277def : T1Pat<(ARMtcall texternalsym:$func), (tBL texternalsym:$func)>, 1278 Requires<[IsThumb, IsNotDarwin]>; 1279def : T1Pat<(ARMtcall texternalsym:$func), (tBLr9 texternalsym:$func)>, 1280 Requires<[IsThumb, IsDarwin]>; 1281 1282def : Tv5Pat<(ARMcall texternalsym:$func), (tBLXi texternalsym:$func)>, 1283 Requires<[IsThumb, HasV5T, IsNotDarwin]>; 1284def : Tv5Pat<(ARMcall texternalsym:$func), (tBLXi_r9 texternalsym:$func)>, 1285 Requires<[IsThumb, HasV5T, IsDarwin]>; 1286 1287// Indirect calls to ARM routines 1288def : Tv5Pat<(ARMcall GPR:$dst), (tBLXr GPR:$dst)>, 1289 Requires<[IsThumb, HasV5T, IsNotDarwin]>; 1290def : Tv5Pat<(ARMcall GPR:$dst), (tBLXr_r9 GPR:$dst)>, 1291 Requires<[IsThumb, HasV5T, IsDarwin]>; 1292 1293// zextload i1 -> zextload i8 1294def : T1Pat<(zextloadi1 t_addrmode_rrs1:$addr), 1295 (tLDRBr t_addrmode_rrs1:$addr)>; 1296def : T1Pat<(zextloadi1 t_addrmode_is1:$addr), 1297 (tLDRBi t_addrmode_is1:$addr)>; 1298 1299// extload -> zextload 1300def : T1Pat<(extloadi1 t_addrmode_rrs1:$addr), (tLDRBr t_addrmode_rrs1:$addr)>; 1301def : T1Pat<(extloadi1 t_addrmode_is1:$addr), (tLDRBi t_addrmode_is1:$addr)>; 1302def : T1Pat<(extloadi8 t_addrmode_rrs1:$addr), (tLDRBr t_addrmode_rrs1:$addr)>; 1303def : T1Pat<(extloadi8 t_addrmode_is1:$addr), (tLDRBi t_addrmode_is1:$addr)>; 1304def : T1Pat<(extloadi16 t_addrmode_rrs2:$addr), (tLDRHr t_addrmode_rrs2:$addr)>; 1305def : T1Pat<(extloadi16 t_addrmode_is2:$addr), (tLDRHi t_addrmode_is2:$addr)>; 1306 1307// If it's impossible to use [r,r] address mode for sextload, select to 1308// ldr{b|h} + sxt{b|h} instead. 1309def : T1Pat<(sextloadi8 t_addrmode_is1:$addr), 1310 (tSXTB (tLDRBi t_addrmode_is1:$addr))>, 1311 Requires<[IsThumb, IsThumb1Only, HasV6]>; 1312def : T1Pat<(sextloadi8 t_addrmode_rrs1:$addr), 1313 (tSXTB (tLDRBr t_addrmode_rrs1:$addr))>, 1314 Requires<[IsThumb, IsThumb1Only, HasV6]>; 1315def : T1Pat<(sextloadi16 t_addrmode_is2:$addr), 1316 (tSXTH (tLDRHi t_addrmode_is2:$addr))>, 1317 Requires<[IsThumb, IsThumb1Only, HasV6]>; 1318def : T1Pat<(sextloadi16 t_addrmode_rrs2:$addr), 1319 (tSXTH (tLDRHr t_addrmode_rrs2:$addr))>, 1320 Requires<[IsThumb, IsThumb1Only, HasV6]>; 1321 1322def : T1Pat<(sextloadi8 t_addrmode_rrs1:$addr), 1323 (tASRri (tLSLri (tLDRBr t_addrmode_rrs1:$addr), 24), 24)>; 1324def : T1Pat<(sextloadi8 t_addrmode_is1:$addr), 1325 (tASRri (tLSLri (tLDRBi t_addrmode_is1:$addr), 24), 24)>; 1326def : T1Pat<(sextloadi16 t_addrmode_rrs2:$addr), 1327 (tASRri (tLSLri (tLDRHr t_addrmode_rrs2:$addr), 16), 16)>; 1328def : T1Pat<(sextloadi16 t_addrmode_is2:$addr), 1329 (tASRri (tLSLri (tLDRHi t_addrmode_is2:$addr), 16), 16)>; 1330 1331// Large immediate handling. 1332 1333// Two piece imms. 1334def : T1Pat<(i32 thumb_immshifted:$src), 1335 (tLSLri (tMOVi8 (thumb_immshifted_val imm:$src)), 1336 (thumb_immshifted_shamt imm:$src))>; 1337 1338def : T1Pat<(i32 imm0_255_comp:$src), 1339 (tMVN (tMOVi8 (imm_comp_XFORM imm:$src)))>; 1340 1341// Pseudo instruction that combines ldr from constpool and add pc. This should 1342// be expanded into two instructions late to allow if-conversion and 1343// scheduling. 1344let isReMaterializable = 1 in 1345def tLDRpci_pic : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr, pclabel:$cp), 1346 NoItinerary, 1347 [(set GPR:$dst, (ARMpic_add (load (ARMWrapper tconstpool:$addr)), 1348 imm:$cp))]>, 1349 Requires<[IsThumb, IsThumb1Only]>; 1350 1351// Pseudo-instruction for merged POP and return. 1352// FIXME: remove when we have a way to marking a MI with these properties. 1353let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1, 1354 hasExtraDefRegAllocReq = 1 in 1355def tPOP_RET : tPseudoExpand<(outs), (ins pred:$p, reglist:$regs, variable_ops), 1356 2, IIC_iPop_Br, [], 1357 (tPOP pred:$p, reglist:$regs)>; 1358 1359// Indirect branch using "mov pc, $Rm" 1360let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { 1361 def tBRIND : tPseudoExpand<(outs), (ins GPR:$Rm, pred:$p), 1362 2, IIC_Br, [(brind GPR:$Rm)], 1363 (tMOVr PC, GPR:$Rm, pred:$p)>; 1364} 1365