ARMInstrThumb.td revision 208599
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, 19205407Srdivacky [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag, 20205407Srdivacky SDNPVariadic]>; 21193323Sed 22193323Seddef imm_neg_XFORM : SDNodeXForm<imm, [{ 23193323Sed return CurDAG->getTargetConstant(-(int)N->getZExtValue(), MVT::i32); 24193323Sed}]>; 25193323Seddef imm_comp_XFORM : SDNodeXForm<imm, [{ 26193323Sed return CurDAG->getTargetConstant(~((uint32_t)N->getZExtValue()), MVT::i32); 27193323Sed}]>; 28193323Sed 29193323Sed 30193323Sed/// imm0_7 predicate - True if the 32-bit immediate is in the range [0,7]. 31193323Seddef imm0_7 : PatLeaf<(i32 imm), [{ 32193323Sed return (uint32_t)N->getZExtValue() < 8; 33193323Sed}]>; 34193323Seddef imm0_7_neg : PatLeaf<(i32 imm), [{ 35193323Sed return (uint32_t)-N->getZExtValue() < 8; 36193323Sed}], imm_neg_XFORM>; 37193323Sed 38193323Seddef imm0_255 : PatLeaf<(i32 imm), [{ 39193323Sed return (uint32_t)N->getZExtValue() < 256; 40193323Sed}]>; 41193323Seddef imm0_255_comp : PatLeaf<(i32 imm), [{ 42193323Sed return ~((uint32_t)N->getZExtValue()) < 256; 43193323Sed}]>; 44193323Sed 45193323Seddef imm8_255 : PatLeaf<(i32 imm), [{ 46193323Sed return (uint32_t)N->getZExtValue() >= 8 && (uint32_t)N->getZExtValue() < 256; 47193323Sed}]>; 48193323Seddef imm8_255_neg : PatLeaf<(i32 imm), [{ 49193323Sed unsigned Val = -N->getZExtValue(); 50193323Sed return Val >= 8 && Val < 256; 51193323Sed}], imm_neg_XFORM>; 52193323Sed 53193323Sed// Break imm's up into two pieces: an immediate + a left shift. 54193323Sed// This uses thumb_immshifted to match and thumb_immshifted_val and 55193323Sed// thumb_immshifted_shamt to get the val/shift pieces. 56193323Seddef thumb_immshifted : PatLeaf<(imm), [{ 57193323Sed return ARM_AM::isThumbImmShiftedVal((unsigned)N->getZExtValue()); 58193323Sed}]>; 59193323Sed 60193323Seddef thumb_immshifted_val : SDNodeXForm<imm, [{ 61193323Sed unsigned V = ARM_AM::getThumbImmNonShiftedVal((unsigned)N->getZExtValue()); 62193323Sed return CurDAG->getTargetConstant(V, MVT::i32); 63193323Sed}]>; 64193323Sed 65193323Seddef thumb_immshifted_shamt : SDNodeXForm<imm, [{ 66193323Sed unsigned V = ARM_AM::getThumbImmValShift((unsigned)N->getZExtValue()); 67193323Sed return CurDAG->getTargetConstant(V, MVT::i32); 68193323Sed}]>; 69193323Sed 70199511Srdivacky// Scaled 4 immediate. 71199511Srdivackydef t_imm_s4 : Operand<i32> { 72199511Srdivacky let PrintMethod = "printThumbS4ImmOperand"; 73199511Srdivacky} 74199511Srdivacky 75193323Sed// Define Thumb specific addressing modes. 76193323Sed 77193323Sed// t_addrmode_rr := reg + reg 78193323Sed// 79193323Seddef t_addrmode_rr : Operand<i32>, 80193323Sed ComplexPattern<i32, 2, "SelectThumbAddrModeRR", []> { 81193323Sed let PrintMethod = "printThumbAddrModeRROperand"; 82193323Sed let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); 83193323Sed} 84193323Sed 85193323Sed// t_addrmode_s4 := reg + reg 86193323Sed// reg + imm5 * 4 87193323Sed// 88193323Seddef t_addrmode_s4 : Operand<i32>, 89193323Sed ComplexPattern<i32, 3, "SelectThumbAddrModeS4", []> { 90193323Sed let PrintMethod = "printThumbAddrModeS4Operand"; 91193323Sed let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg); 92193323Sed} 93193323Sed 94193323Sed// t_addrmode_s2 := reg + reg 95193323Sed// reg + imm5 * 2 96193323Sed// 97193323Seddef t_addrmode_s2 : Operand<i32>, 98193323Sed ComplexPattern<i32, 3, "SelectThumbAddrModeS2", []> { 99193323Sed let PrintMethod = "printThumbAddrModeS2Operand"; 100193323Sed let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg); 101193323Sed} 102193323Sed 103193323Sed// t_addrmode_s1 := reg + reg 104193323Sed// reg + imm5 105193323Sed// 106193323Seddef t_addrmode_s1 : Operand<i32>, 107193323Sed ComplexPattern<i32, 3, "SelectThumbAddrModeS1", []> { 108193323Sed let PrintMethod = "printThumbAddrModeS1Operand"; 109193323Sed let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg); 110193323Sed} 111193323Sed 112193323Sed// t_addrmode_sp := sp + imm8 * 4 113193323Sed// 114193323Seddef t_addrmode_sp : Operand<i32>, 115193323Sed ComplexPattern<i32, 2, "SelectThumbAddrModeSP", []> { 116193323Sed let PrintMethod = "printThumbAddrModeSPOperand"; 117202375Srdivacky let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); 118193323Sed} 119193323Sed 120193323Sed//===----------------------------------------------------------------------===// 121193323Sed// Miscellaneous Instructions. 122193323Sed// 123193323Sed 124204642Srdivacky// FIXME: Marking these as hasSideEffects is necessary to prevent machine DCE 125204642Srdivacky// from removing one half of the matched pairs. That breaks PEI, which assumes 126204642Srdivacky// these will always be in pairs, and asserts if it finds otherwise. Better way? 127204642Srdivackylet Defs = [SP], Uses = [SP], hasSideEffects = 1 in { 128193323Seddef tADJCALLSTACKUP : 129198090SrdivackyPseudoInst<(outs), (ins i32imm:$amt1, i32imm:$amt2), NoItinerary, 130208599Srdivacky "${:comment} tADJCALLSTACKUP $amt1", 131198090Srdivacky [(ARMcallseq_end imm:$amt1, imm:$amt2)]>, Requires<[IsThumb1Only]>; 132193323Sed 133193323Seddef tADJCALLSTACKDOWN : 134198090SrdivackyPseudoInst<(outs), (ins i32imm:$amt), NoItinerary, 135208599Srdivacky "${:comment} tADJCALLSTACKDOWN $amt", 136198090Srdivacky [(ARMcallseq_start imm:$amt)]>, Requires<[IsThumb1Only]>; 137193323Sed} 138193323Sed 139204642Srdivackydef tNOP : T1pI<(outs), (ins), NoItinerary, "nop", "", 140204642Srdivacky [/* For disassembly only; pattern left blank */]>, 141204642Srdivacky T1Encoding<0b101111> { 142204642Srdivacky let Inst{9-8} = 0b11; 143204642Srdivacky let Inst{7-0} = 0b00000000; 144204642Srdivacky} 145204642Srdivacky 146204642Srdivackydef tYIELD : T1pI<(outs), (ins), NoItinerary, "yield", "", 147204642Srdivacky [/* For disassembly only; pattern left blank */]>, 148204642Srdivacky T1Encoding<0b101111> { 149204642Srdivacky let Inst{9-8} = 0b11; 150204642Srdivacky let Inst{7-0} = 0b00010000; 151204642Srdivacky} 152204642Srdivacky 153204642Srdivackydef tWFE : T1pI<(outs), (ins), NoItinerary, "wfe", "", 154204642Srdivacky [/* For disassembly only; pattern left blank */]>, 155204642Srdivacky T1Encoding<0b101111> { 156204642Srdivacky let Inst{9-8} = 0b11; 157204642Srdivacky let Inst{7-0} = 0b00100000; 158204642Srdivacky} 159204642Srdivacky 160204642Srdivackydef tWFI : T1pI<(outs), (ins), NoItinerary, "wfi", "", 161204642Srdivacky [/* For disassembly only; pattern left blank */]>, 162204642Srdivacky T1Encoding<0b101111> { 163204642Srdivacky let Inst{9-8} = 0b11; 164204642Srdivacky let Inst{7-0} = 0b00110000; 165204642Srdivacky} 166204642Srdivacky 167204642Srdivackydef tSEV : T1pI<(outs), (ins), NoItinerary, "sev", "", 168204642Srdivacky [/* For disassembly only; pattern left blank */]>, 169204642Srdivacky T1Encoding<0b101111> { 170204642Srdivacky let Inst{9-8} = 0b11; 171204642Srdivacky let Inst{7-0} = 0b01000000; 172204642Srdivacky} 173204642Srdivacky 174204642Srdivackydef tSETENDBE : T1I<(outs), (ins), NoItinerary, "setend\tbe", 175204642Srdivacky [/* For disassembly only; pattern left blank */]>, 176204642Srdivacky T1Encoding<0b101101> { 177204642Srdivacky let Inst{9-5} = 0b10010; 178204642Srdivacky let Inst{3} = 1; 179204642Srdivacky} 180204642Srdivacky 181204642Srdivackydef tSETENDLE : T1I<(outs), (ins), NoItinerary, "setend\tle", 182204642Srdivacky [/* For disassembly only; pattern left blank */]>, 183204642Srdivacky T1Encoding<0b101101> { 184204642Srdivacky let Inst{9-5} = 0b10010; 185204642Srdivacky let Inst{3} = 0; 186204642Srdivacky} 187204642Srdivacky 188203954Srdivacky// The i32imm operand $val can be used by a debugger to store more information 189203954Srdivacky// about the breakpoint. 190203954Srdivackydef tBKPT : T1I<(outs), (ins i32imm:$val), NoItinerary, "bkpt\t$val", 191203954Srdivacky [/* For disassembly only; pattern left blank */]>, 192203954Srdivacky T1Encoding<0b101111> { 193203954Srdivacky let Inst{9-8} = 0b10; 194203954Srdivacky} 195203954Srdivacky 196204642Srdivacky// Change Processor State is a system instruction -- for disassembly only. 197204642Srdivacky// The singleton $opt operand contains the following information: 198204642Srdivacky// opt{4-0} = mode ==> don't care 199204642Srdivacky// opt{5} = changemode ==> 0 (false for 16-bit Thumb instr) 200204642Srdivacky// opt{8-6} = AIF from Inst{2-0} 201204642Srdivacky// opt{10-9} = 1:imod from Inst{4} with 0b10 as enable and 0b11 as disable 202204642Srdivacky// 203204642Srdivacky// The opt{4-0} and opt{5} sub-fields are to accommodate 32-bit Thumb and ARM 204204642Srdivacky// CPS which has more options. 205205218Srdivackydef tCPS : T1I<(outs), (ins cps_opt:$opt), NoItinerary, "cps$opt", 206204642Srdivacky [/* For disassembly only; pattern left blank */]>, 207204642Srdivacky T1Misc<0b0110011>; 208204642Srdivacky 209198090Srdivacky// For both thumb1 and thumb2. 210193323Sedlet isNotDuplicable = 1 in 211198090Srdivackydef tPICADD : TIt<(outs GPR:$dst), (ins GPR:$lhs, pclabel:$cp), IIC_iALUr, 212198892Srdivacky "\n$cp:\n\tadd\t$dst, pc", 213201360Srdivacky [(set GPR:$dst, (ARMpic_add GPR:$lhs, imm:$cp))]>, 214201360Srdivacky T1Special<{0,0,?,?}> { 215201360Srdivacky let Inst{6-3} = 0b1111; // A8.6.6 Rm = pc 216201360Srdivacky} 217193323Sed 218195098Sed// PC relative add. 219199511Srdivackydef tADDrPCi : T1I<(outs tGPR:$dst), (ins t_imm_s4:$rhs), IIC_iALUi, 220201360Srdivacky "add\t$dst, pc, $rhs", []>, 221201360Srdivacky T1Encoding<{1,0,1,0,0,?}>; // A6.2 & A8.6.10 222195098Sed 223195098Sed// ADD rd, sp, #imm8 224199511Srdivackydef tADDrSPi : T1I<(outs tGPR:$dst), (ins GPR:$sp, t_imm_s4:$rhs), IIC_iALUi, 225201360Srdivacky "add\t$dst, $sp, $rhs", []>, 226201360Srdivacky T1Encoding<{1,0,1,0,1,?}>; // A6.2 & A8.6.8 227195098Sed 228195098Sed// ADD sp, sp, #imm7 229199511Srdivackydef tADDspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), IIC_iALUi, 230201360Srdivacky "add\t$dst, $rhs", []>, 231201360Srdivacky T1Misc<{0,0,0,0,0,?,?}>; // A6.2.5 & A8.6.8 232195098Sed 233198090Srdivacky// SUB sp, sp, #imm7 234199511Srdivackydef tSUBspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), IIC_iALUi, 235201360Srdivacky "sub\t$dst, $rhs", []>, 236201360Srdivacky T1Misc<{0,0,0,0,1,?,?}>; // A6.2.5 & A8.6.215 237198090Srdivacky 238198090Srdivacky// ADD rm, sp 239198090Srdivackydef tADDrSP : TIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, 240201360Srdivacky "add\t$dst, $rhs", []>, 241201360Srdivacky T1Special<{0,0,?,?}> { 242201360Srdivacky let Inst{6-3} = 0b1101; // A8.6.9 Encoding T1 243201360Srdivacky} 244198090Srdivacky 245195098Sed// ADD sp, rm 246198090Srdivackydef tADDspr : TIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, 247201360Srdivacky "add\t$dst, $rhs", []>, 248201360Srdivacky T1Special<{0,0,?,?}> { 249201360Srdivacky // A8.6.9 Encoding T2 250201360Srdivacky let Inst{7} = 1; 251201360Srdivacky let Inst{2-0} = 0b101; 252201360Srdivacky} 253195098Sed 254198090Srdivacky// Pseudo instruction that will expand into a tSUBspi + a copy. 255198892Srdivackylet usesCustomInserter = 1 in { // Expanded after instruction selection. 256199511Srdivackydef tSUBspi_ : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), 257208599Srdivacky NoItinerary, "${:comment} sub\t$dst, $rhs", []>; 258198090Srdivacky 259198090Srdivackydef tADDspr_ : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), 260208599Srdivacky NoItinerary, "${:comment} add\t$dst, $rhs", []>; 261198090Srdivacky 262198090Srdivackylet Defs = [CPSR] in 263198090Srdivackydef tANDsp : PseudoInst<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), 264208599Srdivacky NoItinerary, "${:comment} and\t$dst, $rhs", []>; 265198892Srdivacky} // usesCustomInserter 266198090Srdivacky 267193323Sed//===----------------------------------------------------------------------===// 268193323Sed// Control Flow Instructions. 269193323Sed// 270193323Sed 271198090Srdivackylet isReturn = 1, isTerminator = 1, isBarrier = 1 in { 272201360Srdivacky def tBX_RET : TI<(outs), (ins), IIC_Br, "bx\tlr", [(ARMretflag)]>, 273201360Srdivacky T1Special<{1,1,0,?}> { // A6.2.3 & A8.6.25 274201360Srdivacky let Inst{6-3} = 0b1110; // Rm = lr 275201360Srdivacky } 276193323Sed // Alternative return instruction used by vararg functions. 277204642Srdivacky def tBX_RET_vararg : TI<(outs), (ins tGPR:$target), IIC_Br, "bx\t$target",[]>, 278201360Srdivacky T1Special<{1,1,0,?}>; // A6.2.3 & A8.6.25 279193323Sed} 280193323Sed 281198892Srdivacky// Indirect branches 282198892Srdivackylet isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { 283198892Srdivacky def tBRIND : TI<(outs), (ins GPR:$dst), IIC_Br, "mov\tpc, $dst", 284201360Srdivacky [(brind GPR:$dst)]>, 285202878Srdivacky T1Special<{1,0,1,?}> { 286202375Srdivacky // <Rd> = Inst{7:2-0} = pc 287201360Srdivacky let Inst{2-0} = 0b111; 288201360Srdivacky } 289198892Srdivacky} 290198892Srdivacky 291193323Sed// FIXME: remove when we have a way to marking a MI with these properties. 292198090Srdivackylet isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1, 293198090Srdivacky hasExtraDefRegAllocReq = 1 in 294205218Srdivackydef tPOP_RET : T1I<(outs), (ins pred:$p, reglist:$dsts, variable_ops), IIC_Br, 295205218Srdivacky "pop${p}\t$dsts", []>, 296201360Srdivacky T1Misc<{1,1,0,?,?,?,?}>; 297193323Sed 298193323Sedlet isCall = 1, 299198090Srdivacky Defs = [R0, R1, R2, R3, R12, LR, 300198090Srdivacky D0, D1, D2, D3, D4, D5, D6, D7, 301198090Srdivacky D16, D17, D18, D19, D20, D21, D22, D23, 302198090Srdivacky D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR] in { 303198090Srdivacky // Also used for Thumb2 304201360Srdivacky def tBL : TIx2<0b11110, 0b11, 1, 305204642Srdivacky (outs), (ins i32imm:$func, variable_ops), IIC_Br, 306201360Srdivacky "bl\t${func:call}", 307201360Srdivacky [(ARMtcall tglobaladdr:$func)]>, 308198090Srdivacky Requires<[IsThumb, IsNotDarwin]>; 309198090Srdivacky 310198090Srdivacky // ARMv5T and above, also used for Thumb2 311201360Srdivacky def tBLXi : TIx2<0b11110, 0b11, 0, 312204642Srdivacky (outs), (ins i32imm:$func, variable_ops), IIC_Br, 313201360Srdivacky "blx\t${func:call}", 314201360Srdivacky [(ARMcall tglobaladdr:$func)]>, 315198090Srdivacky Requires<[IsThumb, HasV5T, IsNotDarwin]>; 316198090Srdivacky 317198090Srdivacky // Also used for Thumb2 318204642Srdivacky def tBLXr : TI<(outs), (ins GPR:$func, variable_ops), IIC_Br, 319198892Srdivacky "blx\t$func", 320198090Srdivacky [(ARMtcall GPR:$func)]>, 321201360Srdivacky Requires<[IsThumb, HasV5T, IsNotDarwin]>, 322201360Srdivacky T1Special<{1,1,1,?}>; // A6.2.3 & A8.6.24; 323198090Srdivacky 324193323Sed // ARMv4T 325201360Srdivacky def tBX : TIx2<{?,?,?,?,?}, {?,?}, ?, 326204642Srdivacky (outs), (ins tGPR:$func, variable_ops), IIC_Br, 327198892Srdivacky "mov\tlr, pc\n\tbx\t$func", 328198090Srdivacky [(ARMcall_nolink tGPR:$func)]>, 329198090Srdivacky Requires<[IsThumb1Only, IsNotDarwin]>; 330193323Sed} 331193323Sed 332198090Srdivacky// On Darwin R9 is call-clobbered. 333198090Srdivackylet isCall = 1, 334198090Srdivacky Defs = [R0, R1, R2, R3, R9, R12, LR, 335198090Srdivacky D0, D1, D2, D3, D4, D5, D6, D7, 336198090Srdivacky D16, D17, D18, D19, D20, D21, D22, D23, 337198090Srdivacky D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR] in { 338198090Srdivacky // Also used for Thumb2 339201360Srdivacky def tBLr9 : TIx2<0b11110, 0b11, 1, 340204642Srdivacky (outs), (ins i32imm:$func, variable_ops), IIC_Br, 341198892Srdivacky "bl\t${func:call}", 342198090Srdivacky [(ARMtcall tglobaladdr:$func)]>, 343198090Srdivacky Requires<[IsThumb, IsDarwin]>; 344198090Srdivacky 345198090Srdivacky // ARMv5T and above, also used for Thumb2 346201360Srdivacky def tBLXi_r9 : TIx2<0b11110, 0b11, 0, 347204642Srdivacky (outs), (ins i32imm:$func, variable_ops), IIC_Br, 348198892Srdivacky "blx\t${func:call}", 349198090Srdivacky [(ARMcall tglobaladdr:$func)]>, 350198090Srdivacky Requires<[IsThumb, HasV5T, IsDarwin]>; 351198090Srdivacky 352198090Srdivacky // Also used for Thumb2 353204642Srdivacky def tBLXr_r9 : TI<(outs), (ins GPR:$func, variable_ops), IIC_Br, 354201360Srdivacky "blx\t$func", 355201360Srdivacky [(ARMtcall GPR:$func)]>, 356201360Srdivacky Requires<[IsThumb, HasV5T, IsDarwin]>, 357201360Srdivacky T1Special<{1,1,1,?}>; // A6.2.3 & A8.6.24 358198090Srdivacky 359198090Srdivacky // ARMv4T 360201360Srdivacky def tBXr9 : TIx2<{?,?,?,?,?}, {?,?}, ?, 361204642Srdivacky (outs), (ins tGPR:$func, variable_ops), IIC_Br, 362201360Srdivacky "mov\tlr, pc\n\tbx\t$func", 363201360Srdivacky [(ARMcall_nolink tGPR:$func)]>, 364198090Srdivacky Requires<[IsThumb1Only, IsDarwin]>; 365198090Srdivacky} 366198090Srdivacky 367193323Sedlet isBranch = 1, isTerminator = 1 in { 368193323Sed let isBarrier = 1 in { 369193323Sed let isPredicable = 1 in 370198090Srdivacky def tB : T1I<(outs), (ins brtarget:$target), IIC_Br, 371201360Srdivacky "b\t$target", [(br bb:$target)]>, 372201360Srdivacky T1Encoding<{1,1,1,0,0,?}>; 373193323Sed 374193323Sed // Far jump 375198090Srdivacky let Defs = [LR] in 376204642Srdivacky def tBfar : TIx2<0b11110, 0b11, 1, (outs), (ins brtarget:$target), IIC_Br, 377208599Srdivacky "bl\t$target\t${:comment} far jump",[]>; 378193323Sed 379195340Sed def tBR_JTr : T1JTI<(outs), 380195340Sed (ins tGPR:$target, jtblock_operand:$jt, i32imm:$id), 381198892Srdivacky IIC_Br, "mov\tpc, $target\n\t.align\t2\n$jt", 382201360Srdivacky [(ARMbrjt tGPR:$target, tjumptable:$jt, imm:$id)]>, 383201360Srdivacky Encoding16 { 384201360Srdivacky let Inst{15-7} = 0b010001101; 385201360Srdivacky let Inst{2-0} = 0b111; 386193323Sed } 387201360Srdivacky } 388193323Sed} 389193323Sed 390193323Sed// FIXME: should be able to write a pattern for ARMBrcond, but can't use 391193323Sed// a two-value operand where a dag node expects two operands. :( 392193323Sedlet isBranch = 1, isTerminator = 1 in 393198090Srdivacky def tBcc : T1I<(outs), (ins brtarget:$target, pred:$cc), IIC_Br, 394198892Srdivacky "b$cc\t$target", 395201360Srdivacky [/*(ARMbrcond bb:$target, imm:$cc)*/]>, 396201360Srdivacky T1Encoding<{1,1,0,1,?,?}>; 397193323Sed 398198892Srdivacky// Compare and branch on zero / non-zero 399198892Srdivackylet isBranch = 1, isTerminator = 1 in { 400198892Srdivacky def tCBZ : T1I<(outs), (ins tGPR:$cmp, brtarget:$target), IIC_Br, 401201360Srdivacky "cbz\t$cmp, $target", []>, 402201360Srdivacky T1Misc<{0,0,?,1,?,?,?}>; 403198892Srdivacky 404198892Srdivacky def tCBNZ : T1I<(outs), (ins tGPR:$cmp, brtarget:$target), IIC_Br, 405201360Srdivacky "cbnz\t$cmp, $target", []>, 406201360Srdivacky T1Misc<{1,0,?,1,?,?,?}>; 407198892Srdivacky} 408198892Srdivacky 409204642Srdivacky// A8.6.218 Supervisor Call (Software Interrupt) -- for disassembly only 410204642Srdivacky// A8.6.16 B: Encoding T1 411204642Srdivacky// If Inst{11-8} == 0b1111 then SEE SVC 412204642Srdivackylet isCall = 1 in { 413204642Srdivackydef tSVC : T1pI<(outs), (ins i32imm:$svc), IIC_Br, "svc", "\t$svc", []>, 414204642Srdivacky Encoding16 { 415204642Srdivacky let Inst{15-12} = 0b1101; 416204642Srdivacky let Inst{11-8} = 0b1111; 417204642Srdivacky} 418204642Srdivacky} 419204642Srdivacky 420208599Srdivacky// A8.6.16 B: Encoding T1 421204642Srdivacky// If Inst{11-8} == 0b1110 then UNDEFINED 422208599Srdivacky// FIXME: Temporary emitted as raw bytes until this pseudo-op will be added to 423208599Srdivacky// binutils 424208599Srdivackylet isBarrier = 1, isTerminator = 1 in 425208599Srdivackydef tTRAP : TI<(outs), (ins), IIC_Br, 426208599Srdivacky ".short 0xdefe ${:comment} trap", [(trap)]>, Encoding16 { 427204642Srdivacky let Inst{15-12} = 0b1101; 428204642Srdivacky let Inst{11-8} = 0b1110; 429204642Srdivacky} 430204642Srdivacky 431193323Sed//===----------------------------------------------------------------------===// 432193323Sed// Load Store Instructions. 433193323Sed// 434193323Sed 435204642Srdivackylet canFoldAsLoad = 1, isReMaterializable = 1 in 436204642Srdivackydef tLDR : T1pI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr), IIC_iLoadr, 437198892Srdivacky "ldr", "\t$dst, $addr", 438201360Srdivacky [(set tGPR:$dst, (load t_addrmode_s4:$addr))]>, 439201360Srdivacky T1LdSt<0b100>; 440204642Srdivackydef tLDRi: T1pI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr), IIC_iLoadr, 441202375Srdivacky "ldr", "\t$dst, $addr", 442202375Srdivacky []>, 443202375Srdivacky T1LdSt4Imm<{1,?,?}>; 444193323Sed 445198090Srdivackydef tLDRB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr), IIC_iLoadr, 446198892Srdivacky "ldrb", "\t$dst, $addr", 447201360Srdivacky [(set tGPR:$dst, (zextloadi8 t_addrmode_s1:$addr))]>, 448201360Srdivacky T1LdSt<0b110>; 449202375Srdivackydef tLDRBi: T1pI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr), IIC_iLoadr, 450202375Srdivacky "ldrb", "\t$dst, $addr", 451202375Srdivacky []>, 452202375Srdivacky T1LdSt1Imm<{1,?,?}>; 453193323Sed 454198090Srdivackydef tLDRH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr), IIC_iLoadr, 455198892Srdivacky "ldrh", "\t$dst, $addr", 456201360Srdivacky [(set tGPR:$dst, (zextloadi16 t_addrmode_s2:$addr))]>, 457201360Srdivacky T1LdSt<0b101>; 458202375Srdivackydef tLDRHi: T1pI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr), IIC_iLoadr, 459202375Srdivacky "ldrh", "\t$dst, $addr", 460202375Srdivacky []>, 461202375Srdivacky T1LdSt2Imm<{1,?,?}>; 462193323Sed 463198090Srdivackylet AddedComplexity = 10 in 464198090Srdivackydef tLDRSB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), IIC_iLoadr, 465198892Srdivacky "ldrsb", "\t$dst, $addr", 466201360Srdivacky [(set tGPR:$dst, (sextloadi8 t_addrmode_rr:$addr))]>, 467201360Srdivacky T1LdSt<0b011>; 468193323Sed 469198090Srdivackylet AddedComplexity = 10 in 470198090Srdivackydef tLDRSH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), IIC_iLoadr, 471198892Srdivacky "ldrsh", "\t$dst, $addr", 472201360Srdivacky [(set tGPR:$dst, (sextloadi16 t_addrmode_rr:$addr))]>, 473201360Srdivacky T1LdSt<0b111>; 474193323Sed 475193323Sedlet canFoldAsLoad = 1 in 476198090Srdivackydef tLDRspi : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), IIC_iLoadi, 477198892Srdivacky "ldr", "\t$dst, $addr", 478201360Srdivacky [(set tGPR:$dst, (load t_addrmode_sp:$addr))]>, 479201360Srdivacky T1LdStSP<{1,?,?}>; 480193323Sed 481193323Sed// Special instruction for restore. It cannot clobber condition register 482193323Sed// when it's expanded by eliminateCallFramePseudoInstr(). 483208599Srdivackylet canFoldAsLoad = 1, mayLoad = 1, neverHasSideEffects = 1 in 484198090Srdivackydef tRestore : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), IIC_iLoadi, 485201360Srdivacky "ldr", "\t$dst, $addr", []>, 486201360Srdivacky T1LdStSP<{1,?,?}>; 487193323Sed 488193323Sed// Load tconstpool 489198892Srdivacky// FIXME: Use ldr.n to work around a Darwin assembler bug. 490204642Srdivackylet canFoldAsLoad = 1, isReMaterializable = 1 in 491198090Srdivackydef tLDRpci : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr), IIC_iLoadi, 492198892Srdivacky "ldr", ".n\t$dst, $addr", 493201360Srdivacky [(set tGPR:$dst, (load (ARMWrapper tconstpool:$addr)))]>, 494201360Srdivacky T1Encoding<{0,1,0,0,1,?}>; // A6.2 & A8.6.59 495193323Sed 496193323Sed// Special LDR for loads from non-pc-relative constpools. 497208599Srdivackylet canFoldAsLoad = 1, mayLoad = 1, neverHasSideEffects = 1, 498208599Srdivacky isReMaterializable = 1 in 499198090Srdivackydef tLDRcp : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr), IIC_iLoadi, 500201360Srdivacky "ldr", "\t$dst, $addr", []>, 501201360Srdivacky T1LdStSP<{1,?,?}>; 502193323Sed 503198090Srdivackydef tSTR : T1pI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr), IIC_iStorer, 504198892Srdivacky "str", "\t$src, $addr", 505201360Srdivacky [(store tGPR:$src, t_addrmode_s4:$addr)]>, 506201360Srdivacky T1LdSt<0b000>; 507202375Srdivackydef tSTRi: T1pI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr), IIC_iStorer, 508202375Srdivacky "str", "\t$src, $addr", 509202375Srdivacky []>, 510202375Srdivacky T1LdSt4Imm<{0,?,?}>; 511193323Sed 512198090Srdivackydef tSTRB : T1pI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr), IIC_iStorer, 513198892Srdivacky "strb", "\t$src, $addr", 514201360Srdivacky [(truncstorei8 tGPR:$src, t_addrmode_s1:$addr)]>, 515201360Srdivacky T1LdSt<0b010>; 516202375Srdivackydef tSTRBi: T1pI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr), IIC_iStorer, 517202375Srdivacky "strb", "\t$src, $addr", 518202375Srdivacky []>, 519202375Srdivacky T1LdSt1Imm<{0,?,?}>; 520193323Sed 521198090Srdivackydef tSTRH : T1pI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr), IIC_iStorer, 522198892Srdivacky "strh", "\t$src, $addr", 523201360Srdivacky [(truncstorei16 tGPR:$src, t_addrmode_s2:$addr)]>, 524201360Srdivacky T1LdSt<0b001>; 525202375Srdivackydef tSTRHi: T1pI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr), IIC_iStorer, 526202375Srdivacky "strh", "\t$src, $addr", 527202375Srdivacky []>, 528202375Srdivacky T1LdSt2Imm<{0,?,?}>; 529193323Sed 530198090Srdivackydef tSTRspi : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStorei, 531198892Srdivacky "str", "\t$src, $addr", 532201360Srdivacky [(store tGPR:$src, t_addrmode_sp:$addr)]>, 533201360Srdivacky T1LdStSP<{0,?,?}>; 534193323Sed 535208599Srdivackylet mayStore = 1, neverHasSideEffects = 1 in { 536193323Sed// Special instruction for spill. It cannot clobber condition register 537193323Sed// when it's expanded by eliminateCallFramePseudoInstr(). 538198090Srdivackydef tSpill : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStorei, 539201360Srdivacky "str", "\t$src, $addr", []>, 540201360Srdivacky T1LdStSP<{0,?,?}>; 541193323Sed} 542193323Sed 543193323Sed//===----------------------------------------------------------------------===// 544193323Sed// Load / store multiple Instructions. 545193323Sed// 546193323Sed 547198090Srdivacky// These requires base address to be written back or one of the loaded regs. 548208599Srdivackylet mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1 in { 549198090Srdivackydef tLDM : T1I<(outs), 550205218Srdivacky (ins addrmode4:$addr, pred:$p, reglist:$dsts, variable_ops), 551198090Srdivacky IIC_iLoadm, 552205218Srdivacky "ldm${addr:submode}${p}\t$addr, $dsts", []>, 553201360Srdivacky T1Encoding<{1,1,0,0,1,?}>; // A6.2 & A8.6.53 554193323Sed 555205218Srdivackydef tLDM_UPD : T1It<(outs tGPR:$wb), 556205218Srdivacky (ins addrmode4:$addr, pred:$p, reglist:$dsts, variable_ops), 557205218Srdivacky IIC_iLoadm, 558205407Srdivacky "ldm${addr:submode}${p}\t$addr!, $dsts", 559205218Srdivacky "$addr.addr = $wb", []>, 560205218Srdivacky T1Encoding<{1,1,0,0,1,?}>; // A6.2 & A8.6.53 561208599Srdivacky} // mayLoad, neverHasSideEffects = 1, hasExtraDefRegAllocReq 562205218Srdivacky 563208599Srdivackylet mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in 564205218Srdivackydef tSTM_UPD : T1It<(outs tGPR:$wb), 565205218Srdivacky (ins addrmode4:$addr, pred:$p, reglist:$srcs, variable_ops), 566205218Srdivacky IIC_iStorem, 567205407Srdivacky "stm${addr:submode}${p}\t$addr!, $srcs", 568205218Srdivacky "$addr.addr = $wb", []>, 569201360Srdivacky T1Encoding<{1,1,0,0,0,?}>; // A6.2 & A8.6.189 570193323Sed 571198090Srdivackylet mayLoad = 1, Uses = [SP], Defs = [SP], hasExtraDefRegAllocReq = 1 in 572205218Srdivackydef tPOP : T1I<(outs), (ins pred:$p, reglist:$dsts, variable_ops), IIC_Br, 573205218Srdivacky "pop${p}\t$dsts", []>, 574201360Srdivacky T1Misc<{1,1,0,?,?,?,?}>; 575193323Sed 576198090Srdivackylet mayStore = 1, Uses = [SP], Defs = [SP], hasExtraSrcRegAllocReq = 1 in 577205218Srdivackydef tPUSH : T1I<(outs), (ins pred:$p, reglist:$srcs, variable_ops), IIC_Br, 578205218Srdivacky "push${p}\t$srcs", []>, 579201360Srdivacky T1Misc<{0,1,0,?,?,?,?}>; 580198090Srdivacky 581193323Sed//===----------------------------------------------------------------------===// 582193323Sed// Arithmetic Instructions. 583193323Sed// 584193323Sed 585195098Sed// Add with carry register 586198090Srdivackylet isCommutable = 1, Uses = [CPSR] in 587198090Srdivackydef tADC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 588198892Srdivacky "adc", "\t$dst, $rhs", 589201360Srdivacky [(set tGPR:$dst, (adde tGPR:$lhs, tGPR:$rhs))]>, 590201360Srdivacky T1DataProcessing<0b0101>; 591193323Sed 592195098Sed// Add immediate 593198090Srdivackydef tADDi3 : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi, 594198892Srdivacky "add", "\t$dst, $lhs, $rhs", 595201360Srdivacky [(set tGPR:$dst, (add tGPR:$lhs, imm0_7:$rhs))]>, 596201360Srdivacky T1General<0b01110>; 597193323Sed 598198090Srdivackydef tADDi8 : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi, 599198892Srdivacky "add", "\t$dst, $rhs", 600201360Srdivacky [(set tGPR:$dst, (add tGPR:$lhs, imm8_255:$rhs))]>, 601201360Srdivacky T1General<{1,1,0,?,?}>; 602193323Sed 603195098Sed// Add register 604198090Srdivackylet isCommutable = 1 in 605198090Srdivackydef tADDrr : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 606198892Srdivacky "add", "\t$dst, $lhs, $rhs", 607201360Srdivacky [(set tGPR:$dst, (add tGPR:$lhs, tGPR:$rhs))]>, 608201360Srdivacky T1General<0b01100>; 609193323Sed 610194178Sedlet neverHasSideEffects = 1 in 611198090Srdivackydef tADDhirr : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, 612201360Srdivacky "add", "\t$dst, $rhs", []>, 613201360Srdivacky T1Special<{0,0,?,?}>; 614193323Sed 615195098Sed// And register 616198090Srdivackylet isCommutable = 1 in 617198090Srdivackydef tAND : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 618198892Srdivacky "and", "\t$dst, $rhs", 619201360Srdivacky [(set tGPR:$dst, (and tGPR:$lhs, tGPR:$rhs))]>, 620201360Srdivacky T1DataProcessing<0b0000>; 621193323Sed 622195098Sed// ASR immediate 623198090Srdivackydef tASRri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iMOVsi, 624198892Srdivacky "asr", "\t$dst, $lhs, $rhs", 625201360Srdivacky [(set tGPR:$dst, (sra tGPR:$lhs, (i32 imm:$rhs)))]>, 626201360Srdivacky T1General<{0,1,0,?,?}>; 627193323Sed 628195098Sed// ASR register 629198090Srdivackydef tASRrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, 630198892Srdivacky "asr", "\t$dst, $rhs", 631201360Srdivacky [(set tGPR:$dst, (sra tGPR:$lhs, tGPR:$rhs))]>, 632201360Srdivacky T1DataProcessing<0b0100>; 633193323Sed 634195098Sed// BIC register 635198090Srdivackydef tBIC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 636198892Srdivacky "bic", "\t$dst, $rhs", 637201360Srdivacky [(set tGPR:$dst, (and tGPR:$lhs, (not tGPR:$rhs)))]>, 638201360Srdivacky T1DataProcessing<0b1110>; 639193323Sed 640195098Sed// CMN register 641195098Sedlet Defs = [CPSR] in { 642202878Srdivacky//FIXME: Disable CMN, as CCodes are backwards from compare expectations 643202878Srdivacky// Compare-to-zero still works out, just not the relationals 644202878Srdivacky//def tCMN : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, 645202878Srdivacky// "cmn", "\t$lhs, $rhs", 646202878Srdivacky// [(ARMcmp tGPR:$lhs, (ineg tGPR:$rhs))]>, 647202878Srdivacky// T1DataProcessing<0b1011>; 648201360Srdivackydef tCMNz : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, 649198892Srdivacky "cmn", "\t$lhs, $rhs", 650201360Srdivacky [(ARMcmpZ tGPR:$lhs, (ineg tGPR:$rhs))]>, 651201360Srdivacky T1DataProcessing<0b1011>; 652195098Sed} 653193323Sed 654195098Sed// CMP immediate 655195098Sedlet Defs = [CPSR] in { 656198090Srdivackydef tCMPi8 : T1pI<(outs), (ins tGPR:$lhs, i32imm:$rhs), IIC_iCMPi, 657198892Srdivacky "cmp", "\t$lhs, $rhs", 658201360Srdivacky [(ARMcmp tGPR:$lhs, imm0_255:$rhs)]>, 659201360Srdivacky T1General<{1,0,1,?,?}>; 660198090Srdivackydef tCMPzi8 : T1pI<(outs), (ins tGPR:$lhs, i32imm:$rhs), IIC_iCMPi, 661198892Srdivacky "cmp", "\t$lhs, $rhs", 662201360Srdivacky [(ARMcmpZ tGPR:$lhs, imm0_255:$rhs)]>, 663201360Srdivacky T1General<{1,0,1,?,?}>; 664195098Sed} 665195098Sed 666195098Sed// CMP register 667195098Sedlet Defs = [CPSR] in { 668198090Srdivackydef tCMPr : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, 669198892Srdivacky "cmp", "\t$lhs, $rhs", 670201360Srdivacky [(ARMcmp tGPR:$lhs, tGPR:$rhs)]>, 671201360Srdivacky T1DataProcessing<0b1010>; 672198090Srdivackydef tCMPzr : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, 673198892Srdivacky "cmp", "\t$lhs, $rhs", 674201360Srdivacky [(ARMcmpZ tGPR:$lhs, tGPR:$rhs)]>, 675201360Srdivacky T1DataProcessing<0b1010>; 676198090Srdivacky 677198090Srdivackydef tCMPhir : T1pI<(outs), (ins GPR:$lhs, GPR:$rhs), IIC_iCMPr, 678201360Srdivacky "cmp", "\t$lhs, $rhs", []>, 679201360Srdivacky T1Special<{0,1,?,?}>; 680198090Srdivackydef tCMPzhir : T1pI<(outs), (ins GPR:$lhs, GPR:$rhs), IIC_iCMPr, 681201360Srdivacky "cmp", "\t$lhs, $rhs", []>, 682201360Srdivacky T1Special<{0,1,?,?}>; 683195098Sed} 684193323Sed 685193323Sed 686195098Sed// XOR register 687198090Srdivackylet isCommutable = 1 in 688198090Srdivackydef tEOR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 689198892Srdivacky "eor", "\t$dst, $rhs", 690201360Srdivacky [(set tGPR:$dst, (xor tGPR:$lhs, tGPR:$rhs))]>, 691201360Srdivacky T1DataProcessing<0b0001>; 692193323Sed 693195098Sed// LSL immediate 694198090Srdivackydef tLSLri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iMOVsi, 695198892Srdivacky "lsl", "\t$dst, $lhs, $rhs", 696201360Srdivacky [(set tGPR:$dst, (shl tGPR:$lhs, (i32 imm:$rhs)))]>, 697201360Srdivacky T1General<{0,0,0,?,?}>; 698193323Sed 699195098Sed// LSL register 700198090Srdivackydef tLSLrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, 701198892Srdivacky "lsl", "\t$dst, $rhs", 702201360Srdivacky [(set tGPR:$dst, (shl tGPR:$lhs, tGPR:$rhs))]>, 703201360Srdivacky T1DataProcessing<0b0010>; 704193323Sed 705195098Sed// LSR immediate 706198090Srdivackydef tLSRri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iMOVsi, 707198892Srdivacky "lsr", "\t$dst, $lhs, $rhs", 708201360Srdivacky [(set tGPR:$dst, (srl tGPR:$lhs, (i32 imm:$rhs)))]>, 709201360Srdivacky T1General<{0,0,1,?,?}>; 710193323Sed 711195098Sed// LSR register 712198090Srdivackydef tLSRrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, 713198892Srdivacky "lsr", "\t$dst, $rhs", 714201360Srdivacky [(set tGPR:$dst, (srl tGPR:$lhs, tGPR:$rhs))]>, 715201360Srdivacky T1DataProcessing<0b0011>; 716193323Sed 717195098Sed// move register 718198090Srdivackydef tMOVi8 : T1sI<(outs tGPR:$dst), (ins i32imm:$src), IIC_iMOVi, 719198892Srdivacky "mov", "\t$dst, $src", 720201360Srdivacky [(set tGPR:$dst, imm0_255:$src)]>, 721201360Srdivacky T1General<{1,0,0,?,?}>; 722193323Sed 723193323Sed// TODO: A7-73: MOV(2) - mov setting flag. 724193323Sed 725193323Sed 726194178Sedlet neverHasSideEffects = 1 in { 727198090Srdivacky// FIXME: Make this predicable. 728198090Srdivackydef tMOVr : T1I<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr, 729201360Srdivacky "mov\t$dst, $src", []>, 730201360Srdivacky T1Special<0b1000>; 731198090Srdivackylet Defs = [CPSR] in 732198090Srdivackydef tMOVSr : T1I<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr, 733201360Srdivacky "movs\t$dst, $src", []>, Encoding16 { 734201360Srdivacky let Inst{15-6} = 0b0000000000; 735201360Srdivacky} 736198090Srdivacky 737198090Srdivacky// FIXME: Make these predicable. 738198090Srdivackydef tMOVgpr2tgpr : T1I<(outs tGPR:$dst), (ins GPR:$src), IIC_iMOVr, 739201360Srdivacky "mov\t$dst, $src", []>, 740202878Srdivacky T1Special<{1,0,0,?}>; 741198090Srdivackydef tMOVtgpr2gpr : T1I<(outs GPR:$dst), (ins tGPR:$src), IIC_iMOVr, 742201360Srdivacky "mov\t$dst, $src", []>, 743202878Srdivacky T1Special<{1,0,?,0}>; 744198090Srdivackydef tMOVgpr2gpr : T1I<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVr, 745201360Srdivacky "mov\t$dst, $src", []>, 746202878Srdivacky T1Special<{1,0,?,?}>; 747194178Sed} // neverHasSideEffects 748193323Sed 749195098Sed// multiply register 750198090Srdivackylet isCommutable = 1 in 751198090Srdivackydef tMUL : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMUL32, 752204792Srdivacky "mul", "\t$dst, $rhs, $dst", /* A8.6.105 MUL Encoding T1 */ 753201360Srdivacky [(set tGPR:$dst, (mul tGPR:$lhs, tGPR:$rhs))]>, 754201360Srdivacky T1DataProcessing<0b1101>; 755193323Sed 756195098Sed// move inverse register 757198090Srdivackydef tMVN : T1sI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr, 758198892Srdivacky "mvn", "\t$dst, $src", 759201360Srdivacky [(set tGPR:$dst, (not tGPR:$src))]>, 760201360Srdivacky T1DataProcessing<0b1111>; 761193323Sed 762195098Sed// bitwise or register 763198090Srdivackylet isCommutable = 1 in 764198090Srdivackydef tORR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 765198892Srdivacky "orr", "\t$dst, $rhs", 766201360Srdivacky [(set tGPR:$dst, (or tGPR:$lhs, tGPR:$rhs))]>, 767201360Srdivacky T1DataProcessing<0b1100>; 768193323Sed 769195098Sed// swaps 770198090Srdivackydef tREV : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 771198892Srdivacky "rev", "\t$dst, $src", 772198090Srdivacky [(set tGPR:$dst, (bswap tGPR:$src))]>, 773201360Srdivacky Requires<[IsThumb1Only, HasV6]>, 774201360Srdivacky T1Misc<{1,0,1,0,0,0,?}>; 775193323Sed 776198090Srdivackydef tREV16 : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 777198892Srdivacky "rev16", "\t$dst, $src", 778198090Srdivacky [(set tGPR:$dst, 779198090Srdivacky (or (and (srl tGPR:$src, (i32 8)), 0xFF), 780198090Srdivacky (or (and (shl tGPR:$src, (i32 8)), 0xFF00), 781198090Srdivacky (or (and (srl tGPR:$src, (i32 8)), 0xFF0000), 782198090Srdivacky (and (shl tGPR:$src, (i32 8)), 0xFF000000)))))]>, 783201360Srdivacky Requires<[IsThumb1Only, HasV6]>, 784201360Srdivacky T1Misc<{1,0,1,0,0,1,?}>; 785193323Sed 786198090Srdivackydef tREVSH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 787198892Srdivacky "revsh", "\t$dst, $src", 788198090Srdivacky [(set tGPR:$dst, 789198090Srdivacky (sext_inreg 790198090Srdivacky (or (srl (and tGPR:$src, 0xFF00), (i32 8)), 791198090Srdivacky (shl tGPR:$src, (i32 8))), i16))]>, 792201360Srdivacky Requires<[IsThumb1Only, HasV6]>, 793201360Srdivacky T1Misc<{1,0,1,0,1,1,?}>; 794193323Sed 795195098Sed// rotate right register 796198090Srdivackydef tROR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, 797198892Srdivacky "ror", "\t$dst, $rhs", 798201360Srdivacky [(set tGPR:$dst, (rotr tGPR:$lhs, tGPR:$rhs))]>, 799201360Srdivacky T1DataProcessing<0b0111>; 800193323Sed 801198090Srdivacky// negate register 802198090Srdivackydef tRSB : T1sI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iALUi, 803198892Srdivacky "rsb", "\t$dst, $src, #0", 804201360Srdivacky [(set tGPR:$dst, (ineg tGPR:$src))]>, 805201360Srdivacky T1DataProcessing<0b1001>; 806198090Srdivacky 807195098Sed// Subtract with carry register 808198090Srdivackylet Uses = [CPSR] in 809198090Srdivackydef tSBC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 810198892Srdivacky "sbc", "\t$dst, $rhs", 811201360Srdivacky [(set tGPR:$dst, (sube tGPR:$lhs, tGPR:$rhs))]>, 812201360Srdivacky T1DataProcessing<0b0110>; 813193323Sed 814195098Sed// Subtract immediate 815198090Srdivackydef tSUBi3 : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi, 816198892Srdivacky "sub", "\t$dst, $lhs, $rhs", 817201360Srdivacky [(set tGPR:$dst, (add tGPR:$lhs, imm0_7_neg:$rhs))]>, 818201360Srdivacky T1General<0b01111>; 819193323Sed 820198090Srdivackydef tSUBi8 : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi, 821198892Srdivacky "sub", "\t$dst, $rhs", 822201360Srdivacky [(set tGPR:$dst, (add tGPR:$lhs, imm8_255_neg:$rhs))]>, 823201360Srdivacky T1General<{1,1,1,?,?}>; 824193323Sed 825195098Sed// subtract register 826198090Srdivackydef tSUBrr : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, 827198892Srdivacky "sub", "\t$dst, $lhs, $rhs", 828201360Srdivacky [(set tGPR:$dst, (sub tGPR:$lhs, tGPR:$rhs))]>, 829201360Srdivacky T1General<0b01101>; 830193323Sed 831195098Sed// TODO: A7-96: STMIA - store multiple. 832195098Sed 833195098Sed// sign-extend byte 834198090Srdivackydef tSXTB : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 835198892Srdivacky "sxtb", "\t$dst, $src", 836198090Srdivacky [(set tGPR:$dst, (sext_inreg tGPR:$src, i8))]>, 837201360Srdivacky Requires<[IsThumb1Only, HasV6]>, 838201360Srdivacky T1Misc<{0,0,1,0,0,1,?}>; 839195098Sed 840195098Sed// sign-extend short 841198090Srdivackydef tSXTH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 842198892Srdivacky "sxth", "\t$dst, $src", 843198090Srdivacky [(set tGPR:$dst, (sext_inreg tGPR:$src, i16))]>, 844201360Srdivacky Requires<[IsThumb1Only, HasV6]>, 845201360Srdivacky T1Misc<{0,0,1,0,0,0,?}>; 846193323Sed 847195098Sed// test 848195098Sedlet isCommutable = 1, Defs = [CPSR] in 849198090Srdivackydef tTST : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, 850198892Srdivacky "tst", "\t$lhs, $rhs", 851201360Srdivacky [(ARMcmpZ (and tGPR:$lhs, tGPR:$rhs), 0)]>, 852201360Srdivacky T1DataProcessing<0b1000>; 853193323Sed 854195098Sed// zero-extend byte 855198090Srdivackydef tUXTB : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 856198892Srdivacky "uxtb", "\t$dst, $src", 857198090Srdivacky [(set tGPR:$dst, (and tGPR:$src, 0xFF))]>, 858201360Srdivacky Requires<[IsThumb1Only, HasV6]>, 859201360Srdivacky T1Misc<{0,0,1,0,1,1,?}>; 860195098Sed 861195098Sed// zero-extend short 862198090Srdivackydef tUXTH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, 863198892Srdivacky "uxth", "\t$dst, $src", 864198090Srdivacky [(set tGPR:$dst, (and tGPR:$src, 0xFFFF))]>, 865201360Srdivacky Requires<[IsThumb1Only, HasV6]>, 866201360Srdivacky T1Misc<{0,0,1,0,1,0,?}>; 867193323Sed 868193323Sed 869204642Srdivacky// Conditional move tMOVCCr - Used to implement the Thumb SELECT_CC operation. 870198892Srdivacky// Expanded after instruction selection into a branch sequence. 871198892Srdivackylet usesCustomInserter = 1 in // Expanded after instruction selection. 872198090Srdivacky def tMOVCCr_pseudo : 873193323Sed PseudoInst<(outs tGPR:$dst), (ins tGPR:$false, tGPR:$true, pred:$cc), 874208599Srdivacky NoItinerary, "${:comment} tMOVCCr $cc", 875198090Srdivacky [/*(set tGPR:$dst, (ARMcmov tGPR:$false, tGPR:$true, imm:$cc))*/]>; 876193323Sed 877198090Srdivacky 878198090Srdivacky// 16-bit movcc in IT blocks for Thumb2. 879208599Srdivackylet neverHasSideEffects = 1 in { 880198090Srdivackydef tMOVCCr : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iCMOVr, 881201360Srdivacky "mov", "\t$dst, $rhs", []>, 882202878Srdivacky T1Special<{1,0,?,?}>; 883198090Srdivacky 884203954Srdivackydef tMOVCCi : T1pIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iCMOVi, 885201360Srdivacky "mov", "\t$dst, $rhs", []>, 886201360Srdivacky T1General<{1,0,0,?,?}>; 887208599Srdivacky} // neverHasSideEffects 888198090Srdivacky 889193323Sed// tLEApcrel - Load a pc-relative address into a register without offending the 890193323Sed// assembler. 891208599Srdivackylet neverHasSideEffects = 1 in { 892208599Srdivackylet isReMaterializable = 1 in 893198090Srdivackydef tLEApcrel : T1I<(outs tGPR:$dst), (ins i32imm:$label, pred:$p), IIC_iALUi, 894201360Srdivacky "adr$p\t$dst, #$label", []>, 895201360Srdivacky T1Encoding<{1,0,1,0,0,?}>; // A6.2 & A8.6.10 896193323Sed 897198090Srdivackydef tLEApcrelJT : T1I<(outs tGPR:$dst), 898198090Srdivacky (ins i32imm:$label, nohash_imm:$id, pred:$p), 899201360Srdivacky IIC_iALUi, "adr$p\t$dst, #${label}_${id}", []>, 900201360Srdivacky T1Encoding<{1,0,1,0,0,?}>; // A6.2 & A8.6.10 901208599Srdivacky} // neverHasSideEffects 902193323Sed 903193323Sed//===----------------------------------------------------------------------===// 904193323Sed// TLS Instructions 905193323Sed// 906193323Sed 907193323Sed// __aeabi_read_tp preserves the registers r1-r3. 908193323Sedlet isCall = 1, 909193323Sed Defs = [R0, LR] in { 910201360Srdivacky def tTPsoft : TIx2<0b11110, 0b11, 1, (outs), (ins), IIC_Br, 911201360Srdivacky "bl\t__aeabi_read_tp", 912201360Srdivacky [(set R0, ARMthread_pointer)]>; 913193323Sed} 914193323Sed 915200581Srdivacky// SJLJ Exception handling intrinsics 916200581Srdivacky// eh_sjlj_setjmp() is an instruction sequence to store the return 917200581Srdivacky// address and save #0 in R0 for the non-longjmp case. 918200581Srdivacky// Since by its nature we may be coming from some other function to get 919200581Srdivacky// here, and we're using the stack frame for the containing function to 920200581Srdivacky// save/restore registers, we can't keep anything live in regs across 921200581Srdivacky// the eh_sjlj_setjmp(), else it will almost certainly have been tromped upon 922200581Srdivacky// when we get here from a longjmp(). We force everthing out of registers 923200581Srdivacky// except for our own input by listing the relevant registers in Defs. By 924200581Srdivacky// doing so, we also cause the prologue/epilogue code to actively preserve 925200581Srdivacky// all of the callee-saved resgisters, which is exactly what we want. 926203954Srdivacky// The current SP is passed in $val, and we reuse the reg as a scratch. 927200581Srdivackylet Defs = 928200581Srdivacky [ R0, R1, R2, R3, R4, R5, R6, R7, R12 ] in { 929203954Srdivacky def tInt_eh_sjlj_setjmp : ThumbXI<(outs),(ins tGPR:$src, tGPR:$val), 930200581Srdivacky AddrModeNone, SizeSpecial, NoItinerary, 931208599Srdivacky "str\t$val, [$src, #8]\t${:comment} begin eh.setjmp\n" 932203954Srdivacky "\tmov\t$val, pc\n" 933208599Srdivacky "\tadds\t$val, #7\n" 934203954Srdivacky "\tstr\t$val, [$src, #4]\n" 935200581Srdivacky "\tmovs\tr0, #0\n" 936200581Srdivacky "\tb\t1f\n" 937208599Srdivacky "\tmovs\tr0, #1\t${:comment} end eh.setjmp\n" 938200581Srdivacky "1:", "", 939203954Srdivacky [(set R0, (ARMeh_sjlj_setjmp tGPR:$src, tGPR:$val))]>; 940200581Srdivacky} 941208599Srdivacky 942208599Srdivacky// FIXME: Non-Darwin version(s) 943208599Srdivackylet isBarrier = 1, hasSideEffects = 1, isTerminator = 1, 944208599Srdivacky Defs = [ R7, LR, SP ] in { 945208599Srdivackydef tInt_eh_sjlj_longjmp : XI<(outs), (ins GPR:$src, GPR:$scratch), 946208599Srdivacky AddrModeNone, SizeSpecial, IndexModeNone, 947208599Srdivacky Pseudo, NoItinerary, 948208599Srdivacky "ldr\t$scratch, [$src, #8]\n\t" 949208599Srdivacky "mov\tsp, $scratch\n\t" 950208599Srdivacky "ldr\t$scratch, [$src, #4]\n\t" 951208599Srdivacky "ldr\tr7, [$src]\n\t" 952208599Srdivacky "bx\t$scratch", "", 953208599Srdivacky [(ARMeh_sjlj_longjmp GPR:$src, GPR:$scratch)]>, 954208599Srdivacky Requires<[IsThumb, IsDarwin]>; 955208599Srdivacky} 956208599Srdivacky 957193323Sed//===----------------------------------------------------------------------===// 958193323Sed// Non-Instruction Patterns 959193323Sed// 960193323Sed 961198090Srdivacky// Add with carry 962198090Srdivackydef : T1Pat<(addc tGPR:$lhs, imm0_7:$rhs), 963198090Srdivacky (tADDi3 tGPR:$lhs, imm0_7:$rhs)>; 964198090Srdivackydef : T1Pat<(addc tGPR:$lhs, imm8_255:$rhs), 965198090Srdivacky (tADDi8 tGPR:$lhs, imm8_255:$rhs)>; 966198090Srdivackydef : T1Pat<(addc tGPR:$lhs, tGPR:$rhs), 967198090Srdivacky (tADDrr tGPR:$lhs, tGPR:$rhs)>; 968198090Srdivacky 969198090Srdivacky// Subtract with carry 970198090Srdivackydef : T1Pat<(addc tGPR:$lhs, imm0_7_neg:$rhs), 971198090Srdivacky (tSUBi3 tGPR:$lhs, imm0_7_neg:$rhs)>; 972198090Srdivackydef : T1Pat<(addc tGPR:$lhs, imm8_255_neg:$rhs), 973198090Srdivacky (tSUBi8 tGPR:$lhs, imm8_255_neg:$rhs)>; 974198090Srdivackydef : T1Pat<(subc tGPR:$lhs, tGPR:$rhs), 975198090Srdivacky (tSUBrr tGPR:$lhs, tGPR:$rhs)>; 976198090Srdivacky 977193323Sed// ConstantPool, GlobalAddress 978198090Srdivackydef : T1Pat<(ARMWrapper tglobaladdr :$dst), (tLEApcrel tglobaladdr :$dst)>; 979198090Srdivackydef : T1Pat<(ARMWrapper tconstpool :$dst), (tLEApcrel tconstpool :$dst)>; 980193323Sed 981193323Sed// JumpTable 982198090Srdivackydef : T1Pat<(ARMWrapperJT tjumptable:$dst, imm:$id), 983198090Srdivacky (tLEApcrelJT tjumptable:$dst, imm:$id)>; 984193323Sed 985193323Sed// Direct calls 986198090Srdivackydef : T1Pat<(ARMtcall texternalsym:$func), (tBL texternalsym:$func)>, 987198090Srdivacky Requires<[IsThumb, IsNotDarwin]>; 988198090Srdivackydef : T1Pat<(ARMtcall texternalsym:$func), (tBLr9 texternalsym:$func)>, 989198090Srdivacky Requires<[IsThumb, IsDarwin]>; 990193323Sed 991198090Srdivackydef : Tv5Pat<(ARMcall texternalsym:$func), (tBLXi texternalsym:$func)>, 992198090Srdivacky Requires<[IsThumb, HasV5T, IsNotDarwin]>; 993198090Srdivackydef : Tv5Pat<(ARMcall texternalsym:$func), (tBLXi_r9 texternalsym:$func)>, 994198090Srdivacky Requires<[IsThumb, HasV5T, IsDarwin]>; 995198090Srdivacky 996193323Sed// Indirect calls to ARM routines 997198090Srdivackydef : Tv5Pat<(ARMcall GPR:$dst), (tBLXr GPR:$dst)>, 998198090Srdivacky Requires<[IsThumb, HasV5T, IsNotDarwin]>; 999198090Srdivackydef : Tv5Pat<(ARMcall GPR:$dst), (tBLXr_r9 GPR:$dst)>, 1000198090Srdivacky Requires<[IsThumb, HasV5T, IsDarwin]>; 1001193323Sed 1002193323Sed// zextload i1 -> zextload i8 1003195340Seddef : T1Pat<(zextloadi1 t_addrmode_s1:$addr), 1004195340Sed (tLDRB t_addrmode_s1:$addr)>; 1005193323Sed 1006193323Sed// extload -> zextload 1007195340Seddef : T1Pat<(extloadi1 t_addrmode_s1:$addr), (tLDRB t_addrmode_s1:$addr)>; 1008195340Seddef : T1Pat<(extloadi8 t_addrmode_s1:$addr), (tLDRB t_addrmode_s1:$addr)>; 1009195340Seddef : T1Pat<(extloadi16 t_addrmode_s2:$addr), (tLDRH t_addrmode_s2:$addr)>; 1010193323Sed 1011198090Srdivacky// If it's impossible to use [r,r] address mode for sextload, select to 1012198090Srdivacky// ldr{b|h} + sxt{b|h} instead. 1013198090Srdivackydef : T1Pat<(sextloadi8 t_addrmode_s1:$addr), 1014198090Srdivacky (tSXTB (tLDRB t_addrmode_s1:$addr))>, 1015198090Srdivacky Requires<[IsThumb1Only, HasV6]>; 1016198090Srdivackydef : T1Pat<(sextloadi16 t_addrmode_s2:$addr), 1017198090Srdivacky (tSXTH (tLDRH t_addrmode_s2:$addr))>, 1018198090Srdivacky Requires<[IsThumb1Only, HasV6]>; 1019198090Srdivacky 1020198090Srdivackydef : T1Pat<(sextloadi8 t_addrmode_s1:$addr), 1021198090Srdivacky (tASRri (tLSLri (tLDRB t_addrmode_s1:$addr), 24), 24)>; 1022198090Srdivackydef : T1Pat<(sextloadi16 t_addrmode_s1:$addr), 1023198090Srdivacky (tASRri (tLSLri (tLDRH t_addrmode_s1:$addr), 16), 16)>; 1024198090Srdivacky 1025193323Sed// Large immediate handling. 1026193323Sed 1027193323Sed// Two piece imms. 1028195098Seddef : T1Pat<(i32 thumb_immshifted:$src), 1029195098Sed (tLSLri (tMOVi8 (thumb_immshifted_val imm:$src)), 1030195098Sed (thumb_immshifted_shamt imm:$src))>; 1031193323Sed 1032195098Seddef : T1Pat<(i32 imm0_255_comp:$src), 1033195098Sed (tMVN (tMOVi8 (imm_comp_XFORM imm:$src)))>; 1034199481Srdivacky 1035199481Srdivacky// Pseudo instruction that combines ldr from constpool and add pc. This should 1036199481Srdivacky// be expanded into two instructions late to allow if-conversion and 1037199481Srdivacky// scheduling. 1038199481Srdivackylet isReMaterializable = 1 in 1039199481Srdivackydef tLDRpci_pic : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr, pclabel:$cp), 1040208599Srdivacky NoItinerary, "${:comment} ldr.n\t$dst, $addr\n$cp:\n\tadd\t$dst, pc", 1041199481Srdivacky [(set GPR:$dst, (ARMpic_add (load (ARMWrapper tconstpool:$addr)), 1042199481Srdivacky imm:$cp))]>, 1043199481Srdivacky Requires<[IsThumb1Only]>; 1044