ARMInstrThumb.td revision 202375
1193323Sed//===- ARMInstrThumb.td - Thumb support for ARM ---------------------------===// 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, 19193323Sed [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; 20193323Sed 21193323Seddef imm_neg_XFORM : SDNodeXForm<imm, [{ 22193323Sed return CurDAG->getTargetConstant(-(int)N->getZExtValue(), MVT::i32); 23193323Sed}]>; 24193323Seddef imm_comp_XFORM : SDNodeXForm<imm, [{ 25193323Sed return CurDAG->getTargetConstant(~((uint32_t)N->getZExtValue()), MVT::i32); 26193323Sed}]>; 27193323Sed 28193323Sed 29193323Sed/// imm0_7 predicate - True if the 32-bit immediate is in the range [0,7]. 30193323Seddef imm0_7 : PatLeaf<(i32 imm), [{ 31193323Sed return (uint32_t)N->getZExtValue() < 8; 32193323Sed}]>; 33193323Seddef imm0_7_neg : PatLeaf<(i32 imm), [{ 34193323Sed return (uint32_t)-N->getZExtValue() < 8; 35193323Sed}], imm_neg_XFORM>; 36193323Sed 37193323Seddef imm0_255 : PatLeaf<(i32 imm), [{ 38193323Sed return (uint32_t)N->getZExtValue() < 256; 39193323Sed}]>; 40193323Seddef imm0_255_comp : PatLeaf<(i32 imm), [{ 41193323Sed return ~((uint32_t)N->getZExtValue()) < 256; 42193323Sed}]>; 43193323Sed 44193323Seddef imm8_255 : PatLeaf<(i32 imm), [{ 45193323Sed return (uint32_t)N->getZExtValue() >= 8 && (uint32_t)N->getZExtValue() < 256; 46193323Sed}]>; 47193323Seddef imm8_255_neg : PatLeaf<(i32 imm), [{ 48193323Sed unsigned Val = -N->getZExtValue(); 49193323Sed return Val >= 8 && Val < 256; 50193323Sed}], imm_neg_XFORM>; 51193323Sed 52193323Sed// Break imm's up into two pieces: an immediate + a left shift. 53193323Sed// This uses thumb_immshifted to match and thumb_immshifted_val and 54193323Sed// thumb_immshifted_shamt to get the val/shift pieces. 55193323Seddef thumb_immshifted : PatLeaf<(imm), [{ 56193323Sed return ARM_AM::isThumbImmShiftedVal((unsigned)N->getZExtValue()); 57193323Sed}]>; 58193323Sed 59193323Seddef thumb_immshifted_val : SDNodeXForm<imm, [{ 60193323Sed unsigned V = ARM_AM::getThumbImmNonShiftedVal((unsigned)N->getZExtValue()); 61193323Sed return CurDAG->getTargetConstant(V, MVT::i32); 62193323Sed}]>; 63193323Sed 64193323Seddef thumb_immshifted_shamt : SDNodeXForm<imm, [{ 65193323Sed unsigned V = ARM_AM::getThumbImmValShift((unsigned)N->getZExtValue()); 66193323Sed return CurDAG->getTargetConstant(V, MVT::i32); 67193323Sed}]>; 68193323Sed 69199511Srdivacky// Scaled 4 immediate. 70199511Srdivackydef t_imm_s4 : Operand<i32> { 71199511Srdivacky let PrintMethod = "printThumbS4ImmOperand"; 72199511Srdivacky} 73199511Srdivacky 74193323Sed// Define Thumb specific addressing modes. 75193323Sed 76193323Sed// t_addrmode_rr := reg + reg 77193323Sed// 78193323Seddef t_addrmode_rr : Operand<i32>, 79193323Sed ComplexPattern<i32, 2, "SelectThumbAddrModeRR", []> { 80193323Sed let PrintMethod = "printThumbAddrModeRROperand"; 81193323Sed let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); 82193323Sed} 83193323Sed 84193323Sed// t_addrmode_s4 := reg + reg 85193323Sed// reg + imm5 * 4 86193323Sed// 87193323Seddef t_addrmode_s4 : Operand<i32>, 88193323Sed ComplexPattern<i32, 3, "SelectThumbAddrModeS4", []> { 89193323Sed let PrintMethod = "printThumbAddrModeS4Operand"; 90193323Sed let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg); 91193323Sed} 92193323Sed 93193323Sed// t_addrmode_s2 := reg + reg 94193323Sed// reg + imm5 * 2 95193323Sed// 96193323Seddef t_addrmode_s2 : Operand<i32>, 97193323Sed ComplexPattern<i32, 3, "SelectThumbAddrModeS2", []> { 98193323Sed let PrintMethod = "printThumbAddrModeS2Operand"; 99193323Sed let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg); 100193323Sed} 101193323Sed 102193323Sed// t_addrmode_s1 := reg + reg 103193323Sed// reg + imm5 104193323Sed// 105193323Seddef t_addrmode_s1 : Operand<i32>, 106193323Sed ComplexPattern<i32, 3, "SelectThumbAddrModeS1", []> { 107193323Sed let PrintMethod = "printThumbAddrModeS1Operand"; 108193323Sed let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg); 109193323Sed} 110193323Sed 111193323Sed// t_addrmode_sp := sp + imm8 * 4 112193323Sed// 113193323Seddef t_addrmode_sp : Operand<i32>, 114193323Sed ComplexPattern<i32, 2, "SelectThumbAddrModeSP", []> { 115193323Sed let PrintMethod = "printThumbAddrModeSPOperand"; 116202375Srdivacky let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); 117193323Sed} 118193323Sed 119193323Sed//===----------------------------------------------------------------------===// 120193323Sed// Miscellaneous Instructions. 121193323Sed// 122193323Sed 123193323Sedlet Defs = [SP], Uses = [SP] in { 124193323Seddef tADJCALLSTACKUP : 125198090SrdivackyPseudoInst<(outs), (ins i32imm:$amt1, i32imm:$amt2), NoItinerary, 126193323Sed "@ tADJCALLSTACKUP $amt1", 127198090Srdivacky [(ARMcallseq_end imm:$amt1, imm:$amt2)]>, Requires<[IsThumb1Only]>; 128193323Sed 129193323Seddef tADJCALLSTACKDOWN : 130198090SrdivackyPseudoInst<(outs), (ins i32imm:$amt), NoItinerary, 131193323Sed "@ tADJCALLSTACKDOWN $amt", 132198090Srdivacky [(ARMcallseq_start imm:$amt)]>, Requires<[IsThumb1Only]>; 133193323Sed} 134193323Sed 135198090Srdivacky// For both thumb1 and thumb2. 136193323Sedlet isNotDuplicable = 1 in 137198090Srdivackydef tPICADD : TIt<(outs GPR:$dst), (ins GPR:$lhs, pclabel:$cp), IIC_iALUr, 138198892Srdivacky "\n$cp:\n\tadd\t$dst, pc", 139201360Srdivacky [(set GPR:$dst, (ARMpic_add GPR:$lhs, imm:$cp))]>, 140201360Srdivacky T1Special<{0,0,?,?}> { 141201360Srdivacky let Inst{6-3} = 0b1111; // A8.6.6 Rm = pc 142201360Srdivacky} 143193323Sed 144195098Sed// PC relative add. 145199511Srdivackydef tADDrPCi : T1I<(outs tGPR:$dst), (ins t_imm_s4:$rhs), IIC_iALUi, 146201360Srdivacky "add\t$dst, pc, $rhs", []>, 147201360Srdivacky T1Encoding<{1,0,1,0,0,?}>; // A6.2 & A8.6.10 148195098Sed 149195098Sed// ADD rd, sp, #imm8 150199511Srdivackydef tADDrSPi : T1I<(outs tGPR:$dst), (ins GPR:$sp, t_imm_s4:$rhs), IIC_iALUi, 151201360Srdivacky "add\t$dst, $sp, $rhs", []>, 152201360Srdivacky T1Encoding<{1,0,1,0,1,?}>; // A6.2 & A8.6.8 153195098Sed 154195098Sed// ADD sp, sp, #imm7 155199511Srdivackydef tADDspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), IIC_iALUi, 156201360Srdivacky "add\t$dst, $rhs", []>, 157201360Srdivacky T1Misc<{0,0,0,0,0,?,?}>; // A6.2.5 & A8.6.8 158195098Sed 159198090Srdivacky// SUB sp, sp, #imm7 160199511Srdivackydef tSUBspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), IIC_iALUi, 161201360Srdivacky "sub\t$dst, $rhs", []>, 162201360Srdivacky T1Misc<{0,0,0,0,1,?,?}>; // A6.2.5 & A8.6.215 163198090Srdivacky 164198090Srdivacky// ADD rm, sp 165198090Srdivackydef tADDrSP : TIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, 166201360Srdivacky "add\t$dst, $rhs", []>, 167201360Srdivacky T1Special<{0,0,?,?}> { 168201360Srdivacky let Inst{6-3} = 0b1101; // A8.6.9 Encoding T1 169201360Srdivacky} 170198090Srdivacky 171195098Sed// ADD sp, rm 172198090Srdivackydef tADDspr : TIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, 173201360Srdivacky "add\t$dst, $rhs", []>, 174201360Srdivacky T1Special<{0,0,?,?}> { 175201360Srdivacky // A8.6.9 Encoding T2 176201360Srdivacky let Inst{7} = 1; 177201360Srdivacky let Inst{2-0} = 0b101; 178201360Srdivacky} 179195098Sed 180198090Srdivacky// Pseudo instruction that will expand into a tSUBspi + a copy. 181198892Srdivackylet usesCustomInserter = 1 in { // Expanded after instruction selection. 182199511Srdivackydef tSUBspi_ : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), 183199511Srdivacky NoItinerary, "@ sub\t$dst, $rhs", []>; 184198090Srdivacky 185198090Srdivackydef tADDspr_ : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), 186198892Srdivacky NoItinerary, "@ add\t$dst, $rhs", []>; 187198090Srdivacky 188198090Srdivackylet Defs = [CPSR] in 189198090Srdivackydef tANDsp : PseudoInst<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), 190198892Srdivacky NoItinerary, "@ and\t$dst, $rhs", []>; 191198892Srdivacky} // usesCustomInserter 192198090Srdivacky 193193323Sed//===----------------------------------------------------------------------===// 194193323Sed// Control Flow Instructions. 195193323Sed// 196193323Sed 197198090Srdivackylet isReturn = 1, isTerminator = 1, isBarrier = 1 in { 198201360Srdivacky def tBX_RET : TI<(outs), (ins), IIC_Br, "bx\tlr", [(ARMretflag)]>, 199201360Srdivacky T1Special<{1,1,0,?}> { // A6.2.3 & A8.6.25 200201360Srdivacky let Inst{6-3} = 0b1110; // Rm = lr 201201360Srdivacky } 202193323Sed // Alternative return instruction used by vararg functions. 203201360Srdivacky def tBX_RET_vararg : TI<(outs), (ins tGPR:$target), IIC_Br, "bx\t$target", []>, 204201360Srdivacky T1Special<{1,1,0,?}>; // A6.2.3 & A8.6.25 205193323Sed} 206193323Sed 207198892Srdivacky// Indirect branches 208198892Srdivackylet isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { 209198892Srdivacky def tBRIND : TI<(outs), (ins GPR:$dst), IIC_Br, "mov\tpc, $dst", 210201360Srdivacky [(brind GPR:$dst)]>, 211202375Srdivacky T1Special<{1,0,1,1}> { 212202375Srdivacky // <Rd> = Inst{7:2-0} = pc 213201360Srdivacky let Inst{2-0} = 0b111; 214201360Srdivacky } 215198892Srdivacky} 216198892Srdivacky 217193323Sed// FIXME: remove when we have a way to marking a MI with these properties. 218198090Srdivackylet isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1, 219198090Srdivacky hasExtraDefRegAllocReq = 1 in 220198090Srdivackydef tPOP_RET : T1I<(outs), (ins pred:$p, reglist:$wb, variable_ops), IIC_Br, 221201360Srdivacky "pop${p}\t$wb", []>, 222201360Srdivacky T1Misc<{1,1,0,?,?,?,?}>; 223193323Sed 224193323Sedlet isCall = 1, 225198090Srdivacky Defs = [R0, R1, R2, R3, R12, LR, 226198090Srdivacky D0, D1, D2, D3, D4, D5, D6, D7, 227198090Srdivacky D16, D17, D18, D19, D20, D21, D22, D23, 228198090Srdivacky D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR] in { 229198090Srdivacky // Also used for Thumb2 230201360Srdivacky def tBL : TIx2<0b11110, 0b11, 1, 231201360Srdivacky (outs), (ins i32imm:$func, variable_ops), IIC_Br, 232201360Srdivacky "bl\t${func:call}", 233201360Srdivacky [(ARMtcall tglobaladdr:$func)]>, 234198090Srdivacky Requires<[IsThumb, IsNotDarwin]>; 235198090Srdivacky 236198090Srdivacky // ARMv5T and above, also used for Thumb2 237201360Srdivacky def tBLXi : TIx2<0b11110, 0b11, 0, 238201360Srdivacky (outs), (ins i32imm:$func, variable_ops), IIC_Br, 239201360Srdivacky "blx\t${func:call}", 240201360Srdivacky [(ARMcall tglobaladdr:$func)]>, 241198090Srdivacky Requires<[IsThumb, HasV5T, IsNotDarwin]>; 242198090Srdivacky 243198090Srdivacky // Also used for Thumb2 244198090Srdivacky def tBLXr : TI<(outs), (ins GPR:$func, variable_ops), IIC_Br, 245198892Srdivacky "blx\t$func", 246198090Srdivacky [(ARMtcall GPR:$func)]>, 247201360Srdivacky Requires<[IsThumb, HasV5T, IsNotDarwin]>, 248201360Srdivacky T1Special<{1,1,1,?}>; // A6.2.3 & A8.6.24; 249198090Srdivacky 250193323Sed // ARMv4T 251201360Srdivacky def tBX : TIx2<{?,?,?,?,?}, {?,?}, ?, 252201360Srdivacky (outs), (ins tGPR:$func, variable_ops), IIC_Br, 253198892Srdivacky "mov\tlr, pc\n\tbx\t$func", 254198090Srdivacky [(ARMcall_nolink tGPR:$func)]>, 255198090Srdivacky Requires<[IsThumb1Only, IsNotDarwin]>; 256193323Sed} 257193323Sed 258198090Srdivacky// On Darwin R9 is call-clobbered. 259198090Srdivackylet isCall = 1, 260198090Srdivacky Defs = [R0, R1, R2, R3, R9, R12, LR, 261198090Srdivacky D0, D1, D2, D3, D4, D5, D6, D7, 262198090Srdivacky D16, D17, D18, D19, D20, D21, D22, D23, 263198090Srdivacky D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR] in { 264198090Srdivacky // Also used for Thumb2 265201360Srdivacky def tBLr9 : TIx2<0b11110, 0b11, 1, 266201360Srdivacky (outs), (ins i32imm:$func, variable_ops), IIC_Br, 267198892Srdivacky "bl\t${func:call}", 268198090Srdivacky [(ARMtcall tglobaladdr:$func)]>, 269198090Srdivacky Requires<[IsThumb, IsDarwin]>; 270198090Srdivacky 271198090Srdivacky // ARMv5T and above, also used for Thumb2 272201360Srdivacky def tBLXi_r9 : TIx2<0b11110, 0b11, 0, 273201360Srdivacky (outs), (ins i32imm:$func, variable_ops), IIC_Br, 274198892Srdivacky "blx\t${func:call}", 275198090Srdivacky [(ARMcall tglobaladdr:$func)]>, 276198090Srdivacky Requires<[IsThumb, HasV5T, IsDarwin]>; 277198090Srdivacky 278198090Srdivacky // Also used for Thumb2 279198090Srdivacky def tBLXr_r9 : TI<(outs), (ins GPR:$func, variable_ops), IIC_Br, 280201360Srdivacky "blx\t$func", 281201360Srdivacky [(ARMtcall GPR:$func)]>, 282201360Srdivacky Requires<[IsThumb, HasV5T, IsDarwin]>, 283201360Srdivacky T1Special<{1,1,1,?}>; // A6.2.3 & A8.6.24 284198090Srdivacky 285198090Srdivacky // ARMv4T 286201360Srdivacky def tBXr9 : TIx2<{?,?,?,?,?}, {?,?}, ?, 287201360Srdivacky (outs), (ins tGPR:$func, variable_ops), IIC_Br, 288201360Srdivacky "mov\tlr, pc\n\tbx\t$func", 289201360Srdivacky [(ARMcall_nolink tGPR:$func)]>, 290198090Srdivacky Requires<[IsThumb1Only, IsDarwin]>; 291198090Srdivacky} 292198090Srdivacky 293193323Sedlet isBranch = 1, isTerminator = 1 in { 294193323Sed let isBarrier = 1 in { 295193323Sed let isPredicable = 1 in 296198090Srdivacky def tB : T1I<(outs), (ins brtarget:$target), IIC_Br, 297201360Srdivacky "b\t$target", [(br bb:$target)]>, 298201360Srdivacky T1Encoding<{1,1,1,0,0,?}>; 299193323Sed 300193323Sed // Far jump 301198090Srdivacky let Defs = [LR] in 302201360Srdivacky def tBfar : TIx2<0b11110, 0b11, 1, (outs), (ins brtarget:$target), IIC_Br, 303198892Srdivacky "bl\t$target\t@ far jump",[]>; 304193323Sed 305195340Sed def tBR_JTr : T1JTI<(outs), 306195340Sed (ins tGPR:$target, jtblock_operand:$jt, i32imm:$id), 307198892Srdivacky IIC_Br, "mov\tpc, $target\n\t.align\t2\n$jt", 308201360Srdivacky [(ARMbrjt tGPR:$target, tjumptable:$jt, imm:$id)]>, 309201360Srdivacky Encoding16 { 310201360Srdivacky let Inst{15-7} = 0b010001101; 311201360Srdivacky let Inst{2-0} = 0b111; 312193323Sed } 313201360Srdivacky } 314193323Sed} 315193323Sed 316193323Sed// FIXME: should be able to write a pattern for ARMBrcond, but can't use 317193323Sed// a two-value operand where a dag node expects two operands. :( 318193323Sedlet isBranch = 1, isTerminator = 1 in 319198090Srdivacky def tBcc : T1I<(outs), (ins brtarget:$target, pred:$cc), IIC_Br, 320198892Srdivacky "b$cc\t$target", 321201360Srdivacky [/*(ARMbrcond bb:$target, imm:$cc)*/]>, 322201360Srdivacky T1Encoding<{1,1,0,1,?,?}>; 323193323Sed 324198892Srdivacky// Compare and branch on zero / non-zero 325198892Srdivackylet isBranch = 1, isTerminator = 1 in { 326198892Srdivacky def tCBZ : T1I<(outs), (ins tGPR:$cmp, brtarget:$target), IIC_Br, 327201360Srdivacky "cbz\t$cmp, $target", []>, 328201360Srdivacky T1Misc<{0,0,?,1,?,?,?}>; 329198892Srdivacky 330198892Srdivacky def tCBNZ : T1I<(outs), (ins tGPR:$cmp, brtarget:$target), IIC_Br, 331201360Srdivacky "cbnz\t$cmp, $target", []>, 332201360Srdivacky T1Misc<{1,0,?,1,?,?,?}>; 333198892Srdivacky} 334198892Srdivacky 335193323Sed//===----------------------------------------------------------------------===// 336193323Sed// Load Store Instructions. 337193323Sed// 338193323Sed 339199989Srdivackylet canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in 340198090Srdivackydef tLDR : T1pI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr), IIC_iLoadr, 341198892Srdivacky "ldr", "\t$dst, $addr", 342201360Srdivacky [(set tGPR:$dst, (load t_addrmode_s4:$addr))]>, 343201360Srdivacky T1LdSt<0b100>; 344202375Srdivackydef tLDRi: T1pI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr), IIC_iLoadr, 345202375Srdivacky "ldr", "\t$dst, $addr", 346202375Srdivacky []>, 347202375Srdivacky T1LdSt4Imm<{1,?,?}>; 348193323Sed 349198090Srdivackydef tLDRB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr), IIC_iLoadr, 350198892Srdivacky "ldrb", "\t$dst, $addr", 351201360Srdivacky [(set tGPR:$dst, (zextloadi8 t_addrmode_s1:$addr))]>, 352201360Srdivacky T1LdSt<0b110>; 353202375Srdivackydef tLDRBi: T1pI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr), IIC_iLoadr, 354202375Srdivacky "ldrb", "\t$dst, $addr", 355202375Srdivacky []>, 356202375Srdivacky T1LdSt1Imm<{1,?,?}>; 357193323Sed 358198090Srdivackydef tLDRH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr), IIC_iLoadr, 359198892Srdivacky "ldrh", "\t$dst, $addr", 360201360Srdivacky [(set tGPR:$dst, (zextloadi16 t_addrmode_s2:$addr))]>, 361201360Srdivacky T1LdSt<0b101>; 362202375Srdivackydef tLDRHi: T1pI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr), IIC_iLoadr, 363202375Srdivacky "ldrh", "\t$dst, $addr", 364202375Srdivacky []>, 365202375Srdivacky T1LdSt2Imm<{1,?,?}>; 366193323Sed 367198090Srdivackylet AddedComplexity = 10 in 368198090Srdivackydef tLDRSB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), IIC_iLoadr, 369198892Srdivacky "ldrsb", "\t$dst, $addr", 370201360Srdivacky [(set tGPR:$dst, (sextloadi8 t_addrmode_rr:$addr))]>, 371201360Srdivacky T1LdSt<0b011>; 372193323Sed 373198090Srdivackylet AddedComplexity = 10 in 374198090Srdivackydef tLDRSH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), IIC_iLoadr, 375198892Srdivacky "ldrsh", "\t$dst, $addr", 376201360Srdivacky [(set tGPR:$dst, (sextloadi16 t_addrmode_rr:$addr))]>, 377201360Srdivacky T1LdSt<0b111>; 378193323Sed 379193323Sedlet canFoldAsLoad = 1 in 380198090Srdivackydef tLDRspi : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), IIC_iLoadi, 381198892Srdivacky "ldr", "\t$dst, $addr", 382201360Srdivacky [(set tGPR:$dst, (load t_addrmode_sp:$addr))]>, 383201360Srdivacky T1LdStSP<{1,?,?}>; 384193323Sed 385193323Sed// Special instruction for restore. It cannot clobber condition register 386193323Sed// when it's expanded by eliminateCallFramePseudoInstr(). 387193323Sedlet canFoldAsLoad = 1, mayLoad = 1 in 388198090Srdivackydef tRestore : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), IIC_iLoadi, 389201360Srdivacky "ldr", "\t$dst, $addr", []>, 390201360Srdivacky T1LdStSP<{1,?,?}>; 391193323Sed 392193323Sed// Load tconstpool 393198892Srdivacky// FIXME: Use ldr.n to work around a Darwin assembler bug. 394199989Srdivackylet canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in 395198090Srdivackydef tLDRpci : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr), IIC_iLoadi, 396198892Srdivacky "ldr", ".n\t$dst, $addr", 397201360Srdivacky [(set tGPR:$dst, (load (ARMWrapper tconstpool:$addr)))]>, 398201360Srdivacky T1Encoding<{0,1,0,0,1,?}>; // A6.2 & A8.6.59 399193323Sed 400193323Sed// Special LDR for loads from non-pc-relative constpools. 401199989Srdivackylet canFoldAsLoad = 1, mayLoad = 1, isReMaterializable = 1, 402199989Srdivacky mayHaveSideEffects = 1 in 403198090Srdivackydef tLDRcp : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr), IIC_iLoadi, 404201360Srdivacky "ldr", "\t$dst, $addr", []>, 405201360Srdivacky T1LdStSP<{1,?,?}>; 406193323Sed 407198090Srdivackydef tSTR : T1pI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr), IIC_iStorer, 408198892Srdivacky "str", "\t$src, $addr", 409201360Srdivacky [(store tGPR:$src, t_addrmode_s4:$addr)]>, 410201360Srdivacky T1LdSt<0b000>; 411202375Srdivackydef tSTRi: T1pI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr), IIC_iStorer, 412202375Srdivacky "str", "\t$src, $addr", 413202375Srdivacky []>, 414202375Srdivacky T1LdSt4Imm<{0,?,?}>; 415193323Sed 416198090Srdivackydef tSTRB : T1pI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr), IIC_iStorer, 417198892Srdivacky "strb", "\t$src, $addr", 418201360Srdivacky [(truncstorei8 tGPR:$src, t_addrmode_s1:$addr)]>, 419201360Srdivacky T1LdSt<0b010>; 420202375Srdivackydef tSTRBi: T1pI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr), IIC_iStorer, 421202375Srdivacky "strb", "\t$src, $addr", 422202375Srdivacky []>, 423202375Srdivacky T1LdSt1Imm<{0,?,?}>; 424193323Sed 425198090Srdivackydef tSTRH : T1pI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr), IIC_iStorer, 426198892Srdivacky "strh", "\t$src, $addr", 427201360Srdivacky [(truncstorei16 tGPR:$src, t_addrmode_s2:$addr)]>, 428201360Srdivacky T1LdSt<0b001>; 429202375Srdivackydef tSTRHi: T1pI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr), IIC_iStorer, 430202375Srdivacky "strh", "\t$src, $addr", 431202375Srdivacky []>, 432202375Srdivacky T1LdSt2Imm<{0,?,?}>; 433193323Sed 434198090Srdivackydef tSTRspi : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStorei, 435198892Srdivacky "str", "\t$src, $addr", 436201360Srdivacky [(store tGPR:$src, t_addrmode_sp:$addr)]>, 437201360Srdivacky T1LdStSP<{0,?,?}>; 438193323Sed 439193323Sedlet mayStore = 1 in { 440193323Sed// Special instruction for spill. It cannot clobber condition register 441193323Sed// when it's expanded by eliminateCallFramePseudoInstr(). 442198090Srdivackydef tSpill : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStorei, 443201360Srdivacky "str", "\t$src, $addr", []>, 444201360Srdivacky T1LdStSP<{0,?,?}>; 445193323Sed} 446193323Sed 447193323Sed//===----------------------------------------------------------------------===// 448193323Sed// Load / store multiple Instructions. 449193323Sed// 450193323Sed 451198090Srdivacky// These requires base address to be written back or one of the loaded regs. 452198090Srdivackylet mayLoad = 1, hasExtraDefRegAllocReq = 1 in 453198090Srdivackydef tLDM : T1I<(outs), 454198090Srdivacky (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops), 455198090Srdivacky IIC_iLoadm, 456201360Srdivacky "ldm${addr:submode}${p}\t$addr, $wb", []>, 457201360Srdivacky T1Encoding<{1,1,0,0,1,?}>; // A6.2 & A8.6.53 458193323Sed 459198090Srdivackylet mayStore = 1, hasExtraSrcRegAllocReq = 1 in 460198090Srdivackydef tSTM : T1I<(outs), 461198090Srdivacky (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops), 462198090Srdivacky IIC_iStorem, 463201360Srdivacky "stm${addr:submode}${p}\t$addr, $wb", []>, 464201360Srdivacky T1Encoding<{1,1,0,0,0,?}>; // A6.2 & A8.6.189 465193323Sed 466198090Srdivackylet mayLoad = 1, Uses = [SP], Defs = [SP], hasExtraDefRegAllocReq = 1 in 467198090Srdivackydef tPOP : T1I<(outs), (ins pred:$p, reglist:$wb, variable_ops), IIC_Br, 468201360Srdivacky "pop${p}\t$wb", []>, 469201360Srdivacky T1Misc<{1,1,0,?,?,?,?}>; 470193323Sed 471198090Srdivackylet mayStore = 1, Uses = [SP], Defs = [SP], hasExtraSrcRegAllocReq = 1 in 472198090Srdivackydef tPUSH : T1I<(outs), (ins pred:$p, reglist:$wb, variable_ops), IIC_Br, 473201360Srdivacky "push${p}\t$wb", []>, 474201360Srdivacky T1Misc<{0,1,0,?,?,?,?}>; 475198090Srdivacky 476193323Sed//===----------------------------------------------------------------------===// 477193323Sed// Arithmetic Instructions. 478193323Sed// 479193323Sed 480195098Sed// Add with carry register 481198090Srdivackylet isCommutable = 1, Uses = [CPSR] in 482198090Srdivackydef tADC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 483198892Srdivacky "adc", "\t$dst, $rhs", 484201360Srdivacky [(set tGPR:$dst, (adde tGPR:$lhs, tGPR:$rhs))]>, 485201360Srdivacky T1DataProcessing<0b0101>; 486193323Sed 487195098Sed// Add immediate 488198090Srdivackydef tADDi3 : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi, 489198892Srdivacky "add", "\t$dst, $lhs, $rhs", 490201360Srdivacky [(set tGPR:$dst, (add tGPR:$lhs, imm0_7:$rhs))]>, 491201360Srdivacky T1General<0b01110>; 492193323Sed 493198090Srdivackydef tADDi8 : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi, 494198892Srdivacky "add", "\t$dst, $rhs", 495201360Srdivacky [(set tGPR:$dst, (add tGPR:$lhs, imm8_255:$rhs))]>, 496201360Srdivacky T1General<{1,1,0,?,?}>; 497193323Sed 498195098Sed// Add register 499198090Srdivackylet isCommutable = 1 in 500198090Srdivackydef tADDrr : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 501198892Srdivacky "add", "\t$dst, $lhs, $rhs", 502201360Srdivacky [(set tGPR:$dst, (add tGPR:$lhs, tGPR:$rhs))]>, 503201360Srdivacky T1General<0b01100>; 504193323Sed 505194178Sedlet neverHasSideEffects = 1 in 506198090Srdivackydef tADDhirr : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, 507201360Srdivacky "add", "\t$dst, $rhs", []>, 508201360Srdivacky T1Special<{0,0,?,?}>; 509193323Sed 510195098Sed// And register 511198090Srdivackylet isCommutable = 1 in 512198090Srdivackydef tAND : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 513198892Srdivacky "and", "\t$dst, $rhs", 514201360Srdivacky [(set tGPR:$dst, (and tGPR:$lhs, tGPR:$rhs))]>, 515201360Srdivacky T1DataProcessing<0b0000>; 516193323Sed 517195098Sed// ASR immediate 518198090Srdivackydef tASRri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iMOVsi, 519198892Srdivacky "asr", "\t$dst, $lhs, $rhs", 520201360Srdivacky [(set tGPR:$dst, (sra tGPR:$lhs, (i32 imm:$rhs)))]>, 521201360Srdivacky T1General<{0,1,0,?,?}>; 522193323Sed 523195098Sed// ASR register 524198090Srdivackydef tASRrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, 525198892Srdivacky "asr", "\t$dst, $rhs", 526201360Srdivacky [(set tGPR:$dst, (sra tGPR:$lhs, tGPR:$rhs))]>, 527201360Srdivacky T1DataProcessing<0b0100>; 528193323Sed 529195098Sed// BIC register 530198090Srdivackydef tBIC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 531198892Srdivacky "bic", "\t$dst, $rhs", 532201360Srdivacky [(set tGPR:$dst, (and tGPR:$lhs, (not tGPR:$rhs)))]>, 533201360Srdivacky T1DataProcessing<0b1110>; 534193323Sed 535195098Sed// CMN register 536195098Sedlet Defs = [CPSR] in { 537198090Srdivackydef tCMN : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, 538198892Srdivacky "cmn", "\t$lhs, $rhs", 539201360Srdivacky [(ARMcmp tGPR:$lhs, (ineg tGPR:$rhs))]>, 540201360Srdivacky T1DataProcessing<0b1011>; 541201360Srdivackydef tCMNz : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, 542198892Srdivacky "cmn", "\t$lhs, $rhs", 543201360Srdivacky [(ARMcmpZ tGPR:$lhs, (ineg tGPR:$rhs))]>, 544201360Srdivacky T1DataProcessing<0b1011>; 545195098Sed} 546193323Sed 547195098Sed// CMP immediate 548195098Sedlet Defs = [CPSR] in { 549198090Srdivackydef tCMPi8 : T1pI<(outs), (ins tGPR:$lhs, i32imm:$rhs), IIC_iCMPi, 550198892Srdivacky "cmp", "\t$lhs, $rhs", 551201360Srdivacky [(ARMcmp tGPR:$lhs, imm0_255:$rhs)]>, 552201360Srdivacky T1General<{1,0,1,?,?}>; 553198090Srdivackydef tCMPzi8 : T1pI<(outs), (ins tGPR:$lhs, i32imm:$rhs), IIC_iCMPi, 554198892Srdivacky "cmp", "\t$lhs, $rhs", 555201360Srdivacky [(ARMcmpZ tGPR:$lhs, imm0_255:$rhs)]>, 556201360Srdivacky T1General<{1,0,1,?,?}>; 557195098Sed} 558195098Sed 559195098Sed// CMP register 560195098Sedlet Defs = [CPSR] in { 561198090Srdivackydef tCMPr : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, 562198892Srdivacky "cmp", "\t$lhs, $rhs", 563201360Srdivacky [(ARMcmp tGPR:$lhs, tGPR:$rhs)]>, 564201360Srdivacky T1DataProcessing<0b1010>; 565198090Srdivackydef tCMPzr : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, 566198892Srdivacky "cmp", "\t$lhs, $rhs", 567201360Srdivacky [(ARMcmpZ tGPR:$lhs, tGPR:$rhs)]>, 568201360Srdivacky T1DataProcessing<0b1010>; 569198090Srdivacky 570198090Srdivackydef tCMPhir : T1pI<(outs), (ins GPR:$lhs, GPR:$rhs), IIC_iCMPr, 571201360Srdivacky "cmp", "\t$lhs, $rhs", []>, 572201360Srdivacky T1Special<{0,1,?,?}>; 573198090Srdivackydef tCMPzhir : T1pI<(outs), (ins GPR:$lhs, GPR:$rhs), IIC_iCMPr, 574201360Srdivacky "cmp", "\t$lhs, $rhs", []>, 575201360Srdivacky T1Special<{0,1,?,?}>; 576195098Sed} 577193323Sed 578193323Sed 579195098Sed// XOR register 580198090Srdivackylet isCommutable = 1 in 581198090Srdivackydef tEOR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 582198892Srdivacky "eor", "\t$dst, $rhs", 583201360Srdivacky [(set tGPR:$dst, (xor tGPR:$lhs, tGPR:$rhs))]>, 584201360Srdivacky T1DataProcessing<0b0001>; 585193323Sed 586195098Sed// LSL immediate 587198090Srdivackydef tLSLri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iMOVsi, 588198892Srdivacky "lsl", "\t$dst, $lhs, $rhs", 589201360Srdivacky [(set tGPR:$dst, (shl tGPR:$lhs, (i32 imm:$rhs)))]>, 590201360Srdivacky T1General<{0,0,0,?,?}>; 591193323Sed 592195098Sed// LSL register 593198090Srdivackydef tLSLrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, 594198892Srdivacky "lsl", "\t$dst, $rhs", 595201360Srdivacky [(set tGPR:$dst, (shl tGPR:$lhs, tGPR:$rhs))]>, 596201360Srdivacky T1DataProcessing<0b0010>; 597193323Sed 598195098Sed// LSR immediate 599198090Srdivackydef tLSRri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iMOVsi, 600198892Srdivacky "lsr", "\t$dst, $lhs, $rhs", 601201360Srdivacky [(set tGPR:$dst, (srl tGPR:$lhs, (i32 imm:$rhs)))]>, 602201360Srdivacky T1General<{0,0,1,?,?}>; 603193323Sed 604195098Sed// LSR register 605198090Srdivackydef tLSRrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, 606198892Srdivacky "lsr", "\t$dst, $rhs", 607201360Srdivacky [(set tGPR:$dst, (srl tGPR:$lhs, tGPR:$rhs))]>, 608201360Srdivacky T1DataProcessing<0b0011>; 609193323Sed 610195098Sed// move register 611198090Srdivackydef tMOVi8 : T1sI<(outs tGPR:$dst), (ins i32imm:$src), IIC_iMOVi, 612198892Srdivacky "mov", "\t$dst, $src", 613201360Srdivacky [(set tGPR:$dst, imm0_255:$src)]>, 614201360Srdivacky T1General<{1,0,0,?,?}>; 615193323Sed 616193323Sed// TODO: A7-73: MOV(2) - mov setting flag. 617193323Sed 618193323Sed 619194178Sedlet neverHasSideEffects = 1 in { 620198090Srdivacky// FIXME: Make this predicable. 621198090Srdivackydef tMOVr : T1I<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr, 622201360Srdivacky "mov\t$dst, $src", []>, 623201360Srdivacky T1Special<0b1000>; 624198090Srdivackylet Defs = [CPSR] in 625198090Srdivackydef tMOVSr : T1I<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr, 626201360Srdivacky "movs\t$dst, $src", []>, Encoding16 { 627201360Srdivacky let Inst{15-6} = 0b0000000000; 628201360Srdivacky} 629198090Srdivacky 630198090Srdivacky// FIXME: Make these predicable. 631198090Srdivackydef tMOVgpr2tgpr : T1I<(outs tGPR:$dst), (ins GPR:$src), IIC_iMOVr, 632201360Srdivacky "mov\t$dst, $src", []>, 633201360Srdivacky T1Special<{1,0,0,1}>; 634198090Srdivackydef tMOVtgpr2gpr : T1I<(outs GPR:$dst), (ins tGPR:$src), IIC_iMOVr, 635201360Srdivacky "mov\t$dst, $src", []>, 636201360Srdivacky T1Special<{1,0,1,0}>; 637198090Srdivackydef tMOVgpr2gpr : T1I<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVr, 638201360Srdivacky "mov\t$dst, $src", []>, 639201360Srdivacky T1Special<{1,0,1,1}>; 640194178Sed} // neverHasSideEffects 641193323Sed 642195098Sed// multiply register 643198090Srdivackylet isCommutable = 1 in 644198090Srdivackydef tMUL : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMUL32, 645198892Srdivacky "mul", "\t$dst, $rhs", 646201360Srdivacky [(set tGPR:$dst, (mul tGPR:$lhs, tGPR:$rhs))]>, 647201360Srdivacky T1DataProcessing<0b1101>; 648193323Sed 649195098Sed// move inverse register 650198090Srdivackydef tMVN : T1sI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr, 651198892Srdivacky "mvn", "\t$dst, $src", 652201360Srdivacky [(set tGPR:$dst, (not tGPR:$src))]>, 653201360Srdivacky T1DataProcessing<0b1111>; 654193323Sed 655195098Sed// bitwise or register 656198090Srdivackylet isCommutable = 1 in 657198090Srdivackydef tORR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 658198892Srdivacky "orr", "\t$dst, $rhs", 659201360Srdivacky [(set tGPR:$dst, (or tGPR:$lhs, tGPR:$rhs))]>, 660201360Srdivacky T1DataProcessing<0b1100>; 661193323Sed 662195098Sed// swaps 663198090Srdivackydef tREV : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 664198892Srdivacky "rev", "\t$dst, $src", 665198090Srdivacky [(set tGPR:$dst, (bswap tGPR:$src))]>, 666201360Srdivacky Requires<[IsThumb1Only, HasV6]>, 667201360Srdivacky T1Misc<{1,0,1,0,0,0,?}>; 668193323Sed 669198090Srdivackydef tREV16 : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 670198892Srdivacky "rev16", "\t$dst, $src", 671198090Srdivacky [(set tGPR:$dst, 672198090Srdivacky (or (and (srl tGPR:$src, (i32 8)), 0xFF), 673198090Srdivacky (or (and (shl tGPR:$src, (i32 8)), 0xFF00), 674198090Srdivacky (or (and (srl tGPR:$src, (i32 8)), 0xFF0000), 675198090Srdivacky (and (shl tGPR:$src, (i32 8)), 0xFF000000)))))]>, 676201360Srdivacky Requires<[IsThumb1Only, HasV6]>, 677201360Srdivacky T1Misc<{1,0,1,0,0,1,?}>; 678193323Sed 679198090Srdivackydef tREVSH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 680198892Srdivacky "revsh", "\t$dst, $src", 681198090Srdivacky [(set tGPR:$dst, 682198090Srdivacky (sext_inreg 683198090Srdivacky (or (srl (and tGPR:$src, 0xFF00), (i32 8)), 684198090Srdivacky (shl tGPR:$src, (i32 8))), i16))]>, 685201360Srdivacky Requires<[IsThumb1Only, HasV6]>, 686201360Srdivacky T1Misc<{1,0,1,0,1,1,?}>; 687193323Sed 688195098Sed// rotate right register 689198090Srdivackydef tROR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, 690198892Srdivacky "ror", "\t$dst, $rhs", 691201360Srdivacky [(set tGPR:$dst, (rotr tGPR:$lhs, tGPR:$rhs))]>, 692201360Srdivacky T1DataProcessing<0b0111>; 693193323Sed 694198090Srdivacky// negate register 695198090Srdivackydef tRSB : T1sI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iALUi, 696198892Srdivacky "rsb", "\t$dst, $src, #0", 697201360Srdivacky [(set tGPR:$dst, (ineg tGPR:$src))]>, 698201360Srdivacky T1DataProcessing<0b1001>; 699198090Srdivacky 700195098Sed// Subtract with carry register 701198090Srdivackylet Uses = [CPSR] in 702198090Srdivackydef tSBC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 703198892Srdivacky "sbc", "\t$dst, $rhs", 704201360Srdivacky [(set tGPR:$dst, (sube tGPR:$lhs, tGPR:$rhs))]>, 705201360Srdivacky T1DataProcessing<0b0110>; 706193323Sed 707195098Sed// Subtract immediate 708198090Srdivackydef tSUBi3 : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi, 709198892Srdivacky "sub", "\t$dst, $lhs, $rhs", 710201360Srdivacky [(set tGPR:$dst, (add tGPR:$lhs, imm0_7_neg:$rhs))]>, 711201360Srdivacky T1General<0b01111>; 712193323Sed 713198090Srdivackydef tSUBi8 : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi, 714198892Srdivacky "sub", "\t$dst, $rhs", 715201360Srdivacky [(set tGPR:$dst, (add tGPR:$lhs, imm8_255_neg:$rhs))]>, 716201360Srdivacky T1General<{1,1,1,?,?}>; 717193323Sed 718195098Sed// subtract register 719198090Srdivackydef tSUBrr : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 720198892Srdivacky "sub", "\t$dst, $lhs, $rhs", 721201360Srdivacky [(set tGPR:$dst, (sub tGPR:$lhs, tGPR:$rhs))]>, 722201360Srdivacky T1General<0b01101>; 723193323Sed 724195098Sed// TODO: A7-96: STMIA - store multiple. 725195098Sed 726195098Sed// sign-extend byte 727198090Srdivackydef tSXTB : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 728198892Srdivacky "sxtb", "\t$dst, $src", 729198090Srdivacky [(set tGPR:$dst, (sext_inreg tGPR:$src, i8))]>, 730201360Srdivacky Requires<[IsThumb1Only, HasV6]>, 731201360Srdivacky T1Misc<{0,0,1,0,0,1,?}>; 732195098Sed 733195098Sed// sign-extend short 734198090Srdivackydef tSXTH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 735198892Srdivacky "sxth", "\t$dst, $src", 736198090Srdivacky [(set tGPR:$dst, (sext_inreg tGPR:$src, i16))]>, 737201360Srdivacky Requires<[IsThumb1Only, HasV6]>, 738201360Srdivacky T1Misc<{0,0,1,0,0,0,?}>; 739193323Sed 740195098Sed// test 741195098Sedlet isCommutable = 1, Defs = [CPSR] in 742198090Srdivackydef tTST : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, 743198892Srdivacky "tst", "\t$lhs, $rhs", 744201360Srdivacky [(ARMcmpZ (and tGPR:$lhs, tGPR:$rhs), 0)]>, 745201360Srdivacky T1DataProcessing<0b1000>; 746193323Sed 747195098Sed// zero-extend byte 748198090Srdivackydef tUXTB : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 749198892Srdivacky "uxtb", "\t$dst, $src", 750198090Srdivacky [(set tGPR:$dst, (and tGPR:$src, 0xFF))]>, 751201360Srdivacky Requires<[IsThumb1Only, HasV6]>, 752201360Srdivacky T1Misc<{0,0,1,0,1,1,?}>; 753195098Sed 754195098Sed// zero-extend short 755198090Srdivackydef tUXTH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 756198892Srdivacky "uxth", "\t$dst, $src", 757198090Srdivacky [(set tGPR:$dst, (and tGPR:$src, 0xFFFF))]>, 758201360Srdivacky Requires<[IsThumb1Only, HasV6]>, 759201360Srdivacky T1Misc<{0,0,1,0,1,0,?}>; 760193323Sed 761193323Sed 762193323Sed// Conditional move tMOVCCr - Used to implement the Thumb SELECT_CC DAG operation. 763198892Srdivacky// Expanded after instruction selection into a branch sequence. 764198892Srdivackylet usesCustomInserter = 1 in // Expanded after instruction selection. 765198090Srdivacky def tMOVCCr_pseudo : 766193323Sed PseudoInst<(outs tGPR:$dst), (ins tGPR:$false, tGPR:$true, pred:$cc), 767198090Srdivacky NoItinerary, "@ tMOVCCr $cc", 768198090Srdivacky [/*(set tGPR:$dst, (ARMcmov tGPR:$false, tGPR:$true, imm:$cc))*/]>; 769193323Sed 770198090Srdivacky 771198090Srdivacky// 16-bit movcc in IT blocks for Thumb2. 772198090Srdivackydef tMOVCCr : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iCMOVr, 773201360Srdivacky "mov", "\t$dst, $rhs", []>, 774202375Srdivacky T1Special<{1,0,1,1}>; 775198090Srdivacky 776198090Srdivackydef tMOVCCi : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs), IIC_iCMOVi, 777201360Srdivacky "mov", "\t$dst, $rhs", []>, 778201360Srdivacky T1General<{1,0,0,?,?}>; 779198090Srdivacky 780193323Sed// tLEApcrel - Load a pc-relative address into a register without offending the 781193323Sed// assembler. 782198090Srdivackydef tLEApcrel : T1I<(outs tGPR:$dst), (ins i32imm:$label, pred:$p), IIC_iALUi, 783201360Srdivacky "adr$p\t$dst, #$label", []>, 784201360Srdivacky T1Encoding<{1,0,1,0,0,?}>; // A6.2 & A8.6.10 785193323Sed 786198090Srdivackydef tLEApcrelJT : T1I<(outs tGPR:$dst), 787198090Srdivacky (ins i32imm:$label, nohash_imm:$id, pred:$p), 788201360Srdivacky IIC_iALUi, "adr$p\t$dst, #${label}_${id}", []>, 789201360Srdivacky T1Encoding<{1,0,1,0,0,?}>; // A6.2 & A8.6.10 790193323Sed 791193323Sed//===----------------------------------------------------------------------===// 792193323Sed// TLS Instructions 793193323Sed// 794193323Sed 795193323Sed// __aeabi_read_tp preserves the registers r1-r3. 796193323Sedlet isCall = 1, 797193323Sed Defs = [R0, LR] in { 798201360Srdivacky def tTPsoft : TIx2<0b11110, 0b11, 1, (outs), (ins), IIC_Br, 799201360Srdivacky "bl\t__aeabi_read_tp", 800201360Srdivacky [(set R0, ARMthread_pointer)]>; 801193323Sed} 802193323Sed 803200581Srdivacky// SJLJ Exception handling intrinsics 804200581Srdivacky// eh_sjlj_setjmp() is an instruction sequence to store the return 805200581Srdivacky// address and save #0 in R0 for the non-longjmp case. 806200581Srdivacky// Since by its nature we may be coming from some other function to get 807200581Srdivacky// here, and we're using the stack frame for the containing function to 808200581Srdivacky// save/restore registers, we can't keep anything live in regs across 809200581Srdivacky// the eh_sjlj_setjmp(), else it will almost certainly have been tromped upon 810200581Srdivacky// when we get here from a longjmp(). We force everthing out of registers 811200581Srdivacky// except for our own input by listing the relevant registers in Defs. By 812200581Srdivacky// doing so, we also cause the prologue/epilogue code to actively preserve 813200581Srdivacky// all of the callee-saved resgisters, which is exactly what we want. 814200581Srdivackylet Defs = 815200581Srdivacky [ R0, R1, R2, R3, R4, R5, R6, R7, R12 ] in { 816200581Srdivacky def tInt_eh_sjlj_setjmp : ThumbXI<(outs), (ins GPR:$src), 817200581Srdivacky AddrModeNone, SizeSpecial, NoItinerary, 818200581Srdivacky "mov\tr12, r1\t@ begin eh.setjmp\n" 819200581Srdivacky "\tmov\tr1, sp\n" 820200581Srdivacky "\tstr\tr1, [$src, #8]\n" 821200581Srdivacky "\tadr\tr1, 0f\n" 822200581Srdivacky "\tadds\tr1, #1\n" 823200581Srdivacky "\tstr\tr1, [$src, #4]\n" 824200581Srdivacky "\tmov\tr1, r12\n" 825200581Srdivacky "\tmovs\tr0, #0\n" 826200581Srdivacky "\tb\t1f\n" 827200581Srdivacky ".align 2\n" 828200581Srdivacky "0:\tmovs\tr0, #1\t@ end eh.setjmp\n" 829200581Srdivacky "1:", "", 830200581Srdivacky [(set R0, (ARMeh_sjlj_setjmp GPR:$src))]>; 831200581Srdivacky} 832193323Sed//===----------------------------------------------------------------------===// 833193323Sed// Non-Instruction Patterns 834193323Sed// 835193323Sed 836198090Srdivacky// Add with carry 837198090Srdivackydef : T1Pat<(addc tGPR:$lhs, imm0_7:$rhs), 838198090Srdivacky (tADDi3 tGPR:$lhs, imm0_7:$rhs)>; 839198090Srdivackydef : T1Pat<(addc tGPR:$lhs, imm8_255:$rhs), 840198090Srdivacky (tADDi8 tGPR:$lhs, imm8_255:$rhs)>; 841198090Srdivackydef : T1Pat<(addc tGPR:$lhs, tGPR:$rhs), 842198090Srdivacky (tADDrr tGPR:$lhs, tGPR:$rhs)>; 843198090Srdivacky 844198090Srdivacky// Subtract with carry 845198090Srdivackydef : T1Pat<(addc tGPR:$lhs, imm0_7_neg:$rhs), 846198090Srdivacky (tSUBi3 tGPR:$lhs, imm0_7_neg:$rhs)>; 847198090Srdivackydef : T1Pat<(addc tGPR:$lhs, imm8_255_neg:$rhs), 848198090Srdivacky (tSUBi8 tGPR:$lhs, imm8_255_neg:$rhs)>; 849198090Srdivackydef : T1Pat<(subc tGPR:$lhs, tGPR:$rhs), 850198090Srdivacky (tSUBrr tGPR:$lhs, tGPR:$rhs)>; 851198090Srdivacky 852193323Sed// ConstantPool, GlobalAddress 853198090Srdivackydef : T1Pat<(ARMWrapper tglobaladdr :$dst), (tLEApcrel tglobaladdr :$dst)>; 854198090Srdivackydef : T1Pat<(ARMWrapper tconstpool :$dst), (tLEApcrel tconstpool :$dst)>; 855193323Sed 856193323Sed// JumpTable 857198090Srdivackydef : T1Pat<(ARMWrapperJT tjumptable:$dst, imm:$id), 858198090Srdivacky (tLEApcrelJT tjumptable:$dst, imm:$id)>; 859193323Sed 860193323Sed// Direct calls 861198090Srdivackydef : T1Pat<(ARMtcall texternalsym:$func), (tBL texternalsym:$func)>, 862198090Srdivacky Requires<[IsThumb, IsNotDarwin]>; 863198090Srdivackydef : T1Pat<(ARMtcall texternalsym:$func), (tBLr9 texternalsym:$func)>, 864198090Srdivacky Requires<[IsThumb, IsDarwin]>; 865193323Sed 866198090Srdivackydef : Tv5Pat<(ARMcall texternalsym:$func), (tBLXi texternalsym:$func)>, 867198090Srdivacky Requires<[IsThumb, HasV5T, IsNotDarwin]>; 868198090Srdivackydef : Tv5Pat<(ARMcall texternalsym:$func), (tBLXi_r9 texternalsym:$func)>, 869198090Srdivacky Requires<[IsThumb, HasV5T, IsDarwin]>; 870198090Srdivacky 871193323Sed// Indirect calls to ARM routines 872198090Srdivackydef : Tv5Pat<(ARMcall GPR:$dst), (tBLXr GPR:$dst)>, 873198090Srdivacky Requires<[IsThumb, HasV5T, IsNotDarwin]>; 874198090Srdivackydef : Tv5Pat<(ARMcall GPR:$dst), (tBLXr_r9 GPR:$dst)>, 875198090Srdivacky Requires<[IsThumb, HasV5T, IsDarwin]>; 876193323Sed 877193323Sed// zextload i1 -> zextload i8 878195340Seddef : T1Pat<(zextloadi1 t_addrmode_s1:$addr), 879195340Sed (tLDRB t_addrmode_s1:$addr)>; 880193323Sed 881193323Sed// extload -> zextload 882195340Seddef : T1Pat<(extloadi1 t_addrmode_s1:$addr), (tLDRB t_addrmode_s1:$addr)>; 883195340Seddef : T1Pat<(extloadi8 t_addrmode_s1:$addr), (tLDRB t_addrmode_s1:$addr)>; 884195340Seddef : T1Pat<(extloadi16 t_addrmode_s2:$addr), (tLDRH t_addrmode_s2:$addr)>; 885193323Sed 886198090Srdivacky// If it's impossible to use [r,r] address mode for sextload, select to 887198090Srdivacky// ldr{b|h} + sxt{b|h} instead. 888198090Srdivackydef : T1Pat<(sextloadi8 t_addrmode_s1:$addr), 889198090Srdivacky (tSXTB (tLDRB t_addrmode_s1:$addr))>, 890198090Srdivacky Requires<[IsThumb1Only, HasV6]>; 891198090Srdivackydef : T1Pat<(sextloadi16 t_addrmode_s2:$addr), 892198090Srdivacky (tSXTH (tLDRH t_addrmode_s2:$addr))>, 893198090Srdivacky Requires<[IsThumb1Only, HasV6]>; 894198090Srdivacky 895198090Srdivackydef : T1Pat<(sextloadi8 t_addrmode_s1:$addr), 896198090Srdivacky (tASRri (tLSLri (tLDRB t_addrmode_s1:$addr), 24), 24)>; 897198090Srdivackydef : T1Pat<(sextloadi16 t_addrmode_s1:$addr), 898198090Srdivacky (tASRri (tLSLri (tLDRH t_addrmode_s1:$addr), 16), 16)>; 899198090Srdivacky 900193323Sed// Large immediate handling. 901193323Sed 902193323Sed// Two piece imms. 903195098Seddef : T1Pat<(i32 thumb_immshifted:$src), 904195098Sed (tLSLri (tMOVi8 (thumb_immshifted_val imm:$src)), 905195098Sed (thumb_immshifted_shamt imm:$src))>; 906193323Sed 907195098Seddef : T1Pat<(i32 imm0_255_comp:$src), 908195098Sed (tMVN (tMOVi8 (imm_comp_XFORM imm:$src)))>; 909199481Srdivacky 910199481Srdivacky// Pseudo instruction that combines ldr from constpool and add pc. This should 911199481Srdivacky// be expanded into two instructions late to allow if-conversion and 912199481Srdivacky// scheduling. 913199481Srdivackylet isReMaterializable = 1 in 914199481Srdivackydef tLDRpci_pic : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr, pclabel:$cp), 915199481Srdivacky NoItinerary, "@ ldr.n\t$dst, $addr\n$cp:\n\tadd\t$dst, pc", 916199481Srdivacky [(set GPR:$dst, (ARMpic_add (load (ARMWrapper tconstpool:$addr)), 917199481Srdivacky imm:$cp))]>, 918199481Srdivacky Requires<[IsThumb1Only]>; 919