106f32e7eSjoerg//===--- HexagonPseudo.td -------------------------------------------------===// 206f32e7eSjoerg// 306f32e7eSjoerg// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 406f32e7eSjoerg// See https://llvm.org/LICENSE.txt for license information. 506f32e7eSjoerg// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 606f32e7eSjoerg// 706f32e7eSjoerg//===----------------------------------------------------------------------===// 806f32e7eSjoerg 906f32e7eSjoerg// The pat frags in the definitions below need to have a named register, 1006f32e7eSjoerg// otherwise i32 will be assumed regardless of the register class. The 1106f32e7eSjoerg// name of the register does not matter. 1206f32e7eSjoergdef I1 : PatLeaf<(i1 PredRegs:$R)>; 1306f32e7eSjoergdef I32 : PatLeaf<(i32 IntRegs:$R)>; 1406f32e7eSjoergdef I64 : PatLeaf<(i64 DoubleRegs:$R)>; 1506f32e7eSjoergdef F32 : PatLeaf<(f32 IntRegs:$R)>; 1606f32e7eSjoergdef F64 : PatLeaf<(f64 DoubleRegs:$R)>; 1706f32e7eSjoerg 1806f32e7eSjoerglet PrintMethod = "printGlobalOperand" in { 1906f32e7eSjoerg def globaladdress : Operand<i32>; 2006f32e7eSjoerg def globaladdressExt : Operand<i32>; 2106f32e7eSjoerg} 2206f32e7eSjoerg 2306f32e7eSjoerglet isPseudo = 1 in { 2406f32e7eSjoerglet isCodeGenOnly = 0 in 2506f32e7eSjoergdef A2_iconst : Pseudo<(outs IntRegs:$Rd32), 2606f32e7eSjoerg (ins s27_2Imm:$Ii), "${Rd32} = iconst(#${Ii})">; 2706f32e7eSjoerg 2806f32e7eSjoergdef DUPLEX_Pseudo : InstHexagon<(outs), 2906f32e7eSjoerg (ins s32_0Imm:$offset), "DUPLEX", [], "", DUPLEX, TypePSEUDO>; 3006f32e7eSjoerg} 3106f32e7eSjoerg 3206f32e7eSjoerglet isExtendable = 1, opExtendable = 1, opExtentBits = 6, 3306f32e7eSjoerg isAsmParserOnly = 1 in 3406f32e7eSjoergdef TFRI64_V2_ext : InstHexagon<(outs DoubleRegs:$dst), 3506f32e7eSjoerg (ins s32_0Imm:$src1, s8_0Imm:$src2), 3606f32e7eSjoerg "$dst = combine(#$src1,#$src2)", [], "", 3706f32e7eSjoerg A2_combineii.Itinerary, TypeALU32_2op>, OpcodeHexagon; 3806f32e7eSjoerg 3906f32e7eSjoerg// HI/LO Instructions 4006f32e7eSjoerglet isReMaterializable = 1, isMoveImm = 1, hasSideEffects = 0, 4106f32e7eSjoerg hasNewValue = 1, opNewValue = 0 in 4206f32e7eSjoergclass REG_IMMED<string RegHalf, bit Rs, bits<3> MajOp, bit MinOp, 4306f32e7eSjoerg InstHexagon rootInst> 4406f32e7eSjoerg : InstHexagon<(outs IntRegs:$dst), 4506f32e7eSjoerg (ins u16_0Imm:$imm_value), 4606f32e7eSjoerg "$dst"#RegHalf#" = #$imm_value", [], "", 4706f32e7eSjoerg rootInst.Itinerary, rootInst.Type>, OpcodeHexagon { 4806f32e7eSjoerg bits<5> dst; 4906f32e7eSjoerg bits<32> imm_value; 5006f32e7eSjoerg 5106f32e7eSjoerg let Inst{27} = Rs; 5206f32e7eSjoerg let Inst{26-24} = MajOp; 5306f32e7eSjoerg let Inst{21} = MinOp; 5406f32e7eSjoerg let Inst{20-16} = dst; 5506f32e7eSjoerg let Inst{23-22} = imm_value{15-14}; 5606f32e7eSjoerg let Inst{13-0} = imm_value{13-0}; 5706f32e7eSjoerg} 5806f32e7eSjoerg 5906f32e7eSjoerglet isAsmParserOnly = 1 in { 6006f32e7eSjoerg def LO : REG_IMMED<".l", 0b0, 0b001, 0b1, A2_tfril>; 6106f32e7eSjoerg def HI : REG_IMMED<".h", 0b0, 0b010, 0b1, A2_tfrih>; 6206f32e7eSjoerg} 6306f32e7eSjoerg 6406f32e7eSjoerglet isReMaterializable = 1, isMoveImm = 1, isAsmParserOnly = 1 in { 6506f32e7eSjoerg def CONST32 : CONSTLDInst<(outs IntRegs:$Rd), (ins i32imm:$v), 6606f32e7eSjoerg "$Rd = CONST32(#$v)", []>; 6706f32e7eSjoerg def CONST64 : CONSTLDInst<(outs DoubleRegs:$Rd), (ins i64imm:$v), 6806f32e7eSjoerg "$Rd = CONST64(#$v)", []>; 6906f32e7eSjoerg} 7006f32e7eSjoerg 7106f32e7eSjoerglet hasSideEffects = 0, isReMaterializable = 1, isPseudo = 1, 7206f32e7eSjoerg isCodeGenOnly = 1 in 7306f32e7eSjoergdef PS_true : InstHexagon<(outs PredRegs:$dst), (ins), "", 7406f32e7eSjoerg [(set I1:$dst, 1)], "", C2_orn.Itinerary, TypeCR>; 7506f32e7eSjoerg 7606f32e7eSjoerglet hasSideEffects = 0, isReMaterializable = 1, isPseudo = 1, 7706f32e7eSjoerg isCodeGenOnly = 1 in 7806f32e7eSjoergdef PS_false : InstHexagon<(outs PredRegs:$dst), (ins), "", 7906f32e7eSjoerg [(set I1:$dst, 0)], "", C2_andn.Itinerary, TypeCR>; 8006f32e7eSjoerg 8106f32e7eSjoerglet Defs = [R29, R30], Uses = [R31, R30, R29], isPseudo = 1 in 8206f32e7eSjoergdef ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 8306f32e7eSjoerg ".error \"should not emit\" ", []>; 8406f32e7eSjoerg 8506f32e7eSjoerglet Defs = [R29, R30, R31], Uses = [R29], isPseudo = 1 in 8606f32e7eSjoergdef ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 8706f32e7eSjoerg ".error \"should not emit\" ", []>; 8806f32e7eSjoerg 8906f32e7eSjoerg 9006f32e7eSjoerglet isBranch = 1, isTerminator = 1, hasSideEffects = 0, 9106f32e7eSjoerg Defs = [PC, LC0], Uses = [SA0, LC0] in { 9206f32e7eSjoergdef ENDLOOP0 : Endloop<(outs), (ins b30_2Imm:$offset), 9306f32e7eSjoerg ":endloop0", 9406f32e7eSjoerg []>; 9506f32e7eSjoerg} 9606f32e7eSjoerg 9706f32e7eSjoerglet isBranch = 1, isTerminator = 1, hasSideEffects = 0, 9806f32e7eSjoerg Defs = [PC, LC1], Uses = [SA1, LC1] in { 9906f32e7eSjoergdef ENDLOOP1 : Endloop<(outs), (ins b30_2Imm:$offset), 10006f32e7eSjoerg ":endloop1", 10106f32e7eSjoerg []>; 10206f32e7eSjoerg} 10306f32e7eSjoerg 10406f32e7eSjoerglet isBranch = 1, isTerminator = 1, hasSideEffects = 0, 10506f32e7eSjoerg Defs = [PC, LC0, LC1], Uses = [SA0, SA1, LC0, LC1] in { 10606f32e7eSjoergdef ENDLOOP01 : Endloop<(outs), (ins b30_2Imm:$offset), 10706f32e7eSjoerg ":endloop01", 10806f32e7eSjoerg []>; 10906f32e7eSjoerg} 11006f32e7eSjoerg 11106f32e7eSjoerglet isExtendable = 1, isExtentSigned = 1, opExtentBits = 9, opExtentAlign = 2, 11206f32e7eSjoerg opExtendable = 0, hasSideEffects = 0 in 11306f32e7eSjoergclass LOOP_iBase<string mnemonic, InstHexagon rootInst> 11406f32e7eSjoerg : InstHexagon <(outs), (ins b30_2Imm:$offset, u10_0Imm:$src2), 115*da58b97aSjoerg mnemonic#"($offset,#$src2)", 11606f32e7eSjoerg [], "", rootInst.Itinerary, rootInst.Type>, OpcodeHexagon { 11706f32e7eSjoerg bits<9> offset; 11806f32e7eSjoerg bits<10> src2; 11906f32e7eSjoerg 12006f32e7eSjoerg let IClass = 0b0110; 12106f32e7eSjoerg 12206f32e7eSjoerg let Inst{27-22} = 0b100100; 12306f32e7eSjoerg let Inst{21} = !if (!eq(mnemonic, "loop0"), 0b0, 0b1); 12406f32e7eSjoerg let Inst{20-16} = src2{9-5}; 12506f32e7eSjoerg let Inst{12-8} = offset{8-4}; 12606f32e7eSjoerg let Inst{7-5} = src2{4-2}; 12706f32e7eSjoerg let Inst{4-3} = offset{3-2}; 12806f32e7eSjoerg let Inst{1-0} = src2{1-0}; 12906f32e7eSjoerg} 13006f32e7eSjoerg 13106f32e7eSjoerglet isExtendable = 1, isExtentSigned = 1, opExtentBits = 9, opExtentAlign = 2, 13206f32e7eSjoerg opExtendable = 0, hasSideEffects = 0 in 13306f32e7eSjoergclass LOOP_rBase<string mnemonic, InstHexagon rootInst> 13406f32e7eSjoerg : InstHexagon<(outs), (ins b30_2Imm:$offset, IntRegs:$src2), 135*da58b97aSjoerg mnemonic#"($offset,$src2)", 13606f32e7eSjoerg [], "", rootInst.Itinerary, rootInst.Type>, OpcodeHexagon { 13706f32e7eSjoerg bits<9> offset; 13806f32e7eSjoerg bits<5> src2; 13906f32e7eSjoerg 14006f32e7eSjoerg let IClass = 0b0110; 14106f32e7eSjoerg 14206f32e7eSjoerg let Inst{27-22} = 0b000000; 14306f32e7eSjoerg let Inst{21} = !if (!eq(mnemonic, "loop0"), 0b0, 0b1); 14406f32e7eSjoerg let Inst{20-16} = src2; 14506f32e7eSjoerg let Inst{12-8} = offset{8-4}; 14606f32e7eSjoerg let Inst{4-3} = offset{3-2}; 14706f32e7eSjoerg } 14806f32e7eSjoerg 14906f32e7eSjoerglet Defs = [SA0, LC0, USR], isCodeGenOnly = 1, isExtended = 1, 15006f32e7eSjoerg opExtendable = 0 in { 15106f32e7eSjoerg def J2_loop0iext : LOOP_iBase<"loop0", J2_loop0i>; 15206f32e7eSjoerg def J2_loop1iext : LOOP_iBase<"loop1", J2_loop1i>; 15306f32e7eSjoerg} 15406f32e7eSjoerg 15506f32e7eSjoerg// Interestingly only loop0's appear to set usr.lpcfg 15606f32e7eSjoerglet Defs = [SA1, LC1], isCodeGenOnly = 1, isExtended = 1, opExtendable = 0 in { 15706f32e7eSjoerg def J2_loop0rext : LOOP_rBase<"loop0", J2_loop0r>; 15806f32e7eSjoerg def J2_loop1rext : LOOP_rBase<"loop1", J2_loop1r>; 15906f32e7eSjoerg} 16006f32e7eSjoerg 16106f32e7eSjoerglet isCall = 1, hasSideEffects = 1, isPredicable = 0, 16206f32e7eSjoerg isExtended = 0, isExtendable = 1, opExtendable = 0, 16306f32e7eSjoerg isExtentSigned = 1, opExtentBits = 24, opExtentAlign = 2 in 16406f32e7eSjoergclass T_Call<string ExtStr> 16506f32e7eSjoerg : InstHexagon<(outs), (ins a30_2Imm:$dst), 16606f32e7eSjoerg "call " # ExtStr # "$dst", [], "", J2_call.Itinerary, TypeJ>, 16706f32e7eSjoerg OpcodeHexagon { 16806f32e7eSjoerg let BaseOpcode = "call"; 16906f32e7eSjoerg bits<24> dst; 17006f32e7eSjoerg 17106f32e7eSjoerg let IClass = 0b0101; 17206f32e7eSjoerg let Inst{27-25} = 0b101; 17306f32e7eSjoerg let Inst{24-16,13-1} = dst{23-2}; 17406f32e7eSjoerg let Inst{0} = 0b0; 17506f32e7eSjoerg} 17606f32e7eSjoerg 17706f32e7eSjoerglet isCodeGenOnly = 1, isCall = 1, hasSideEffects = 1, Defs = [R16], 17806f32e7eSjoerg isPredicable = 0 in 17906f32e7eSjoergdef CALLProfile : T_Call<"">; 18006f32e7eSjoerg 18106f32e7eSjoerglet isCodeGenOnly = 1, isCall = 1, hasSideEffects = 1, 18206f32e7eSjoerg Defs = [PC, R31, R6, R7, P0] in 18306f32e7eSjoergdef PS_call_stk : T_Call<"">; 18406f32e7eSjoerg 18506f32e7eSjoerg// Call, no return. 18606f32e7eSjoerglet isCall = 1, hasSideEffects = 1, cofMax1 = 1, isCodeGenOnly = 1 in 18706f32e7eSjoergdef PS_callr_nr: InstHexagon<(outs), (ins IntRegs:$Rs), 18806f32e7eSjoerg "callr $Rs", [], "", J2_callr.Itinerary, TypeJ>, OpcodeHexagon { 18906f32e7eSjoerg bits<5> Rs; 19006f32e7eSjoerg bits<2> Pu; 19106f32e7eSjoerg let isPredicatedFalse = 1; 19206f32e7eSjoerg 19306f32e7eSjoerg let IClass = 0b0101; 19406f32e7eSjoerg let Inst{27-21} = 0b0000101; 19506f32e7eSjoerg let Inst{20-16} = Rs; 19606f32e7eSjoerg } 19706f32e7eSjoerg 19806f32e7eSjoerglet isCall = 1, hasSideEffects = 1, 19906f32e7eSjoerg isExtended = 0, isExtendable = 1, opExtendable = 0, isCodeGenOnly = 1, 20006f32e7eSjoerg BaseOpcode = "PS_call_nr", isExtentSigned = 1, opExtentAlign = 2 in 20106f32e7eSjoergclass Call_nr<bits<5> nbits, bit isPred, bit isFalse, dag iops, 20206f32e7eSjoerg InstrItinClass itin> 20306f32e7eSjoerg : Pseudo<(outs), iops, "">, PredRel { 20406f32e7eSjoerg bits<2> Pu; 20506f32e7eSjoerg bits<17> dst; 20606f32e7eSjoerg let opExtentBits = nbits; 20706f32e7eSjoerg let isPredicable = 0; // !if(isPred, 0, 1); 20806f32e7eSjoerg let isPredicated = 0; // isPred; 20906f32e7eSjoerg let isPredicatedFalse = isFalse; 21006f32e7eSjoerg let Itinerary = itin; 21106f32e7eSjoerg} 21206f32e7eSjoerg 21306f32e7eSjoergdef PS_call_nr : Call_nr<24, 0, 0, (ins s32_0Imm:$Ii), J2_call.Itinerary>; 21406f32e7eSjoerg//def PS_call_nrt: Call_nr<17, 1, 0, (ins PredRegs:$Pu, s32_0Imm:$dst), 21506f32e7eSjoerg// J2_callt.Itinerary>; 21606f32e7eSjoerg//def PS_call_nrf: Call_nr<17, 1, 1, (ins PredRegs:$Pu, s32_0Imm:$dst), 21706f32e7eSjoerg// J2_callf.Itinerary>; 21806f32e7eSjoerg 21906f32e7eSjoerglet isBranch = 1, isIndirectBranch = 1, isBarrier = 1, Defs = [PC], 22006f32e7eSjoerg isPredicable = 1, hasSideEffects = 0, InputType = "reg", 22106f32e7eSjoerg cofMax1 = 1 in 22206f32e7eSjoergclass T_JMPr <InstHexagon rootInst> 22306f32e7eSjoerg : InstHexagon<(outs), (ins IntRegs:$dst), "jumpr $dst", [], 22406f32e7eSjoerg "", rootInst.Itinerary, rootInst.Type>, OpcodeHexagon { 22506f32e7eSjoerg bits<5> dst; 22606f32e7eSjoerg 22706f32e7eSjoerg let IClass = 0b0101; 22806f32e7eSjoerg let Inst{27-21} = 0b0010100; 22906f32e7eSjoerg let Inst{20-16} = dst; 23006f32e7eSjoerg} 23106f32e7eSjoerg 23206f32e7eSjoerg// A return through builtin_eh_return. 23306f32e7eSjoerglet isReturn = 1, isTerminator = 1, isBarrier = 1, hasSideEffects = 0, 23406f32e7eSjoerg isCodeGenOnly = 1, Defs = [PC], Uses = [R28], isPredicable = 0 in 23506f32e7eSjoergdef EH_RETURN_JMPR : T_JMPr<J2_jumpr>; 23606f32e7eSjoerg 23706f32e7eSjoerg// Indirect tail-call. 23806f32e7eSjoerglet isPseudo = 1, isCall = 1, isReturn = 1, isBarrier = 1, isPredicable = 0, 23906f32e7eSjoerg isTerminator = 1, isCodeGenOnly = 1 in 24006f32e7eSjoergdef PS_tailcall_r : T_JMPr<J2_jumpr>; 24106f32e7eSjoerg 24206f32e7eSjoerg// 24306f32e7eSjoerg// Direct tail-calls. 24406f32e7eSjoerglet isPseudo = 1, isCall = 1, isReturn = 1, isBarrier = 1, isPredicable = 0, 24506f32e7eSjoerg isTerminator = 1, isCodeGenOnly = 1 in 24606f32e7eSjoergdef PS_tailcall_i : Pseudo<(outs), (ins a30_2Imm:$dst), "", []>; 24706f32e7eSjoerg 24806f32e7eSjoerglet isCodeGenOnly = 1, isPseudo = 1, Uses = [R30], hasSideEffects = 0 in 24906f32e7eSjoergdef PS_aligna : Pseudo<(outs IntRegs:$Rd), (ins u32_0Imm:$A), "", []>; 25006f32e7eSjoerg 25106f32e7eSjoerg// Generate frameindex addresses. The main reason for the offset operand is 25206f32e7eSjoerg// that every instruction that is allowed to have frame index as an operand 25306f32e7eSjoerg// will then have that operand followed by an immediate operand (the offset). 25406f32e7eSjoerg// This simplifies the frame-index elimination code. 25506f32e7eSjoerg// 25606f32e7eSjoerglet isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1, 25706f32e7eSjoerg isPseudo = 1, isCodeGenOnly = 1, hasSideEffects = 0, isExtendable = 1, 25806f32e7eSjoerg isExtentSigned = 1, opExtentBits = 16, opExtentAlign = 0 in { 25906f32e7eSjoerg let opExtendable = 2 in 26006f32e7eSjoerg def PS_fi : Pseudo<(outs IntRegs:$Rd), 26106f32e7eSjoerg (ins IntRegs:$fi, s32_0Imm:$off), "">; 26206f32e7eSjoerg let opExtendable = 3 in 26306f32e7eSjoerg def PS_fia : Pseudo<(outs IntRegs:$Rd), 26406f32e7eSjoerg (ins IntRegs:$Rs, IntRegs:$fi, s32_0Imm:$off), "">; 26506f32e7eSjoerg} 26606f32e7eSjoerg 26706f32e7eSjoergclass CondStr<string CReg, bit True, bit New> { 26806f32e7eSjoerg string S = "if (" # !if(True,"","!") # CReg # !if(New,".new","") # ") "; 26906f32e7eSjoerg} 27006f32e7eSjoergclass JumpOpcStr<string Mnemonic, bit New, bit Taken> { 27106f32e7eSjoerg string S = Mnemonic # !if(Taken, ":t", ":nt"); 27206f32e7eSjoerg} 27306f32e7eSjoerglet isBranch = 1, isIndirectBranch = 1, Defs = [PC], isPredicated = 1, 27406f32e7eSjoerg hasSideEffects = 0, InputType = "reg", cofMax1 = 1 in 27506f32e7eSjoergclass T_JMPr_c <bit PredNot, bit isPredNew, bit isTak, InstHexagon rootInst> 27606f32e7eSjoerg : InstHexagon<(outs), (ins PredRegs:$src, IntRegs:$dst), 27706f32e7eSjoerg CondStr<"$src", !if(PredNot,0,1), isPredNew>.S # 27806f32e7eSjoerg JumpOpcStr<"jumpr", isPredNew, isTak>.S # " $dst", 27906f32e7eSjoerg [], "", rootInst.Itinerary, rootInst.Type>, OpcodeHexagon { 28006f32e7eSjoerg 28106f32e7eSjoerg let isTaken = isTak; 28206f32e7eSjoerg let isPredicatedFalse = PredNot; 28306f32e7eSjoerg let isPredicatedNew = isPredNew; 28406f32e7eSjoerg bits<2> src; 28506f32e7eSjoerg bits<5> dst; 28606f32e7eSjoerg 28706f32e7eSjoerg let IClass = 0b0101; 28806f32e7eSjoerg 28906f32e7eSjoerg let Inst{27-22} = 0b001101; 29006f32e7eSjoerg let Inst{21} = PredNot; 29106f32e7eSjoerg let Inst{20-16} = dst; 29206f32e7eSjoerg let Inst{12} = isTak; 29306f32e7eSjoerg let Inst{11} = isPredNew; 29406f32e7eSjoerg let Inst{9-8} = src; 29506f32e7eSjoerg} 29606f32e7eSjoerg 29706f32e7eSjoerglet isTerminator = 1, hasSideEffects = 0, isReturn = 1, isCodeGenOnly = 1, 29806f32e7eSjoerg isBarrier = 1, BaseOpcode = "JMPret" in { 29906f32e7eSjoerg def PS_jmpret : T_JMPr<J2_jumpr>, PredNewRel; 30006f32e7eSjoerg def PS_jmprett : T_JMPr_c<0, 0, 0, J2_jumprt>, PredNewRel; 30106f32e7eSjoerg def PS_jmpretf : T_JMPr_c<1, 0, 0, J2_jumprf>, PredNewRel; 30206f32e7eSjoerg def PS_jmprettnew : T_JMPr_c<0, 1, 0, J2_jumprtnew>, PredNewRel; 30306f32e7eSjoerg def PS_jmpretfnew : T_JMPr_c<1, 1, 0, J2_jumprfnew>, PredNewRel; 30406f32e7eSjoerg def PS_jmprettnewpt : T_JMPr_c<0, 1, 1, J2_jumprtnewpt>, PredNewRel; 30506f32e7eSjoerg def PS_jmpretfnewpt : T_JMPr_c<1, 1, 1, J2_jumprfnewpt>, PredNewRel; 30606f32e7eSjoerg} 30706f32e7eSjoerg 30806f32e7eSjoerg//defm V6_vtran2x2_map : HexagonMapping<(outs HvxVR:$Vy32, HvxVR:$Vx32), (ins HvxVR:$Vx32in, IntRegs:$Rt32), "vtrans2x2(${Vy32},${Vx32},${Rt32})", (V6_vshuff HvxVR:$Vy32, HvxVR:$Vx32, HvxVR:$Vx32in, IntRegs:$Rt32)>; 30906f32e7eSjoerg 31006f32e7eSjoerg// The reason for the custom inserter is to record all ALLOCA instructions 31106f32e7eSjoerg// in MachineFunctionInfo. 31206f32e7eSjoerglet Defs = [R29], hasSideEffects = 1 in 31306f32e7eSjoergdef PS_alloca: Pseudo <(outs IntRegs:$Rd), 31406f32e7eSjoerg (ins IntRegs:$Rs, u32_0Imm:$A), "", []>; 31506f32e7eSjoerg 31606f32e7eSjoerg// Load predicate. 31706f32e7eSjoerglet isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 13, 31806f32e7eSjoerg isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in 31906f32e7eSjoergdef LDriw_pred : LDInst<(outs PredRegs:$dst), 32006f32e7eSjoerg (ins IntRegs:$addr, s32_0Imm:$off), 32106f32e7eSjoerg ".error \"should not emit\"", []>; 32206f32e7eSjoerg 32306f32e7eSjoerg// Load modifier. 32406f32e7eSjoerglet isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 13, 32506f32e7eSjoerg isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in 32606f32e7eSjoergdef LDriw_ctr : LDInst<(outs CtrRegs:$dst), 32706f32e7eSjoerg (ins IntRegs:$addr, s32_0Imm:$off), 32806f32e7eSjoerg ".error \"should not emit\"", []>; 32906f32e7eSjoerg 33006f32e7eSjoerg 33106f32e7eSjoerglet isCodeGenOnly = 1, isPseudo = 1 in 33206f32e7eSjoergdef PS_pselect: InstHexagon<(outs DoubleRegs:$Rd), 33306f32e7eSjoerg (ins PredRegs:$Pu, DoubleRegs:$Rs, DoubleRegs:$Rt), 33406f32e7eSjoerg ".error \"should not emit\" ", [], "", A2_tfrpt.Itinerary, TypeALU32_2op>; 33506f32e7eSjoerg 33606f32e7eSjoerglet isBranch = 1, isBarrier = 1, Defs = [PC], hasSideEffects = 0, 33706f32e7eSjoerg isPredicable = 1, 33806f32e7eSjoerg isExtendable = 1, opExtendable = 0, isExtentSigned = 1, 33906f32e7eSjoerg opExtentBits = 24, opExtentAlign = 2, InputType = "imm" in 34006f32e7eSjoergclass T_JMP: InstHexagon<(outs), (ins b30_2Imm:$dst), 34106f32e7eSjoerg "jump $dst", 34206f32e7eSjoerg [], "", J2_jump.Itinerary, TypeJ>, OpcodeHexagon { 34306f32e7eSjoerg bits<24> dst; 34406f32e7eSjoerg let IClass = 0b0101; 34506f32e7eSjoerg 34606f32e7eSjoerg let Inst{27-25} = 0b100; 34706f32e7eSjoerg let Inst{24-16} = dst{23-15}; 34806f32e7eSjoerg let Inst{13-1} = dst{14-2}; 34906f32e7eSjoerg} 35006f32e7eSjoerg 35106f32e7eSjoerg// Restore registers and dealloc return function call. 35206f32e7eSjoerglet isCall = 1, isBarrier = 1, isReturn = 1, isTerminator = 1, 35306f32e7eSjoerg Defs = [R29, R30, R31, PC], isPredicable = 0, isAsmParserOnly = 1 in { 35406f32e7eSjoerg def RESTORE_DEALLOC_RET_JMP_V4 : T_JMP; 35506f32e7eSjoerg 35606f32e7eSjoerg let isExtended = 1, opExtendable = 0 in 35706f32e7eSjoerg def RESTORE_DEALLOC_RET_JMP_V4_EXT : T_JMP; 35806f32e7eSjoerg 35906f32e7eSjoerg let Defs = [R14, R15, R28, R29, R30, R31, PC] in { 36006f32e7eSjoerg def RESTORE_DEALLOC_RET_JMP_V4_PIC : T_JMP; 36106f32e7eSjoerg 36206f32e7eSjoerg let isExtended = 1, opExtendable = 0 in 36306f32e7eSjoerg def RESTORE_DEALLOC_RET_JMP_V4_EXT_PIC : T_JMP; 36406f32e7eSjoerg } 36506f32e7eSjoerg} 36606f32e7eSjoerg 36706f32e7eSjoerg// Restore registers and dealloc frame before a tail call. 36806f32e7eSjoerglet isCall = 1, Defs = [R29, R30, R31, PC], isAsmParserOnly = 1 in { 36906f32e7eSjoerg def RESTORE_DEALLOC_BEFORE_TAILCALL_V4 : T_Call<"">, PredRel; 37006f32e7eSjoerg 37106f32e7eSjoerg let isExtended = 1, opExtendable = 0 in 37206f32e7eSjoerg def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT : T_Call<"">, PredRel; 37306f32e7eSjoerg 37406f32e7eSjoerg let Defs = [R14, R15, R28, R29, R30, R31, PC] in { 37506f32e7eSjoerg def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC : T_Call<"">, PredRel; 37606f32e7eSjoerg 37706f32e7eSjoerg let isExtended = 1, opExtendable = 0 in 37806f32e7eSjoerg def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC : T_Call<"">, PredRel; 37906f32e7eSjoerg } 38006f32e7eSjoerg} 38106f32e7eSjoerg 38206f32e7eSjoerg// Save registers function call. 38306f32e7eSjoerglet isCall = 1, Uses = [R29, R31], isAsmParserOnly = 1 in { 38406f32e7eSjoerg def SAVE_REGISTERS_CALL_V4 : T_Call<"">, PredRel; 38506f32e7eSjoerg 38606f32e7eSjoerg let isExtended = 1, opExtendable = 0 in 38706f32e7eSjoerg def SAVE_REGISTERS_CALL_V4_EXT : T_Call<"">, PredRel; 38806f32e7eSjoerg 38906f32e7eSjoerg let Defs = [P0] in 39006f32e7eSjoerg def SAVE_REGISTERS_CALL_V4STK : T_Call<"">, PredRel; 39106f32e7eSjoerg 39206f32e7eSjoerg let Defs = [P0], isExtended = 1, opExtendable = 0 in 39306f32e7eSjoerg def SAVE_REGISTERS_CALL_V4STK_EXT : T_Call<"">, PredRel; 39406f32e7eSjoerg 39506f32e7eSjoerg let Defs = [R14, R15, R28] in 39606f32e7eSjoerg def SAVE_REGISTERS_CALL_V4_PIC : T_Call<"">, PredRel; 39706f32e7eSjoerg 39806f32e7eSjoerg let Defs = [R14, R15, R28], isExtended = 1, opExtendable = 0 in 39906f32e7eSjoerg def SAVE_REGISTERS_CALL_V4_EXT_PIC : T_Call<"">, PredRel; 40006f32e7eSjoerg 40106f32e7eSjoerg let Defs = [R14, R15, R28, P0] in 40206f32e7eSjoerg def SAVE_REGISTERS_CALL_V4STK_PIC : T_Call<"">, PredRel; 40306f32e7eSjoerg 40406f32e7eSjoerg let Defs = [R14, R15, R28, P0], isExtended = 1, opExtendable = 0 in 40506f32e7eSjoerg def SAVE_REGISTERS_CALL_V4STK_EXT_PIC : T_Call<"">, PredRel; 40606f32e7eSjoerg} 40706f32e7eSjoerg 40806f32e7eSjoerg// Vector store pseudos 40906f32e7eSjoerglet Predicates = [HasV60,UseHVX], isPseudo = 1, isCodeGenOnly = 1, 41006f32e7eSjoerg mayStore = 1, accessSize = HVXVectorAccess, hasSideEffects = 0 in 411*da58b97aSjoergclass STriv_template<RegisterClass RC, InstHexagon rootInst> 41206f32e7eSjoerg : InstHexagon<(outs), (ins IntRegs:$addr, s32_0Imm:$off, RC:$src), 41306f32e7eSjoerg "", [], "", rootInst.Itinerary, rootInst.Type>; 41406f32e7eSjoerg 415*da58b97aSjoergdef PS_vstorerv_ai: STriv_template<HvxVR, V6_vS32b_ai>, 41606f32e7eSjoerg Requires<[HasV60,UseHVX]>; 417*da58b97aSjoergdef PS_vstorerv_nt_ai: STriv_template<HvxVR, V6_vS32b_nt_ai>, 41806f32e7eSjoerg Requires<[HasV60,UseHVX]>; 419*da58b97aSjoergdef PS_vstorerw_ai: STriv_template<HvxWR, V6_vS32b_ai>, 420*da58b97aSjoerg Requires<[HasV60,UseHVX]>; 421*da58b97aSjoergdef PS_vstorerw_nt_ai: STriv_template<HvxWR, V6_vS32b_nt_ai>, 42206f32e7eSjoerg Requires<[HasV60,UseHVX]>; 42306f32e7eSjoerg 42406f32e7eSjoerglet isPseudo = 1, isCodeGenOnly = 1, mayStore = 1, hasSideEffects = 0 in 42506f32e7eSjoergdef PS_vstorerq_ai: Pseudo<(outs), 42606f32e7eSjoerg (ins IntRegs:$Rs, s32_0Imm:$Off, HvxQR:$Qt), "", []>, 42706f32e7eSjoerg Requires<[HasV60,UseHVX]>; 42806f32e7eSjoerg 42906f32e7eSjoerg// Vector load pseudos 43006f32e7eSjoerglet Predicates = [HasV60, UseHVX], isPseudo = 1, isCodeGenOnly = 1, 43106f32e7eSjoerg mayLoad = 1, accessSize = HVXVectorAccess, hasSideEffects = 0 in 432*da58b97aSjoergclass LDriv_template<RegisterClass RC, InstHexagon rootInst> 43306f32e7eSjoerg : InstHexagon<(outs RC:$dst), (ins IntRegs:$addr, s32_0Imm:$off), 43406f32e7eSjoerg "", [], "", rootInst.Itinerary, rootInst.Type>; 43506f32e7eSjoerg 436*da58b97aSjoergdef PS_vloadrv_ai: LDriv_template<HvxVR, V6_vL32b_ai>, 43706f32e7eSjoerg Requires<[HasV60,UseHVX]>; 438*da58b97aSjoergdef PS_vloadrv_nt_ai: LDriv_template<HvxVR, V6_vL32b_nt_ai>, 43906f32e7eSjoerg Requires<[HasV60,UseHVX]>; 440*da58b97aSjoergdef PS_vloadrw_ai: LDriv_template<HvxWR, V6_vL32b_ai>, 441*da58b97aSjoerg Requires<[HasV60,UseHVX]>; 442*da58b97aSjoergdef PS_vloadrw_nt_ai: LDriv_template<HvxWR, V6_vL32b_nt_ai>, 44306f32e7eSjoerg Requires<[HasV60,UseHVX]>; 44406f32e7eSjoerg 44506f32e7eSjoerglet isPseudo = 1, isCodeGenOnly = 1, mayLoad = 1, hasSideEffects = 0 in 44606f32e7eSjoergdef PS_vloadrq_ai: Pseudo<(outs HvxQR:$Qd), 44706f32e7eSjoerg (ins IntRegs:$Rs, s32_0Imm:$Off), "", []>, 44806f32e7eSjoerg Requires<[HasV60,UseHVX]>; 44906f32e7eSjoerg 45006f32e7eSjoerg 45106f32e7eSjoerglet isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in 45206f32e7eSjoergclass VSELInst<dag outs, dag ins, InstHexagon rootInst> 45306f32e7eSjoerg : InstHexagon<outs, ins, "", [], "", rootInst.Itinerary, rootInst.Type>; 45406f32e7eSjoerg 45506f32e7eSjoergdef PS_vselect: VSELInst<(outs HvxVR:$dst), 45606f32e7eSjoerg (ins PredRegs:$src1, HvxVR:$src2, HvxVR:$src3), V6_vcmov>, 45706f32e7eSjoerg Requires<[HasV60,UseHVX]>; 45806f32e7eSjoergdef PS_wselect: VSELInst<(outs HvxWR:$dst), 45906f32e7eSjoerg (ins PredRegs:$src1, HvxWR:$src2, HvxWR:$src3), V6_vccombine>, 46006f32e7eSjoerg Requires<[HasV60,UseHVX]>; 46106f32e7eSjoerg 46206f32e7eSjoerglet hasSideEffects = 0, isReMaterializable = 1, isPseudo = 1, 46306f32e7eSjoerg isCodeGenOnly = 1 in { 46406f32e7eSjoerg def PS_qtrue: InstHexagon<(outs HvxQR:$Qd), (ins), "", [], "", 46506f32e7eSjoerg V6_veqw.Itinerary, TypeCVI_VA>; 46606f32e7eSjoerg def PS_qfalse: InstHexagon<(outs HvxQR:$Qd), (ins), "", [], "", 46706f32e7eSjoerg V6_vgtw.Itinerary, TypeCVI_VA>; 46806f32e7eSjoerg def PS_vdd0: InstHexagon<(outs HvxWR:$Vd), (ins), "", [], "", 46906f32e7eSjoerg V6_vsubw_dv.Itinerary, TypeCVI_VA_DV>; 47006f32e7eSjoerg} 47106f32e7eSjoerg 47206f32e7eSjoerg// Store predicate. 47306f32e7eSjoerglet isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 13, 47406f32e7eSjoerg isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in 47506f32e7eSjoergdef STriw_pred : STInst<(outs), 47606f32e7eSjoerg (ins IntRegs:$addr, s32_0Imm:$off, PredRegs:$src1), 47706f32e7eSjoerg ".error \"should not emit\"", []>; 47806f32e7eSjoerg// Store modifier. 47906f32e7eSjoerglet isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 13, 48006f32e7eSjoerg isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in 48106f32e7eSjoergdef STriw_ctr : STInst<(outs), 48206f32e7eSjoerg (ins IntRegs:$addr, s32_0Imm:$off, CtrRegs:$src1), 48306f32e7eSjoerg ".error \"should not emit\"", []>; 48406f32e7eSjoerg 48506f32e7eSjoerglet isExtendable = 1, opExtendable = 1, opExtentBits = 6, 48606f32e7eSjoerg isAsmParserOnly = 1 in 48706f32e7eSjoergdef TFRI64_V4 : InstHexagon<(outs DoubleRegs:$dst), 48806f32e7eSjoerg (ins u64_0Imm:$src1), 48906f32e7eSjoerg "$dst = #$src1", [], "", 49006f32e7eSjoerg A2_combineii.Itinerary, TypeALU32_2op>, OpcodeHexagon; 49106f32e7eSjoerg 49206f32e7eSjoerg// Hexagon doesn't have a vector multiply with C semantics. 493*da58b97aSjoerg// Instead, generate a pseudo instruction that gets expanded into two 49406f32e7eSjoerg// scalar MPYI instructions. 49506f32e7eSjoerg// This is expanded by ExpandPostRAPseudos. 49606f32e7eSjoerglet isPseudo = 1 in 49706f32e7eSjoergdef PS_vmulw : PseudoM<(outs DoubleRegs:$Rd), 49806f32e7eSjoerg (ins DoubleRegs:$Rs, DoubleRegs:$Rt), "", []>; 49906f32e7eSjoerg 50006f32e7eSjoerglet isPseudo = 1 in 50106f32e7eSjoergdef PS_vmulw_acc : PseudoM<(outs DoubleRegs:$Rd), 50206f32e7eSjoerg (ins DoubleRegs:$Rx, DoubleRegs:$Rs, DoubleRegs:$Rt), "", [], 50306f32e7eSjoerg "$Rd = $Rx">; 50406f32e7eSjoerg 50506f32e7eSjoergdef DuplexIClass0: InstDuplex < 0 >; 50606f32e7eSjoergdef DuplexIClass1: InstDuplex < 1 >; 50706f32e7eSjoergdef DuplexIClass2: InstDuplex < 2 >; 50806f32e7eSjoerglet isExtendable = 1 in { 50906f32e7eSjoerg def DuplexIClass3: InstDuplex < 3 >; 51006f32e7eSjoerg def DuplexIClass4: InstDuplex < 4 >; 51106f32e7eSjoerg def DuplexIClass5: InstDuplex < 5 >; 51206f32e7eSjoerg def DuplexIClass6: InstDuplex < 6 >; 51306f32e7eSjoerg def DuplexIClass7: InstDuplex < 7 >; 51406f32e7eSjoerg} 51506f32e7eSjoergdef DuplexIClass8: InstDuplex < 8 >; 51606f32e7eSjoergdef DuplexIClass9: InstDuplex < 9 >; 51706f32e7eSjoergdef DuplexIClassA: InstDuplex < 0xA >; 51806f32e7eSjoergdef DuplexIClassB: InstDuplex < 0xB >; 51906f32e7eSjoergdef DuplexIClassC: InstDuplex < 0xC >; 52006f32e7eSjoergdef DuplexIClassD: InstDuplex < 0xD >; 52106f32e7eSjoergdef DuplexIClassE: InstDuplex < 0xE >; 52206f32e7eSjoergdef DuplexIClassF: InstDuplex < 0xF >; 52306f32e7eSjoerg 52406f32e7eSjoerg// Pseudos for circular buffer instructions. These are needed in order to 52506f32e7eSjoerg// allocate the correct pair of CSx and Mx registers. 52606f32e7eSjoergmulticlass NewCircularLoad<RegisterClass RC, MemAccessSize MS> { 52706f32e7eSjoerg 52806f32e7eSjoerglet isCodeGenOnly = 1, isPseudo = 1, Defs = [CS], Uses = [CS], 52906f32e7eSjoerg addrMode = PostInc, accessSize = MS, hasSideEffects = 0 in { 530*da58b97aSjoerg // Use timing class of L2_loadrb_pci. 53106f32e7eSjoerg def NAME#_pci : LDInst<(outs RC:$Rd32, IntRegs:$Rx32), 53206f32e7eSjoerg (ins IntRegs:$Rx32in, s4_0Imm:$Ii, ModRegs:$Mu2, IntRegs:$Cs), 533*da58b97aSjoerg ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_5ceb2f9e>; 53406f32e7eSjoerg 535*da58b97aSjoerg // Use timing class of L2_loadrb_pcr. 53606f32e7eSjoerg def NAME#_pcr : LDInst<(outs RC:$Rd32, IntRegs:$Rx32), 53706f32e7eSjoerg (ins IntRegs:$Rx32in, ModRegs:$Mu2, IntRegs:$Cs), 538*da58b97aSjoerg ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_075c8dd8>; 53906f32e7eSjoerg} 54006f32e7eSjoerg} 54106f32e7eSjoerg 54206f32e7eSjoergdefm PS_loadrub : NewCircularLoad<IntRegs, ByteAccess>; 54306f32e7eSjoergdefm PS_loadrb : NewCircularLoad<IntRegs, ByteAccess>; 54406f32e7eSjoergdefm PS_loadruh : NewCircularLoad<IntRegs, HalfWordAccess>; 54506f32e7eSjoergdefm PS_loadrh : NewCircularLoad<IntRegs, HalfWordAccess>; 54606f32e7eSjoergdefm PS_loadri : NewCircularLoad<IntRegs, WordAccess>; 54706f32e7eSjoergdefm PS_loadrd : NewCircularLoad<DoubleRegs, DoubleWordAccess>; 54806f32e7eSjoerg 54906f32e7eSjoergmulticlass NewCircularStore<RegisterClass RC, MemAccessSize MS> { 55006f32e7eSjoerg 55106f32e7eSjoerglet isCodeGenOnly = 1, isPseudo = 1, Defs = [CS], Uses = [CS], 55206f32e7eSjoerg addrMode = PostInc, accessSize = MS, hasSideEffects = 0 in { 553*da58b97aSjoerg // Use timing class of S2_storerb_pci. 55406f32e7eSjoerg def NAME#_pci : STInst<(outs IntRegs:$Rx32), 55506f32e7eSjoerg (ins IntRegs:$Rx32in, s4_0Imm:$Ii, ModRegs:$Mu2, RC:$Rt32, IntRegs:$Cs), 556*da58b97aSjoerg ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_b4dc7630>; 55706f32e7eSjoerg 558*da58b97aSjoerg // Use timing class of S2_storerb_pcr. 55906f32e7eSjoerg def NAME#_pcr : STInst<(outs IntRegs:$Rx32), 56006f32e7eSjoerg (ins IntRegs:$Rx32in, ModRegs:$Mu2, RC:$Rt32, IntRegs:$Cs), 561*da58b97aSjoerg ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_a2b365d2>; 56206f32e7eSjoerg} 56306f32e7eSjoerg} 56406f32e7eSjoerg 56506f32e7eSjoergdefm PS_storerb : NewCircularStore<IntRegs, ByteAccess>; 56606f32e7eSjoergdefm PS_storerh : NewCircularStore<IntRegs, HalfWordAccess>; 56706f32e7eSjoergdefm PS_storerf : NewCircularStore<IntRegs, HalfWordAccess>; 56806f32e7eSjoergdefm PS_storeri : NewCircularStore<IntRegs, WordAccess>; 56906f32e7eSjoergdefm PS_storerd : NewCircularStore<DoubleRegs, WordAccess>; 57006f32e7eSjoerg 57106f32e7eSjoerg// A pseudo that generates a runtime crash. This is used to implement 57206f32e7eSjoerg// __builtin_trap. 57306f32e7eSjoerglet hasSideEffects = 1, isPseudo = 1, isCodeGenOnly = 1, isSolo = 1 in 57406f32e7eSjoergdef PS_crash: InstHexagon<(outs), (ins), "", [], "", PSEUDO, TypePSEUDO>; 575