1234353Sdim//===-- ARMInstrThumb.td - Thumb support for ARM -----------*- tablegen -*-===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10193323Sed// This file describes the Thumb instruction set. 11193323Sed// 12193323Sed//===----------------------------------------------------------------------===// 13193323Sed 14193323Sed//===----------------------------------------------------------------------===// 15193323Sed// Thumb specific DAG Nodes. 16193323Sed// 17193323Sed 18193323Seddef ARMtcall : SDNode<"ARMISD::tCALL", SDT_ARMcall, 19218893Sdim [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, 20205407Srdivacky SDNPVariadic]>; 21193323Sed 22226633Sdimdef imm_sr_XFORM: SDNodeXForm<imm, [{ 23226633Sdim unsigned Imm = N->getZExtValue(); 24226633Sdim return CurDAG->getTargetConstant((Imm == 32 ? 0 : Imm), MVT::i32); 25226633Sdim}]>; 26226633Sdimdef ThumbSRImmAsmOperand: AsmOperandClass { let Name = "ImmThumbSR"; } 27226633Sdimdef imm_sr : Operand<i32>, PatLeaf<(imm), [{ 28226633Sdim uint64_t Imm = N->getZExtValue(); 29226633Sdim return Imm > 0 && Imm <= 32; 30226633Sdim}], imm_sr_XFORM> { 31226633Sdim let PrintMethod = "printThumbSRImm"; 32226633Sdim let ParserMatchClass = ThumbSRImmAsmOperand; 33226633Sdim} 34226633Sdim 35193323Seddef imm_comp_XFORM : SDNodeXForm<imm, [{ 36193323Sed return CurDAG->getTargetConstant(~((uint32_t)N->getZExtValue()), MVT::i32); 37193323Sed}]>; 38193323Sed 39193323Seddef imm0_7_neg : PatLeaf<(i32 imm), [{ 40193323Sed return (uint32_t)-N->getZExtValue() < 8; 41193323Sed}], imm_neg_XFORM>; 42193323Sed 43193323Seddef imm0_255_comp : PatLeaf<(i32 imm), [{ 44193323Sed return ~((uint32_t)N->getZExtValue()) < 256; 45193323Sed}]>; 46193323Sed 47221345Sdimdef imm8_255 : ImmLeaf<i32, [{ 48221345Sdim return Imm >= 8 && Imm < 256; 49193323Sed}]>; 50193323Seddef imm8_255_neg : PatLeaf<(i32 imm), [{ 51193323Sed unsigned Val = -N->getZExtValue(); 52193323Sed return Val >= 8 && Val < 256; 53193323Sed}], imm_neg_XFORM>; 54193323Sed 55218893Sdim// Break imm's up into two pieces: an immediate + a left shift. This uses 56218893Sdim// thumb_immshifted to match and thumb_immshifted_val and thumb_immshifted_shamt 57218893Sdim// to get the val/shift pieces. 58193323Seddef thumb_immshifted : PatLeaf<(imm), [{ 59193323Sed return ARM_AM::isThumbImmShiftedVal((unsigned)N->getZExtValue()); 60193323Sed}]>; 61193323Sed 62193323Seddef thumb_immshifted_val : SDNodeXForm<imm, [{ 63193323Sed unsigned V = ARM_AM::getThumbImmNonShiftedVal((unsigned)N->getZExtValue()); 64193323Sed return CurDAG->getTargetConstant(V, MVT::i32); 65193323Sed}]>; 66193323Sed 67193323Seddef thumb_immshifted_shamt : SDNodeXForm<imm, [{ 68193323Sed unsigned V = ARM_AM::getThumbImmValShift((unsigned)N->getZExtValue()); 69193323Sed return CurDAG->getTargetConstant(V, MVT::i32); 70193323Sed}]>; 71193323Sed 72199511Srdivacky// Scaled 4 immediate. 73226633Sdimdef t_imm0_1020s4_asmoperand: AsmOperandClass { let Name = "Imm0_1020s4"; } 74226633Sdimdef t_imm0_1020s4 : Operand<i32> { 75199511Srdivacky let PrintMethod = "printThumbS4ImmOperand"; 76226633Sdim let ParserMatchClass = t_imm0_1020s4_asmoperand; 77224145Sdim let OperandType = "OPERAND_IMMEDIATE"; 78199511Srdivacky} 79199511Srdivacky 80226633Sdimdef t_imm0_508s4_asmoperand: AsmOperandClass { let Name = "Imm0_508s4"; } 81226633Sdimdef t_imm0_508s4 : Operand<i32> { 82226633Sdim let PrintMethod = "printThumbS4ImmOperand"; 83226633Sdim let ParserMatchClass = t_imm0_508s4_asmoperand; 84226633Sdim let OperandType = "OPERAND_IMMEDIATE"; 85226633Sdim} 86234353Sdim// Alias use only, so no printer is necessary. 87234353Sdimdef t_imm0_508s4_neg_asmoperand: AsmOperandClass { let Name = "Imm0_508s4Neg"; } 88234353Sdimdef t_imm0_508s4_neg : Operand<i32> { 89234353Sdim let ParserMatchClass = t_imm0_508s4_neg_asmoperand; 90234353Sdim let OperandType = "OPERAND_IMMEDIATE"; 91234353Sdim} 92226633Sdim 93193323Sed// Define Thumb specific addressing modes. 94193323Sed 95263508Sdim// unsigned 8-bit, 2-scaled memory offset 96263508Sdimclass OperandUnsignedOffset_b8s2 : AsmOperandClass { 97263508Sdim let Name = "UnsignedOffset_b8s2"; 98263508Sdim let PredicateMethod = "isUnsignedOffset<8, 2>"; 99263508Sdim} 100263508Sdim 101263508Sdimdef UnsignedOffset_b8s2 : OperandUnsignedOffset_b8s2; 102263508Sdim 103263508Sdim// thumb style PC relative operand. signed, 8 bits magnitude, 104263508Sdim// two bits shift. can be represented as either [pc, #imm], #imm, 105263508Sdim// or relocatable expression... 106263508Sdimdef ThumbMemPC : AsmOperandClass { 107263508Sdim let Name = "ThumbMemPC"; 108263508Sdim} 109263508Sdim 110224145Sdimlet OperandType = "OPERAND_PCREL" in { 111218893Sdimdef t_brtarget : Operand<OtherVT> { 112218893Sdim let EncoderMethod = "getThumbBRTargetOpValue"; 113226633Sdim let DecoderMethod = "DecodeThumbBROperand"; 114218893Sdim} 115218893Sdim 116263508Sdim// ADR instruction labels. 117263508Sdimdef t_adrlabel : Operand<i32> { 118263508Sdim let EncoderMethod = "getThumbAdrLabelOpValue"; 119263508Sdim let PrintMethod = "printAdrLabelOperand<2>"; 120263508Sdim let ParserMatchClass = UnsignedOffset_b8s2; 121263508Sdim} 122263508Sdim 123218893Sdimdef t_bcctarget : Operand<i32> { 124218893Sdim let EncoderMethod = "getThumbBCCTargetOpValue"; 125226633Sdim let DecoderMethod = "DecodeThumbBCCTargetOperand"; 126218893Sdim} 127218893Sdim 128218893Sdimdef t_cbtarget : Operand<i32> { 129218893Sdim let EncoderMethod = "getThumbCBTargetOpValue"; 130226633Sdim let DecoderMethod = "DecodeThumbCmpBROperand"; 131218893Sdim} 132218893Sdim 133218893Sdimdef t_bltarget : Operand<i32> { 134218893Sdim let EncoderMethod = "getThumbBLTargetOpValue"; 135226633Sdim let DecoderMethod = "DecodeThumbBLTargetOperand"; 136218893Sdim} 137218893Sdim 138218893Sdimdef t_blxtarget : Operand<i32> { 139218893Sdim let EncoderMethod = "getThumbBLXTargetOpValue"; 140226633Sdim let DecoderMethod = "DecodeThumbBLXOffset"; 141218893Sdim} 142263508Sdim 143263508Sdim// t_addrmode_pc := <label> => pc + imm8 * 4 144263508Sdim// 145263508Sdimdef t_addrmode_pc : Operand<i32> { 146263508Sdim let EncoderMethod = "getAddrModePCOpValue"; 147263508Sdim let DecoderMethod = "DecodeThumbAddrModePC"; 148263508Sdim let PrintMethod = "printThumbLdrLabelOperand"; 149263508Sdim let ParserMatchClass = ThumbMemPC; 150224145Sdim} 151263508Sdim} 152218893Sdim 153193323Sed// t_addrmode_rr := reg + reg 154193323Sed// 155226633Sdimdef t_addrmode_rr_asm_operand : AsmOperandClass { let Name = "MemThumbRR"; } 156193323Seddef t_addrmode_rr : Operand<i32>, 157193323Sed ComplexPattern<i32, 2, "SelectThumbAddrModeRR", []> { 158218893Sdim let EncoderMethod = "getThumbAddrModeRegRegOpValue"; 159193323Sed let PrintMethod = "printThumbAddrModeRROperand"; 160226633Sdim let DecoderMethod = "DecodeThumbAddrModeRR"; 161226633Sdim let ParserMatchClass = t_addrmode_rr_asm_operand; 162193323Sed let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); 163193323Sed} 164193323Sed 165218893Sdim// t_addrmode_rrs := reg + reg 166193323Sed// 167226633Sdim// We use separate scaled versions because the Select* functions need 168226633Sdim// to explicitly check for a matching constant and return false here so that 169226633Sdim// the reg+imm forms will match instead. This is a horrible way to do that, 170226633Sdim// as it forces tight coupling between the methods, but it's how selectiondag 171226633Sdim// currently works. 172218893Sdimdef t_addrmode_rrs1 : Operand<i32>, 173218893Sdim ComplexPattern<i32, 2, "SelectThumbAddrModeRI5S1", []> { 174218893Sdim let EncoderMethod = "getThumbAddrModeRegRegOpValue"; 175218893Sdim let PrintMethod = "printThumbAddrModeRROperand"; 176226633Sdim let DecoderMethod = "DecodeThumbAddrModeRR"; 177226633Sdim let ParserMatchClass = t_addrmode_rr_asm_operand; 178218893Sdim let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); 179193323Sed} 180218893Sdimdef t_addrmode_rrs2 : Operand<i32>, 181218893Sdim ComplexPattern<i32, 2, "SelectThumbAddrModeRI5S2", []> { 182218893Sdim let EncoderMethod = "getThumbAddrModeRegRegOpValue"; 183226633Sdim let DecoderMethod = "DecodeThumbAddrModeRR"; 184218893Sdim let PrintMethod = "printThumbAddrModeRROperand"; 185226633Sdim let ParserMatchClass = t_addrmode_rr_asm_operand; 186218893Sdim let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); 187218893Sdim} 188218893Sdimdef t_addrmode_rrs4 : Operand<i32>, 189218893Sdim ComplexPattern<i32, 2, "SelectThumbAddrModeRI5S4", []> { 190218893Sdim let EncoderMethod = "getThumbAddrModeRegRegOpValue"; 191226633Sdim let DecoderMethod = "DecodeThumbAddrModeRR"; 192218893Sdim let PrintMethod = "printThumbAddrModeRROperand"; 193226633Sdim let ParserMatchClass = t_addrmode_rr_asm_operand; 194218893Sdim let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); 195218893Sdim} 196193323Sed 197218893Sdim// t_addrmode_is4 := reg + imm5 * 4 198193323Sed// 199226633Sdimdef t_addrmode_is4_asm_operand : AsmOperandClass { let Name = "MemThumbRIs4"; } 200218893Sdimdef t_addrmode_is4 : Operand<i32>, 201218893Sdim ComplexPattern<i32, 2, "SelectThumbAddrModeImm5S4", []> { 202218893Sdim let EncoderMethod = "getAddrModeISOpValue"; 203226633Sdim let DecoderMethod = "DecodeThumbAddrModeIS"; 204218893Sdim let PrintMethod = "printThumbAddrModeImm5S4Operand"; 205226633Sdim let ParserMatchClass = t_addrmode_is4_asm_operand; 206218893Sdim let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm); 207193323Sed} 208193323Sed 209218893Sdim// t_addrmode_is2 := reg + imm5 * 2 210193323Sed// 211226633Sdimdef t_addrmode_is2_asm_operand : AsmOperandClass { let Name = "MemThumbRIs2"; } 212218893Sdimdef t_addrmode_is2 : Operand<i32>, 213218893Sdim ComplexPattern<i32, 2, "SelectThumbAddrModeImm5S2", []> { 214218893Sdim let EncoderMethod = "getAddrModeISOpValue"; 215226633Sdim let DecoderMethod = "DecodeThumbAddrModeIS"; 216218893Sdim let PrintMethod = "printThumbAddrModeImm5S2Operand"; 217226633Sdim let ParserMatchClass = t_addrmode_is2_asm_operand; 218218893Sdim let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm); 219193323Sed} 220193323Sed 221218893Sdim// t_addrmode_is1 := reg + imm5 222218893Sdim// 223226633Sdimdef t_addrmode_is1_asm_operand : AsmOperandClass { let Name = "MemThumbRIs1"; } 224218893Sdimdef t_addrmode_is1 : Operand<i32>, 225218893Sdim ComplexPattern<i32, 2, "SelectThumbAddrModeImm5S1", []> { 226218893Sdim let EncoderMethod = "getAddrModeISOpValue"; 227226633Sdim let DecoderMethod = "DecodeThumbAddrModeIS"; 228218893Sdim let PrintMethod = "printThumbAddrModeImm5S1Operand"; 229226633Sdim let ParserMatchClass = t_addrmode_is1_asm_operand; 230218893Sdim let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm); 231218893Sdim} 232218893Sdim 233193323Sed// t_addrmode_sp := sp + imm8 * 4 234193323Sed// 235226633Sdim// FIXME: This really shouldn't have an explicit SP operand at all. It should 236226633Sdim// be implicit, just like in the instruction encoding itself. 237226633Sdimdef t_addrmode_sp_asm_operand : AsmOperandClass { let Name = "MemThumbSPI"; } 238193323Seddef t_addrmode_sp : Operand<i32>, 239193323Sed ComplexPattern<i32, 2, "SelectThumbAddrModeSP", []> { 240218893Sdim let EncoderMethod = "getAddrModeThumbSPOpValue"; 241226633Sdim let DecoderMethod = "DecodeThumbAddrModeSP"; 242193323Sed let PrintMethod = "printThumbAddrModeSPOperand"; 243226633Sdim let ParserMatchClass = t_addrmode_sp_asm_operand; 244202375Srdivacky let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); 245193323Sed} 246193323Sed 247193323Sed//===----------------------------------------------------------------------===// 248193323Sed// Miscellaneous Instructions. 249193323Sed// 250193323Sed 251204642Srdivacky// FIXME: Marking these as hasSideEffects is necessary to prevent machine DCE 252204642Srdivacky// from removing one half of the matched pairs. That breaks PEI, which assumes 253204642Srdivacky// these will always be in pairs, and asserts if it finds otherwise. Better way? 254204642Srdivackylet Defs = [SP], Uses = [SP], hasSideEffects = 1 in { 255193323Seddef tADJCALLSTACKUP : 256218893Sdim PseudoInst<(outs), (ins i32imm:$amt1, i32imm:$amt2), NoItinerary, 257218893Sdim [(ARMcallseq_end imm:$amt1, imm:$amt2)]>, 258218893Sdim Requires<[IsThumb, IsThumb1Only]>; 259193323Sed 260193323Seddef tADJCALLSTACKDOWN : 261218893Sdim PseudoInst<(outs), (ins i32imm:$amt), NoItinerary, 262218893Sdim [(ARMcallseq_start imm:$amt)]>, 263218893Sdim Requires<[IsThumb, IsThumb1Only]>; 264193323Sed} 265193323Sed 266226633Sdimclass T1SystemEncoding<bits<8> opc> 267218893Sdim : T1Encoding<0b101111> { 268226633Sdim let Inst{9-8} = 0b11; 269226633Sdim let Inst{7-0} = opc; 270218893Sdim} 271218893Sdim 272263508Sdimdef tHINT : T1pI<(outs), (ins imm0_15:$imm), NoItinerary, "hint", "\t$imm", []>, 273263508Sdim T1SystemEncoding<0x00>, 274263508Sdim Requires<[IsThumb, HasV6M]> { 275263508Sdim bits<4> imm; 276263508Sdim let Inst{7-4} = imm; 277263508Sdim} 278204642Srdivacky 279263508Sdimclass tHintAlias<string Asm, dag Result> : tInstAlias<Asm, Result> { 280263508Sdim let Predicates = [IsThumb, HasV6M]; 281263508Sdim} 282204642Srdivacky 283263508Sdimdef : tHintAlias<"nop$p", (tHINT 0, pred:$p)>; // A8.6.110 284263508Sdimdef : tHintAlias<"yield$p", (tHINT 1, pred:$p)>; // A8.6.410 285263508Sdimdef : tHintAlias<"wfe$p", (tHINT 2, pred:$p)>; // A8.6.408 286263508Sdimdef : tHintAlias<"wfi$p", (tHINT 3, pred:$p)>; // A8.6.409 287263508Sdimdef : tHintAlias<"sev$p", (tHINT 4, pred:$p)>; // A8.6.157 288263508Sdimdef : tInstAlias<"sevl$p", (tHINT 5, pred:$p)> { 289263508Sdim let Predicates = [IsThumb2, HasV8]; 290263508Sdim} 291263508Sdimdef : T2Pat<(int_arm_sevl), (tHINT 5)>; 292204642Srdivacky 293226633Sdim// The imm operand $val can be used by a debugger to store more information 294218893Sdim// about the breakpoint. 295226633Sdimdef tBKPT : T1I<(outs), (ins imm0_255:$val), NoItinerary, "bkpt\t$val", 296226633Sdim []>, 297226633Sdim T1Encoding<0b101111> { 298226633Sdim let Inst{9-8} = 0b10; 299218893Sdim // A8.6.22 300218893Sdim bits<8> val; 301218893Sdim let Inst{7-0} = val; 302218893Sdim} 303218893Sdim 304263508Sdimdef tHLT : T1I<(outs), (ins imm0_63:$val), NoItinerary, "hlt\t$val", 305263508Sdim []>, T1Encoding<0b101110>, Requires<[IsThumb, HasV8]> { 306263508Sdim let Inst{9-6} = 0b1010; 307263508Sdim bits<6> val; 308263508Sdim let Inst{5-0} = val; 309263508Sdim} 310263508Sdim 311226633Sdimdef tSETEND : T1I<(outs), (ins setend_op:$end), NoItinerary, "setend\t$end", 312263508Sdim []>, T1Encoding<0b101101>, Deprecated<HasV8Ops> { 313226633Sdim bits<1> end; 314218893Sdim // A8.6.156 315204642Srdivacky let Inst{9-5} = 0b10010; 316218893Sdim let Inst{4} = 1; 317226633Sdim let Inst{3} = end; 318218893Sdim let Inst{2-0} = 0b000; 319204642Srdivacky} 320204642Srdivacky 321218893Sdim// Change Processor State is a system instruction -- for disassembly only. 322218893Sdimdef tCPS : T1I<(outs), (ins imod_op:$imod, iflags_op:$iflags), 323226633Sdim NoItinerary, "cps$imod $iflags", []>, 324218893Sdim T1Misc<0b0110011> { 325218893Sdim // A8.6.38 & B6.1.1 326218893Sdim bit imod; 327218893Sdim bits<3> iflags; 328218893Sdim 329218893Sdim let Inst{4} = imod; 330218893Sdim let Inst{3} = 0; 331218893Sdim let Inst{2-0} = iflags; 332226633Sdim let DecoderMethod = "DecodeThumbCPS"; 333203954Srdivacky} 334203954Srdivacky 335198090Srdivacky// For both thumb1 and thumb2. 336218893Sdimlet isNotDuplicable = 1, isCodeGenOnly = 1 in 337218893Sdimdef tPICADD : TIt<(outs GPR:$dst), (ins GPR:$lhs, pclabel:$cp), IIC_iALUr, "", 338218893Sdim [(set GPR:$dst, (ARMpic_add GPR:$lhs, imm:$cp))]>, 339263508Sdim T1Special<{0,0,?,?}>, Sched<[WriteALU]> { 340218893Sdim // A8.6.6 341218893Sdim bits<3> dst; 342218893Sdim let Inst{6-3} = 0b1111; // Rm = pc 343218893Sdim let Inst{2-0} = dst; 344201360Srdivacky} 345193323Sed 346218893Sdim// ADD <Rd>, sp, #<imm8> 347226633Sdim// FIXME: This should not be marked as having side effects, and it should be 348226633Sdim// rematerializable. Clearing the side effect bit causes miscompilations, 349226633Sdim// probably because the instruction can be moved around. 350226633Sdimdef tADDrSPi : T1pI<(outs tGPR:$dst), (ins GPRsp:$sp, t_imm0_1020s4:$imm), 351226633Sdim IIC_iALUi, "add", "\t$dst, $sp, $imm", []>, 352263508Sdim T1Encoding<{1,0,1,0,1,?}>, Sched<[WriteALU]> { 353218893Sdim // A6.2 & A8.6.8 354218893Sdim bits<3> dst; 355226633Sdim bits<8> imm; 356218893Sdim let Inst{10-8} = dst; 357226633Sdim let Inst{7-0} = imm; 358226633Sdim let DecoderMethod = "DecodeThumbAddSpecialReg"; 359212904Sdim} 360195098Sed 361218893Sdim// ADD sp, sp, #<imm7> 362226633Sdimdef tADDspi : T1pIt<(outs GPRsp:$Rdn), (ins GPRsp:$Rn, t_imm0_508s4:$imm), 363226633Sdim IIC_iALUi, "add", "\t$Rdn, $imm", []>, 364263508Sdim T1Misc<{0,0,0,0,0,?,?}>, Sched<[WriteALU]> { 365218893Sdim // A6.2.5 & A8.6.8 366226633Sdim bits<7> imm; 367226633Sdim let Inst{6-0} = imm; 368226633Sdim let DecoderMethod = "DecodeThumbAddSPImm"; 369218893Sdim} 370195098Sed 371218893Sdim// SUB sp, sp, #<imm7> 372218893Sdim// FIXME: The encoding and the ASM string don't match up. 373226633Sdimdef tSUBspi : T1pIt<(outs GPRsp:$Rdn), (ins GPRsp:$Rn, t_imm0_508s4:$imm), 374226633Sdim IIC_iALUi, "sub", "\t$Rdn, $imm", []>, 375263508Sdim T1Misc<{0,0,0,0,1,?,?}>, Sched<[WriteALU]> { 376218893Sdim // A6.2.5 & A8.6.214 377226633Sdim bits<7> imm; 378226633Sdim let Inst{6-0} = imm; 379226633Sdim let DecoderMethod = "DecodeThumbAddSPImm"; 380218893Sdim} 381198090Srdivacky 382234353Sdimdef : tInstAlias<"add${p} sp, $imm", 383234353Sdim (tSUBspi SP, t_imm0_508s4_neg:$imm, pred:$p)>; 384234353Sdimdef : tInstAlias<"add${p} sp, sp, $imm", 385234353Sdim (tSUBspi SP, t_imm0_508s4_neg:$imm, pred:$p)>; 386234353Sdim 387226633Sdim// Can optionally specify SP as a three operand instruction. 388226633Sdimdef : tInstAlias<"add${p} sp, sp, $imm", 389226633Sdim (tADDspi SP, t_imm0_508s4:$imm, pred:$p)>; 390226633Sdimdef : tInstAlias<"sub${p} sp, sp, $imm", 391226633Sdim (tSUBspi SP, t_imm0_508s4:$imm, pred:$p)>; 392226633Sdim 393218893Sdim// ADD <Rm>, sp 394239462Sdimdef tADDrSP : T1pI<(outs GPR:$Rdn), (ins GPRsp:$sp, GPR:$Rn), IIC_iALUr, 395239462Sdim "add", "\t$Rdn, $sp, $Rn", []>, 396263508Sdim T1Special<{0,0,?,?}>, Sched<[WriteALU]> { 397218893Sdim // A8.6.9 Encoding T1 398226633Sdim bits<4> Rdn; 399226633Sdim let Inst{7} = Rdn{3}; 400218893Sdim let Inst{6-3} = 0b1101; 401226633Sdim let Inst{2-0} = Rdn{2-0}; 402226633Sdim let DecoderMethod = "DecodeThumbAddSPReg"; 403201360Srdivacky} 404198090Srdivacky 405218893Sdim// ADD sp, <Rm> 406226633Sdimdef tADDspr : T1pIt<(outs GPRsp:$Rdn), (ins GPRsp:$Rn, GPR:$Rm), IIC_iALUr, 407226633Sdim "add", "\t$Rdn, $Rm", []>, 408263508Sdim T1Special<{0,0,?,?}>, Sched<[WriteALU]> { 409201360Srdivacky // A8.6.9 Encoding T2 410226633Sdim bits<4> Rm; 411201360Srdivacky let Inst{7} = 1; 412226633Sdim let Inst{6-3} = Rm; 413201360Srdivacky let Inst{2-0} = 0b101; 414226633Sdim let DecoderMethod = "DecodeThumbAddSPReg"; 415201360Srdivacky} 416195098Sed 417193323Sed//===----------------------------------------------------------------------===// 418193323Sed// Control Flow Instructions. 419193323Sed// 420193323Sed 421198892Srdivacky// Indirect branches 422198892Srdivackylet isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { 423223017Sdim def tBX : TI<(outs), (ins GPR:$Rm, pred:$p), IIC_Br, "bx${p}\t$Rm", []>, 424263508Sdim T1Special<{1,1,0,?}>, Sched<[WriteBr]> { 425223017Sdim // A6.2.3 & A8.6.25 426223017Sdim bits<4> Rm; 427223017Sdim let Inst{6-3} = Rm; 428223017Sdim let Inst{2-0} = 0b000; 429234353Sdim let Unpredictable{2-0} = 0b111; 430223017Sdim } 431198892Srdivacky} 432198892Srdivacky 433224145Sdimlet isReturn = 1, isTerminator = 1, isBarrier = 1 in { 434224145Sdim def tBX_RET : tPseudoExpand<(outs), (ins pred:$p), 2, IIC_Br, 435263508Sdim [(ARMretflag)], (tBX LR, pred:$p)>, Sched<[WriteBr]>; 436224145Sdim 437224145Sdim // Alternative return instruction used by vararg functions. 438224145Sdim def tBX_RET_vararg : tPseudoExpand<(outs), (ins tGPR:$Rm, pred:$p), 439224145Sdim 2, IIC_Br, [], 440263508Sdim (tBX GPR:$Rm, pred:$p)>, Sched<[WriteBr]>; 441218893Sdim} 442193323Sed 443218893Sdim// All calls clobber the non-callee saved registers. SP is marked as a use to 444218893Sdim// prevent stack-pointer assignments that appear immediately before calls from 445218893Sdim// potentially appearing dead. 446193323Sedlet isCall = 1, 447234353Sdim Defs = [LR], Uses = [SP] in { 448198090Srdivacky // Also used for Thumb2 449201360Srdivacky def tBL : TIx2<0b11110, 0b11, 1, 450239462Sdim (outs), (ins pred:$p, t_bltarget:$func), IIC_Br, 451226633Sdim "bl${p}\t$func", 452201360Srdivacky [(ARMtcall tglobaladdr:$func)]>, 453263508Sdim Requires<[IsThumb]>, Sched<[WriteBrL]> { 454239462Sdim bits<24> func; 455239462Sdim let Inst{26} = func{23}; 456218893Sdim let Inst{25-16} = func{20-11}; 457239462Sdim let Inst{13} = func{22}; 458239462Sdim let Inst{11} = func{21}; 459218893Sdim let Inst{10-0} = func{10-0}; 460218893Sdim } 461198090Srdivacky 462198090Srdivacky // ARMv5T and above, also used for Thumb2 463201360Srdivacky def tBLXi : TIx2<0b11110, 0b11, 0, 464239462Sdim (outs), (ins pred:$p, t_blxtarget:$func), IIC_Br, 465226633Sdim "blx${p}\t$func", 466201360Srdivacky [(ARMcall tglobaladdr:$func)]>, 467263508Sdim Requires<[IsThumb, HasV5T]>, Sched<[WriteBrL]> { 468239462Sdim bits<24> func; 469239462Sdim let Inst{26} = func{23}; 470218893Sdim let Inst{25-16} = func{20-11}; 471239462Sdim let Inst{13} = func{22}; 472239462Sdim let Inst{11} = func{21}; 473218893Sdim let Inst{10-1} = func{10-1}; 474218893Sdim let Inst{0} = 0; // func{0} is assumed zero 475218893Sdim } 476198090Srdivacky 477198090Srdivacky // Also used for Thumb2 478239462Sdim def tBLXr : TI<(outs), (ins pred:$p, GPR:$func), IIC_Br, 479226633Sdim "blx${p}\t$func", 480198090Srdivacky [(ARMtcall GPR:$func)]>, 481234353Sdim Requires<[IsThumb, HasV5T]>, 482263508Sdim T1Special<{1,1,1,?}>, Sched<[WriteBrL]> { // A6.2.3 & A8.6.24; 483223017Sdim bits<4> func; 484223017Sdim let Inst{6-3} = func; 485223017Sdim let Inst{2-0} = 0b000; 486223017Sdim } 487198090Srdivacky 488193323Sed // ARMv4T 489239462Sdim def tBX_CALL : tPseudoInst<(outs), (ins tGPR:$func), 490224145Sdim 4, IIC_Br, 491198090Srdivacky [(ARMcall_nolink tGPR:$func)]>, 492263508Sdim Requires<[IsThumb, IsThumb1Only]>, Sched<[WriteBr]>; 493193323Sed} 494193323Sed 495218893Sdimlet isBranch = 1, isTerminator = 1, isBarrier = 1 in { 496218893Sdim let isPredicable = 1 in 497226633Sdim def tB : T1pI<(outs), (ins t_brtarget:$target), IIC_Br, 498226633Sdim "b", "\t$target", [(br bb:$target)]>, 499263508Sdim T1Encoding<{1,1,1,0,0,?}>, Sched<[WriteBr]> { 500218893Sdim bits<11> target; 501218893Sdim let Inst{10-0} = target; 502263508Sdim let AsmMatchConverter = "cvtThumbBranches"; 503263508Sdim } 504193323Sed 505193323Sed // Far jump 506218893Sdim // Just a pseudo for a tBL instruction. Needed to let regalloc know about 507218893Sdim // the clobber of LR. 508198090Srdivacky let Defs = [LR] in 509226633Sdim def tBfar : tPseudoExpand<(outs), (ins t_bltarget:$target, pred:$p), 510263508Sdim 4, IIC_Br, [], (tBL pred:$p, t_bltarget:$target)>, 511263508Sdim Sched<[WriteBrTbl]>; 512193323Sed 513218893Sdim def tBR_JTr : tPseudoInst<(outs), 514218893Sdim (ins tGPR:$target, i32imm:$jt, i32imm:$id), 515224145Sdim 0, IIC_Br, 516263508Sdim [(ARMbrjt tGPR:$target, tjumptable:$jt, imm:$id)]>, 517263508Sdim Sched<[WriteBrTbl]> { 518218893Sdim list<Predicate> Predicates = [IsThumb, IsThumb1Only]; 519193323Sed } 520193323Sed} 521193323Sed 522193323Sed// FIXME: should be able to write a pattern for ARMBrcond, but can't use 523193323Sed// a two-value operand where a dag node expects two operands. :( 524193323Sedlet isBranch = 1, isTerminator = 1 in 525218893Sdim def tBcc : T1I<(outs), (ins t_bcctarget:$target, pred:$p), IIC_Br, 526218893Sdim "b${p}\t$target", 527201360Srdivacky [/*(ARMbrcond bb:$target, imm:$cc)*/]>, 528263508Sdim T1BranchCond<{1,1,0,1}>, Sched<[WriteBr]> { 529218893Sdim bits<4> p; 530218893Sdim bits<8> target; 531218893Sdim let Inst{11-8} = p; 532218893Sdim let Inst{7-0} = target; 533263508Sdim let AsmMatchConverter = "cvtThumbBranches"; 534218893Sdim} 535193323Sed 536263508Sdim 537224145Sdim// Tail calls 538224145Sdimlet isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in { 539234353Sdim // IOS versions. 540234353Sdim let Uses = [SP] in { 541239462Sdim def tTAILJMPr : tPseudoExpand<(outs), (ins tcGPR:$dst), 542224145Sdim 4, IIC_Br, [], 543224145Sdim (tBX GPR:$dst, (ops 14, zero_reg))>, 544263508Sdim Requires<[IsThumb]>, Sched<[WriteBr]>; 545224145Sdim } 546234353Sdim // tTAILJMPd: IOS version uses a Thumb2 branch (no Thumb1 tail calls 547234353Sdim // on IOS), so it's in ARMInstrThumb2.td. 548234353Sdim // Non-IOS version: 549234353Sdim let Uses = [SP] in { 550226633Sdim def tTAILJMPdND : tPseudoExpand<(outs), 551239462Sdim (ins t_brtarget:$dst, pred:$p), 552224145Sdim 4, IIC_Br, [], 553226633Sdim (tB t_brtarget:$dst, pred:$p)>, 554263508Sdim Requires<[IsThumb, IsNotIOS]>, Sched<[WriteBr]>; 555224145Sdim } 556224145Sdim} 557224145Sdim 558224145Sdim 559226633Sdim// A8.6.218 Supervisor Call (Software Interrupt) 560204642Srdivacky// A8.6.16 B: Encoding T1 561204642Srdivacky// If Inst{11-8} == 0b1111 then SEE SVC 562218893Sdimlet isCall = 1, Uses = [SP] in 563226633Sdimdef tSVC : T1pI<(outs), (ins imm0_255:$imm), IIC_Br, 564263508Sdim "svc", "\t$imm", []>, Encoding16, Sched<[WriteBr]> { 565218893Sdim bits<8> imm; 566204642Srdivacky let Inst{15-12} = 0b1101; 567218893Sdim let Inst{11-8} = 0b1111; 568218893Sdim let Inst{7-0} = imm; 569204642Srdivacky} 570204642Srdivacky 571218893Sdim// The assembler uses 0xDEFE for a trap instruction. 572208599Srdivackylet isBarrier = 1, isTerminator = 1 in 573223017Sdimdef tTRAP : TI<(outs), (ins), IIC_Br, 574263508Sdim "trap", [(trap)]>, Encoding16, Sched<[WriteBr]> { 575218893Sdim let Inst = 0xdefe; 576204642Srdivacky} 577204642Srdivacky 578193323Sed//===----------------------------------------------------------------------===// 579193323Sed// Load Store Instructions. 580193323Sed// 581193323Sed 582218893Sdim// Loads: reg/reg and reg/imm5 583204642Srdivackylet canFoldAsLoad = 1, isReMaterializable = 1 in 584218893Sdimmulticlass thumb_ld_rr_ri_enc<bits<3> reg_opc, bits<4> imm_opc, 585218893Sdim Operand AddrMode_r, Operand AddrMode_i, 586218893Sdim AddrMode am, InstrItinClass itin_r, 587218893Sdim InstrItinClass itin_i, string asm, 588218893Sdim PatFrag opnode> { 589218893Sdim def r : // reg/reg 590218893Sdim T1pILdStEncode<reg_opc, 591218893Sdim (outs tGPR:$Rt), (ins AddrMode_r:$addr), 592218893Sdim am, itin_r, asm, "\t$Rt, $addr", 593218893Sdim [(set tGPR:$Rt, (opnode AddrMode_r:$addr))]>; 594218893Sdim def i : // reg/imm5 595218893Sdim T1pILdStEncodeImm<imm_opc, 1 /* Load */, 596218893Sdim (outs tGPR:$Rt), (ins AddrMode_i:$addr), 597218893Sdim am, itin_i, asm, "\t$Rt, $addr", 598218893Sdim [(set tGPR:$Rt, (opnode AddrMode_i:$addr))]>; 599218893Sdim} 600218893Sdim// Stores: reg/reg and reg/imm5 601218893Sdimmulticlass thumb_st_rr_ri_enc<bits<3> reg_opc, bits<4> imm_opc, 602218893Sdim Operand AddrMode_r, Operand AddrMode_i, 603218893Sdim AddrMode am, InstrItinClass itin_r, 604218893Sdim InstrItinClass itin_i, string asm, 605218893Sdim PatFrag opnode> { 606218893Sdim def r : // reg/reg 607218893Sdim T1pILdStEncode<reg_opc, 608218893Sdim (outs), (ins tGPR:$Rt, AddrMode_r:$addr), 609218893Sdim am, itin_r, asm, "\t$Rt, $addr", 610218893Sdim [(opnode tGPR:$Rt, AddrMode_r:$addr)]>; 611218893Sdim def i : // reg/imm5 612218893Sdim T1pILdStEncodeImm<imm_opc, 0 /* Store */, 613218893Sdim (outs), (ins tGPR:$Rt, AddrMode_i:$addr), 614218893Sdim am, itin_i, asm, "\t$Rt, $addr", 615218893Sdim [(opnode tGPR:$Rt, AddrMode_i:$addr)]>; 616218893Sdim} 617193323Sed 618218893Sdim// A8.6.57 & A8.6.60 619218893Sdimdefm tLDR : thumb_ld_rr_ri_enc<0b100, 0b0110, t_addrmode_rrs4, 620218893Sdim t_addrmode_is4, AddrModeT1_4, 621218893Sdim IIC_iLoad_r, IIC_iLoad_i, "ldr", 622218893Sdim UnOpFrag<(load node:$Src)>>; 623193323Sed 624218893Sdim// A8.6.64 & A8.6.61 625218893Sdimdefm tLDRB : thumb_ld_rr_ri_enc<0b110, 0b0111, t_addrmode_rrs1, 626218893Sdim t_addrmode_is1, AddrModeT1_1, 627218893Sdim IIC_iLoad_bh_r, IIC_iLoad_bh_i, "ldrb", 628218893Sdim UnOpFrag<(zextloadi8 node:$Src)>>; 629193323Sed 630218893Sdim// A8.6.76 & A8.6.73 631218893Sdimdefm tLDRH : thumb_ld_rr_ri_enc<0b101, 0b1000, t_addrmode_rrs2, 632218893Sdim t_addrmode_is2, AddrModeT1_2, 633218893Sdim IIC_iLoad_bh_r, IIC_iLoad_bh_i, "ldrh", 634218893Sdim UnOpFrag<(zextloadi16 node:$Src)>>; 635218893Sdim 636198090Srdivackylet AddedComplexity = 10 in 637218893Sdimdef tLDRSB : // A8.6.80 638226633Sdim T1pILdStEncode<0b011, (outs tGPR:$Rt), (ins t_addrmode_rr:$addr), 639218893Sdim AddrModeT1_1, IIC_iLoad_bh_r, 640226633Sdim "ldrsb", "\t$Rt, $addr", 641226633Sdim [(set tGPR:$Rt, (sextloadi8 t_addrmode_rr:$addr))]>; 642193323Sed 643198090Srdivackylet AddedComplexity = 10 in 644218893Sdimdef tLDRSH : // A8.6.84 645226633Sdim T1pILdStEncode<0b111, (outs tGPR:$Rt), (ins t_addrmode_rr:$addr), 646218893Sdim AddrModeT1_2, IIC_iLoad_bh_r, 647226633Sdim "ldrsh", "\t$Rt, $addr", 648226633Sdim [(set tGPR:$Rt, (sextloadi16 t_addrmode_rr:$addr))]>; 649193323Sed 650193323Sedlet canFoldAsLoad = 1 in 651218893Sdimdef tLDRspi : T1pIs<(outs tGPR:$Rt), (ins t_addrmode_sp:$addr), IIC_iLoad_i, 652218893Sdim "ldr", "\t$Rt, $addr", 653218893Sdim [(set tGPR:$Rt, (load t_addrmode_sp:$addr))]>, 654218893Sdim T1LdStSP<{1,?,?}> { 655218893Sdim bits<3> Rt; 656218893Sdim bits<8> addr; 657218893Sdim let Inst{10-8} = Rt; 658218893Sdim let Inst{7-0} = addr; 659218893Sdim} 660193323Sed 661263508Sdimlet canFoldAsLoad = 1, isReMaterializable = 1 in 662218893Sdimdef tLDRpci : T1pIs<(outs tGPR:$Rt), (ins t_addrmode_pc:$addr), IIC_iLoad_i, 663263508Sdim "ldr", "\t$Rt, $addr", 664218893Sdim [(set tGPR:$Rt, (load (ARMWrapper tconstpool:$addr)))]>, 665218893Sdim T1Encoding<{0,1,0,0,1,?}> { 666218893Sdim // A6.2 & A8.6.59 667218893Sdim bits<3> Rt; 668218893Sdim bits<8> addr; 669218893Sdim let Inst{10-8} = Rt; 670218893Sdim let Inst{7-0} = addr; 671218893Sdim} 672193323Sed 673218893Sdim// A8.6.194 & A8.6.192 674218893Sdimdefm tSTR : thumb_st_rr_ri_enc<0b000, 0b0110, t_addrmode_rrs4, 675218893Sdim t_addrmode_is4, AddrModeT1_4, 676218893Sdim IIC_iStore_r, IIC_iStore_i, "str", 677218893Sdim BinOpFrag<(store node:$LHS, node:$RHS)>>; 678193323Sed 679218893Sdim// A8.6.197 & A8.6.195 680218893Sdimdefm tSTRB : thumb_st_rr_ri_enc<0b010, 0b0111, t_addrmode_rrs1, 681218893Sdim t_addrmode_is1, AddrModeT1_1, 682218893Sdim IIC_iStore_bh_r, IIC_iStore_bh_i, "strb", 683218893Sdim BinOpFrag<(truncstorei8 node:$LHS, node:$RHS)>>; 684193323Sed 685218893Sdim// A8.6.207 & A8.6.205 686218893Sdimdefm tSTRH : thumb_st_rr_ri_enc<0b001, 0b1000, t_addrmode_rrs2, 687224145Sdim t_addrmode_is2, AddrModeT1_2, 688224145Sdim IIC_iStore_bh_r, IIC_iStore_bh_i, "strh", 689224145Sdim BinOpFrag<(truncstorei16 node:$LHS, node:$RHS)>>; 690193323Sed 691193323Sed 692218893Sdimdef tSTRspi : T1pIs<(outs), (ins tGPR:$Rt, t_addrmode_sp:$addr), IIC_iStore_i, 693218893Sdim "str", "\t$Rt, $addr", 694218893Sdim [(store tGPR:$Rt, t_addrmode_sp:$addr)]>, 695218893Sdim T1LdStSP<{0,?,?}> { 696218893Sdim bits<3> Rt; 697218893Sdim bits<8> addr; 698218893Sdim let Inst{10-8} = Rt; 699218893Sdim let Inst{7-0} = addr; 700218893Sdim} 701193323Sed 702193323Sed//===----------------------------------------------------------------------===// 703193323Sed// Load / store multiple Instructions. 704193323Sed// 705193323Sed 706218893Sdim// These require base address to be written back or one of the loaded regs. 707218893Sdimlet neverHasSideEffects = 1 in { 708205218Srdivacky 709218893Sdimlet mayLoad = 1, hasExtraDefRegAllocReq = 1 in 710226633Sdimdef tLDMIA : T1I<(outs), (ins tGPR:$Rn, pred:$p, reglist:$regs, variable_ops), 711226633Sdim IIC_iLoad_m, "ldm${p}\t$Rn, $regs", []>, T1Encoding<{1,1,0,0,1,?}> { 712226633Sdim bits<3> Rn; 713226633Sdim bits<8> regs; 714226633Sdim let Inst{10-8} = Rn; 715226633Sdim let Inst{7-0} = regs; 716226633Sdim} 717193323Sed 718226633Sdim// Writeback version is just a pseudo, as there's no encoding difference. 719226633Sdim// Writeback happens iff the base register is not in the destination register 720226633Sdim// list. 721226633Sdimdef tLDMIA_UPD : 722226633Sdim InstTemplate<AddrModeNone, 0, IndexModeNone, Pseudo, GenericDomain, 723226633Sdim "$Rn = $wb", IIC_iLoad_mu>, 724226633Sdim PseudoInstExpansion<(tLDMIA tGPR:$Rn, pred:$p, reglist:$regs)> { 725226633Sdim let Size = 2; 726226633Sdim let OutOperandList = (outs GPR:$wb); 727226633Sdim let InOperandList = (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops); 728226633Sdim let Pattern = []; 729226633Sdim let isCodeGenOnly = 1; 730226633Sdim let isPseudo = 1; 731226633Sdim list<Predicate> Predicates = [IsThumb]; 732226633Sdim} 733226633Sdim 734226633Sdim// There is no non-writeback version of STM for Thumb. 735218893Sdimlet mayStore = 1, hasExtraSrcRegAllocReq = 1 in 736226633Sdimdef tSTMIA_UPD : Thumb1I<(outs GPR:$wb), 737226633Sdim (ins tGPR:$Rn, pred:$p, reglist:$regs, variable_ops), 738226633Sdim AddrModeNone, 2, IIC_iStore_mu, 739226633Sdim "stm${p}\t$Rn!, $regs", "$Rn = $wb", []>, 740226633Sdim T1Encoding<{1,1,0,0,0,?}> { 741226633Sdim bits<3> Rn; 742226633Sdim bits<8> regs; 743226633Sdim let Inst{10-8} = Rn; 744226633Sdim let Inst{7-0} = regs; 745226633Sdim} 746223017Sdim 747218893Sdim} // neverHasSideEffects 748218893Sdim 749226633Sdimdef : InstAlias<"ldm${p} $Rn!, $regs", 750226633Sdim (tLDMIA tGPR:$Rn, pred:$p, reglist:$regs)>, 751226633Sdim Requires<[IsThumb, IsThumb1Only]>; 752226633Sdim 753198090Srdivackylet mayLoad = 1, Uses = [SP], Defs = [SP], hasExtraDefRegAllocReq = 1 in 754218893Sdimdef tPOP : T1I<(outs), (ins pred:$p, reglist:$regs, variable_ops), 755218893Sdim IIC_iPop, 756218893Sdim "pop${p}\t$regs", []>, 757218893Sdim T1Misc<{1,1,0,?,?,?,?}> { 758218893Sdim bits<16> regs; 759218893Sdim let Inst{8} = regs{15}; 760218893Sdim let Inst{7-0} = regs{7-0}; 761218893Sdim} 762193323Sed 763198090Srdivackylet mayStore = 1, Uses = [SP], Defs = [SP], hasExtraSrcRegAllocReq = 1 in 764218893Sdimdef tPUSH : T1I<(outs), (ins pred:$p, reglist:$regs, variable_ops), 765218893Sdim IIC_iStore_m, 766218893Sdim "push${p}\t$regs", []>, 767218893Sdim T1Misc<{0,1,0,?,?,?,?}> { 768218893Sdim bits<16> regs; 769218893Sdim let Inst{8} = regs{14}; 770218893Sdim let Inst{7-0} = regs{7-0}; 771218893Sdim} 772198090Srdivacky 773193323Sed//===----------------------------------------------------------------------===// 774193323Sed// Arithmetic Instructions. 775193323Sed// 776193323Sed 777218893Sdim// Helper classes for encoding T1pI patterns: 778218893Sdimclass T1pIDPEncode<bits<4> opA, dag oops, dag iops, InstrItinClass itin, 779218893Sdim string opc, string asm, list<dag> pattern> 780218893Sdim : T1pI<oops, iops, itin, opc, asm, pattern>, 781218893Sdim T1DataProcessing<opA> { 782218893Sdim bits<3> Rm; 783218893Sdim bits<3> Rn; 784218893Sdim let Inst{5-3} = Rm; 785218893Sdim let Inst{2-0} = Rn; 786218893Sdim} 787218893Sdimclass T1pIMiscEncode<bits<7> opA, dag oops, dag iops, InstrItinClass itin, 788218893Sdim string opc, string asm, list<dag> pattern> 789218893Sdim : T1pI<oops, iops, itin, opc, asm, pattern>, 790218893Sdim T1Misc<opA> { 791218893Sdim bits<3> Rm; 792218893Sdim bits<3> Rd; 793218893Sdim let Inst{5-3} = Rm; 794218893Sdim let Inst{2-0} = Rd; 795218893Sdim} 796218893Sdim 797218893Sdim// Helper classes for encoding T1sI patterns: 798218893Sdimclass T1sIDPEncode<bits<4> opA, dag oops, dag iops, InstrItinClass itin, 799218893Sdim string opc, string asm, list<dag> pattern> 800218893Sdim : T1sI<oops, iops, itin, opc, asm, pattern>, 801218893Sdim T1DataProcessing<opA> { 802218893Sdim bits<3> Rd; 803218893Sdim bits<3> Rn; 804218893Sdim let Inst{5-3} = Rn; 805218893Sdim let Inst{2-0} = Rd; 806218893Sdim} 807218893Sdimclass T1sIGenEncode<bits<5> opA, dag oops, dag iops, InstrItinClass itin, 808218893Sdim string opc, string asm, list<dag> pattern> 809218893Sdim : T1sI<oops, iops, itin, opc, asm, pattern>, 810218893Sdim T1General<opA> { 811218893Sdim bits<3> Rm; 812218893Sdim bits<3> Rn; 813218893Sdim bits<3> Rd; 814218893Sdim let Inst{8-6} = Rm; 815218893Sdim let Inst{5-3} = Rn; 816218893Sdim let Inst{2-0} = Rd; 817218893Sdim} 818218893Sdimclass T1sIGenEncodeImm<bits<5> opA, dag oops, dag iops, InstrItinClass itin, 819218893Sdim string opc, string asm, list<dag> pattern> 820218893Sdim : T1sI<oops, iops, itin, opc, asm, pattern>, 821218893Sdim T1General<opA> { 822218893Sdim bits<3> Rd; 823218893Sdim bits<3> Rm; 824218893Sdim let Inst{5-3} = Rm; 825218893Sdim let Inst{2-0} = Rd; 826218893Sdim} 827218893Sdim 828218893Sdim// Helper classes for encoding T1sIt patterns: 829218893Sdimclass T1sItDPEncode<bits<4> opA, dag oops, dag iops, InstrItinClass itin, 830218893Sdim string opc, string asm, list<dag> pattern> 831218893Sdim : T1sIt<oops, iops, itin, opc, asm, pattern>, 832218893Sdim T1DataProcessing<opA> { 833218893Sdim bits<3> Rdn; 834218893Sdim bits<3> Rm; 835218893Sdim let Inst{5-3} = Rm; 836218893Sdim let Inst{2-0} = Rdn; 837218893Sdim} 838218893Sdimclass T1sItGenEncodeImm<bits<5> opA, dag oops, dag iops, InstrItinClass itin, 839218893Sdim string opc, string asm, list<dag> pattern> 840218893Sdim : T1sIt<oops, iops, itin, opc, asm, pattern>, 841218893Sdim T1General<opA> { 842218893Sdim bits<3> Rdn; 843218893Sdim bits<8> imm8; 844218893Sdim let Inst{10-8} = Rdn; 845218893Sdim let Inst{7-0} = imm8; 846218893Sdim} 847218893Sdim 848195098Sed// Add with carry register 849198090Srdivackylet isCommutable = 1, Uses = [CPSR] in 850218893Sdimdef tADC : // A8.6.2 851218893Sdim T1sItDPEncode<0b0101, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), IIC_iALUr, 852218893Sdim "adc", "\t$Rdn, $Rm", 853263508Sdim [(set tGPR:$Rdn, (adde tGPR:$Rn, tGPR:$Rm))]>, Sched<[WriteALU]>; 854193323Sed 855195098Sed// Add immediate 856218893Sdimdef tADDi3 : // A8.6.4 T1 857226633Sdim T1sIGenEncodeImm<0b01110, (outs tGPR:$Rd), (ins tGPR:$Rm, imm0_7:$imm3), 858224145Sdim IIC_iALUi, 859218893Sdim "add", "\t$Rd, $Rm, $imm3", 860263508Sdim [(set tGPR:$Rd, (add tGPR:$Rm, imm0_7:$imm3))]>, 861263508Sdim Sched<[WriteALU]> { 862218893Sdim bits<3> imm3; 863218893Sdim let Inst{8-6} = imm3; 864218893Sdim} 865193323Sed 866218893Sdimdef tADDi8 : // A8.6.4 T2 867226633Sdim T1sItGenEncodeImm<{1,1,0,?,?}, (outs tGPR:$Rdn), 868226633Sdim (ins tGPR:$Rn, imm0_255:$imm8), IIC_iALUi, 869218893Sdim "add", "\t$Rdn, $imm8", 870263508Sdim [(set tGPR:$Rdn, (add tGPR:$Rn, imm8_255:$imm8))]>, 871263508Sdim Sched<[WriteALU]>; 872193323Sed 873195098Sed// Add register 874198090Srdivackylet isCommutable = 1 in 875218893Sdimdef tADDrr : // A8.6.6 T1 876218893Sdim T1sIGenEncode<0b01100, (outs tGPR:$Rd), (ins tGPR:$Rn, tGPR:$Rm), 877218893Sdim IIC_iALUr, 878218893Sdim "add", "\t$Rd, $Rn, $Rm", 879263508Sdim [(set tGPR:$Rd, (add tGPR:$Rn, tGPR:$Rm))]>, Sched<[WriteALU]>; 880193323Sed 881194178Sedlet neverHasSideEffects = 1 in 882218893Sdimdef tADDhirr : T1pIt<(outs GPR:$Rdn), (ins GPR:$Rn, GPR:$Rm), IIC_iALUr, 883218893Sdim "add", "\t$Rdn, $Rm", []>, 884263508Sdim T1Special<{0,0,?,?}>, Sched<[WriteALU]> { 885218893Sdim // A8.6.6 T2 886218893Sdim bits<4> Rdn; 887218893Sdim bits<4> Rm; 888218893Sdim let Inst{7} = Rdn{3}; 889218893Sdim let Inst{6-3} = Rm; 890218893Sdim let Inst{2-0} = Rdn{2-0}; 891218893Sdim} 892193323Sed 893218893Sdim// AND register 894198090Srdivackylet isCommutable = 1 in 895218893Sdimdef tAND : // A8.6.12 896218893Sdim T1sItDPEncode<0b0000, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 897218893Sdim IIC_iBITr, 898218893Sdim "and", "\t$Rdn, $Rm", 899263508Sdim [(set tGPR:$Rdn, (and tGPR:$Rn, tGPR:$Rm))]>, Sched<[WriteALU]>; 900193323Sed 901195098Sed// ASR immediate 902218893Sdimdef tASRri : // A8.6.14 903226633Sdim T1sIGenEncodeImm<{0,1,0,?,?}, (outs tGPR:$Rd), (ins tGPR:$Rm, imm_sr:$imm5), 904218893Sdim IIC_iMOVsi, 905218893Sdim "asr", "\t$Rd, $Rm, $imm5", 906263508Sdim [(set tGPR:$Rd, (sra tGPR:$Rm, (i32 imm_sr:$imm5)))]>, 907263508Sdim Sched<[WriteALU]> { 908218893Sdim bits<5> imm5; 909218893Sdim let Inst{10-6} = imm5; 910218893Sdim} 911193323Sed 912195098Sed// ASR register 913218893Sdimdef tASRrr : // A8.6.15 914218893Sdim T1sItDPEncode<0b0100, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 915218893Sdim IIC_iMOVsr, 916218893Sdim "asr", "\t$Rdn, $Rm", 917263508Sdim [(set tGPR:$Rdn, (sra tGPR:$Rn, tGPR:$Rm))]>, Sched<[WriteALU]>; 918193323Sed 919195098Sed// BIC register 920218893Sdimdef tBIC : // A8.6.20 921218893Sdim T1sItDPEncode<0b1110, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 922218893Sdim IIC_iBITr, 923218893Sdim "bic", "\t$Rdn, $Rm", 924263508Sdim [(set tGPR:$Rdn, (and tGPR:$Rn, (not tGPR:$Rm)))]>, 925263508Sdim Sched<[WriteALU]>; 926193323Sed 927195098Sed// CMN register 928218893Sdimlet isCompare = 1, Defs = [CPSR] in { 929202878Srdivacky//FIXME: Disable CMN, as CCodes are backwards from compare expectations 930202878Srdivacky// Compare-to-zero still works out, just not the relationals 931218893Sdim//def tCMN : // A8.6.33 932218893Sdim// T1pIDPEncode<0b1011, (outs), (ins tGPR:$lhs, tGPR:$rhs), 933218893Sdim// IIC_iCMPr, 934218893Sdim// "cmn", "\t$lhs, $rhs", 935218893Sdim// [(ARMcmp tGPR:$lhs, (ineg tGPR:$rhs))]>; 936193323Sed 937218893Sdimdef tCMNz : // A8.6.33 938218893Sdim T1pIDPEncode<0b1011, (outs), (ins tGPR:$Rn, tGPR:$Rm), 939218893Sdim IIC_iCMPr, 940218893Sdim "cmn", "\t$Rn, $Rm", 941263508Sdim [(ARMcmpZ tGPR:$Rn, (ineg tGPR:$Rm))]>, Sched<[WriteCMP]>; 942218893Sdim 943218893Sdim} // isCompare = 1, Defs = [CPSR] 944218893Sdim 945195098Sed// CMP immediate 946218893Sdimlet isCompare = 1, Defs = [CPSR] in { 947226633Sdimdef tCMPi8 : T1pI<(outs), (ins tGPR:$Rn, imm0_255:$imm8), IIC_iCMPi, 948218893Sdim "cmp", "\t$Rn, $imm8", 949218893Sdim [(ARMcmp tGPR:$Rn, imm0_255:$imm8)]>, 950263508Sdim T1General<{1,0,1,?,?}>, Sched<[WriteCMP]> { 951218893Sdim // A8.6.35 952218893Sdim bits<3> Rn; 953218893Sdim bits<8> imm8; 954218893Sdim let Inst{10-8} = Rn; 955218893Sdim let Inst{7-0} = imm8; 956195098Sed} 957195098Sed 958195098Sed// CMP register 959218893Sdimdef tCMPr : // A8.6.36 T1 960218893Sdim T1pIDPEncode<0b1010, (outs), (ins tGPR:$Rn, tGPR:$Rm), 961218893Sdim IIC_iCMPr, 962218893Sdim "cmp", "\t$Rn, $Rm", 963263508Sdim [(ARMcmp tGPR:$Rn, tGPR:$Rm)]>, Sched<[WriteCMP]>; 964198090Srdivacky 965218893Sdimdef tCMPhir : T1pI<(outs), (ins GPR:$Rn, GPR:$Rm), IIC_iCMPr, 966218893Sdim "cmp", "\t$Rn, $Rm", []>, 967263508Sdim T1Special<{0,1,?,?}>, Sched<[WriteCMP]> { 968218893Sdim // A8.6.36 T2 969218893Sdim bits<4> Rm; 970218893Sdim bits<4> Rn; 971218893Sdim let Inst{7} = Rn{3}; 972218893Sdim let Inst{6-3} = Rm; 973218893Sdim let Inst{2-0} = Rn{2-0}; 974195098Sed} 975218893Sdim} // isCompare = 1, Defs = [CPSR] 976193323Sed 977193323Sed 978195098Sed// XOR register 979198090Srdivackylet isCommutable = 1 in 980218893Sdimdef tEOR : // A8.6.45 981218893Sdim T1sItDPEncode<0b0001, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 982218893Sdim IIC_iBITr, 983218893Sdim "eor", "\t$Rdn, $Rm", 984263508Sdim [(set tGPR:$Rdn, (xor tGPR:$Rn, tGPR:$Rm))]>, Sched<[WriteALU]>; 985193323Sed 986195098Sed// LSL immediate 987218893Sdimdef tLSLri : // A8.6.88 988226633Sdim T1sIGenEncodeImm<{0,0,0,?,?}, (outs tGPR:$Rd), (ins tGPR:$Rm, imm0_31:$imm5), 989218893Sdim IIC_iMOVsi, 990218893Sdim "lsl", "\t$Rd, $Rm, $imm5", 991263508Sdim [(set tGPR:$Rd, (shl tGPR:$Rm, (i32 imm:$imm5)))]>, 992263508Sdim Sched<[WriteALU]> { 993218893Sdim bits<5> imm5; 994218893Sdim let Inst{10-6} = imm5; 995218893Sdim} 996193323Sed 997195098Sed// LSL register 998218893Sdimdef tLSLrr : // A8.6.89 999218893Sdim T1sItDPEncode<0b0010, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 1000218893Sdim IIC_iMOVsr, 1001218893Sdim "lsl", "\t$Rdn, $Rm", 1002263508Sdim [(set tGPR:$Rdn, (shl tGPR:$Rn, tGPR:$Rm))]>, Sched<[WriteALU]>; 1003193323Sed 1004195098Sed// LSR immediate 1005218893Sdimdef tLSRri : // A8.6.90 1006226633Sdim T1sIGenEncodeImm<{0,0,1,?,?}, (outs tGPR:$Rd), (ins tGPR:$Rm, imm_sr:$imm5), 1007218893Sdim IIC_iMOVsi, 1008218893Sdim "lsr", "\t$Rd, $Rm, $imm5", 1009263508Sdim [(set tGPR:$Rd, (srl tGPR:$Rm, (i32 imm_sr:$imm5)))]>, 1010263508Sdim Sched<[WriteALU]> { 1011218893Sdim bits<5> imm5; 1012218893Sdim let Inst{10-6} = imm5; 1013218893Sdim} 1014193323Sed 1015195098Sed// LSR register 1016218893Sdimdef tLSRrr : // A8.6.91 1017218893Sdim T1sItDPEncode<0b0011, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 1018218893Sdim IIC_iMOVsr, 1019218893Sdim "lsr", "\t$Rdn, $Rm", 1020263508Sdim [(set tGPR:$Rdn, (srl tGPR:$Rn, tGPR:$Rm))]>, Sched<[WriteALU]>; 1021193323Sed 1022218893Sdim// Move register 1023218893Sdimlet isMoveImm = 1 in 1024224145Sdimdef tMOVi8 : T1sI<(outs tGPR:$Rd), (ins imm0_255:$imm8), IIC_iMOVi, 1025218893Sdim "mov", "\t$Rd, $imm8", 1026218893Sdim [(set tGPR:$Rd, imm0_255:$imm8)]>, 1027263508Sdim T1General<{1,0,0,?,?}>, Sched<[WriteALU]> { 1028218893Sdim // A8.6.96 1029218893Sdim bits<3> Rd; 1030218893Sdim bits<8> imm8; 1031218893Sdim let Inst{10-8} = Rd; 1032218893Sdim let Inst{7-0} = imm8; 1033218893Sdim} 1034226633Sdim// Because we have an explicit tMOVSr below, we need an alias to handle 1035226633Sdim// the immediate "movs" form here. Blech. 1036226633Sdimdef : tInstAlias <"movs $Rdn, $imm", 1037226633Sdim (tMOVi8 tGPR:$Rdn, CPSR, imm0_255:$imm, 14, 0)>; 1038193323Sed 1039224145Sdim// A7-73: MOV(2) - mov setting flag. 1040193323Sed 1041194178Sedlet neverHasSideEffects = 1 in { 1042224145Sdimdef tMOVr : Thumb1pI<(outs GPR:$Rd), (ins GPR:$Rm), AddrModeNone, 1043224145Sdim 2, IIC_iMOVr, 1044224145Sdim "mov", "\t$Rd, $Rm", "", []>, 1045263508Sdim T1Special<{1,0,?,?}>, Sched<[WriteALU]> { 1046218893Sdim // A8.6.97 1047218893Sdim bits<4> Rd; 1048218893Sdim bits<4> Rm; 1049224145Sdim let Inst{7} = Rd{3}; 1050224145Sdim let Inst{6-3} = Rm; 1051218893Sdim let Inst{2-0} = Rd{2-0}; 1052218893Sdim} 1053198090Srdivackylet Defs = [CPSR] in 1054218893Sdimdef tMOVSr : T1I<(outs tGPR:$Rd), (ins tGPR:$Rm), IIC_iMOVr, 1055263508Sdim "movs\t$Rd, $Rm", []>, Encoding16, Sched<[WriteALU]> { 1056218893Sdim // A8.6.97 1057218893Sdim bits<3> Rd; 1058218893Sdim bits<3> Rm; 1059201360Srdivacky let Inst{15-6} = 0b0000000000; 1060218893Sdim let Inst{5-3} = Rm; 1061218893Sdim let Inst{2-0} = Rd; 1062201360Srdivacky} 1063194178Sed} // neverHasSideEffects 1064193323Sed 1065218893Sdim// Multiply register 1066198090Srdivackylet isCommutable = 1 in 1067218893Sdimdef tMUL : // A8.6.105 T1 1068226633Sdim Thumb1sI<(outs tGPR:$Rd), (ins tGPR:$Rn, tGPR:$Rm), AddrModeNone, 2, 1069226633Sdim IIC_iMUL32, "mul", "\t$Rd, $Rn, $Rm", "$Rm = $Rd", 1070226633Sdim [(set tGPR:$Rd, (mul tGPR:$Rn, tGPR:$Rm))]>, 1071226633Sdim T1DataProcessing<0b1101> { 1072226633Sdim bits<3> Rd; 1073226633Sdim bits<3> Rn; 1074226633Sdim let Inst{5-3} = Rn; 1075226633Sdim let Inst{2-0} = Rd; 1076226633Sdim let AsmMatchConverter = "cvtThumbMultiply"; 1077226633Sdim} 1078193323Sed 1079226633Sdimdef :tInstAlias<"mul${s}${p} $Rdm, $Rn", (tMUL tGPR:$Rdm, s_cc_out:$s, tGPR:$Rn, 1080226633Sdim pred:$p)>; 1081226633Sdim 1082218893Sdim// Move inverse register 1083218893Sdimdef tMVN : // A8.6.107 1084218893Sdim T1sIDPEncode<0b1111, (outs tGPR:$Rd), (ins tGPR:$Rn), IIC_iMVNr, 1085218893Sdim "mvn", "\t$Rd, $Rn", 1086263508Sdim [(set tGPR:$Rd, (not tGPR:$Rn))]>, Sched<[WriteALU]>; 1087193323Sed 1088218893Sdim// Bitwise or register 1089198090Srdivackylet isCommutable = 1 in 1090218893Sdimdef tORR : // A8.6.114 1091218893Sdim T1sItDPEncode<0b1100, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 1092218893Sdim IIC_iBITr, 1093218893Sdim "orr", "\t$Rdn, $Rm", 1094263508Sdim [(set tGPR:$Rdn, (or tGPR:$Rn, tGPR:$Rm))]>, Sched<[WriteALU]>; 1095193323Sed 1096218893Sdim// Swaps 1097218893Sdimdef tREV : // A8.6.134 1098218893Sdim T1pIMiscEncode<{1,0,1,0,0,0,?}, (outs tGPR:$Rd), (ins tGPR:$Rm), 1099218893Sdim IIC_iUNAr, 1100218893Sdim "rev", "\t$Rd, $Rm", 1101218893Sdim [(set tGPR:$Rd, (bswap tGPR:$Rm))]>, 1102263508Sdim Requires<[IsThumb, IsThumb1Only, HasV6]>, Sched<[WriteALU]>; 1103193323Sed 1104218893Sdimdef tREV16 : // A8.6.135 1105218893Sdim T1pIMiscEncode<{1,0,1,0,0,1,?}, (outs tGPR:$Rd), (ins tGPR:$Rm), 1106218893Sdim IIC_iUNAr, 1107218893Sdim "rev16", "\t$Rd, $Rm", 1108224145Sdim [(set tGPR:$Rd, (rotr (bswap tGPR:$Rm), (i32 16)))]>, 1109263508Sdim Requires<[IsThumb, IsThumb1Only, HasV6]>, Sched<[WriteALU]>; 1110193323Sed 1111218893Sdimdef tREVSH : // A8.6.136 1112218893Sdim T1pIMiscEncode<{1,0,1,0,1,1,?}, (outs tGPR:$Rd), (ins tGPR:$Rm), 1113218893Sdim IIC_iUNAr, 1114218893Sdim "revsh", "\t$Rd, $Rm", 1115224145Sdim [(set tGPR:$Rd, (sra (bswap tGPR:$Rm), (i32 16)))]>, 1116263508Sdim Requires<[IsThumb, IsThumb1Only, HasV6]>, Sched<[WriteALU]>; 1117193323Sed 1118218893Sdim// Rotate right register 1119218893Sdimdef tROR : // A8.6.139 1120218893Sdim T1sItDPEncode<0b0111, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 1121218893Sdim IIC_iMOVsr, 1122218893Sdim "ror", "\t$Rdn, $Rm", 1123263508Sdim [(set tGPR:$Rdn, (rotr tGPR:$Rn, tGPR:$Rm))]>, 1124263508Sdim Sched<[WriteALU]>; 1125193323Sed 1126218893Sdim// Negate register 1127218893Sdimdef tRSB : // A8.6.141 1128218893Sdim T1sIDPEncode<0b1001, (outs tGPR:$Rd), (ins tGPR:$Rn), 1129218893Sdim IIC_iALUi, 1130218893Sdim "rsb", "\t$Rd, $Rn, #0", 1131263508Sdim [(set tGPR:$Rd, (ineg tGPR:$Rn))]>, Sched<[WriteALU]>; 1132198090Srdivacky 1133195098Sed// Subtract with carry register 1134198090Srdivackylet Uses = [CPSR] in 1135218893Sdimdef tSBC : // A8.6.151 1136218893Sdim T1sItDPEncode<0b0110, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), 1137218893Sdim IIC_iALUr, 1138218893Sdim "sbc", "\t$Rdn, $Rm", 1139263508Sdim [(set tGPR:$Rdn, (sube tGPR:$Rn, tGPR:$Rm))]>, 1140263508Sdim Sched<[WriteALU]>; 1141193323Sed 1142195098Sed// Subtract immediate 1143218893Sdimdef tSUBi3 : // A8.6.210 T1 1144226633Sdim T1sIGenEncodeImm<0b01111, (outs tGPR:$Rd), (ins tGPR:$Rm, imm0_7:$imm3), 1145218893Sdim IIC_iALUi, 1146218893Sdim "sub", "\t$Rd, $Rm, $imm3", 1147263508Sdim [(set tGPR:$Rd, (add tGPR:$Rm, imm0_7_neg:$imm3))]>, 1148263508Sdim Sched<[WriteALU]> { 1149218893Sdim bits<3> imm3; 1150218893Sdim let Inst{8-6} = imm3; 1151218893Sdim} 1152193323Sed 1153218893Sdimdef tSUBi8 : // A8.6.210 T2 1154226633Sdim T1sItGenEncodeImm<{1,1,1,?,?}, (outs tGPR:$Rdn), 1155226633Sdim (ins tGPR:$Rn, imm0_255:$imm8), IIC_iALUi, 1156218893Sdim "sub", "\t$Rdn, $imm8", 1157263508Sdim [(set tGPR:$Rdn, (add tGPR:$Rn, imm8_255_neg:$imm8))]>, 1158263508Sdim Sched<[WriteALU]>; 1159193323Sed 1160218893Sdim// Subtract register 1161218893Sdimdef tSUBrr : // A8.6.212 1162218893Sdim T1sIGenEncode<0b01101, (outs tGPR:$Rd), (ins tGPR:$Rn, tGPR:$Rm), 1163218893Sdim IIC_iALUr, 1164218893Sdim "sub", "\t$Rd, $Rn, $Rm", 1165263508Sdim [(set tGPR:$Rd, (sub tGPR:$Rn, tGPR:$Rm))]>, 1166263508Sdim Sched<[WriteALU]>; 1167193323Sed 1168218893Sdim// Sign-extend byte 1169218893Sdimdef tSXTB : // A8.6.222 1170218893Sdim T1pIMiscEncode<{0,0,1,0,0,1,?}, (outs tGPR:$Rd), (ins tGPR:$Rm), 1171218893Sdim IIC_iUNAr, 1172218893Sdim "sxtb", "\t$Rd, $Rm", 1173218893Sdim [(set tGPR:$Rd, (sext_inreg tGPR:$Rm, i8))]>, 1174263508Sdim Requires<[IsThumb, IsThumb1Only, HasV6]>, 1175263508Sdim Sched<[WriteALU]>; 1176195098Sed 1177218893Sdim// Sign-extend short 1178218893Sdimdef tSXTH : // A8.6.224 1179218893Sdim T1pIMiscEncode<{0,0,1,0,0,0,?}, (outs tGPR:$Rd), (ins tGPR:$Rm), 1180218893Sdim IIC_iUNAr, 1181218893Sdim "sxth", "\t$Rd, $Rm", 1182218893Sdim [(set tGPR:$Rd, (sext_inreg tGPR:$Rm, i16))]>, 1183263508Sdim Requires<[IsThumb, IsThumb1Only, HasV6]>, 1184263508Sdim Sched<[WriteALU]>; 1185193323Sed 1186218893Sdim// Test 1187218893Sdimlet isCompare = 1, isCommutable = 1, Defs = [CPSR] in 1188218893Sdimdef tTST : // A8.6.230 1189218893Sdim T1pIDPEncode<0b1000, (outs), (ins tGPR:$Rn, tGPR:$Rm), IIC_iTSTr, 1190218893Sdim "tst", "\t$Rn, $Rm", 1191263508Sdim [(ARMcmpZ (and_su tGPR:$Rn, tGPR:$Rm), 0)]>, 1192263508Sdim Sched<[WriteALU]>; 1193193323Sed 1194218893Sdim// Zero-extend byte 1195218893Sdimdef tUXTB : // A8.6.262 1196218893Sdim T1pIMiscEncode<{0,0,1,0,1,1,?}, (outs tGPR:$Rd), (ins tGPR:$Rm), 1197218893Sdim IIC_iUNAr, 1198218893Sdim "uxtb", "\t$Rd, $Rm", 1199218893Sdim [(set tGPR:$Rd, (and tGPR:$Rm, 0xFF))]>, 1200263508Sdim Requires<[IsThumb, IsThumb1Only, HasV6]>, 1201263508Sdim Sched<[WriteALU]>; 1202195098Sed 1203218893Sdim// Zero-extend short 1204218893Sdimdef tUXTH : // A8.6.264 1205218893Sdim T1pIMiscEncode<{0,0,1,0,1,0,?}, (outs tGPR:$Rd), (ins tGPR:$Rm), 1206218893Sdim IIC_iUNAr, 1207218893Sdim "uxth", "\t$Rd, $Rm", 1208218893Sdim [(set tGPR:$Rd, (and tGPR:$Rm, 0xFFFF))]>, 1209263508Sdim Requires<[IsThumb, IsThumb1Only, HasV6]>, Sched<[WriteALU]>; 1210193323Sed 1211204642Srdivacky// Conditional move tMOVCCr - Used to implement the Thumb SELECT_CC operation. 1212198892Srdivacky// Expanded after instruction selection into a branch sequence. 1213198892Srdivackylet usesCustomInserter = 1 in // Expanded after instruction selection. 1214198090Srdivacky def tMOVCCr_pseudo : 1215263508Sdim PseudoInst<(outs tGPR:$dst), (ins tGPR:$false, tGPR:$true, cmovpred:$p), 1216263508Sdim NoItinerary, 1217263508Sdim [(set tGPR:$dst, (ARMcmov tGPR:$false, tGPR:$true, cmovpred:$p))]>; 1218193323Sed 1219193323Sed// tLEApcrel - Load a pc-relative address into a register without offending the 1220193323Sed// assembler. 1221193323Sed 1222218893Sdimdef tADR : T1I<(outs tGPR:$Rd), (ins t_adrlabel:$addr, pred:$p), 1223226633Sdim IIC_iALUi, "adr{$p}\t$Rd, $addr", []>, 1224263508Sdim T1Encoding<{1,0,1,0,0,?}>, Sched<[WriteALU]> { 1225218893Sdim bits<3> Rd; 1226218893Sdim bits<8> addr; 1227218893Sdim let Inst{10-8} = Rd; 1228218893Sdim let Inst{7-0} = addr; 1229226633Sdim let DecoderMethod = "DecodeThumbAddSpecialReg"; 1230218893Sdim} 1231193323Sed 1232218893Sdimlet neverHasSideEffects = 1, isReMaterializable = 1 in 1233218893Sdimdef tLEApcrel : tPseudoInst<(outs tGPR:$Rd), (ins i32imm:$label, pred:$p), 1234263508Sdim 2, IIC_iALUi, []>, Sched<[WriteALU]>; 1235218893Sdim 1236243830Sdimlet hasSideEffects = 1 in 1237218893Sdimdef tLEApcrelJT : tPseudoInst<(outs tGPR:$Rd), 1238218893Sdim (ins i32imm:$label, nohash_imm:$id, pred:$p), 1239263508Sdim 2, IIC_iALUi, []>, Sched<[WriteALU]>; 1240218893Sdim 1241193323Sed//===----------------------------------------------------------------------===// 1242193323Sed// TLS Instructions 1243193323Sed// 1244193323Sed 1245193323Sed// __aeabi_read_tp preserves the registers r1-r3. 1246224145Sdim// This is a pseudo inst so that we can get the encoding right, 1247224145Sdim// complete with fixup for the aeabi_read_tp function. 1248224145Sdimlet isCall = 1, Defs = [R0, R12, LR, CPSR], Uses = [SP] in 1249224145Sdimdef tTPsoft : tPseudoInst<(outs), (ins), 4, IIC_Br, 1250263508Sdim [(set R0, ARMthread_pointer)]>, 1251263508Sdim Sched<[WriteBr]>; 1252193323Sed 1253218893Sdim//===----------------------------------------------------------------------===// 1254200581Srdivacky// SJLJ Exception handling intrinsics 1255223017Sdim// 1256208599Srdivacky 1257218893Sdim// eh_sjlj_setjmp() is an instruction sequence to store the return address and 1258218893Sdim// save #0 in R0 for the non-longjmp case. Since by its nature we may be coming 1259218893Sdim// from some other function to get here, and we're using the stack frame for the 1260218893Sdim// containing function to save/restore registers, we can't keep anything live in 1261218893Sdim// regs across the eh_sjlj_setjmp(), else it will almost certainly have been 1262221345Sdim// tromped upon when we get here from a longjmp(). We force everything out of 1263218893Sdim// registers except for our own input by listing the relevant registers in 1264218893Sdim// Defs. By doing so, we also cause the prologue/epilogue code to actively 1265218893Sdim// preserve all of the callee-saved resgisters, which is exactly what we want. 1266218893Sdim// $val is a scratch register for our use. 1267223017Sdimlet Defs = [ R0, R1, R2, R3, R4, R5, R6, R7, R12, CPSR ], 1268234353Sdim hasSideEffects = 1, isBarrier = 1, isCodeGenOnly = 1, 1269234353Sdim usesCustomInserter = 1 in 1270218893Sdimdef tInt_eh_sjlj_setjmp : ThumbXI<(outs),(ins tGPR:$src, tGPR:$val), 1271224145Sdim AddrModeNone, 0, NoItinerary, "","", 1272218893Sdim [(set R0, (ARMeh_sjlj_setjmp tGPR:$src, tGPR:$val))]>; 1273218893Sdim 1274234353Sdim// FIXME: Non-IOS version(s) 1275218893Sdimlet isBarrier = 1, hasSideEffects = 1, isTerminator = 1, isCodeGenOnly = 1, 1276218893Sdim Defs = [ R7, LR, SP ] in 1277208599Srdivackydef tInt_eh_sjlj_longjmp : XI<(outs), (ins GPR:$src, GPR:$scratch), 1278224145Sdim AddrModeNone, 0, IndexModeNone, 1279218893Sdim Pseudo, NoItinerary, "", "", 1280218893Sdim [(ARMeh_sjlj_longjmp GPR:$src, GPR:$scratch)]>, 1281234353Sdim Requires<[IsThumb, IsIOS]>; 1282208599Srdivacky 1283193323Sed//===----------------------------------------------------------------------===// 1284193323Sed// Non-Instruction Patterns 1285193323Sed// 1286193323Sed 1287218893Sdim// Comparisons 1288218893Sdimdef : T1Pat<(ARMcmpZ tGPR:$Rn, imm0_255:$imm8), 1289218893Sdim (tCMPi8 tGPR:$Rn, imm0_255:$imm8)>; 1290218893Sdimdef : T1Pat<(ARMcmpZ tGPR:$Rn, tGPR:$Rm), 1291218893Sdim (tCMPr tGPR:$Rn, tGPR:$Rm)>; 1292218893Sdim 1293198090Srdivacky// Add with carry 1294198090Srdivackydef : T1Pat<(addc tGPR:$lhs, imm0_7:$rhs), 1295198090Srdivacky (tADDi3 tGPR:$lhs, imm0_7:$rhs)>; 1296198090Srdivackydef : T1Pat<(addc tGPR:$lhs, imm8_255:$rhs), 1297198090Srdivacky (tADDi8 tGPR:$lhs, imm8_255:$rhs)>; 1298198090Srdivackydef : T1Pat<(addc tGPR:$lhs, tGPR:$rhs), 1299198090Srdivacky (tADDrr tGPR:$lhs, tGPR:$rhs)>; 1300198090Srdivacky 1301198090Srdivacky// Subtract with carry 1302198090Srdivackydef : T1Pat<(addc tGPR:$lhs, imm0_7_neg:$rhs), 1303198090Srdivacky (tSUBi3 tGPR:$lhs, imm0_7_neg:$rhs)>; 1304198090Srdivackydef : T1Pat<(addc tGPR:$lhs, imm8_255_neg:$rhs), 1305198090Srdivacky (tSUBi8 tGPR:$lhs, imm8_255_neg:$rhs)>; 1306198090Srdivackydef : T1Pat<(subc tGPR:$lhs, tGPR:$rhs), 1307198090Srdivacky (tSUBrr tGPR:$lhs, tGPR:$rhs)>; 1308198090Srdivacky 1309193323Sed// ConstantPool, GlobalAddress 1310198090Srdivackydef : T1Pat<(ARMWrapper tglobaladdr :$dst), (tLEApcrel tglobaladdr :$dst)>; 1311198090Srdivackydef : T1Pat<(ARMWrapper tconstpool :$dst), (tLEApcrel tconstpool :$dst)>; 1312193323Sed 1313193323Sed// JumpTable 1314198090Srdivackydef : T1Pat<(ARMWrapperJT tjumptable:$dst, imm:$id), 1315198090Srdivacky (tLEApcrelJT tjumptable:$dst, imm:$id)>; 1316193323Sed 1317193323Sed// Direct calls 1318198090Srdivackydef : T1Pat<(ARMtcall texternalsym:$func), (tBL texternalsym:$func)>, 1319234353Sdim Requires<[IsThumb]>; 1320193323Sed 1321198090Srdivackydef : Tv5Pat<(ARMcall texternalsym:$func), (tBLXi texternalsym:$func)>, 1322234353Sdim Requires<[IsThumb, HasV5T]>; 1323198090Srdivacky 1324193323Sed// Indirect calls to ARM routines 1325198090Srdivackydef : Tv5Pat<(ARMcall GPR:$dst), (tBLXr GPR:$dst)>, 1326234353Sdim Requires<[IsThumb, HasV5T]>; 1327193323Sed 1328193323Sed// zextload i1 -> zextload i8 1329218893Sdimdef : T1Pat<(zextloadi1 t_addrmode_rrs1:$addr), 1330218893Sdim (tLDRBr t_addrmode_rrs1:$addr)>; 1331218893Sdimdef : T1Pat<(zextloadi1 t_addrmode_is1:$addr), 1332218893Sdim (tLDRBi t_addrmode_is1:$addr)>; 1333193323Sed 1334193323Sed// extload -> zextload 1335218893Sdimdef : T1Pat<(extloadi1 t_addrmode_rrs1:$addr), (tLDRBr t_addrmode_rrs1:$addr)>; 1336218893Sdimdef : T1Pat<(extloadi1 t_addrmode_is1:$addr), (tLDRBi t_addrmode_is1:$addr)>; 1337218893Sdimdef : T1Pat<(extloadi8 t_addrmode_rrs1:$addr), (tLDRBr t_addrmode_rrs1:$addr)>; 1338218893Sdimdef : T1Pat<(extloadi8 t_addrmode_is1:$addr), (tLDRBi t_addrmode_is1:$addr)>; 1339218893Sdimdef : T1Pat<(extloadi16 t_addrmode_rrs2:$addr), (tLDRHr t_addrmode_rrs2:$addr)>; 1340218893Sdimdef : T1Pat<(extloadi16 t_addrmode_is2:$addr), (tLDRHi t_addrmode_is2:$addr)>; 1341193323Sed 1342198090Srdivacky// If it's impossible to use [r,r] address mode for sextload, select to 1343198090Srdivacky// ldr{b|h} + sxt{b|h} instead. 1344218893Sdimdef : T1Pat<(sextloadi8 t_addrmode_is1:$addr), 1345218893Sdim (tSXTB (tLDRBi t_addrmode_is1:$addr))>, 1346218893Sdim Requires<[IsThumb, IsThumb1Only, HasV6]>; 1347218893Sdimdef : T1Pat<(sextloadi8 t_addrmode_rrs1:$addr), 1348218893Sdim (tSXTB (tLDRBr t_addrmode_rrs1:$addr))>, 1349218893Sdim Requires<[IsThumb, IsThumb1Only, HasV6]>; 1350218893Sdimdef : T1Pat<(sextloadi16 t_addrmode_is2:$addr), 1351218893Sdim (tSXTH (tLDRHi t_addrmode_is2:$addr))>, 1352218893Sdim Requires<[IsThumb, IsThumb1Only, HasV6]>; 1353218893Sdimdef : T1Pat<(sextloadi16 t_addrmode_rrs2:$addr), 1354218893Sdim (tSXTH (tLDRHr t_addrmode_rrs2:$addr))>, 1355218893Sdim Requires<[IsThumb, IsThumb1Only, HasV6]>; 1356198090Srdivacky 1357218893Sdimdef : T1Pat<(sextloadi8 t_addrmode_rrs1:$addr), 1358218893Sdim (tASRri (tLSLri (tLDRBr t_addrmode_rrs1:$addr), 24), 24)>; 1359218893Sdimdef : T1Pat<(sextloadi8 t_addrmode_is1:$addr), 1360218893Sdim (tASRri (tLSLri (tLDRBi t_addrmode_is1:$addr), 24), 24)>; 1361218893Sdimdef : T1Pat<(sextloadi16 t_addrmode_rrs2:$addr), 1362218893Sdim (tASRri (tLSLri (tLDRHr t_addrmode_rrs2:$addr), 16), 16)>; 1363218893Sdimdef : T1Pat<(sextloadi16 t_addrmode_is2:$addr), 1364218893Sdim (tASRri (tLSLri (tLDRHi t_addrmode_is2:$addr), 16), 16)>; 1365198090Srdivacky 1366226633Sdimdef : T1Pat<(atomic_load_8 t_addrmode_is1:$src), 1367226633Sdim (tLDRBi t_addrmode_is1:$src)>; 1368226633Sdimdef : T1Pat<(atomic_load_8 t_addrmode_rrs1:$src), 1369226633Sdim (tLDRBr t_addrmode_rrs1:$src)>; 1370226633Sdimdef : T1Pat<(atomic_load_16 t_addrmode_is2:$src), 1371226633Sdim (tLDRHi t_addrmode_is2:$src)>; 1372226633Sdimdef : T1Pat<(atomic_load_16 t_addrmode_rrs2:$src), 1373226633Sdim (tLDRHr t_addrmode_rrs2:$src)>; 1374226633Sdimdef : T1Pat<(atomic_load_32 t_addrmode_is4:$src), 1375226633Sdim (tLDRi t_addrmode_is4:$src)>; 1376226633Sdimdef : T1Pat<(atomic_load_32 t_addrmode_rrs4:$src), 1377226633Sdim (tLDRr t_addrmode_rrs4:$src)>; 1378226633Sdimdef : T1Pat<(atomic_store_8 t_addrmode_is1:$ptr, tGPR:$val), 1379226633Sdim (tSTRBi tGPR:$val, t_addrmode_is1:$ptr)>; 1380226633Sdimdef : T1Pat<(atomic_store_8 t_addrmode_rrs1:$ptr, tGPR:$val), 1381226633Sdim (tSTRBr tGPR:$val, t_addrmode_rrs1:$ptr)>; 1382226633Sdimdef : T1Pat<(atomic_store_16 t_addrmode_is2:$ptr, tGPR:$val), 1383226633Sdim (tSTRHi tGPR:$val, t_addrmode_is2:$ptr)>; 1384226633Sdimdef : T1Pat<(atomic_store_16 t_addrmode_rrs2:$ptr, tGPR:$val), 1385226633Sdim (tSTRHr tGPR:$val, t_addrmode_rrs2:$ptr)>; 1386226633Sdimdef : T1Pat<(atomic_store_32 t_addrmode_is4:$ptr, tGPR:$val), 1387226633Sdim (tSTRi tGPR:$val, t_addrmode_is4:$ptr)>; 1388226633Sdimdef : T1Pat<(atomic_store_32 t_addrmode_rrs4:$ptr, tGPR:$val), 1389226633Sdim (tSTRr tGPR:$val, t_addrmode_rrs4:$ptr)>; 1390226633Sdim 1391193323Sed// Large immediate handling. 1392193323Sed 1393193323Sed// Two piece imms. 1394195098Seddef : T1Pat<(i32 thumb_immshifted:$src), 1395195098Sed (tLSLri (tMOVi8 (thumb_immshifted_val imm:$src)), 1396195098Sed (thumb_immshifted_shamt imm:$src))>; 1397193323Sed 1398195098Seddef : T1Pat<(i32 imm0_255_comp:$src), 1399195098Sed (tMVN (tMOVi8 (imm_comp_XFORM imm:$src)))>; 1400199481Srdivacky 1401199481Srdivacky// Pseudo instruction that combines ldr from constpool and add pc. This should 1402199481Srdivacky// be expanded into two instructions late to allow if-conversion and 1403199481Srdivacky// scheduling. 1404199481Srdivackylet isReMaterializable = 1 in 1405199481Srdivackydef tLDRpci_pic : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr, pclabel:$cp), 1406218893Sdim NoItinerary, 1407199481Srdivacky [(set GPR:$dst, (ARMpic_add (load (ARMWrapper tconstpool:$addr)), 1408199481Srdivacky imm:$cp))]>, 1409218893Sdim Requires<[IsThumb, IsThumb1Only]>; 1410224145Sdim 1411224145Sdim// Pseudo-instruction for merged POP and return. 1412224145Sdim// FIXME: remove when we have a way to marking a MI with these properties. 1413224145Sdimlet isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1, 1414224145Sdim hasExtraDefRegAllocReq = 1 in 1415224145Sdimdef tPOP_RET : tPseudoExpand<(outs), (ins pred:$p, reglist:$regs, variable_ops), 1416224145Sdim 2, IIC_iPop_Br, [], 1417263508Sdim (tPOP pred:$p, reglist:$regs)>, Sched<[WriteBrL]>; 1418224145Sdim 1419224145Sdim// Indirect branch using "mov pc, $Rm" 1420224145Sdimlet isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { 1421224145Sdim def tBRIND : tPseudoExpand<(outs), (ins GPR:$Rm, pred:$p), 1422224145Sdim 2, IIC_Br, [(brind GPR:$Rm)], 1423263508Sdim (tMOVr PC, GPR:$Rm, pred:$p)>, Sched<[WriteBr]>; 1424224145Sdim} 1425226633Sdim 1426226633Sdim 1427226633Sdim// In Thumb1, "nop" is encoded as a "mov r8, r8". Technically, the bf00 1428226633Sdim// encoding is available on ARMv6K, but we don't differentiate that finely. 1429226633Sdimdef : InstAlias<"nop", (tMOVr R8, R8, 14, 0)>,Requires<[IsThumb, IsThumb1Only]>; 1430226633Sdim 1431226633Sdim 1432226633Sdim// For round-trip assembly/disassembly, we have to handle a CPS instruction 1433226633Sdim// without any iflags. That's not, strictly speaking, valid syntax, but it's 1434239462Sdim// a useful extension and assembles to defined behaviour (the insn does 1435226633Sdim// nothing). 1436226633Sdimdef : tInstAlias<"cps$imod", (tCPS imod_op:$imod, 0)>; 1437226633Sdimdef : tInstAlias<"cps$imod", (tCPS imod_op:$imod, 0)>; 1438234353Sdim 1439234353Sdim// "neg" is and alias for "rsb rd, rn, #0" 1440234353Sdimdef : tInstAlias<"neg${s}${p} $Rd, $Rm", 1441234353Sdim (tRSB tGPR:$Rd, s_cc_out:$s, tGPR:$Rm, pred:$p)>; 1442234353Sdim 1443234353Sdim 1444234353Sdim// Implied destination operand forms for shifts. 1445234353Sdimdef : tInstAlias<"lsl${s}${p} $Rdm, $imm", 1446234353Sdim (tLSLri tGPR:$Rdm, cc_out:$s, tGPR:$Rdm, imm0_31:$imm, pred:$p)>; 1447234353Sdimdef : tInstAlias<"lsr${s}${p} $Rdm, $imm", 1448234353Sdim (tLSRri tGPR:$Rdm, cc_out:$s, tGPR:$Rdm, imm_sr:$imm, pred:$p)>; 1449234353Sdimdef : tInstAlias<"asr${s}${p} $Rdm, $imm", 1450234353Sdim (tASRri tGPR:$Rdm, cc_out:$s, tGPR:$Rdm, imm_sr:$imm, pred:$p)>; 1451