ARMInstrThumb.td revision 203954
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 135203954Srdivacky// The i32imm operand $val can be used by a debugger to store more information 136203954Srdivacky// about the breakpoint. 137203954Srdivackydef tBKPT : T1I<(outs), (ins i32imm:$val), NoItinerary, "bkpt\t$val", 138203954Srdivacky [/* For disassembly only; pattern left blank */]>, 139203954Srdivacky T1Encoding<0b101111> { 140203954Srdivacky let Inst{9-8} = 0b10; 141203954Srdivacky} 142203954Srdivacky 143198090Srdivacky// For both thumb1 and thumb2. 144193323Sedlet isNotDuplicable = 1 in 145198090Srdivackydef tPICADD : TIt<(outs GPR:$dst), (ins GPR:$lhs, pclabel:$cp), IIC_iALUr, 146198892Srdivacky "\n$cp:\n\tadd\t$dst, pc", 147201360Srdivacky [(set GPR:$dst, (ARMpic_add GPR:$lhs, imm:$cp))]>, 148201360Srdivacky T1Special<{0,0,?,?}> { 149201360Srdivacky let Inst{6-3} = 0b1111; // A8.6.6 Rm = pc 150201360Srdivacky} 151193323Sed 152195098Sed// PC relative add. 153199511Srdivackydef tADDrPCi : T1I<(outs tGPR:$dst), (ins t_imm_s4:$rhs), IIC_iALUi, 154201360Srdivacky "add\t$dst, pc, $rhs", []>, 155201360Srdivacky T1Encoding<{1,0,1,0,0,?}>; // A6.2 & A8.6.10 156195098Sed 157195098Sed// ADD rd, sp, #imm8 158199511Srdivackydef tADDrSPi : T1I<(outs tGPR:$dst), (ins GPR:$sp, t_imm_s4:$rhs), IIC_iALUi, 159201360Srdivacky "add\t$dst, $sp, $rhs", []>, 160201360Srdivacky T1Encoding<{1,0,1,0,1,?}>; // A6.2 & A8.6.8 161195098Sed 162195098Sed// ADD sp, sp, #imm7 163199511Srdivackydef tADDspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), IIC_iALUi, 164201360Srdivacky "add\t$dst, $rhs", []>, 165201360Srdivacky T1Misc<{0,0,0,0,0,?,?}>; // A6.2.5 & A8.6.8 166195098Sed 167198090Srdivacky// SUB sp, sp, #imm7 168199511Srdivackydef tSUBspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), IIC_iALUi, 169201360Srdivacky "sub\t$dst, $rhs", []>, 170201360Srdivacky T1Misc<{0,0,0,0,1,?,?}>; // A6.2.5 & A8.6.215 171198090Srdivacky 172198090Srdivacky// ADD rm, sp 173198090Srdivackydef tADDrSP : TIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, 174201360Srdivacky "add\t$dst, $rhs", []>, 175201360Srdivacky T1Special<{0,0,?,?}> { 176201360Srdivacky let Inst{6-3} = 0b1101; // A8.6.9 Encoding T1 177201360Srdivacky} 178198090Srdivacky 179195098Sed// ADD sp, rm 180198090Srdivackydef tADDspr : TIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, 181201360Srdivacky "add\t$dst, $rhs", []>, 182201360Srdivacky T1Special<{0,0,?,?}> { 183201360Srdivacky // A8.6.9 Encoding T2 184201360Srdivacky let Inst{7} = 1; 185201360Srdivacky let Inst{2-0} = 0b101; 186201360Srdivacky} 187195098Sed 188198090Srdivacky// Pseudo instruction that will expand into a tSUBspi + a copy. 189198892Srdivackylet usesCustomInserter = 1 in { // Expanded after instruction selection. 190199511Srdivackydef tSUBspi_ : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), 191199511Srdivacky NoItinerary, "@ sub\t$dst, $rhs", []>; 192198090Srdivacky 193198090Srdivackydef tADDspr_ : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), 194198892Srdivacky NoItinerary, "@ add\t$dst, $rhs", []>; 195198090Srdivacky 196198090Srdivackylet Defs = [CPSR] in 197198090Srdivackydef tANDsp : PseudoInst<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), 198198892Srdivacky NoItinerary, "@ and\t$dst, $rhs", []>; 199198892Srdivacky} // usesCustomInserter 200198090Srdivacky 201193323Sed//===----------------------------------------------------------------------===// 202193323Sed// Control Flow Instructions. 203193323Sed// 204193323Sed 205198090Srdivackylet isReturn = 1, isTerminator = 1, isBarrier = 1 in { 206201360Srdivacky def tBX_RET : TI<(outs), (ins), IIC_Br, "bx\tlr", [(ARMretflag)]>, 207201360Srdivacky T1Special<{1,1,0,?}> { // A6.2.3 & A8.6.25 208201360Srdivacky let Inst{6-3} = 0b1110; // Rm = lr 209201360Srdivacky } 210193323Sed // Alternative return instruction used by vararg functions. 211201360Srdivacky def tBX_RET_vararg : TI<(outs), (ins tGPR:$target), IIC_Br, "bx\t$target", []>, 212201360Srdivacky T1Special<{1,1,0,?}>; // A6.2.3 & A8.6.25 213193323Sed} 214193323Sed 215198892Srdivacky// Indirect branches 216198892Srdivackylet isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { 217198892Srdivacky def tBRIND : TI<(outs), (ins GPR:$dst), IIC_Br, "mov\tpc, $dst", 218201360Srdivacky [(brind GPR:$dst)]>, 219202878Srdivacky T1Special<{1,0,1,?}> { 220202375Srdivacky // <Rd> = Inst{7:2-0} = pc 221201360Srdivacky let Inst{2-0} = 0b111; 222201360Srdivacky } 223198892Srdivacky} 224198892Srdivacky 225193323Sed// FIXME: remove when we have a way to marking a MI with these properties. 226198090Srdivackylet isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1, 227198090Srdivacky hasExtraDefRegAllocReq = 1 in 228198090Srdivackydef tPOP_RET : T1I<(outs), (ins pred:$p, reglist:$wb, variable_ops), IIC_Br, 229201360Srdivacky "pop${p}\t$wb", []>, 230201360Srdivacky T1Misc<{1,1,0,?,?,?,?}>; 231193323Sed 232193323Sedlet isCall = 1, 233198090Srdivacky Defs = [R0, R1, R2, R3, R12, LR, 234198090Srdivacky D0, D1, D2, D3, D4, D5, D6, D7, 235198090Srdivacky D16, D17, D18, D19, D20, D21, D22, D23, 236198090Srdivacky D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR] in { 237198090Srdivacky // Also used for Thumb2 238201360Srdivacky def tBL : TIx2<0b11110, 0b11, 1, 239201360Srdivacky (outs), (ins i32imm:$func, variable_ops), IIC_Br, 240201360Srdivacky "bl\t${func:call}", 241201360Srdivacky [(ARMtcall tglobaladdr:$func)]>, 242198090Srdivacky Requires<[IsThumb, IsNotDarwin]>; 243198090Srdivacky 244198090Srdivacky // ARMv5T and above, also used for Thumb2 245201360Srdivacky def tBLXi : TIx2<0b11110, 0b11, 0, 246201360Srdivacky (outs), (ins i32imm:$func, variable_ops), IIC_Br, 247201360Srdivacky "blx\t${func:call}", 248201360Srdivacky [(ARMcall tglobaladdr:$func)]>, 249198090Srdivacky Requires<[IsThumb, HasV5T, IsNotDarwin]>; 250198090Srdivacky 251198090Srdivacky // Also used for Thumb2 252198090Srdivacky def tBLXr : TI<(outs), (ins GPR:$func, variable_ops), IIC_Br, 253198892Srdivacky "blx\t$func", 254198090Srdivacky [(ARMtcall GPR:$func)]>, 255201360Srdivacky Requires<[IsThumb, HasV5T, IsNotDarwin]>, 256201360Srdivacky T1Special<{1,1,1,?}>; // A6.2.3 & A8.6.24; 257198090Srdivacky 258193323Sed // ARMv4T 259201360Srdivacky def tBX : TIx2<{?,?,?,?,?}, {?,?}, ?, 260201360Srdivacky (outs), (ins tGPR:$func, variable_ops), IIC_Br, 261198892Srdivacky "mov\tlr, pc\n\tbx\t$func", 262198090Srdivacky [(ARMcall_nolink tGPR:$func)]>, 263198090Srdivacky Requires<[IsThumb1Only, IsNotDarwin]>; 264193323Sed} 265193323Sed 266198090Srdivacky// On Darwin R9 is call-clobbered. 267198090Srdivackylet isCall = 1, 268198090Srdivacky Defs = [R0, R1, R2, R3, R9, R12, LR, 269198090Srdivacky D0, D1, D2, D3, D4, D5, D6, D7, 270198090Srdivacky D16, D17, D18, D19, D20, D21, D22, D23, 271198090Srdivacky D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR] in { 272198090Srdivacky // Also used for Thumb2 273201360Srdivacky def tBLr9 : TIx2<0b11110, 0b11, 1, 274201360Srdivacky (outs), (ins i32imm:$func, variable_ops), IIC_Br, 275198892Srdivacky "bl\t${func:call}", 276198090Srdivacky [(ARMtcall tglobaladdr:$func)]>, 277198090Srdivacky Requires<[IsThumb, IsDarwin]>; 278198090Srdivacky 279198090Srdivacky // ARMv5T and above, also used for Thumb2 280201360Srdivacky def tBLXi_r9 : TIx2<0b11110, 0b11, 0, 281201360Srdivacky (outs), (ins i32imm:$func, variable_ops), IIC_Br, 282198892Srdivacky "blx\t${func:call}", 283198090Srdivacky [(ARMcall tglobaladdr:$func)]>, 284198090Srdivacky Requires<[IsThumb, HasV5T, IsDarwin]>; 285198090Srdivacky 286198090Srdivacky // Also used for Thumb2 287198090Srdivacky def tBLXr_r9 : TI<(outs), (ins GPR:$func, variable_ops), IIC_Br, 288201360Srdivacky "blx\t$func", 289201360Srdivacky [(ARMtcall GPR:$func)]>, 290201360Srdivacky Requires<[IsThumb, HasV5T, IsDarwin]>, 291201360Srdivacky T1Special<{1,1,1,?}>; // A6.2.3 & A8.6.24 292198090Srdivacky 293198090Srdivacky // ARMv4T 294201360Srdivacky def tBXr9 : TIx2<{?,?,?,?,?}, {?,?}, ?, 295201360Srdivacky (outs), (ins tGPR:$func, variable_ops), IIC_Br, 296201360Srdivacky "mov\tlr, pc\n\tbx\t$func", 297201360Srdivacky [(ARMcall_nolink tGPR:$func)]>, 298198090Srdivacky Requires<[IsThumb1Only, IsDarwin]>; 299198090Srdivacky} 300198090Srdivacky 301193323Sedlet isBranch = 1, isTerminator = 1 in { 302193323Sed let isBarrier = 1 in { 303193323Sed let isPredicable = 1 in 304198090Srdivacky def tB : T1I<(outs), (ins brtarget:$target), IIC_Br, 305201360Srdivacky "b\t$target", [(br bb:$target)]>, 306201360Srdivacky T1Encoding<{1,1,1,0,0,?}>; 307193323Sed 308193323Sed // Far jump 309198090Srdivacky let Defs = [LR] in 310201360Srdivacky def tBfar : TIx2<0b11110, 0b11, 1, (outs), (ins brtarget:$target), IIC_Br, 311198892Srdivacky "bl\t$target\t@ far jump",[]>; 312193323Sed 313195340Sed def tBR_JTr : T1JTI<(outs), 314195340Sed (ins tGPR:$target, jtblock_operand:$jt, i32imm:$id), 315198892Srdivacky IIC_Br, "mov\tpc, $target\n\t.align\t2\n$jt", 316201360Srdivacky [(ARMbrjt tGPR:$target, tjumptable:$jt, imm:$id)]>, 317201360Srdivacky Encoding16 { 318201360Srdivacky let Inst{15-7} = 0b010001101; 319201360Srdivacky let Inst{2-0} = 0b111; 320193323Sed } 321201360Srdivacky } 322193323Sed} 323193323Sed 324193323Sed// FIXME: should be able to write a pattern for ARMBrcond, but can't use 325193323Sed// a two-value operand where a dag node expects two operands. :( 326193323Sedlet isBranch = 1, isTerminator = 1 in 327198090Srdivacky def tBcc : T1I<(outs), (ins brtarget:$target, pred:$cc), IIC_Br, 328198892Srdivacky "b$cc\t$target", 329201360Srdivacky [/*(ARMbrcond bb:$target, imm:$cc)*/]>, 330201360Srdivacky T1Encoding<{1,1,0,1,?,?}>; 331193323Sed 332198892Srdivacky// Compare and branch on zero / non-zero 333198892Srdivackylet isBranch = 1, isTerminator = 1 in { 334198892Srdivacky def tCBZ : T1I<(outs), (ins tGPR:$cmp, brtarget:$target), IIC_Br, 335201360Srdivacky "cbz\t$cmp, $target", []>, 336201360Srdivacky T1Misc<{0,0,?,1,?,?,?}>; 337198892Srdivacky 338198892Srdivacky def tCBNZ : T1I<(outs), (ins tGPR:$cmp, brtarget:$target), IIC_Br, 339201360Srdivacky "cbnz\t$cmp, $target", []>, 340201360Srdivacky T1Misc<{1,0,?,1,?,?,?}>; 341198892Srdivacky} 342198892Srdivacky 343193323Sed//===----------------------------------------------------------------------===// 344193323Sed// Load Store Instructions. 345193323Sed// 346193323Sed 347199989Srdivackylet canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in 348198090Srdivackydef tLDR : T1pI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr), IIC_iLoadr, 349198892Srdivacky "ldr", "\t$dst, $addr", 350201360Srdivacky [(set tGPR:$dst, (load t_addrmode_s4:$addr))]>, 351201360Srdivacky T1LdSt<0b100>; 352202375Srdivackydef tLDRi: T1pI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr), IIC_iLoadr, 353202375Srdivacky "ldr", "\t$dst, $addr", 354202375Srdivacky []>, 355202375Srdivacky T1LdSt4Imm<{1,?,?}>; 356193323Sed 357198090Srdivackydef tLDRB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr), IIC_iLoadr, 358198892Srdivacky "ldrb", "\t$dst, $addr", 359201360Srdivacky [(set tGPR:$dst, (zextloadi8 t_addrmode_s1:$addr))]>, 360201360Srdivacky T1LdSt<0b110>; 361202375Srdivackydef tLDRBi: T1pI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr), IIC_iLoadr, 362202375Srdivacky "ldrb", "\t$dst, $addr", 363202375Srdivacky []>, 364202375Srdivacky T1LdSt1Imm<{1,?,?}>; 365193323Sed 366198090Srdivackydef tLDRH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr), IIC_iLoadr, 367198892Srdivacky "ldrh", "\t$dst, $addr", 368201360Srdivacky [(set tGPR:$dst, (zextloadi16 t_addrmode_s2:$addr))]>, 369201360Srdivacky T1LdSt<0b101>; 370202375Srdivackydef tLDRHi: T1pI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr), IIC_iLoadr, 371202375Srdivacky "ldrh", "\t$dst, $addr", 372202375Srdivacky []>, 373202375Srdivacky T1LdSt2Imm<{1,?,?}>; 374193323Sed 375198090Srdivackylet AddedComplexity = 10 in 376198090Srdivackydef tLDRSB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), IIC_iLoadr, 377198892Srdivacky "ldrsb", "\t$dst, $addr", 378201360Srdivacky [(set tGPR:$dst, (sextloadi8 t_addrmode_rr:$addr))]>, 379201360Srdivacky T1LdSt<0b011>; 380193323Sed 381198090Srdivackylet AddedComplexity = 10 in 382198090Srdivackydef tLDRSH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), IIC_iLoadr, 383198892Srdivacky "ldrsh", "\t$dst, $addr", 384201360Srdivacky [(set tGPR:$dst, (sextloadi16 t_addrmode_rr:$addr))]>, 385201360Srdivacky T1LdSt<0b111>; 386193323Sed 387193323Sedlet canFoldAsLoad = 1 in 388198090Srdivackydef tLDRspi : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), IIC_iLoadi, 389198892Srdivacky "ldr", "\t$dst, $addr", 390201360Srdivacky [(set tGPR:$dst, (load t_addrmode_sp:$addr))]>, 391201360Srdivacky T1LdStSP<{1,?,?}>; 392193323Sed 393193323Sed// Special instruction for restore. It cannot clobber condition register 394193323Sed// when it's expanded by eliminateCallFramePseudoInstr(). 395193323Sedlet canFoldAsLoad = 1, mayLoad = 1 in 396198090Srdivackydef tRestore : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), IIC_iLoadi, 397201360Srdivacky "ldr", "\t$dst, $addr", []>, 398201360Srdivacky T1LdStSP<{1,?,?}>; 399193323Sed 400193323Sed// Load tconstpool 401198892Srdivacky// FIXME: Use ldr.n to work around a Darwin assembler bug. 402199989Srdivackylet canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in 403198090Srdivackydef tLDRpci : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr), IIC_iLoadi, 404198892Srdivacky "ldr", ".n\t$dst, $addr", 405201360Srdivacky [(set tGPR:$dst, (load (ARMWrapper tconstpool:$addr)))]>, 406201360Srdivacky T1Encoding<{0,1,0,0,1,?}>; // A6.2 & A8.6.59 407193323Sed 408193323Sed// Special LDR for loads from non-pc-relative constpools. 409199989Srdivackylet canFoldAsLoad = 1, mayLoad = 1, isReMaterializable = 1, 410199989Srdivacky mayHaveSideEffects = 1 in 411198090Srdivackydef tLDRcp : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr), IIC_iLoadi, 412201360Srdivacky "ldr", "\t$dst, $addr", []>, 413201360Srdivacky T1LdStSP<{1,?,?}>; 414193323Sed 415198090Srdivackydef tSTR : T1pI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr), IIC_iStorer, 416198892Srdivacky "str", "\t$src, $addr", 417201360Srdivacky [(store tGPR:$src, t_addrmode_s4:$addr)]>, 418201360Srdivacky T1LdSt<0b000>; 419202375Srdivackydef tSTRi: T1pI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr), IIC_iStorer, 420202375Srdivacky "str", "\t$src, $addr", 421202375Srdivacky []>, 422202375Srdivacky T1LdSt4Imm<{0,?,?}>; 423193323Sed 424198090Srdivackydef tSTRB : T1pI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr), IIC_iStorer, 425198892Srdivacky "strb", "\t$src, $addr", 426201360Srdivacky [(truncstorei8 tGPR:$src, t_addrmode_s1:$addr)]>, 427201360Srdivacky T1LdSt<0b010>; 428202375Srdivackydef tSTRBi: T1pI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr), IIC_iStorer, 429202375Srdivacky "strb", "\t$src, $addr", 430202375Srdivacky []>, 431202375Srdivacky T1LdSt1Imm<{0,?,?}>; 432193323Sed 433198090Srdivackydef tSTRH : T1pI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr), IIC_iStorer, 434198892Srdivacky "strh", "\t$src, $addr", 435201360Srdivacky [(truncstorei16 tGPR:$src, t_addrmode_s2:$addr)]>, 436201360Srdivacky T1LdSt<0b001>; 437202375Srdivackydef tSTRHi: T1pI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr), IIC_iStorer, 438202375Srdivacky "strh", "\t$src, $addr", 439202375Srdivacky []>, 440202375Srdivacky T1LdSt2Imm<{0,?,?}>; 441193323Sed 442198090Srdivackydef tSTRspi : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStorei, 443198892Srdivacky "str", "\t$src, $addr", 444201360Srdivacky [(store tGPR:$src, t_addrmode_sp:$addr)]>, 445201360Srdivacky T1LdStSP<{0,?,?}>; 446193323Sed 447193323Sedlet mayStore = 1 in { 448193323Sed// Special instruction for spill. It cannot clobber condition register 449193323Sed// when it's expanded by eliminateCallFramePseudoInstr(). 450198090Srdivackydef tSpill : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStorei, 451201360Srdivacky "str", "\t$src, $addr", []>, 452201360Srdivacky T1LdStSP<{0,?,?}>; 453193323Sed} 454193323Sed 455193323Sed//===----------------------------------------------------------------------===// 456193323Sed// Load / store multiple Instructions. 457193323Sed// 458193323Sed 459198090Srdivacky// These requires base address to be written back or one of the loaded regs. 460198090Srdivackylet mayLoad = 1, hasExtraDefRegAllocReq = 1 in 461198090Srdivackydef tLDM : T1I<(outs), 462198090Srdivacky (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops), 463198090Srdivacky IIC_iLoadm, 464201360Srdivacky "ldm${addr:submode}${p}\t$addr, $wb", []>, 465201360Srdivacky T1Encoding<{1,1,0,0,1,?}>; // A6.2 & A8.6.53 466193323Sed 467198090Srdivackylet mayStore = 1, hasExtraSrcRegAllocReq = 1 in 468198090Srdivackydef tSTM : T1I<(outs), 469198090Srdivacky (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops), 470198090Srdivacky IIC_iStorem, 471201360Srdivacky "stm${addr:submode}${p}\t$addr, $wb", []>, 472201360Srdivacky T1Encoding<{1,1,0,0,0,?}>; // A6.2 & A8.6.189 473193323Sed 474198090Srdivackylet mayLoad = 1, Uses = [SP], Defs = [SP], hasExtraDefRegAllocReq = 1 in 475198090Srdivackydef tPOP : T1I<(outs), (ins pred:$p, reglist:$wb, variable_ops), IIC_Br, 476201360Srdivacky "pop${p}\t$wb", []>, 477201360Srdivacky T1Misc<{1,1,0,?,?,?,?}>; 478193323Sed 479198090Srdivackylet mayStore = 1, Uses = [SP], Defs = [SP], hasExtraSrcRegAllocReq = 1 in 480198090Srdivackydef tPUSH : T1I<(outs), (ins pred:$p, reglist:$wb, variable_ops), IIC_Br, 481201360Srdivacky "push${p}\t$wb", []>, 482201360Srdivacky T1Misc<{0,1,0,?,?,?,?}>; 483198090Srdivacky 484193323Sed//===----------------------------------------------------------------------===// 485193323Sed// Arithmetic Instructions. 486193323Sed// 487193323Sed 488195098Sed// Add with carry register 489198090Srdivackylet isCommutable = 1, Uses = [CPSR] in 490198090Srdivackydef tADC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 491198892Srdivacky "adc", "\t$dst, $rhs", 492201360Srdivacky [(set tGPR:$dst, (adde tGPR:$lhs, tGPR:$rhs))]>, 493201360Srdivacky T1DataProcessing<0b0101>; 494193323Sed 495195098Sed// Add immediate 496198090Srdivackydef tADDi3 : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi, 497198892Srdivacky "add", "\t$dst, $lhs, $rhs", 498201360Srdivacky [(set tGPR:$dst, (add tGPR:$lhs, imm0_7:$rhs))]>, 499201360Srdivacky T1General<0b01110>; 500193323Sed 501198090Srdivackydef tADDi8 : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi, 502198892Srdivacky "add", "\t$dst, $rhs", 503201360Srdivacky [(set tGPR:$dst, (add tGPR:$lhs, imm8_255:$rhs))]>, 504201360Srdivacky T1General<{1,1,0,?,?}>; 505193323Sed 506195098Sed// Add register 507198090Srdivackylet isCommutable = 1 in 508198090Srdivackydef tADDrr : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 509198892Srdivacky "add", "\t$dst, $lhs, $rhs", 510201360Srdivacky [(set tGPR:$dst, (add tGPR:$lhs, tGPR:$rhs))]>, 511201360Srdivacky T1General<0b01100>; 512193323Sed 513194178Sedlet neverHasSideEffects = 1 in 514198090Srdivackydef tADDhirr : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, 515201360Srdivacky "add", "\t$dst, $rhs", []>, 516201360Srdivacky T1Special<{0,0,?,?}>; 517193323Sed 518195098Sed// And register 519198090Srdivackylet isCommutable = 1 in 520198090Srdivackydef tAND : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 521198892Srdivacky "and", "\t$dst, $rhs", 522201360Srdivacky [(set tGPR:$dst, (and tGPR:$lhs, tGPR:$rhs))]>, 523201360Srdivacky T1DataProcessing<0b0000>; 524193323Sed 525195098Sed// ASR immediate 526198090Srdivackydef tASRri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iMOVsi, 527198892Srdivacky "asr", "\t$dst, $lhs, $rhs", 528201360Srdivacky [(set tGPR:$dst, (sra tGPR:$lhs, (i32 imm:$rhs)))]>, 529201360Srdivacky T1General<{0,1,0,?,?}>; 530193323Sed 531195098Sed// ASR register 532198090Srdivackydef tASRrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, 533198892Srdivacky "asr", "\t$dst, $rhs", 534201360Srdivacky [(set tGPR:$dst, (sra tGPR:$lhs, tGPR:$rhs))]>, 535201360Srdivacky T1DataProcessing<0b0100>; 536193323Sed 537195098Sed// BIC register 538198090Srdivackydef tBIC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 539198892Srdivacky "bic", "\t$dst, $rhs", 540201360Srdivacky [(set tGPR:$dst, (and tGPR:$lhs, (not tGPR:$rhs)))]>, 541201360Srdivacky T1DataProcessing<0b1110>; 542193323Sed 543195098Sed// CMN register 544195098Sedlet Defs = [CPSR] in { 545202878Srdivacky//FIXME: Disable CMN, as CCodes are backwards from compare expectations 546202878Srdivacky// Compare-to-zero still works out, just not the relationals 547202878Srdivacky//def tCMN : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, 548202878Srdivacky// "cmn", "\t$lhs, $rhs", 549202878Srdivacky// [(ARMcmp tGPR:$lhs, (ineg tGPR:$rhs))]>, 550202878Srdivacky// T1DataProcessing<0b1011>; 551201360Srdivackydef tCMNz : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, 552198892Srdivacky "cmn", "\t$lhs, $rhs", 553201360Srdivacky [(ARMcmpZ tGPR:$lhs, (ineg tGPR:$rhs))]>, 554201360Srdivacky T1DataProcessing<0b1011>; 555195098Sed} 556193323Sed 557195098Sed// CMP immediate 558195098Sedlet Defs = [CPSR] in { 559198090Srdivackydef tCMPi8 : T1pI<(outs), (ins tGPR:$lhs, i32imm:$rhs), IIC_iCMPi, 560198892Srdivacky "cmp", "\t$lhs, $rhs", 561201360Srdivacky [(ARMcmp tGPR:$lhs, imm0_255:$rhs)]>, 562201360Srdivacky T1General<{1,0,1,?,?}>; 563198090Srdivackydef tCMPzi8 : T1pI<(outs), (ins tGPR:$lhs, i32imm:$rhs), IIC_iCMPi, 564198892Srdivacky "cmp", "\t$lhs, $rhs", 565201360Srdivacky [(ARMcmpZ tGPR:$lhs, imm0_255:$rhs)]>, 566201360Srdivacky T1General<{1,0,1,?,?}>; 567195098Sed} 568195098Sed 569195098Sed// CMP register 570195098Sedlet Defs = [CPSR] in { 571198090Srdivackydef tCMPr : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, 572198892Srdivacky "cmp", "\t$lhs, $rhs", 573201360Srdivacky [(ARMcmp tGPR:$lhs, tGPR:$rhs)]>, 574201360Srdivacky T1DataProcessing<0b1010>; 575198090Srdivackydef tCMPzr : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, 576198892Srdivacky "cmp", "\t$lhs, $rhs", 577201360Srdivacky [(ARMcmpZ tGPR:$lhs, tGPR:$rhs)]>, 578201360Srdivacky T1DataProcessing<0b1010>; 579198090Srdivacky 580198090Srdivackydef tCMPhir : T1pI<(outs), (ins GPR:$lhs, GPR:$rhs), IIC_iCMPr, 581201360Srdivacky "cmp", "\t$lhs, $rhs", []>, 582201360Srdivacky T1Special<{0,1,?,?}>; 583198090Srdivackydef tCMPzhir : T1pI<(outs), (ins GPR:$lhs, GPR:$rhs), IIC_iCMPr, 584201360Srdivacky "cmp", "\t$lhs, $rhs", []>, 585201360Srdivacky T1Special<{0,1,?,?}>; 586195098Sed} 587193323Sed 588193323Sed 589195098Sed// XOR register 590198090Srdivackylet isCommutable = 1 in 591198090Srdivackydef tEOR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 592198892Srdivacky "eor", "\t$dst, $rhs", 593201360Srdivacky [(set tGPR:$dst, (xor tGPR:$lhs, tGPR:$rhs))]>, 594201360Srdivacky T1DataProcessing<0b0001>; 595193323Sed 596195098Sed// LSL immediate 597198090Srdivackydef tLSLri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iMOVsi, 598198892Srdivacky "lsl", "\t$dst, $lhs, $rhs", 599201360Srdivacky [(set tGPR:$dst, (shl tGPR:$lhs, (i32 imm:$rhs)))]>, 600201360Srdivacky T1General<{0,0,0,?,?}>; 601193323Sed 602195098Sed// LSL register 603198090Srdivackydef tLSLrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, 604198892Srdivacky "lsl", "\t$dst, $rhs", 605201360Srdivacky [(set tGPR:$dst, (shl tGPR:$lhs, tGPR:$rhs))]>, 606201360Srdivacky T1DataProcessing<0b0010>; 607193323Sed 608195098Sed// LSR immediate 609198090Srdivackydef tLSRri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iMOVsi, 610198892Srdivacky "lsr", "\t$dst, $lhs, $rhs", 611201360Srdivacky [(set tGPR:$dst, (srl tGPR:$lhs, (i32 imm:$rhs)))]>, 612201360Srdivacky T1General<{0,0,1,?,?}>; 613193323Sed 614195098Sed// LSR register 615198090Srdivackydef tLSRrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, 616198892Srdivacky "lsr", "\t$dst, $rhs", 617201360Srdivacky [(set tGPR:$dst, (srl tGPR:$lhs, tGPR:$rhs))]>, 618201360Srdivacky T1DataProcessing<0b0011>; 619193323Sed 620195098Sed// move register 621198090Srdivackydef tMOVi8 : T1sI<(outs tGPR:$dst), (ins i32imm:$src), IIC_iMOVi, 622198892Srdivacky "mov", "\t$dst, $src", 623201360Srdivacky [(set tGPR:$dst, imm0_255:$src)]>, 624201360Srdivacky T1General<{1,0,0,?,?}>; 625193323Sed 626193323Sed// TODO: A7-73: MOV(2) - mov setting flag. 627193323Sed 628193323Sed 629194178Sedlet neverHasSideEffects = 1 in { 630198090Srdivacky// FIXME: Make this predicable. 631198090Srdivackydef tMOVr : T1I<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr, 632201360Srdivacky "mov\t$dst, $src", []>, 633201360Srdivacky T1Special<0b1000>; 634198090Srdivackylet Defs = [CPSR] in 635198090Srdivackydef tMOVSr : T1I<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr, 636201360Srdivacky "movs\t$dst, $src", []>, Encoding16 { 637201360Srdivacky let Inst{15-6} = 0b0000000000; 638201360Srdivacky} 639198090Srdivacky 640198090Srdivacky// FIXME: Make these predicable. 641198090Srdivackydef tMOVgpr2tgpr : T1I<(outs tGPR:$dst), (ins GPR:$src), IIC_iMOVr, 642201360Srdivacky "mov\t$dst, $src", []>, 643202878Srdivacky T1Special<{1,0,0,?}>; 644198090Srdivackydef tMOVtgpr2gpr : T1I<(outs GPR:$dst), (ins tGPR:$src), IIC_iMOVr, 645201360Srdivacky "mov\t$dst, $src", []>, 646202878Srdivacky T1Special<{1,0,?,0}>; 647198090Srdivackydef tMOVgpr2gpr : T1I<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVr, 648201360Srdivacky "mov\t$dst, $src", []>, 649202878Srdivacky T1Special<{1,0,?,?}>; 650194178Sed} // neverHasSideEffects 651193323Sed 652195098Sed// multiply register 653198090Srdivackylet isCommutable = 1 in 654198090Srdivackydef tMUL : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMUL32, 655198892Srdivacky "mul", "\t$dst, $rhs", 656201360Srdivacky [(set tGPR:$dst, (mul tGPR:$lhs, tGPR:$rhs))]>, 657201360Srdivacky T1DataProcessing<0b1101>; 658193323Sed 659195098Sed// move inverse register 660198090Srdivackydef tMVN : T1sI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr, 661198892Srdivacky "mvn", "\t$dst, $src", 662201360Srdivacky [(set tGPR:$dst, (not tGPR:$src))]>, 663201360Srdivacky T1DataProcessing<0b1111>; 664193323Sed 665195098Sed// bitwise or register 666198090Srdivackylet isCommutable = 1 in 667198090Srdivackydef tORR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 668198892Srdivacky "orr", "\t$dst, $rhs", 669201360Srdivacky [(set tGPR:$dst, (or tGPR:$lhs, tGPR:$rhs))]>, 670201360Srdivacky T1DataProcessing<0b1100>; 671193323Sed 672195098Sed// swaps 673198090Srdivackydef tREV : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 674198892Srdivacky "rev", "\t$dst, $src", 675198090Srdivacky [(set tGPR:$dst, (bswap tGPR:$src))]>, 676201360Srdivacky Requires<[IsThumb1Only, HasV6]>, 677201360Srdivacky T1Misc<{1,0,1,0,0,0,?}>; 678193323Sed 679198090Srdivackydef tREV16 : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 680198892Srdivacky "rev16", "\t$dst, $src", 681198090Srdivacky [(set tGPR:$dst, 682198090Srdivacky (or (and (srl tGPR:$src, (i32 8)), 0xFF), 683198090Srdivacky (or (and (shl tGPR:$src, (i32 8)), 0xFF00), 684198090Srdivacky (or (and (srl tGPR:$src, (i32 8)), 0xFF0000), 685198090Srdivacky (and (shl tGPR:$src, (i32 8)), 0xFF000000)))))]>, 686201360Srdivacky Requires<[IsThumb1Only, HasV6]>, 687201360Srdivacky T1Misc<{1,0,1,0,0,1,?}>; 688193323Sed 689198090Srdivackydef tREVSH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 690198892Srdivacky "revsh", "\t$dst, $src", 691198090Srdivacky [(set tGPR:$dst, 692198090Srdivacky (sext_inreg 693198090Srdivacky (or (srl (and tGPR:$src, 0xFF00), (i32 8)), 694198090Srdivacky (shl tGPR:$src, (i32 8))), i16))]>, 695201360Srdivacky Requires<[IsThumb1Only, HasV6]>, 696201360Srdivacky T1Misc<{1,0,1,0,1,1,?}>; 697193323Sed 698195098Sed// rotate right register 699198090Srdivackydef tROR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, 700198892Srdivacky "ror", "\t$dst, $rhs", 701201360Srdivacky [(set tGPR:$dst, (rotr tGPR:$lhs, tGPR:$rhs))]>, 702201360Srdivacky T1DataProcessing<0b0111>; 703193323Sed 704198090Srdivacky// negate register 705198090Srdivackydef tRSB : T1sI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iALUi, 706198892Srdivacky "rsb", "\t$dst, $src, #0", 707201360Srdivacky [(set tGPR:$dst, (ineg tGPR:$src))]>, 708201360Srdivacky T1DataProcessing<0b1001>; 709198090Srdivacky 710195098Sed// Subtract with carry register 711198090Srdivackylet Uses = [CPSR] in 712198090Srdivackydef tSBC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 713198892Srdivacky "sbc", "\t$dst, $rhs", 714201360Srdivacky [(set tGPR:$dst, (sube tGPR:$lhs, tGPR:$rhs))]>, 715201360Srdivacky T1DataProcessing<0b0110>; 716193323Sed 717195098Sed// Subtract immediate 718198090Srdivackydef tSUBi3 : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi, 719198892Srdivacky "sub", "\t$dst, $lhs, $rhs", 720201360Srdivacky [(set tGPR:$dst, (add tGPR:$lhs, imm0_7_neg:$rhs))]>, 721201360Srdivacky T1General<0b01111>; 722193323Sed 723198090Srdivackydef tSUBi8 : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi, 724198892Srdivacky "sub", "\t$dst, $rhs", 725201360Srdivacky [(set tGPR:$dst, (add tGPR:$lhs, imm8_255_neg:$rhs))]>, 726201360Srdivacky T1General<{1,1,1,?,?}>; 727193323Sed 728195098Sed// subtract register 729198090Srdivackydef tSUBrr : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 730198892Srdivacky "sub", "\t$dst, $lhs, $rhs", 731201360Srdivacky [(set tGPR:$dst, (sub tGPR:$lhs, tGPR:$rhs))]>, 732201360Srdivacky T1General<0b01101>; 733193323Sed 734195098Sed// TODO: A7-96: STMIA - store multiple. 735195098Sed 736195098Sed// sign-extend byte 737198090Srdivackydef tSXTB : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 738198892Srdivacky "sxtb", "\t$dst, $src", 739198090Srdivacky [(set tGPR:$dst, (sext_inreg tGPR:$src, i8))]>, 740201360Srdivacky Requires<[IsThumb1Only, HasV6]>, 741201360Srdivacky T1Misc<{0,0,1,0,0,1,?}>; 742195098Sed 743195098Sed// sign-extend short 744198090Srdivackydef tSXTH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 745198892Srdivacky "sxth", "\t$dst, $src", 746198090Srdivacky [(set tGPR:$dst, (sext_inreg tGPR:$src, i16))]>, 747201360Srdivacky Requires<[IsThumb1Only, HasV6]>, 748201360Srdivacky T1Misc<{0,0,1,0,0,0,?}>; 749193323Sed 750195098Sed// test 751195098Sedlet isCommutable = 1, Defs = [CPSR] in 752198090Srdivackydef tTST : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, 753198892Srdivacky "tst", "\t$lhs, $rhs", 754201360Srdivacky [(ARMcmpZ (and tGPR:$lhs, tGPR:$rhs), 0)]>, 755201360Srdivacky T1DataProcessing<0b1000>; 756193323Sed 757195098Sed// zero-extend byte 758198090Srdivackydef tUXTB : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 759198892Srdivacky "uxtb", "\t$dst, $src", 760198090Srdivacky [(set tGPR:$dst, (and tGPR:$src, 0xFF))]>, 761201360Srdivacky Requires<[IsThumb1Only, HasV6]>, 762201360Srdivacky T1Misc<{0,0,1,0,1,1,?}>; 763195098Sed 764195098Sed// zero-extend short 765198090Srdivackydef tUXTH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 766198892Srdivacky "uxth", "\t$dst, $src", 767198090Srdivacky [(set tGPR:$dst, (and tGPR:$src, 0xFFFF))]>, 768201360Srdivacky Requires<[IsThumb1Only, HasV6]>, 769201360Srdivacky T1Misc<{0,0,1,0,1,0,?}>; 770193323Sed 771193323Sed 772193323Sed// Conditional move tMOVCCr - Used to implement the Thumb SELECT_CC DAG operation. 773198892Srdivacky// Expanded after instruction selection into a branch sequence. 774198892Srdivackylet usesCustomInserter = 1 in // Expanded after instruction selection. 775198090Srdivacky def tMOVCCr_pseudo : 776193323Sed PseudoInst<(outs tGPR:$dst), (ins tGPR:$false, tGPR:$true, pred:$cc), 777198090Srdivacky NoItinerary, "@ tMOVCCr $cc", 778198090Srdivacky [/*(set tGPR:$dst, (ARMcmov tGPR:$false, tGPR:$true, imm:$cc))*/]>; 779193323Sed 780198090Srdivacky 781198090Srdivacky// 16-bit movcc in IT blocks for Thumb2. 782198090Srdivackydef tMOVCCr : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iCMOVr, 783201360Srdivacky "mov", "\t$dst, $rhs", []>, 784202878Srdivacky T1Special<{1,0,?,?}>; 785198090Srdivacky 786203954Srdivackydef tMOVCCi : T1pIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iCMOVi, 787201360Srdivacky "mov", "\t$dst, $rhs", []>, 788201360Srdivacky T1General<{1,0,0,?,?}>; 789198090Srdivacky 790193323Sed// tLEApcrel - Load a pc-relative address into a register without offending the 791193323Sed// assembler. 792198090Srdivackydef tLEApcrel : T1I<(outs tGPR:$dst), (ins i32imm:$label, pred:$p), IIC_iALUi, 793201360Srdivacky "adr$p\t$dst, #$label", []>, 794201360Srdivacky T1Encoding<{1,0,1,0,0,?}>; // A6.2 & A8.6.10 795193323Sed 796198090Srdivackydef tLEApcrelJT : T1I<(outs tGPR:$dst), 797198090Srdivacky (ins i32imm:$label, nohash_imm:$id, pred:$p), 798201360Srdivacky IIC_iALUi, "adr$p\t$dst, #${label}_${id}", []>, 799201360Srdivacky T1Encoding<{1,0,1,0,0,?}>; // A6.2 & A8.6.10 800193323Sed 801193323Sed//===----------------------------------------------------------------------===// 802193323Sed// TLS Instructions 803193323Sed// 804193323Sed 805193323Sed// __aeabi_read_tp preserves the registers r1-r3. 806193323Sedlet isCall = 1, 807193323Sed Defs = [R0, LR] in { 808201360Srdivacky def tTPsoft : TIx2<0b11110, 0b11, 1, (outs), (ins), IIC_Br, 809201360Srdivacky "bl\t__aeabi_read_tp", 810201360Srdivacky [(set R0, ARMthread_pointer)]>; 811193323Sed} 812193323Sed 813200581Srdivacky// SJLJ Exception handling intrinsics 814200581Srdivacky// eh_sjlj_setjmp() is an instruction sequence to store the return 815200581Srdivacky// address and save #0 in R0 for the non-longjmp case. 816200581Srdivacky// Since by its nature we may be coming from some other function to get 817200581Srdivacky// here, and we're using the stack frame for the containing function to 818200581Srdivacky// save/restore registers, we can't keep anything live in regs across 819200581Srdivacky// the eh_sjlj_setjmp(), else it will almost certainly have been tromped upon 820200581Srdivacky// when we get here from a longjmp(). We force everthing out of registers 821200581Srdivacky// except for our own input by listing the relevant registers in Defs. By 822200581Srdivacky// doing so, we also cause the prologue/epilogue code to actively preserve 823200581Srdivacky// all of the callee-saved resgisters, which is exactly what we want. 824203954Srdivacky// The current SP is passed in $val, and we reuse the reg as a scratch. 825200581Srdivackylet Defs = 826200581Srdivacky [ R0, R1, R2, R3, R4, R5, R6, R7, R12 ] in { 827203954Srdivacky def tInt_eh_sjlj_setjmp : ThumbXI<(outs),(ins tGPR:$src, tGPR:$val), 828200581Srdivacky AddrModeNone, SizeSpecial, NoItinerary, 829203954Srdivacky "str\t$val, [$src, #8]\t@ begin eh.setjmp\n" 830203954Srdivacky "\tmov\t$val, pc\n" 831203954Srdivacky "\tadds\t$val, #9\n" 832203954Srdivacky "\tstr\t$val, [$src, #4]\n" 833200581Srdivacky "\tmovs\tr0, #0\n" 834200581Srdivacky "\tb\t1f\n" 835203954Srdivacky "\tmovs\tr0, #1\t@ end eh.setjmp\n" 836200581Srdivacky "1:", "", 837203954Srdivacky [(set R0, (ARMeh_sjlj_setjmp tGPR:$src, tGPR:$val))]>; 838200581Srdivacky} 839193323Sed//===----------------------------------------------------------------------===// 840193323Sed// Non-Instruction Patterns 841193323Sed// 842193323Sed 843198090Srdivacky// Add with carry 844198090Srdivackydef : T1Pat<(addc tGPR:$lhs, imm0_7:$rhs), 845198090Srdivacky (tADDi3 tGPR:$lhs, imm0_7:$rhs)>; 846198090Srdivackydef : T1Pat<(addc tGPR:$lhs, imm8_255:$rhs), 847198090Srdivacky (tADDi8 tGPR:$lhs, imm8_255:$rhs)>; 848198090Srdivackydef : T1Pat<(addc tGPR:$lhs, tGPR:$rhs), 849198090Srdivacky (tADDrr tGPR:$lhs, tGPR:$rhs)>; 850198090Srdivacky 851198090Srdivacky// Subtract with carry 852198090Srdivackydef : T1Pat<(addc tGPR:$lhs, imm0_7_neg:$rhs), 853198090Srdivacky (tSUBi3 tGPR:$lhs, imm0_7_neg:$rhs)>; 854198090Srdivackydef : T1Pat<(addc tGPR:$lhs, imm8_255_neg:$rhs), 855198090Srdivacky (tSUBi8 tGPR:$lhs, imm8_255_neg:$rhs)>; 856198090Srdivackydef : T1Pat<(subc tGPR:$lhs, tGPR:$rhs), 857198090Srdivacky (tSUBrr tGPR:$lhs, tGPR:$rhs)>; 858198090Srdivacky 859193323Sed// ConstantPool, GlobalAddress 860198090Srdivackydef : T1Pat<(ARMWrapper tglobaladdr :$dst), (tLEApcrel tglobaladdr :$dst)>; 861198090Srdivackydef : T1Pat<(ARMWrapper tconstpool :$dst), (tLEApcrel tconstpool :$dst)>; 862193323Sed 863193323Sed// JumpTable 864198090Srdivackydef : T1Pat<(ARMWrapperJT tjumptable:$dst, imm:$id), 865198090Srdivacky (tLEApcrelJT tjumptable:$dst, imm:$id)>; 866193323Sed 867193323Sed// Direct calls 868198090Srdivackydef : T1Pat<(ARMtcall texternalsym:$func), (tBL texternalsym:$func)>, 869198090Srdivacky Requires<[IsThumb, IsNotDarwin]>; 870198090Srdivackydef : T1Pat<(ARMtcall texternalsym:$func), (tBLr9 texternalsym:$func)>, 871198090Srdivacky Requires<[IsThumb, IsDarwin]>; 872193323Sed 873198090Srdivackydef : Tv5Pat<(ARMcall texternalsym:$func), (tBLXi texternalsym:$func)>, 874198090Srdivacky Requires<[IsThumb, HasV5T, IsNotDarwin]>; 875198090Srdivackydef : Tv5Pat<(ARMcall texternalsym:$func), (tBLXi_r9 texternalsym:$func)>, 876198090Srdivacky Requires<[IsThumb, HasV5T, IsDarwin]>; 877198090Srdivacky 878193323Sed// Indirect calls to ARM routines 879198090Srdivackydef : Tv5Pat<(ARMcall GPR:$dst), (tBLXr GPR:$dst)>, 880198090Srdivacky Requires<[IsThumb, HasV5T, IsNotDarwin]>; 881198090Srdivackydef : Tv5Pat<(ARMcall GPR:$dst), (tBLXr_r9 GPR:$dst)>, 882198090Srdivacky Requires<[IsThumb, HasV5T, IsDarwin]>; 883193323Sed 884193323Sed// zextload i1 -> zextload i8 885195340Seddef : T1Pat<(zextloadi1 t_addrmode_s1:$addr), 886195340Sed (tLDRB t_addrmode_s1:$addr)>; 887193323Sed 888193323Sed// extload -> zextload 889195340Seddef : T1Pat<(extloadi1 t_addrmode_s1:$addr), (tLDRB t_addrmode_s1:$addr)>; 890195340Seddef : T1Pat<(extloadi8 t_addrmode_s1:$addr), (tLDRB t_addrmode_s1:$addr)>; 891195340Seddef : T1Pat<(extloadi16 t_addrmode_s2:$addr), (tLDRH t_addrmode_s2:$addr)>; 892193323Sed 893198090Srdivacky// If it's impossible to use [r,r] address mode for sextload, select to 894198090Srdivacky// ldr{b|h} + sxt{b|h} instead. 895198090Srdivackydef : T1Pat<(sextloadi8 t_addrmode_s1:$addr), 896198090Srdivacky (tSXTB (tLDRB t_addrmode_s1:$addr))>, 897198090Srdivacky Requires<[IsThumb1Only, HasV6]>; 898198090Srdivackydef : T1Pat<(sextloadi16 t_addrmode_s2:$addr), 899198090Srdivacky (tSXTH (tLDRH t_addrmode_s2:$addr))>, 900198090Srdivacky Requires<[IsThumb1Only, HasV6]>; 901198090Srdivacky 902198090Srdivackydef : T1Pat<(sextloadi8 t_addrmode_s1:$addr), 903198090Srdivacky (tASRri (tLSLri (tLDRB t_addrmode_s1:$addr), 24), 24)>; 904198090Srdivackydef : T1Pat<(sextloadi16 t_addrmode_s1:$addr), 905198090Srdivacky (tASRri (tLSLri (tLDRH t_addrmode_s1:$addr), 16), 16)>; 906198090Srdivacky 907193323Sed// Large immediate handling. 908193323Sed 909193323Sed// Two piece imms. 910195098Seddef : T1Pat<(i32 thumb_immshifted:$src), 911195098Sed (tLSLri (tMOVi8 (thumb_immshifted_val imm:$src)), 912195098Sed (thumb_immshifted_shamt imm:$src))>; 913193323Sed 914195098Seddef : T1Pat<(i32 imm0_255_comp:$src), 915195098Sed (tMVN (tMOVi8 (imm_comp_XFORM imm:$src)))>; 916199481Srdivacky 917199481Srdivacky// Pseudo instruction that combines ldr from constpool and add pc. This should 918199481Srdivacky// be expanded into two instructions late to allow if-conversion and 919199481Srdivacky// scheduling. 920199481Srdivackylet isReMaterializable = 1 in 921199481Srdivackydef tLDRpci_pic : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr, pclabel:$cp), 922199481Srdivacky NoItinerary, "@ ldr.n\t$dst, $addr\n$cp:\n\tadd\t$dst, pc", 923199481Srdivacky [(set GPR:$dst, (ARMpic_add (load (ARMWrapper tconstpool:$addr)), 924199481Srdivacky imm:$cp))]>, 925199481Srdivacky Requires<[IsThumb1Only]>; 926