ARMInstrThumb.td revision 205218
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 123204642Srdivacky// FIXME: Marking these as hasSideEffects is necessary to prevent machine DCE 124204642Srdivacky// from removing one half of the matched pairs. That breaks PEI, which assumes 125204642Srdivacky// these will always be in pairs, and asserts if it finds otherwise. Better way? 126204642Srdivackylet Defs = [SP], Uses = [SP], hasSideEffects = 1 in { 127193323Seddef tADJCALLSTACKUP : 128198090SrdivackyPseudoInst<(outs), (ins i32imm:$amt1, i32imm:$amt2), NoItinerary, 129193323Sed "@ tADJCALLSTACKUP $amt1", 130198090Srdivacky [(ARMcallseq_end imm:$amt1, imm:$amt2)]>, Requires<[IsThumb1Only]>; 131193323Sed 132193323Seddef tADJCALLSTACKDOWN : 133198090SrdivackyPseudoInst<(outs), (ins i32imm:$amt), NoItinerary, 134193323Sed "@ tADJCALLSTACKDOWN $amt", 135198090Srdivacky [(ARMcallseq_start imm:$amt)]>, Requires<[IsThumb1Only]>; 136193323Sed} 137193323Sed 138204642Srdivackydef tNOP : T1pI<(outs), (ins), NoItinerary, "nop", "", 139204642Srdivacky [/* For disassembly only; pattern left blank */]>, 140204642Srdivacky T1Encoding<0b101111> { 141204642Srdivacky let Inst{9-8} = 0b11; 142204642Srdivacky let Inst{7-0} = 0b00000000; 143204642Srdivacky} 144204642Srdivacky 145204642Srdivackydef tYIELD : T1pI<(outs), (ins), NoItinerary, "yield", "", 146204642Srdivacky [/* For disassembly only; pattern left blank */]>, 147204642Srdivacky T1Encoding<0b101111> { 148204642Srdivacky let Inst{9-8} = 0b11; 149204642Srdivacky let Inst{7-0} = 0b00010000; 150204642Srdivacky} 151204642Srdivacky 152204642Srdivackydef tWFE : T1pI<(outs), (ins), NoItinerary, "wfe", "", 153204642Srdivacky [/* For disassembly only; pattern left blank */]>, 154204642Srdivacky T1Encoding<0b101111> { 155204642Srdivacky let Inst{9-8} = 0b11; 156204642Srdivacky let Inst{7-0} = 0b00100000; 157204642Srdivacky} 158204642Srdivacky 159204642Srdivackydef tWFI : T1pI<(outs), (ins), NoItinerary, "wfi", "", 160204642Srdivacky [/* For disassembly only; pattern left blank */]>, 161204642Srdivacky T1Encoding<0b101111> { 162204642Srdivacky let Inst{9-8} = 0b11; 163204642Srdivacky let Inst{7-0} = 0b00110000; 164204642Srdivacky} 165204642Srdivacky 166204642Srdivackydef tSEV : T1pI<(outs), (ins), NoItinerary, "sev", "", 167204642Srdivacky [/* For disassembly only; pattern left blank */]>, 168204642Srdivacky T1Encoding<0b101111> { 169204642Srdivacky let Inst{9-8} = 0b11; 170204642Srdivacky let Inst{7-0} = 0b01000000; 171204642Srdivacky} 172204642Srdivacky 173204642Srdivackydef tSETENDBE : T1I<(outs), (ins), NoItinerary, "setend\tbe", 174204642Srdivacky [/* For disassembly only; pattern left blank */]>, 175204642Srdivacky T1Encoding<0b101101> { 176204642Srdivacky let Inst{9-5} = 0b10010; 177204642Srdivacky let Inst{3} = 1; 178204642Srdivacky} 179204642Srdivacky 180204642Srdivackydef tSETENDLE : T1I<(outs), (ins), NoItinerary, "setend\tle", 181204642Srdivacky [/* For disassembly only; pattern left blank */]>, 182204642Srdivacky T1Encoding<0b101101> { 183204642Srdivacky let Inst{9-5} = 0b10010; 184204642Srdivacky let Inst{3} = 0; 185204642Srdivacky} 186204642Srdivacky 187203954Srdivacky// The i32imm operand $val can be used by a debugger to store more information 188203954Srdivacky// about the breakpoint. 189203954Srdivackydef tBKPT : T1I<(outs), (ins i32imm:$val), NoItinerary, "bkpt\t$val", 190203954Srdivacky [/* For disassembly only; pattern left blank */]>, 191203954Srdivacky T1Encoding<0b101111> { 192203954Srdivacky let Inst{9-8} = 0b10; 193203954Srdivacky} 194203954Srdivacky 195204642Srdivacky// Change Processor State is a system instruction -- for disassembly only. 196204642Srdivacky// The singleton $opt operand contains the following information: 197204642Srdivacky// opt{4-0} = mode ==> don't care 198204642Srdivacky// opt{5} = changemode ==> 0 (false for 16-bit Thumb instr) 199204642Srdivacky// opt{8-6} = AIF from Inst{2-0} 200204642Srdivacky// opt{10-9} = 1:imod from Inst{4} with 0b10 as enable and 0b11 as disable 201204642Srdivacky// 202204642Srdivacky// The opt{4-0} and opt{5} sub-fields are to accommodate 32-bit Thumb and ARM 203204642Srdivacky// CPS which has more options. 204205218Srdivackydef tCPS : T1I<(outs), (ins cps_opt:$opt), NoItinerary, "cps$opt", 205204642Srdivacky [/* For disassembly only; pattern left blank */]>, 206204642Srdivacky T1Misc<0b0110011>; 207204642Srdivacky 208198090Srdivacky// For both thumb1 and thumb2. 209193323Sedlet isNotDuplicable = 1 in 210198090Srdivackydef tPICADD : TIt<(outs GPR:$dst), (ins GPR:$lhs, pclabel:$cp), IIC_iALUr, 211198892Srdivacky "\n$cp:\n\tadd\t$dst, pc", 212201360Srdivacky [(set GPR:$dst, (ARMpic_add GPR:$lhs, imm:$cp))]>, 213201360Srdivacky T1Special<{0,0,?,?}> { 214201360Srdivacky let Inst{6-3} = 0b1111; // A8.6.6 Rm = pc 215201360Srdivacky} 216193323Sed 217195098Sed// PC relative add. 218199511Srdivackydef tADDrPCi : T1I<(outs tGPR:$dst), (ins t_imm_s4:$rhs), IIC_iALUi, 219201360Srdivacky "add\t$dst, pc, $rhs", []>, 220201360Srdivacky T1Encoding<{1,0,1,0,0,?}>; // A6.2 & A8.6.10 221195098Sed 222195098Sed// ADD rd, sp, #imm8 223199511Srdivackydef tADDrSPi : T1I<(outs tGPR:$dst), (ins GPR:$sp, t_imm_s4:$rhs), IIC_iALUi, 224201360Srdivacky "add\t$dst, $sp, $rhs", []>, 225201360Srdivacky T1Encoding<{1,0,1,0,1,?}>; // A6.2 & A8.6.8 226195098Sed 227195098Sed// ADD sp, sp, #imm7 228199511Srdivackydef tADDspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), IIC_iALUi, 229201360Srdivacky "add\t$dst, $rhs", []>, 230201360Srdivacky T1Misc<{0,0,0,0,0,?,?}>; // A6.2.5 & A8.6.8 231195098Sed 232198090Srdivacky// SUB sp, sp, #imm7 233199511Srdivackydef tSUBspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), IIC_iALUi, 234201360Srdivacky "sub\t$dst, $rhs", []>, 235201360Srdivacky T1Misc<{0,0,0,0,1,?,?}>; // A6.2.5 & A8.6.215 236198090Srdivacky 237198090Srdivacky// ADD rm, sp 238198090Srdivackydef tADDrSP : TIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, 239201360Srdivacky "add\t$dst, $rhs", []>, 240201360Srdivacky T1Special<{0,0,?,?}> { 241201360Srdivacky let Inst{6-3} = 0b1101; // A8.6.9 Encoding T1 242201360Srdivacky} 243198090Srdivacky 244195098Sed// ADD sp, rm 245198090Srdivackydef tADDspr : TIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, 246201360Srdivacky "add\t$dst, $rhs", []>, 247201360Srdivacky T1Special<{0,0,?,?}> { 248201360Srdivacky // A8.6.9 Encoding T2 249201360Srdivacky let Inst{7} = 1; 250201360Srdivacky let Inst{2-0} = 0b101; 251201360Srdivacky} 252195098Sed 253198090Srdivacky// Pseudo instruction that will expand into a tSUBspi + a copy. 254198892Srdivackylet usesCustomInserter = 1 in { // Expanded after instruction selection. 255199511Srdivackydef tSUBspi_ : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), 256199511Srdivacky NoItinerary, "@ sub\t$dst, $rhs", []>; 257198090Srdivacky 258198090Srdivackydef tADDspr_ : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), 259198892Srdivacky NoItinerary, "@ add\t$dst, $rhs", []>; 260198090Srdivacky 261198090Srdivackylet Defs = [CPSR] in 262198090Srdivackydef tANDsp : PseudoInst<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), 263198892Srdivacky NoItinerary, "@ and\t$dst, $rhs", []>; 264198892Srdivacky} // usesCustomInserter 265198090Srdivacky 266193323Sed//===----------------------------------------------------------------------===// 267193323Sed// Control Flow Instructions. 268193323Sed// 269193323Sed 270198090Srdivackylet isReturn = 1, isTerminator = 1, isBarrier = 1 in { 271201360Srdivacky def tBX_RET : TI<(outs), (ins), IIC_Br, "bx\tlr", [(ARMretflag)]>, 272201360Srdivacky T1Special<{1,1,0,?}> { // A6.2.3 & A8.6.25 273201360Srdivacky let Inst{6-3} = 0b1110; // Rm = lr 274201360Srdivacky } 275193323Sed // Alternative return instruction used by vararg functions. 276204642Srdivacky def tBX_RET_vararg : TI<(outs), (ins tGPR:$target), IIC_Br, "bx\t$target",[]>, 277201360Srdivacky T1Special<{1,1,0,?}>; // A6.2.3 & A8.6.25 278193323Sed} 279193323Sed 280198892Srdivacky// Indirect branches 281198892Srdivackylet isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { 282198892Srdivacky def tBRIND : TI<(outs), (ins GPR:$dst), IIC_Br, "mov\tpc, $dst", 283201360Srdivacky [(brind GPR:$dst)]>, 284202878Srdivacky T1Special<{1,0,1,?}> { 285202375Srdivacky // <Rd> = Inst{7:2-0} = pc 286201360Srdivacky let Inst{2-0} = 0b111; 287201360Srdivacky } 288198892Srdivacky} 289198892Srdivacky 290193323Sed// FIXME: remove when we have a way to marking a MI with these properties. 291198090Srdivackylet isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1, 292198090Srdivacky hasExtraDefRegAllocReq = 1 in 293205218Srdivackydef tPOP_RET : T1I<(outs), (ins pred:$p, reglist:$dsts, variable_ops), IIC_Br, 294205218Srdivacky "pop${p}\t$dsts", []>, 295201360Srdivacky T1Misc<{1,1,0,?,?,?,?}>; 296193323Sed 297193323Sedlet isCall = 1, 298198090Srdivacky Defs = [R0, R1, R2, R3, R12, LR, 299198090Srdivacky D0, D1, D2, D3, D4, D5, D6, D7, 300198090Srdivacky D16, D17, D18, D19, D20, D21, D22, D23, 301198090Srdivacky D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR] in { 302198090Srdivacky // Also used for Thumb2 303201360Srdivacky def tBL : TIx2<0b11110, 0b11, 1, 304204642Srdivacky (outs), (ins i32imm:$func, variable_ops), IIC_Br, 305201360Srdivacky "bl\t${func:call}", 306201360Srdivacky [(ARMtcall tglobaladdr:$func)]>, 307198090Srdivacky Requires<[IsThumb, IsNotDarwin]>; 308198090Srdivacky 309198090Srdivacky // ARMv5T and above, also used for Thumb2 310201360Srdivacky def tBLXi : TIx2<0b11110, 0b11, 0, 311204642Srdivacky (outs), (ins i32imm:$func, variable_ops), IIC_Br, 312201360Srdivacky "blx\t${func:call}", 313201360Srdivacky [(ARMcall tglobaladdr:$func)]>, 314198090Srdivacky Requires<[IsThumb, HasV5T, IsNotDarwin]>; 315198090Srdivacky 316198090Srdivacky // Also used for Thumb2 317204642Srdivacky def tBLXr : TI<(outs), (ins GPR:$func, variable_ops), IIC_Br, 318198892Srdivacky "blx\t$func", 319198090Srdivacky [(ARMtcall GPR:$func)]>, 320201360Srdivacky Requires<[IsThumb, HasV5T, IsNotDarwin]>, 321201360Srdivacky T1Special<{1,1,1,?}>; // A6.2.3 & A8.6.24; 322198090Srdivacky 323193323Sed // ARMv4T 324201360Srdivacky def tBX : TIx2<{?,?,?,?,?}, {?,?}, ?, 325204642Srdivacky (outs), (ins tGPR:$func, variable_ops), IIC_Br, 326198892Srdivacky "mov\tlr, pc\n\tbx\t$func", 327198090Srdivacky [(ARMcall_nolink tGPR:$func)]>, 328198090Srdivacky Requires<[IsThumb1Only, IsNotDarwin]>; 329193323Sed} 330193323Sed 331198090Srdivacky// On Darwin R9 is call-clobbered. 332198090Srdivackylet isCall = 1, 333198090Srdivacky Defs = [R0, R1, R2, R3, R9, R12, LR, 334198090Srdivacky D0, D1, D2, D3, D4, D5, D6, D7, 335198090Srdivacky D16, D17, D18, D19, D20, D21, D22, D23, 336198090Srdivacky D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR] in { 337198090Srdivacky // Also used for Thumb2 338201360Srdivacky def tBLr9 : TIx2<0b11110, 0b11, 1, 339204642Srdivacky (outs), (ins i32imm:$func, variable_ops), IIC_Br, 340198892Srdivacky "bl\t${func:call}", 341198090Srdivacky [(ARMtcall tglobaladdr:$func)]>, 342198090Srdivacky Requires<[IsThumb, IsDarwin]>; 343198090Srdivacky 344198090Srdivacky // ARMv5T and above, also used for Thumb2 345201360Srdivacky def tBLXi_r9 : TIx2<0b11110, 0b11, 0, 346204642Srdivacky (outs), (ins i32imm:$func, variable_ops), IIC_Br, 347198892Srdivacky "blx\t${func:call}", 348198090Srdivacky [(ARMcall tglobaladdr:$func)]>, 349198090Srdivacky Requires<[IsThumb, HasV5T, IsDarwin]>; 350198090Srdivacky 351198090Srdivacky // Also used for Thumb2 352204642Srdivacky def tBLXr_r9 : TI<(outs), (ins GPR:$func, variable_ops), IIC_Br, 353201360Srdivacky "blx\t$func", 354201360Srdivacky [(ARMtcall GPR:$func)]>, 355201360Srdivacky Requires<[IsThumb, HasV5T, IsDarwin]>, 356201360Srdivacky T1Special<{1,1,1,?}>; // A6.2.3 & A8.6.24 357198090Srdivacky 358198090Srdivacky // ARMv4T 359201360Srdivacky def tBXr9 : TIx2<{?,?,?,?,?}, {?,?}, ?, 360204642Srdivacky (outs), (ins tGPR:$func, variable_ops), IIC_Br, 361201360Srdivacky "mov\tlr, pc\n\tbx\t$func", 362201360Srdivacky [(ARMcall_nolink tGPR:$func)]>, 363198090Srdivacky Requires<[IsThumb1Only, IsDarwin]>; 364198090Srdivacky} 365198090Srdivacky 366193323Sedlet isBranch = 1, isTerminator = 1 in { 367193323Sed let isBarrier = 1 in { 368193323Sed let isPredicable = 1 in 369198090Srdivacky def tB : T1I<(outs), (ins brtarget:$target), IIC_Br, 370201360Srdivacky "b\t$target", [(br bb:$target)]>, 371201360Srdivacky T1Encoding<{1,1,1,0,0,?}>; 372193323Sed 373193323Sed // Far jump 374198090Srdivacky let Defs = [LR] in 375204642Srdivacky def tBfar : TIx2<0b11110, 0b11, 1, (outs), (ins brtarget:$target), IIC_Br, 376198892Srdivacky "bl\t$target\t@ far jump",[]>; 377193323Sed 378195340Sed def tBR_JTr : T1JTI<(outs), 379195340Sed (ins tGPR:$target, jtblock_operand:$jt, i32imm:$id), 380198892Srdivacky IIC_Br, "mov\tpc, $target\n\t.align\t2\n$jt", 381201360Srdivacky [(ARMbrjt tGPR:$target, tjumptable:$jt, imm:$id)]>, 382201360Srdivacky Encoding16 { 383201360Srdivacky let Inst{15-7} = 0b010001101; 384201360Srdivacky let Inst{2-0} = 0b111; 385193323Sed } 386201360Srdivacky } 387193323Sed} 388193323Sed 389193323Sed// FIXME: should be able to write a pattern for ARMBrcond, but can't use 390193323Sed// a two-value operand where a dag node expects two operands. :( 391193323Sedlet isBranch = 1, isTerminator = 1 in 392198090Srdivacky def tBcc : T1I<(outs), (ins brtarget:$target, pred:$cc), IIC_Br, 393198892Srdivacky "b$cc\t$target", 394201360Srdivacky [/*(ARMbrcond bb:$target, imm:$cc)*/]>, 395201360Srdivacky T1Encoding<{1,1,0,1,?,?}>; 396193323Sed 397198892Srdivacky// Compare and branch on zero / non-zero 398198892Srdivackylet isBranch = 1, isTerminator = 1 in { 399198892Srdivacky def tCBZ : T1I<(outs), (ins tGPR:$cmp, brtarget:$target), IIC_Br, 400201360Srdivacky "cbz\t$cmp, $target", []>, 401201360Srdivacky T1Misc<{0,0,?,1,?,?,?}>; 402198892Srdivacky 403198892Srdivacky def tCBNZ : T1I<(outs), (ins tGPR:$cmp, brtarget:$target), IIC_Br, 404201360Srdivacky "cbnz\t$cmp, $target", []>, 405201360Srdivacky T1Misc<{1,0,?,1,?,?,?}>; 406198892Srdivacky} 407198892Srdivacky 408204642Srdivacky// A8.6.218 Supervisor Call (Software Interrupt) -- for disassembly only 409204642Srdivacky// A8.6.16 B: Encoding T1 410204642Srdivacky// If Inst{11-8} == 0b1111 then SEE SVC 411204642Srdivackylet isCall = 1 in { 412204642Srdivackydef tSVC : T1pI<(outs), (ins i32imm:$svc), IIC_Br, "svc", "\t$svc", []>, 413204642Srdivacky Encoding16 { 414204642Srdivacky let Inst{15-12} = 0b1101; 415204642Srdivacky let Inst{11-8} = 0b1111; 416204642Srdivacky} 417204642Srdivacky} 418204642Srdivacky 419204642Srdivacky// A8.6.16 B: Encoding T1 -- for disassembly only 420204642Srdivacky// If Inst{11-8} == 0b1110 then UNDEFINED 421204642Srdivackydef tTRAP : T1I<(outs), (ins), IIC_Br, "trap", []>, Encoding16 { 422204642Srdivacky let Inst{15-12} = 0b1101; 423204642Srdivacky let Inst{11-8} = 0b1110; 424204642Srdivacky} 425204642Srdivacky 426193323Sed//===----------------------------------------------------------------------===// 427193323Sed// Load Store Instructions. 428193323Sed// 429193323Sed 430204642Srdivackylet canFoldAsLoad = 1, isReMaterializable = 1 in 431204642Srdivackydef tLDR : T1pI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr), IIC_iLoadr, 432198892Srdivacky "ldr", "\t$dst, $addr", 433201360Srdivacky [(set tGPR:$dst, (load t_addrmode_s4:$addr))]>, 434201360Srdivacky T1LdSt<0b100>; 435204642Srdivackydef tLDRi: T1pI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr), IIC_iLoadr, 436202375Srdivacky "ldr", "\t$dst, $addr", 437202375Srdivacky []>, 438202375Srdivacky T1LdSt4Imm<{1,?,?}>; 439193323Sed 440198090Srdivackydef tLDRB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr), IIC_iLoadr, 441198892Srdivacky "ldrb", "\t$dst, $addr", 442201360Srdivacky [(set tGPR:$dst, (zextloadi8 t_addrmode_s1:$addr))]>, 443201360Srdivacky T1LdSt<0b110>; 444202375Srdivackydef tLDRBi: T1pI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr), IIC_iLoadr, 445202375Srdivacky "ldrb", "\t$dst, $addr", 446202375Srdivacky []>, 447202375Srdivacky T1LdSt1Imm<{1,?,?}>; 448193323Sed 449198090Srdivackydef tLDRH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr), IIC_iLoadr, 450198892Srdivacky "ldrh", "\t$dst, $addr", 451201360Srdivacky [(set tGPR:$dst, (zextloadi16 t_addrmode_s2:$addr))]>, 452201360Srdivacky T1LdSt<0b101>; 453202375Srdivackydef tLDRHi: T1pI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr), IIC_iLoadr, 454202375Srdivacky "ldrh", "\t$dst, $addr", 455202375Srdivacky []>, 456202375Srdivacky T1LdSt2Imm<{1,?,?}>; 457193323Sed 458198090Srdivackylet AddedComplexity = 10 in 459198090Srdivackydef tLDRSB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), IIC_iLoadr, 460198892Srdivacky "ldrsb", "\t$dst, $addr", 461201360Srdivacky [(set tGPR:$dst, (sextloadi8 t_addrmode_rr:$addr))]>, 462201360Srdivacky T1LdSt<0b011>; 463193323Sed 464198090Srdivackylet AddedComplexity = 10 in 465198090Srdivackydef tLDRSH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), IIC_iLoadr, 466198892Srdivacky "ldrsh", "\t$dst, $addr", 467201360Srdivacky [(set tGPR:$dst, (sextloadi16 t_addrmode_rr:$addr))]>, 468201360Srdivacky T1LdSt<0b111>; 469193323Sed 470193323Sedlet canFoldAsLoad = 1 in 471198090Srdivackydef tLDRspi : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), IIC_iLoadi, 472198892Srdivacky "ldr", "\t$dst, $addr", 473201360Srdivacky [(set tGPR:$dst, (load t_addrmode_sp:$addr))]>, 474201360Srdivacky T1LdStSP<{1,?,?}>; 475193323Sed 476193323Sed// Special instruction for restore. It cannot clobber condition register 477193323Sed// when it's expanded by eliminateCallFramePseudoInstr(). 478193323Sedlet canFoldAsLoad = 1, mayLoad = 1 in 479198090Srdivackydef tRestore : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), IIC_iLoadi, 480201360Srdivacky "ldr", "\t$dst, $addr", []>, 481201360Srdivacky T1LdStSP<{1,?,?}>; 482193323Sed 483193323Sed// Load tconstpool 484198892Srdivacky// FIXME: Use ldr.n to work around a Darwin assembler bug. 485204642Srdivackylet canFoldAsLoad = 1, isReMaterializable = 1 in 486198090Srdivackydef tLDRpci : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr), IIC_iLoadi, 487198892Srdivacky "ldr", ".n\t$dst, $addr", 488201360Srdivacky [(set tGPR:$dst, (load (ARMWrapper tconstpool:$addr)))]>, 489201360Srdivacky T1Encoding<{0,1,0,0,1,?}>; // A6.2 & A8.6.59 490193323Sed 491193323Sed// Special LDR for loads from non-pc-relative constpools. 492204642Srdivackylet canFoldAsLoad = 1, mayLoad = 1, isReMaterializable = 1 in 493198090Srdivackydef tLDRcp : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr), IIC_iLoadi, 494201360Srdivacky "ldr", "\t$dst, $addr", []>, 495201360Srdivacky T1LdStSP<{1,?,?}>; 496193323Sed 497198090Srdivackydef tSTR : T1pI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr), IIC_iStorer, 498198892Srdivacky "str", "\t$src, $addr", 499201360Srdivacky [(store tGPR:$src, t_addrmode_s4:$addr)]>, 500201360Srdivacky T1LdSt<0b000>; 501202375Srdivackydef tSTRi: T1pI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr), IIC_iStorer, 502202375Srdivacky "str", "\t$src, $addr", 503202375Srdivacky []>, 504202375Srdivacky T1LdSt4Imm<{0,?,?}>; 505193323Sed 506198090Srdivackydef tSTRB : T1pI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr), IIC_iStorer, 507198892Srdivacky "strb", "\t$src, $addr", 508201360Srdivacky [(truncstorei8 tGPR:$src, t_addrmode_s1:$addr)]>, 509201360Srdivacky T1LdSt<0b010>; 510202375Srdivackydef tSTRBi: T1pI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr), IIC_iStorer, 511202375Srdivacky "strb", "\t$src, $addr", 512202375Srdivacky []>, 513202375Srdivacky T1LdSt1Imm<{0,?,?}>; 514193323Sed 515198090Srdivackydef tSTRH : T1pI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr), IIC_iStorer, 516198892Srdivacky "strh", "\t$src, $addr", 517201360Srdivacky [(truncstorei16 tGPR:$src, t_addrmode_s2:$addr)]>, 518201360Srdivacky T1LdSt<0b001>; 519202375Srdivackydef tSTRHi: T1pI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr), IIC_iStorer, 520202375Srdivacky "strh", "\t$src, $addr", 521202375Srdivacky []>, 522202375Srdivacky T1LdSt2Imm<{0,?,?}>; 523193323Sed 524198090Srdivackydef tSTRspi : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStorei, 525198892Srdivacky "str", "\t$src, $addr", 526201360Srdivacky [(store tGPR:$src, t_addrmode_sp:$addr)]>, 527201360Srdivacky T1LdStSP<{0,?,?}>; 528193323Sed 529193323Sedlet mayStore = 1 in { 530193323Sed// Special instruction for spill. It cannot clobber condition register 531193323Sed// when it's expanded by eliminateCallFramePseudoInstr(). 532198090Srdivackydef tSpill : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStorei, 533201360Srdivacky "str", "\t$src, $addr", []>, 534201360Srdivacky T1LdStSP<{0,?,?}>; 535193323Sed} 536193323Sed 537193323Sed//===----------------------------------------------------------------------===// 538193323Sed// Load / store multiple Instructions. 539193323Sed// 540193323Sed 541198090Srdivacky// These requires base address to be written back or one of the loaded regs. 542205218Srdivackylet mayLoad = 1, hasExtraDefRegAllocReq = 1 in { 543198090Srdivackydef tLDM : T1I<(outs), 544205218Srdivacky (ins addrmode4:$addr, pred:$p, reglist:$dsts, variable_ops), 545198090Srdivacky IIC_iLoadm, 546205218Srdivacky "ldm${addr:submode}${p}\t$addr, $dsts", []>, 547201360Srdivacky T1Encoding<{1,1,0,0,1,?}>; // A6.2 & A8.6.53 548193323Sed 549205218Srdivackydef tLDM_UPD : T1It<(outs tGPR:$wb), 550205218Srdivacky (ins addrmode4:$addr, pred:$p, reglist:$dsts, variable_ops), 551205218Srdivacky IIC_iLoadm, 552205218Srdivacky "ldm${addr:submode}${p}\t$addr, $dsts", 553205218Srdivacky "$addr.addr = $wb", []>, 554205218Srdivacky T1Encoding<{1,1,0,0,1,?}>; // A6.2 & A8.6.53 555205218Srdivacky} // mayLoad, hasExtraDefRegAllocReq 556205218Srdivacky 557198090Srdivackylet mayStore = 1, hasExtraSrcRegAllocReq = 1 in 558205218Srdivackydef tSTM_UPD : T1It<(outs tGPR:$wb), 559205218Srdivacky (ins addrmode4:$addr, pred:$p, reglist:$srcs, variable_ops), 560205218Srdivacky IIC_iStorem, 561205218Srdivacky "stm${addr:submode}${p}\t$addr, $srcs", 562205218Srdivacky "$addr.addr = $wb", []>, 563201360Srdivacky T1Encoding<{1,1,0,0,0,?}>; // A6.2 & A8.6.189 564193323Sed 565198090Srdivackylet mayLoad = 1, Uses = [SP], Defs = [SP], hasExtraDefRegAllocReq = 1 in 566205218Srdivackydef tPOP : T1I<(outs), (ins pred:$p, reglist:$dsts, variable_ops), IIC_Br, 567205218Srdivacky "pop${p}\t$dsts", []>, 568201360Srdivacky T1Misc<{1,1,0,?,?,?,?}>; 569193323Sed 570198090Srdivackylet mayStore = 1, Uses = [SP], Defs = [SP], hasExtraSrcRegAllocReq = 1 in 571205218Srdivackydef tPUSH : T1I<(outs), (ins pred:$p, reglist:$srcs, variable_ops), IIC_Br, 572205218Srdivacky "push${p}\t$srcs", []>, 573201360Srdivacky T1Misc<{0,1,0,?,?,?,?}>; 574198090Srdivacky 575193323Sed//===----------------------------------------------------------------------===// 576193323Sed// Arithmetic Instructions. 577193323Sed// 578193323Sed 579195098Sed// Add with carry register 580198090Srdivackylet isCommutable = 1, Uses = [CPSR] in 581198090Srdivackydef tADC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 582198892Srdivacky "adc", "\t$dst, $rhs", 583201360Srdivacky [(set tGPR:$dst, (adde tGPR:$lhs, tGPR:$rhs))]>, 584201360Srdivacky T1DataProcessing<0b0101>; 585193323Sed 586195098Sed// Add immediate 587198090Srdivackydef tADDi3 : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi, 588198892Srdivacky "add", "\t$dst, $lhs, $rhs", 589201360Srdivacky [(set tGPR:$dst, (add tGPR:$lhs, imm0_7:$rhs))]>, 590201360Srdivacky T1General<0b01110>; 591193323Sed 592198090Srdivackydef tADDi8 : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi, 593198892Srdivacky "add", "\t$dst, $rhs", 594201360Srdivacky [(set tGPR:$dst, (add tGPR:$lhs, imm8_255:$rhs))]>, 595201360Srdivacky T1General<{1,1,0,?,?}>; 596193323Sed 597195098Sed// Add register 598198090Srdivackylet isCommutable = 1 in 599198090Srdivackydef tADDrr : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 600198892Srdivacky "add", "\t$dst, $lhs, $rhs", 601201360Srdivacky [(set tGPR:$dst, (add tGPR:$lhs, tGPR:$rhs))]>, 602201360Srdivacky T1General<0b01100>; 603193323Sed 604194178Sedlet neverHasSideEffects = 1 in 605198090Srdivackydef tADDhirr : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, 606201360Srdivacky "add", "\t$dst, $rhs", []>, 607201360Srdivacky T1Special<{0,0,?,?}>; 608193323Sed 609195098Sed// And register 610198090Srdivackylet isCommutable = 1 in 611198090Srdivackydef tAND : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 612198892Srdivacky "and", "\t$dst, $rhs", 613201360Srdivacky [(set tGPR:$dst, (and tGPR:$lhs, tGPR:$rhs))]>, 614201360Srdivacky T1DataProcessing<0b0000>; 615193323Sed 616195098Sed// ASR immediate 617198090Srdivackydef tASRri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iMOVsi, 618198892Srdivacky "asr", "\t$dst, $lhs, $rhs", 619201360Srdivacky [(set tGPR:$dst, (sra tGPR:$lhs, (i32 imm:$rhs)))]>, 620201360Srdivacky T1General<{0,1,0,?,?}>; 621193323Sed 622195098Sed// ASR register 623198090Srdivackydef tASRrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, 624198892Srdivacky "asr", "\t$dst, $rhs", 625201360Srdivacky [(set tGPR:$dst, (sra tGPR:$lhs, tGPR:$rhs))]>, 626201360Srdivacky T1DataProcessing<0b0100>; 627193323Sed 628195098Sed// BIC register 629198090Srdivackydef tBIC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 630198892Srdivacky "bic", "\t$dst, $rhs", 631201360Srdivacky [(set tGPR:$dst, (and tGPR:$lhs, (not tGPR:$rhs)))]>, 632201360Srdivacky T1DataProcessing<0b1110>; 633193323Sed 634195098Sed// CMN register 635195098Sedlet Defs = [CPSR] in { 636202878Srdivacky//FIXME: Disable CMN, as CCodes are backwards from compare expectations 637202878Srdivacky// Compare-to-zero still works out, just not the relationals 638202878Srdivacky//def tCMN : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, 639202878Srdivacky// "cmn", "\t$lhs, $rhs", 640202878Srdivacky// [(ARMcmp tGPR:$lhs, (ineg tGPR:$rhs))]>, 641202878Srdivacky// T1DataProcessing<0b1011>; 642201360Srdivackydef tCMNz : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, 643198892Srdivacky "cmn", "\t$lhs, $rhs", 644201360Srdivacky [(ARMcmpZ tGPR:$lhs, (ineg tGPR:$rhs))]>, 645201360Srdivacky T1DataProcessing<0b1011>; 646195098Sed} 647193323Sed 648195098Sed// CMP immediate 649195098Sedlet Defs = [CPSR] in { 650198090Srdivackydef tCMPi8 : T1pI<(outs), (ins tGPR:$lhs, i32imm:$rhs), IIC_iCMPi, 651198892Srdivacky "cmp", "\t$lhs, $rhs", 652201360Srdivacky [(ARMcmp tGPR:$lhs, imm0_255:$rhs)]>, 653201360Srdivacky T1General<{1,0,1,?,?}>; 654198090Srdivackydef tCMPzi8 : T1pI<(outs), (ins tGPR:$lhs, i32imm:$rhs), IIC_iCMPi, 655198892Srdivacky "cmp", "\t$lhs, $rhs", 656201360Srdivacky [(ARMcmpZ tGPR:$lhs, imm0_255:$rhs)]>, 657201360Srdivacky T1General<{1,0,1,?,?}>; 658195098Sed} 659195098Sed 660195098Sed// CMP register 661195098Sedlet Defs = [CPSR] in { 662198090Srdivackydef tCMPr : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, 663198892Srdivacky "cmp", "\t$lhs, $rhs", 664201360Srdivacky [(ARMcmp tGPR:$lhs, tGPR:$rhs)]>, 665201360Srdivacky T1DataProcessing<0b1010>; 666198090Srdivackydef tCMPzr : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, 667198892Srdivacky "cmp", "\t$lhs, $rhs", 668201360Srdivacky [(ARMcmpZ tGPR:$lhs, tGPR:$rhs)]>, 669201360Srdivacky T1DataProcessing<0b1010>; 670198090Srdivacky 671198090Srdivackydef tCMPhir : T1pI<(outs), (ins GPR:$lhs, GPR:$rhs), IIC_iCMPr, 672201360Srdivacky "cmp", "\t$lhs, $rhs", []>, 673201360Srdivacky T1Special<{0,1,?,?}>; 674198090Srdivackydef tCMPzhir : T1pI<(outs), (ins GPR:$lhs, GPR:$rhs), IIC_iCMPr, 675201360Srdivacky "cmp", "\t$lhs, $rhs", []>, 676201360Srdivacky T1Special<{0,1,?,?}>; 677195098Sed} 678193323Sed 679193323Sed 680195098Sed// XOR register 681198090Srdivackylet isCommutable = 1 in 682198090Srdivackydef tEOR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 683198892Srdivacky "eor", "\t$dst, $rhs", 684201360Srdivacky [(set tGPR:$dst, (xor tGPR:$lhs, tGPR:$rhs))]>, 685201360Srdivacky T1DataProcessing<0b0001>; 686193323Sed 687195098Sed// LSL immediate 688198090Srdivackydef tLSLri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iMOVsi, 689198892Srdivacky "lsl", "\t$dst, $lhs, $rhs", 690201360Srdivacky [(set tGPR:$dst, (shl tGPR:$lhs, (i32 imm:$rhs)))]>, 691201360Srdivacky T1General<{0,0,0,?,?}>; 692193323Sed 693195098Sed// LSL register 694198090Srdivackydef tLSLrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, 695198892Srdivacky "lsl", "\t$dst, $rhs", 696201360Srdivacky [(set tGPR:$dst, (shl tGPR:$lhs, tGPR:$rhs))]>, 697201360Srdivacky T1DataProcessing<0b0010>; 698193323Sed 699195098Sed// LSR immediate 700198090Srdivackydef tLSRri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iMOVsi, 701198892Srdivacky "lsr", "\t$dst, $lhs, $rhs", 702201360Srdivacky [(set tGPR:$dst, (srl tGPR:$lhs, (i32 imm:$rhs)))]>, 703201360Srdivacky T1General<{0,0,1,?,?}>; 704193323Sed 705195098Sed// LSR register 706198090Srdivackydef tLSRrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, 707198892Srdivacky "lsr", "\t$dst, $rhs", 708201360Srdivacky [(set tGPR:$dst, (srl tGPR:$lhs, tGPR:$rhs))]>, 709201360Srdivacky T1DataProcessing<0b0011>; 710193323Sed 711195098Sed// move register 712198090Srdivackydef tMOVi8 : T1sI<(outs tGPR:$dst), (ins i32imm:$src), IIC_iMOVi, 713198892Srdivacky "mov", "\t$dst, $src", 714201360Srdivacky [(set tGPR:$dst, imm0_255:$src)]>, 715201360Srdivacky T1General<{1,0,0,?,?}>; 716193323Sed 717193323Sed// TODO: A7-73: MOV(2) - mov setting flag. 718193323Sed 719193323Sed 720194178Sedlet neverHasSideEffects = 1 in { 721198090Srdivacky// FIXME: Make this predicable. 722198090Srdivackydef tMOVr : T1I<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr, 723201360Srdivacky "mov\t$dst, $src", []>, 724201360Srdivacky T1Special<0b1000>; 725198090Srdivackylet Defs = [CPSR] in 726198090Srdivackydef tMOVSr : T1I<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr, 727201360Srdivacky "movs\t$dst, $src", []>, Encoding16 { 728201360Srdivacky let Inst{15-6} = 0b0000000000; 729201360Srdivacky} 730198090Srdivacky 731198090Srdivacky// FIXME: Make these predicable. 732198090Srdivackydef tMOVgpr2tgpr : T1I<(outs tGPR:$dst), (ins GPR:$src), IIC_iMOVr, 733201360Srdivacky "mov\t$dst, $src", []>, 734202878Srdivacky T1Special<{1,0,0,?}>; 735198090Srdivackydef tMOVtgpr2gpr : T1I<(outs GPR:$dst), (ins tGPR:$src), IIC_iMOVr, 736201360Srdivacky "mov\t$dst, $src", []>, 737202878Srdivacky T1Special<{1,0,?,0}>; 738198090Srdivackydef tMOVgpr2gpr : T1I<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVr, 739201360Srdivacky "mov\t$dst, $src", []>, 740202878Srdivacky T1Special<{1,0,?,?}>; 741194178Sed} // neverHasSideEffects 742193323Sed 743195098Sed// multiply register 744198090Srdivackylet isCommutable = 1 in 745198090Srdivackydef tMUL : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMUL32, 746204792Srdivacky "mul", "\t$dst, $rhs, $dst", /* A8.6.105 MUL Encoding T1 */ 747201360Srdivacky [(set tGPR:$dst, (mul tGPR:$lhs, tGPR:$rhs))]>, 748201360Srdivacky T1DataProcessing<0b1101>; 749193323Sed 750195098Sed// move inverse register 751198090Srdivackydef tMVN : T1sI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr, 752198892Srdivacky "mvn", "\t$dst, $src", 753201360Srdivacky [(set tGPR:$dst, (not tGPR:$src))]>, 754201360Srdivacky T1DataProcessing<0b1111>; 755193323Sed 756195098Sed// bitwise or register 757198090Srdivackylet isCommutable = 1 in 758198090Srdivackydef tORR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 759198892Srdivacky "orr", "\t$dst, $rhs", 760201360Srdivacky [(set tGPR:$dst, (or tGPR:$lhs, tGPR:$rhs))]>, 761201360Srdivacky T1DataProcessing<0b1100>; 762193323Sed 763195098Sed// swaps 764198090Srdivackydef tREV : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 765198892Srdivacky "rev", "\t$dst, $src", 766198090Srdivacky [(set tGPR:$dst, (bswap tGPR:$src))]>, 767201360Srdivacky Requires<[IsThumb1Only, HasV6]>, 768201360Srdivacky T1Misc<{1,0,1,0,0,0,?}>; 769193323Sed 770198090Srdivackydef tREV16 : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 771198892Srdivacky "rev16", "\t$dst, $src", 772198090Srdivacky [(set tGPR:$dst, 773198090Srdivacky (or (and (srl tGPR:$src, (i32 8)), 0xFF), 774198090Srdivacky (or (and (shl tGPR:$src, (i32 8)), 0xFF00), 775198090Srdivacky (or (and (srl tGPR:$src, (i32 8)), 0xFF0000), 776198090Srdivacky (and (shl tGPR:$src, (i32 8)), 0xFF000000)))))]>, 777201360Srdivacky Requires<[IsThumb1Only, HasV6]>, 778201360Srdivacky T1Misc<{1,0,1,0,0,1,?}>; 779193323Sed 780198090Srdivackydef tREVSH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 781198892Srdivacky "revsh", "\t$dst, $src", 782198090Srdivacky [(set tGPR:$dst, 783198090Srdivacky (sext_inreg 784198090Srdivacky (or (srl (and tGPR:$src, 0xFF00), (i32 8)), 785198090Srdivacky (shl tGPR:$src, (i32 8))), i16))]>, 786201360Srdivacky Requires<[IsThumb1Only, HasV6]>, 787201360Srdivacky T1Misc<{1,0,1,0,1,1,?}>; 788193323Sed 789195098Sed// rotate right register 790198090Srdivackydef tROR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, 791198892Srdivacky "ror", "\t$dst, $rhs", 792201360Srdivacky [(set tGPR:$dst, (rotr tGPR:$lhs, tGPR:$rhs))]>, 793201360Srdivacky T1DataProcessing<0b0111>; 794193323Sed 795198090Srdivacky// negate register 796198090Srdivackydef tRSB : T1sI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iALUi, 797198892Srdivacky "rsb", "\t$dst, $src, #0", 798201360Srdivacky [(set tGPR:$dst, (ineg tGPR:$src))]>, 799201360Srdivacky T1DataProcessing<0b1001>; 800198090Srdivacky 801195098Sed// Subtract with carry register 802198090Srdivackylet Uses = [CPSR] in 803198090Srdivackydef tSBC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 804198892Srdivacky "sbc", "\t$dst, $rhs", 805201360Srdivacky [(set tGPR:$dst, (sube tGPR:$lhs, tGPR:$rhs))]>, 806201360Srdivacky T1DataProcessing<0b0110>; 807193323Sed 808195098Sed// Subtract immediate 809198090Srdivackydef tSUBi3 : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi, 810198892Srdivacky "sub", "\t$dst, $lhs, $rhs", 811201360Srdivacky [(set tGPR:$dst, (add tGPR:$lhs, imm0_7_neg:$rhs))]>, 812201360Srdivacky T1General<0b01111>; 813193323Sed 814198090Srdivackydef tSUBi8 : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi, 815198892Srdivacky "sub", "\t$dst, $rhs", 816201360Srdivacky [(set tGPR:$dst, (add tGPR:$lhs, imm8_255_neg:$rhs))]>, 817201360Srdivacky T1General<{1,1,1,?,?}>; 818193323Sed 819195098Sed// subtract register 820198090Srdivackydef tSUBrr : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 821198892Srdivacky "sub", "\t$dst, $lhs, $rhs", 822201360Srdivacky [(set tGPR:$dst, (sub tGPR:$lhs, tGPR:$rhs))]>, 823201360Srdivacky T1General<0b01101>; 824193323Sed 825195098Sed// TODO: A7-96: STMIA - store multiple. 826195098Sed 827195098Sed// sign-extend byte 828198090Srdivackydef tSXTB : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 829198892Srdivacky "sxtb", "\t$dst, $src", 830198090Srdivacky [(set tGPR:$dst, (sext_inreg tGPR:$src, i8))]>, 831201360Srdivacky Requires<[IsThumb1Only, HasV6]>, 832201360Srdivacky T1Misc<{0,0,1,0,0,1,?}>; 833195098Sed 834195098Sed// sign-extend short 835198090Srdivackydef tSXTH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 836198892Srdivacky "sxth", "\t$dst, $src", 837198090Srdivacky [(set tGPR:$dst, (sext_inreg tGPR:$src, i16))]>, 838201360Srdivacky Requires<[IsThumb1Only, HasV6]>, 839201360Srdivacky T1Misc<{0,0,1,0,0,0,?}>; 840193323Sed 841195098Sed// test 842195098Sedlet isCommutable = 1, Defs = [CPSR] in 843198090Srdivackydef tTST : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, 844198892Srdivacky "tst", "\t$lhs, $rhs", 845201360Srdivacky [(ARMcmpZ (and tGPR:$lhs, tGPR:$rhs), 0)]>, 846201360Srdivacky T1DataProcessing<0b1000>; 847193323Sed 848195098Sed// zero-extend byte 849198090Srdivackydef tUXTB : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 850198892Srdivacky "uxtb", "\t$dst, $src", 851198090Srdivacky [(set tGPR:$dst, (and tGPR:$src, 0xFF))]>, 852201360Srdivacky Requires<[IsThumb1Only, HasV6]>, 853201360Srdivacky T1Misc<{0,0,1,0,1,1,?}>; 854195098Sed 855195098Sed// zero-extend short 856198090Srdivackydef tUXTH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 857198892Srdivacky "uxth", "\t$dst, $src", 858198090Srdivacky [(set tGPR:$dst, (and tGPR:$src, 0xFFFF))]>, 859201360Srdivacky Requires<[IsThumb1Only, HasV6]>, 860201360Srdivacky T1Misc<{0,0,1,0,1,0,?}>; 861193323Sed 862193323Sed 863204642Srdivacky// Conditional move tMOVCCr - Used to implement the Thumb SELECT_CC operation. 864198892Srdivacky// Expanded after instruction selection into a branch sequence. 865198892Srdivackylet usesCustomInserter = 1 in // Expanded after instruction selection. 866198090Srdivacky def tMOVCCr_pseudo : 867193323Sed PseudoInst<(outs tGPR:$dst), (ins tGPR:$false, tGPR:$true, pred:$cc), 868198090Srdivacky NoItinerary, "@ tMOVCCr $cc", 869198090Srdivacky [/*(set tGPR:$dst, (ARMcmov tGPR:$false, tGPR:$true, imm:$cc))*/]>; 870193323Sed 871198090Srdivacky 872198090Srdivacky// 16-bit movcc in IT blocks for Thumb2. 873198090Srdivackydef tMOVCCr : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iCMOVr, 874201360Srdivacky "mov", "\t$dst, $rhs", []>, 875202878Srdivacky T1Special<{1,0,?,?}>; 876198090Srdivacky 877203954Srdivackydef tMOVCCi : T1pIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iCMOVi, 878201360Srdivacky "mov", "\t$dst, $rhs", []>, 879201360Srdivacky T1General<{1,0,0,?,?}>; 880198090Srdivacky 881193323Sed// tLEApcrel - Load a pc-relative address into a register without offending the 882193323Sed// assembler. 883198090Srdivackydef tLEApcrel : T1I<(outs tGPR:$dst), (ins i32imm:$label, pred:$p), IIC_iALUi, 884201360Srdivacky "adr$p\t$dst, #$label", []>, 885201360Srdivacky T1Encoding<{1,0,1,0,0,?}>; // A6.2 & A8.6.10 886193323Sed 887198090Srdivackydef tLEApcrelJT : T1I<(outs tGPR:$dst), 888198090Srdivacky (ins i32imm:$label, nohash_imm:$id, pred:$p), 889201360Srdivacky IIC_iALUi, "adr$p\t$dst, #${label}_${id}", []>, 890201360Srdivacky T1Encoding<{1,0,1,0,0,?}>; // A6.2 & A8.6.10 891193323Sed 892193323Sed//===----------------------------------------------------------------------===// 893193323Sed// TLS Instructions 894193323Sed// 895193323Sed 896193323Sed// __aeabi_read_tp preserves the registers r1-r3. 897193323Sedlet isCall = 1, 898193323Sed Defs = [R0, LR] in { 899201360Srdivacky def tTPsoft : TIx2<0b11110, 0b11, 1, (outs), (ins), IIC_Br, 900201360Srdivacky "bl\t__aeabi_read_tp", 901201360Srdivacky [(set R0, ARMthread_pointer)]>; 902193323Sed} 903193323Sed 904200581Srdivacky// SJLJ Exception handling intrinsics 905200581Srdivacky// eh_sjlj_setjmp() is an instruction sequence to store the return 906200581Srdivacky// address and save #0 in R0 for the non-longjmp case. 907200581Srdivacky// Since by its nature we may be coming from some other function to get 908200581Srdivacky// here, and we're using the stack frame for the containing function to 909200581Srdivacky// save/restore registers, we can't keep anything live in regs across 910200581Srdivacky// the eh_sjlj_setjmp(), else it will almost certainly have been tromped upon 911200581Srdivacky// when we get here from a longjmp(). We force everthing out of registers 912200581Srdivacky// except for our own input by listing the relevant registers in Defs. By 913200581Srdivacky// doing so, we also cause the prologue/epilogue code to actively preserve 914200581Srdivacky// all of the callee-saved resgisters, which is exactly what we want. 915203954Srdivacky// The current SP is passed in $val, and we reuse the reg as a scratch. 916200581Srdivackylet Defs = 917200581Srdivacky [ R0, R1, R2, R3, R4, R5, R6, R7, R12 ] in { 918203954Srdivacky def tInt_eh_sjlj_setjmp : ThumbXI<(outs),(ins tGPR:$src, tGPR:$val), 919200581Srdivacky AddrModeNone, SizeSpecial, NoItinerary, 920203954Srdivacky "str\t$val, [$src, #8]\t@ begin eh.setjmp\n" 921203954Srdivacky "\tmov\t$val, pc\n" 922203954Srdivacky "\tadds\t$val, #9\n" 923203954Srdivacky "\tstr\t$val, [$src, #4]\n" 924200581Srdivacky "\tmovs\tr0, #0\n" 925200581Srdivacky "\tb\t1f\n" 926203954Srdivacky "\tmovs\tr0, #1\t@ end eh.setjmp\n" 927200581Srdivacky "1:", "", 928203954Srdivacky [(set R0, (ARMeh_sjlj_setjmp tGPR:$src, tGPR:$val))]>; 929200581Srdivacky} 930193323Sed//===----------------------------------------------------------------------===// 931193323Sed// Non-Instruction Patterns 932193323Sed// 933193323Sed 934198090Srdivacky// Add with carry 935198090Srdivackydef : T1Pat<(addc tGPR:$lhs, imm0_7:$rhs), 936198090Srdivacky (tADDi3 tGPR:$lhs, imm0_7:$rhs)>; 937198090Srdivackydef : T1Pat<(addc tGPR:$lhs, imm8_255:$rhs), 938198090Srdivacky (tADDi8 tGPR:$lhs, imm8_255:$rhs)>; 939198090Srdivackydef : T1Pat<(addc tGPR:$lhs, tGPR:$rhs), 940198090Srdivacky (tADDrr tGPR:$lhs, tGPR:$rhs)>; 941198090Srdivacky 942198090Srdivacky// Subtract with carry 943198090Srdivackydef : T1Pat<(addc tGPR:$lhs, imm0_7_neg:$rhs), 944198090Srdivacky (tSUBi3 tGPR:$lhs, imm0_7_neg:$rhs)>; 945198090Srdivackydef : T1Pat<(addc tGPR:$lhs, imm8_255_neg:$rhs), 946198090Srdivacky (tSUBi8 tGPR:$lhs, imm8_255_neg:$rhs)>; 947198090Srdivackydef : T1Pat<(subc tGPR:$lhs, tGPR:$rhs), 948198090Srdivacky (tSUBrr tGPR:$lhs, tGPR:$rhs)>; 949198090Srdivacky 950193323Sed// ConstantPool, GlobalAddress 951198090Srdivackydef : T1Pat<(ARMWrapper tglobaladdr :$dst), (tLEApcrel tglobaladdr :$dst)>; 952198090Srdivackydef : T1Pat<(ARMWrapper tconstpool :$dst), (tLEApcrel tconstpool :$dst)>; 953193323Sed 954193323Sed// JumpTable 955198090Srdivackydef : T1Pat<(ARMWrapperJT tjumptable:$dst, imm:$id), 956198090Srdivacky (tLEApcrelJT tjumptable:$dst, imm:$id)>; 957193323Sed 958193323Sed// Direct calls 959198090Srdivackydef : T1Pat<(ARMtcall texternalsym:$func), (tBL texternalsym:$func)>, 960198090Srdivacky Requires<[IsThumb, IsNotDarwin]>; 961198090Srdivackydef : T1Pat<(ARMtcall texternalsym:$func), (tBLr9 texternalsym:$func)>, 962198090Srdivacky Requires<[IsThumb, IsDarwin]>; 963193323Sed 964198090Srdivackydef : Tv5Pat<(ARMcall texternalsym:$func), (tBLXi texternalsym:$func)>, 965198090Srdivacky Requires<[IsThumb, HasV5T, IsNotDarwin]>; 966198090Srdivackydef : Tv5Pat<(ARMcall texternalsym:$func), (tBLXi_r9 texternalsym:$func)>, 967198090Srdivacky Requires<[IsThumb, HasV5T, IsDarwin]>; 968198090Srdivacky 969193323Sed// Indirect calls to ARM routines 970198090Srdivackydef : Tv5Pat<(ARMcall GPR:$dst), (tBLXr GPR:$dst)>, 971198090Srdivacky Requires<[IsThumb, HasV5T, IsNotDarwin]>; 972198090Srdivackydef : Tv5Pat<(ARMcall GPR:$dst), (tBLXr_r9 GPR:$dst)>, 973198090Srdivacky Requires<[IsThumb, HasV5T, IsDarwin]>; 974193323Sed 975193323Sed// zextload i1 -> zextload i8 976195340Seddef : T1Pat<(zextloadi1 t_addrmode_s1:$addr), 977195340Sed (tLDRB t_addrmode_s1:$addr)>; 978193323Sed 979193323Sed// extload -> zextload 980195340Seddef : T1Pat<(extloadi1 t_addrmode_s1:$addr), (tLDRB t_addrmode_s1:$addr)>; 981195340Seddef : T1Pat<(extloadi8 t_addrmode_s1:$addr), (tLDRB t_addrmode_s1:$addr)>; 982195340Seddef : T1Pat<(extloadi16 t_addrmode_s2:$addr), (tLDRH t_addrmode_s2:$addr)>; 983193323Sed 984198090Srdivacky// If it's impossible to use [r,r] address mode for sextload, select to 985198090Srdivacky// ldr{b|h} + sxt{b|h} instead. 986198090Srdivackydef : T1Pat<(sextloadi8 t_addrmode_s1:$addr), 987198090Srdivacky (tSXTB (tLDRB t_addrmode_s1:$addr))>, 988198090Srdivacky Requires<[IsThumb1Only, HasV6]>; 989198090Srdivackydef : T1Pat<(sextloadi16 t_addrmode_s2:$addr), 990198090Srdivacky (tSXTH (tLDRH t_addrmode_s2:$addr))>, 991198090Srdivacky Requires<[IsThumb1Only, HasV6]>; 992198090Srdivacky 993198090Srdivackydef : T1Pat<(sextloadi8 t_addrmode_s1:$addr), 994198090Srdivacky (tASRri (tLSLri (tLDRB t_addrmode_s1:$addr), 24), 24)>; 995198090Srdivackydef : T1Pat<(sextloadi16 t_addrmode_s1:$addr), 996198090Srdivacky (tASRri (tLSLri (tLDRH t_addrmode_s1:$addr), 16), 16)>; 997198090Srdivacky 998193323Sed// Large immediate handling. 999193323Sed 1000193323Sed// Two piece imms. 1001195098Seddef : T1Pat<(i32 thumb_immshifted:$src), 1002195098Sed (tLSLri (tMOVi8 (thumb_immshifted_val imm:$src)), 1003195098Sed (thumb_immshifted_shamt imm:$src))>; 1004193323Sed 1005195098Seddef : T1Pat<(i32 imm0_255_comp:$src), 1006195098Sed (tMVN (tMOVi8 (imm_comp_XFORM imm:$src)))>; 1007199481Srdivacky 1008199481Srdivacky// Pseudo instruction that combines ldr from constpool and add pc. This should 1009199481Srdivacky// be expanded into two instructions late to allow if-conversion and 1010199481Srdivacky// scheduling. 1011199481Srdivackylet isReMaterializable = 1 in 1012199481Srdivackydef tLDRpci_pic : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr, pclabel:$cp), 1013199481Srdivacky NoItinerary, "@ ldr.n\t$dst, $addr\n$cp:\n\tadd\t$dst, pc", 1014199481Srdivacky [(set GPR:$dst, (ARMpic_add (load (ARMWrapper tconstpool:$addr)), 1015199481Srdivacky imm:$cp))]>, 1016199481Srdivacky Requires<[IsThumb1Only]>; 1017