You've already forked linux-packaging-mono
							
							
		
			
	
	
		
			502 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			TableGen
		
	
	
	
	
	
		
		
			
		
	
	
			502 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			TableGen
		
	
	
	
	
	
|   | //===--- HexagonPseudo.td -------------------------------------------------===//
 | ||
|  | //
 | ||
|  | //                     The LLVM Compiler Infrastructure
 | ||
|  | //
 | ||
|  | // This file is distributed under the University of Illinois Open Source
 | ||
|  | // License. See LICENSE.TXT for details.
 | ||
|  | //
 | ||
|  | //===----------------------------------------------------------------------===//
 | ||
|  | 
 | ||
|  | // The pat frags in the definitions below need to have a named register,
 | ||
|  | // otherwise i32 will be assumed regardless of the register class. The
 | ||
|  | // name of the register does not matter.
 | ||
|  | def I1  : PatLeaf<(i1 PredRegs:$R)>; | ||
|  | def I32 : PatLeaf<(i32 IntRegs:$R)>; | ||
|  | def I64 : PatLeaf<(i64 DoubleRegs:$R)>; | ||
|  | def F32 : PatLeaf<(f32 IntRegs:$R)>; | ||
|  | def F64 : PatLeaf<(f64 DoubleRegs:$R)>; | ||
|  | 
 | ||
|  | let PrintMethod = "printGlobalOperand" in { | ||
|  |   def globaladdress : Operand<i32>; | ||
|  |   def globaladdressExt : Operand<i32>; | ||
|  | } | ||
|  | 
 | ||
|  | let isPseudo = 1 in { | ||
|  | let isCodeGenOnly = 0 in | ||
|  | def A2_iconst : Pseudo<(outs IntRegs:$Rd32), | ||
|  |     (ins s27_2Imm:$Ii), "${Rd32}=iconst(#${Ii})">; | ||
|  | 
 | ||
|  | def DUPLEX_Pseudo : InstHexagon<(outs), | ||
|  |     (ins s32_0Imm:$offset), "DUPLEX", [], "", DUPLEX, TypePSEUDO>; | ||
|  | } | ||
|  | 
 | ||
|  | let isExtendable = 1, opExtendable = 1, opExtentBits = 6, | ||
|  |     isAsmParserOnly = 1 in | ||
|  | def TFRI64_V2_ext : InstHexagon<(outs DoubleRegs:$dst), | ||
|  |     (ins s32_0Imm:$src1, s8_0Imm:$src2), | ||
|  |     "$dst=combine(#$src1,#$src2)", [], "", | ||
|  |     A2_combineii.Itinerary, TypeALU32_2op>, OpcodeHexagon; | ||
|  | 
 | ||
|  | // HI/LO Instructions
 | ||
|  | let isReMaterializable = 1, isMoveImm = 1, hasSideEffects = 0, | ||
|  |     hasNewValue = 1, opNewValue = 0 in | ||
|  | class REG_IMMED<string RegHalf, bit Rs, bits<3> MajOp, bit MinOp, | ||
|  |                 InstHexagon rootInst> | ||
|  |   : InstHexagon<(outs IntRegs:$dst), | ||
|  |                 (ins u16_0Imm:$imm_value), | ||
|  |                 "$dst"#RegHalf#"=#$imm_value", [], "", | ||
|  |                 rootInst.Itinerary, rootInst.Type>, OpcodeHexagon { | ||
|  |     bits<5> dst; | ||
|  |     bits<32> imm_value; | ||
|  | 
 | ||
|  |     let Inst{27} = Rs; | ||
|  |     let Inst{26-24} = MajOp; | ||
|  |     let Inst{21} = MinOp; | ||
|  |     let Inst{20-16} = dst; | ||
|  |     let Inst{23-22} = imm_value{15-14}; | ||
|  |     let Inst{13-0} = imm_value{13-0}; | ||
|  | } | ||
|  | 
 | ||
|  | let isAsmParserOnly = 1 in { | ||
|  |   def LO : REG_IMMED<".l", 0b0, 0b001, 0b1, A2_tfril>; | ||
|  |   def HI : REG_IMMED<".h", 0b0, 0b010, 0b1, A2_tfrih>; | ||
|  | } | ||
|  | 
 | ||
|  | let isReMaterializable = 1, isMoveImm = 1, isAsmParserOnly = 1 in { | ||
|  |   def CONST32 : CONSTLDInst<(outs IntRegs:$Rd), (ins i32imm:$v), | ||
|  |                 "$Rd = CONST32(#$v)", []>; | ||
|  |   def CONST64 : CONSTLDInst<(outs DoubleRegs:$Rd), (ins i64imm:$v), | ||
|  |                 "$Rd = CONST64(#$v)", []>; | ||
|  | } | ||
|  | 
 | ||
|  | let hasSideEffects = 0, isReMaterializable = 1, isPseudo = 1, | ||
|  |     isCodeGenOnly = 1 in | ||
|  | def PS_true : InstHexagon<(outs PredRegs:$dst), (ins), "", | ||
|  |               [(set I1:$dst, 1)], "", C2_orn.Itinerary, TypeCR>; | ||
|  | 
 | ||
|  | let hasSideEffects = 0, isReMaterializable = 1, isPseudo = 1, | ||
|  |     isCodeGenOnly = 1 in | ||
|  | def PS_false : InstHexagon<(outs PredRegs:$dst), (ins), "", | ||
|  |                [(set I1:$dst, 0)], "", C2_andn.Itinerary, TypeCR>; | ||
|  | 
 | ||
|  | let Defs = [R29, R30], Uses = [R31, R30, R29], isPseudo = 1 in | ||
|  | def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), | ||
|  |                               ".error \"should not emit\" ", []>; | ||
|  | 
 | ||
|  | let Defs = [R29, R30, R31], Uses = [R29], isPseudo = 1 in | ||
|  | def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), | ||
|  |                              ".error \"should not emit\" ", []>; | ||
|  | 
 | ||
|  | 
 | ||
|  | let isBranch = 1, isTerminator = 1, hasSideEffects = 0, | ||
|  |     Defs = [PC, LC0], Uses = [SA0, LC0] in { | ||
|  | def ENDLOOP0 : Endloop<(outs), (ins b30_2Imm:$offset), | ||
|  |                        ":endloop0", | ||
|  |                        []>; | ||
|  | } | ||
|  | 
 | ||
|  | let isBranch = 1, isTerminator = 1, hasSideEffects = 0, | ||
|  |     Defs = [PC, LC1], Uses = [SA1, LC1] in { | ||
|  | def ENDLOOP1 : Endloop<(outs), (ins b30_2Imm:$offset), | ||
|  |                        ":endloop1", | ||
|  |                        []>; | ||
|  | } | ||
|  | 
 | ||
|  | let isExtendable = 1, isExtentSigned = 1, opExtentBits = 9, opExtentAlign = 2, | ||
|  |     opExtendable = 0, hasSideEffects = 0 in | ||
|  | class LOOP_iBase<string mnemonic, InstHexagon rootInst> | ||
|  |          : InstHexagon <(outs), (ins b30_2Imm:$offset, u10_0Imm:$src2), | ||
|  |            #mnemonic#"($offset,#$src2)", | ||
|  |            [], "", rootInst.Itinerary, rootInst.Type>, OpcodeHexagon { | ||
|  |     bits<9> offset; | ||
|  |     bits<10> src2; | ||
|  | 
 | ||
|  |     let IClass = 0b0110; | ||
|  | 
 | ||
|  |     let Inst{27-22} = 0b100100; | ||
|  |     let Inst{21} = !if (!eq(mnemonic, "loop0"), 0b0, 0b1); | ||
|  |     let Inst{20-16} = src2{9-5}; | ||
|  |     let Inst{12-8} = offset{8-4}; | ||
|  |     let Inst{7-5} = src2{4-2}; | ||
|  |     let Inst{4-3} = offset{3-2}; | ||
|  |     let Inst{1-0} = src2{1-0}; | ||
|  | } | ||
|  | 
 | ||
|  | let isExtendable = 1, isExtentSigned = 1, opExtentBits = 9, opExtentAlign = 2, | ||
|  |     opExtendable = 0, hasSideEffects = 0 in | ||
|  | class LOOP_rBase<string mnemonic, InstHexagon rootInst> | ||
|  |          : InstHexagon<(outs), (ins b30_2Imm:$offset, IntRegs:$src2), | ||
|  |            #mnemonic#"($offset,$src2)", | ||
|  |            [], "", rootInst.Itinerary, rootInst.Type>, OpcodeHexagon { | ||
|  |     bits<9> offset; | ||
|  |     bits<5> src2; | ||
|  | 
 | ||
|  |     let IClass = 0b0110; | ||
|  | 
 | ||
|  |     let Inst{27-22} = 0b000000; | ||
|  |     let Inst{21} = !if (!eq(mnemonic, "loop0"), 0b0, 0b1); | ||
|  |     let Inst{20-16} = src2; | ||
|  |     let Inst{12-8} = offset{8-4}; | ||
|  |     let Inst{4-3} = offset{3-2}; | ||
|  |   } | ||
|  | 
 | ||
|  | let Defs = [SA0, LC0, USR], isCodeGenOnly = 1, isExtended = 1, | ||
|  |     opExtendable = 0 in { | ||
|  |   def J2_loop0iext : LOOP_iBase<"loop0", J2_loop0i>; | ||
|  |   def J2_loop1iext : LOOP_iBase<"loop1", J2_loop1i>; | ||
|  | } | ||
|  | 
 | ||
|  | // Interestingly only loop0's appear to set usr.lpcfg
 | ||
|  | let Defs = [SA1, LC1], isCodeGenOnly = 1, isExtended = 1, opExtendable = 0 in { | ||
|  |   def J2_loop0rext : LOOP_rBase<"loop0", J2_loop0r>; | ||
|  |   def J2_loop1rext : LOOP_rBase<"loop1", J2_loop1r>; | ||
|  | } | ||
|  | 
 | ||
|  | let isCall = 1, hasSideEffects = 1, isPredicable = 0, | ||
|  |     isExtended = 0, isExtendable = 1, opExtendable = 0, | ||
|  |     isExtentSigned = 1, opExtentBits = 24, opExtentAlign = 2 in | ||
|  | class T_Call<string ExtStr> | ||
|  |   : InstHexagon<(outs), (ins a30_2Imm:$dst), | ||
|  |       "call " # ExtStr # "$dst", [], "", J2_call.Itinerary, TypeJ>, | ||
|  |     OpcodeHexagon { | ||
|  |   let BaseOpcode = "call"; | ||
|  |   bits<24> dst; | ||
|  | 
 | ||
|  |   let IClass = 0b0101; | ||
|  |   let Inst{27-25} = 0b101; | ||
|  |   let Inst{24-16,13-1} = dst{23-2}; | ||
|  |   let Inst{0} = 0b0; | ||
|  | } | ||
|  | 
 | ||
|  | let isCodeGenOnly = 1, isCall = 1, hasSideEffects = 1, Defs = [R16], | ||
|  |     isPredicable = 0 in | ||
|  | def CALLProfile :  T_Call<"">; | ||
|  | 
 | ||
|  | let isCodeGenOnly = 1, isCall = 1, hasSideEffects = 1, | ||
|  |     Defs = [PC, R31, R6, R7, P0] in | ||
|  | def PS_call_stk : T_Call<"">; | ||
|  | 
 | ||
|  | // Call, no return.
 | ||
|  | let isCall = 1, hasSideEffects = 1, cofMax1 = 1, isCodeGenOnly = 1 in | ||
|  | def PS_callr_nr: InstHexagon<(outs), (ins IntRegs:$Rs), | ||
|  |     "callr $Rs", [], "", J2_callr.Itinerary, TypeJ>, OpcodeHexagon { | ||
|  |     bits<5> Rs; | ||
|  |     bits<2> Pu; | ||
|  |     let isPredicatedFalse = 1; | ||
|  | 
 | ||
|  |     let IClass = 0b0101; | ||
|  |     let Inst{27-21} = 0b0000101; | ||
|  |     let Inst{20-16} = Rs; | ||
|  |   } | ||
|  | 
 | ||
|  | let isCall = 1, hasSideEffects = 1, | ||
|  |     isExtended = 0, isExtendable = 1, opExtendable = 0, isCodeGenOnly = 1, | ||
|  |     BaseOpcode = "PS_call_nr", isExtentSigned = 1, opExtentAlign = 2 in | ||
|  | class Call_nr<bits<5> nbits, bit isPred, bit isFalse, dag iops, | ||
|  |               InstrItinClass itin> | ||
|  |   : Pseudo<(outs), iops, "">, PredRel { | ||
|  |     bits<2> Pu; | ||
|  |     bits<17> dst; | ||
|  |     let opExtentBits = nbits; | ||
|  |     let isPredicable = 0;  // !if(isPred, 0, 1);
 | ||
|  |     let isPredicated = 0;  // isPred;
 | ||
|  |     let isPredicatedFalse = isFalse; | ||
|  | } | ||
|  | 
 | ||
|  | def PS_call_nr : Call_nr<24, 0, 0, (ins s32_0Imm:$Ii), J2_call.Itinerary>; | ||
|  | //def PS_call_nrt: Call_nr<17, 1, 0, (ins PredRegs:$Pu, s32_0Imm:$dst),
 | ||
|  | //                         J2_callt.Itinerary>;
 | ||
|  | //def PS_call_nrf: Call_nr<17, 1, 1, (ins PredRegs:$Pu, s32_0Imm:$dst),
 | ||
|  | //                         J2_callf.Itinerary>;
 | ||
|  | 
 | ||
|  | let isBranch = 1, isIndirectBranch = 1, isBarrier = 1, Defs = [PC], | ||
|  |     isPredicable = 1, hasSideEffects = 0, InputType = "reg", | ||
|  |     cofMax1 = 1 in | ||
|  | class T_JMPr <InstHexagon rootInst> | ||
|  |   :  InstHexagon<(outs), (ins IntRegs:$dst), "jumpr $dst", [], | ||
|  |                  "", rootInst.Itinerary, rootInst.Type>, OpcodeHexagon { | ||
|  |     bits<5> dst; | ||
|  | 
 | ||
|  |     let IClass = 0b0101; | ||
|  |     let Inst{27-21} = 0b0010100; | ||
|  |     let Inst{20-16} = dst; | ||
|  | } | ||
|  | 
 | ||
|  | // A return through builtin_eh_return.
 | ||
|  | let isReturn = 1, isTerminator = 1, isBarrier = 1, hasSideEffects = 0, | ||
|  |     isCodeGenOnly = 1, Defs = [PC], Uses = [R28], isPredicable = 0 in | ||
|  | def EH_RETURN_JMPR : T_JMPr<J2_jumpr>; | ||
|  | 
 | ||
|  | // Indirect tail-call.
 | ||
|  | let isPseudo = 1, isCall = 1, isReturn = 1, isBarrier = 1, isPredicable = 0, | ||
|  |     isTerminator = 1, isCodeGenOnly = 1 in | ||
|  | def PS_tailcall_r : T_JMPr<J2_jumpr>; | ||
|  | 
 | ||
|  | //
 | ||
|  | // Direct tail-calls.
 | ||
|  | let isPseudo = 1, isCall = 1, isReturn = 1, isBarrier = 1, isPredicable = 0, | ||
|  |     isTerminator = 1, isCodeGenOnly = 1 in | ||
|  | def PS_tailcall_i : Pseudo<(outs), (ins a30_2Imm:$dst), "", []>; | ||
|  | 
 | ||
|  | let isCodeGenOnly = 1, isPseudo = 1, Uses = [R30], hasSideEffects = 0 in | ||
|  | def PS_aligna : Pseudo<(outs IntRegs:$Rd), (ins u32_0Imm:$A), "", []>; | ||
|  | 
 | ||
|  | // Generate frameindex addresses. The main reason for the offset operand is
 | ||
|  | // that every instruction that is allowed to have frame index as an operand
 | ||
|  | // will then have that operand followed by an immediate operand (the offset).
 | ||
|  | // This simplifies the frame-index elimination code.
 | ||
|  | //
 | ||
|  | let isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1, | ||
|  |     isPseudo = 1, isCodeGenOnly = 1, hasSideEffects = 0, isExtendable = 1, | ||
|  |     isExtentSigned = 1, opExtentBits = 16, opExtentAlign = 0 in { | ||
|  |   let opExtendable = 2 in | ||
|  |   def PS_fi  : Pseudo<(outs IntRegs:$Rd), | ||
|  |                       (ins IntRegs:$fi, s32_0Imm:$off), "">; | ||
|  |   let opExtendable = 3 in | ||
|  |   def PS_fia : Pseudo<(outs IntRegs:$Rd), | ||
|  |                       (ins IntRegs:$Rs, IntRegs:$fi, s32_0Imm:$off), "">; | ||
|  | } | ||
|  | 
 | ||
|  | class CondStr<string CReg, bit True, bit New> { | ||
|  |   string S = "if (" # !if(True,"","!") # CReg # !if(New,".new","") # ") "; | ||
|  | } | ||
|  | class JumpOpcStr<string Mnemonic, bit New, bit Taken> { | ||
|  |   string S = Mnemonic # !if(Taken, ":t", ":nt"); | ||
|  | } | ||
|  | let isBranch = 1, isIndirectBranch = 1, Defs = [PC], isPredicated = 1, | ||
|  |     hasSideEffects = 0, InputType = "reg", cofMax1 = 1 in | ||
|  | class T_JMPr_c <bit PredNot, bit isPredNew, bit isTak, InstHexagon rootInst> | ||
|  |   :  InstHexagon<(outs), (ins PredRegs:$src, IntRegs:$dst), | ||
|  |                  CondStr<"$src", !if(PredNot,0,1), isPredNew>.S # | ||
|  |                  JumpOpcStr<"jumpr", isPredNew, isTak>.S # " $dst", | ||
|  |                  [], "", rootInst.Itinerary, rootInst.Type>, OpcodeHexagon { | ||
|  | 
 | ||
|  |     let isTaken = isTak; | ||
|  |     let isPredicatedFalse = PredNot; | ||
|  |     let isPredicatedNew = isPredNew; | ||
|  |     bits<2> src; | ||
|  |     bits<5> dst; | ||
|  | 
 | ||
|  |     let IClass = 0b0101; | ||
|  | 
 | ||
|  |     let Inst{27-22} = 0b001101; | ||
|  |     let Inst{21} = PredNot; | ||
|  |     let Inst{20-16} = dst; | ||
|  |     let Inst{12} = isTak; | ||
|  |     let Inst{11} = isPredNew; | ||
|  |     let Inst{9-8} = src; | ||
|  | } | ||
|  | 
 | ||
|  | let isTerminator = 1, hasSideEffects = 0, isReturn = 1, isCodeGenOnly = 1, | ||
|  |     isBarrier = 1, BaseOpcode = "JMPret" in { | ||
|  |   def PS_jmpret : T_JMPr<J2_jumpr>, PredNewRel; | ||
|  |   def PS_jmprett : T_JMPr_c<0, 0, 0, J2_jumprt>, PredNewRel; | ||
|  |   def PS_jmpretf : T_JMPr_c<1, 0, 0, J2_jumprf>, PredNewRel; | ||
|  |   def PS_jmprettnew : T_JMPr_c<0, 1, 0, J2_jumprtnew>, PredNewRel; | ||
|  |   def PS_jmpretfnew : T_JMPr_c<1, 1, 0, J2_jumprfnew>, PredNewRel; | ||
|  |   def PS_jmprettnewpt : T_JMPr_c<0, 1, 1, J2_jumprtnewpt>, PredNewRel; | ||
|  |   def PS_jmpretfnewpt : T_JMPr_c<1, 1, 1, J2_jumprfnewpt>, PredNewRel; | ||
|  | } | ||
|  | 
 | ||
|  | //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)>;
 | ||
|  | 
 | ||
|  | // The reason for the custom inserter is to record all ALLOCA instructions
 | ||
|  | // in MachineFunctionInfo.
 | ||
|  | let Defs = [R29], hasSideEffects = 1 in | ||
|  | def PS_alloca: Pseudo <(outs IntRegs:$Rd), | ||
|  |                        (ins IntRegs:$Rs, u32_0Imm:$A), "", []>; | ||
|  | 
 | ||
|  | // Load predicate.
 | ||
|  | let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 13, | ||
|  |     isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in | ||
|  | def LDriw_pred : LDInst<(outs PredRegs:$dst), | ||
|  |                         (ins IntRegs:$addr, s32_0Imm:$off), | ||
|  |                         ".error \"should not emit\"", []>; | ||
|  | 
 | ||
|  | // Load modifier.
 | ||
|  | let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 13, | ||
|  |     isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in | ||
|  | def LDriw_mod : LDInst<(outs ModRegs:$dst), | ||
|  |                         (ins IntRegs:$addr, s32_0Imm:$off), | ||
|  |                         ".error \"should not emit\"", []>; | ||
|  | 
 | ||
|  | 
 | ||
|  | let isCodeGenOnly = 1, isPseudo = 1 in | ||
|  | def PS_pselect: InstHexagon<(outs DoubleRegs:$Rd), | ||
|  |       (ins PredRegs:$Pu, DoubleRegs:$Rs, DoubleRegs:$Rt), | ||
|  |       ".error \"should not emit\" ", [], "", A2_tfrpt.Itinerary, TypeALU32_2op>; | ||
|  | 
 | ||
|  | let isBranch = 1, isBarrier = 1, Defs = [PC], hasSideEffects = 0, | ||
|  |     isPredicable = 1, | ||
|  |     isExtendable = 1, opExtendable = 0, isExtentSigned = 1, | ||
|  |     opExtentBits = 24, opExtentAlign = 2, InputType = "imm" in | ||
|  | class T_JMP: InstHexagon<(outs), (ins b30_2Imm:$dst), | ||
|  |       "jump $dst", | ||
|  |       [], "", J2_jump.Itinerary, TypeJ>, OpcodeHexagon { | ||
|  |     bits<24> dst; | ||
|  |     let IClass = 0b0101; | ||
|  | 
 | ||
|  |     let Inst{27-25} = 0b100; | ||
|  |     let Inst{24-16} = dst{23-15}; | ||
|  |     let Inst{13-1} = dst{14-2}; | ||
|  | } | ||
|  | 
 | ||
|  | // Restore registers and dealloc return function call.
 | ||
|  | let isCall = 1, isBarrier = 1, isReturn = 1, isTerminator = 1, | ||
|  |     Defs = [R29, R30, R31, PC], isPredicable = 0, isAsmParserOnly = 1 in { | ||
|  |   def RESTORE_DEALLOC_RET_JMP_V4 : T_JMP; | ||
|  | 
 | ||
|  |   let isExtended = 1, opExtendable = 0 in | ||
|  |   def RESTORE_DEALLOC_RET_JMP_V4_EXT : T_JMP; | ||
|  | 
 | ||
|  |   let Defs = [R14, R15, R28, R29, R30, R31, PC] in { | ||
|  |     def RESTORE_DEALLOC_RET_JMP_V4_PIC : T_JMP; | ||
|  | 
 | ||
|  |     let isExtended = 1, opExtendable = 0 in | ||
|  |     def RESTORE_DEALLOC_RET_JMP_V4_EXT_PIC : T_JMP; | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | // Restore registers and dealloc frame before a tail call.
 | ||
|  | let isCall = 1, Defs = [R29, R30, R31, PC], isAsmParserOnly = 1 in { | ||
|  |   def RESTORE_DEALLOC_BEFORE_TAILCALL_V4 : T_Call<"">, PredRel; | ||
|  | 
 | ||
|  |   let isExtended = 1, opExtendable = 0 in | ||
|  |   def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT : T_Call<"">, PredRel; | ||
|  | 
 | ||
|  |   let Defs = [R14, R15, R28, R29, R30, R31, PC] in { | ||
|  |     def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC : T_Call<"">, PredRel; | ||
|  | 
 | ||
|  |     let isExtended = 1, opExtendable = 0 in | ||
|  |     def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC : T_Call<"">, PredRel; | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | // Save registers function call.
 | ||
|  | let isCall = 1, Uses = [R29, R31], isAsmParserOnly = 1 in { | ||
|  |   def SAVE_REGISTERS_CALL_V4 : T_Call<"">, PredRel; | ||
|  | 
 | ||
|  |   let isExtended = 1, opExtendable = 0 in | ||
|  |   def SAVE_REGISTERS_CALL_V4_EXT : T_Call<"">, PredRel; | ||
|  | 
 | ||
|  |   let Defs = [P0] in | ||
|  |   def SAVE_REGISTERS_CALL_V4STK : T_Call<"">, PredRel; | ||
|  | 
 | ||
|  |   let Defs = [P0], isExtended = 1, opExtendable = 0 in | ||
|  |   def SAVE_REGISTERS_CALL_V4STK_EXT : T_Call<"">, PredRel; | ||
|  | 
 | ||
|  |   let Defs = [R14, R15, R28] in | ||
|  |   def SAVE_REGISTERS_CALL_V4_PIC : T_Call<"">, PredRel; | ||
|  | 
 | ||
|  |   let Defs = [R14, R15, R28], isExtended = 1, opExtendable = 0 in | ||
|  |   def SAVE_REGISTERS_CALL_V4_EXT_PIC : T_Call<"">, PredRel; | ||
|  | 
 | ||
|  |   let Defs = [R14, R15, R28, P0] in | ||
|  |   def SAVE_REGISTERS_CALL_V4STK_PIC : T_Call<"">, PredRel; | ||
|  | 
 | ||
|  |   let Defs = [R14, R15, R28, P0], isExtended = 1, opExtendable = 0 in | ||
|  |   def SAVE_REGISTERS_CALL_V4STK_EXT_PIC : T_Call<"">, PredRel; | ||
|  | } | ||
|  | 
 | ||
|  | // Vector store pseudos
 | ||
|  | let Predicates = [HasV60T, UseHVX], isPseudo = 1, isCodeGenOnly = 1, | ||
|  |     mayStore = 1, accessSize = HVXVectorAccess, hasSideEffects = 0 in | ||
|  | class STrivv_template<RegisterClass RC, InstHexagon rootInst> | ||
|  |   : InstHexagon<(outs), (ins IntRegs:$addr, s32_0Imm:$off, RC:$src), | ||
|  |     "", [], "", rootInst.Itinerary, rootInst.Type>; | ||
|  | 
 | ||
|  | def PS_vstorerw_ai: STrivv_template<HvxWR, V6_vS32b_ai>, | ||
|  |       Requires<[HasV60T,UseHVX]>; | ||
|  | def PS_vstorerw_nt_ai: STrivv_template<HvxWR, V6_vS32b_nt_ai>, | ||
|  |       Requires<[HasV60T,UseHVX]>; | ||
|  | def PS_vstorerwu_ai: STrivv_template<HvxWR, V6_vS32Ub_ai>, | ||
|  |       Requires<[HasV60T,UseHVX]>; | ||
|  | 
 | ||
|  | let isPseudo = 1, isCodeGenOnly = 1, mayStore = 1, hasSideEffects = 0 in | ||
|  | def PS_vstorerq_ai: Pseudo<(outs), | ||
|  |       (ins IntRegs:$Rs, s32_0Imm:$Off, HvxQR:$Qt), "", []>, | ||
|  |       Requires<[HasV60T,UseHVX]>; | ||
|  | 
 | ||
|  | // Vector load pseudos
 | ||
|  | let Predicates = [HasV60T, UseHVX], isPseudo = 1, isCodeGenOnly = 1, | ||
|  |     mayLoad = 1, accessSize = HVXVectorAccess, hasSideEffects = 0 in | ||
|  | class LDrivv_template<RegisterClass RC, InstHexagon rootInst> | ||
|  |   : InstHexagon<(outs RC:$dst), (ins IntRegs:$addr, s32_0Imm:$off), | ||
|  |     "", [], "", rootInst.Itinerary, rootInst.Type>; | ||
|  | 
 | ||
|  | def PS_vloadrw_ai: LDrivv_template<HvxWR, V6_vL32b_ai>, | ||
|  |       Requires<[HasV60T,UseHVX]>; | ||
|  | def PS_vloadrw_nt_ai: LDrivv_template<HvxWR, V6_vL32b_nt_ai>, | ||
|  |       Requires<[HasV60T,UseHVX]>; | ||
|  | def PS_vloadrwu_ai: LDrivv_template<HvxWR, V6_vL32Ub_ai>, | ||
|  |       Requires<[HasV60T,UseHVX]>; | ||
|  | 
 | ||
|  | let isPseudo = 1, isCodeGenOnly = 1, mayLoad = 1, hasSideEffects = 0 in | ||
|  | def PS_vloadrq_ai: Pseudo<(outs HvxQR:$Qd), | ||
|  |       (ins IntRegs:$Rs, s32_0Imm:$Off), "", []>, | ||
|  |       Requires<[HasV60T,UseHVX]>; | ||
|  | 
 | ||
|  | 
 | ||
|  | let isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in | ||
|  | class VSELInst<dag outs, dag ins, InstHexagon rootInst> | ||
|  |   : InstHexagon<outs, ins, "", [], "", rootInst.Itinerary, rootInst.Type>; | ||
|  | 
 | ||
|  | def PS_vselect: VSELInst<(outs HvxVR:$dst), | ||
|  |       (ins PredRegs:$src1, HvxVR:$src2, HvxVR:$src3), V6_vcmov>, | ||
|  |       Requires<[HasV60T,UseHVX]>; | ||
|  | def PS_wselect: VSELInst<(outs HvxWR:$dst), | ||
|  |       (ins PredRegs:$src1, HvxWR:$src2, HvxWR:$src3), V6_vccombine>, | ||
|  |       Requires<[HasV60T,UseHVX]>; | ||
|  | 
 | ||
|  | // Store predicate.
 | ||
|  | let isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 13, | ||
|  |     isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in | ||
|  | def STriw_pred : STInst<(outs), | ||
|  |       (ins IntRegs:$addr, s32_0Imm:$off, PredRegs:$src1), | ||
|  |       ".error \"should not emit\"", []>; | ||
|  | // Store modifier.
 | ||
|  | let isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 13, | ||
|  |     isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in | ||
|  | def STriw_mod : STInst<(outs), | ||
|  |       (ins IntRegs:$addr, s32_0Imm:$off, ModRegs:$src1), | ||
|  |       ".error \"should not emit\"", []>; | ||
|  | 
 | ||
|  | let isExtendable = 1, opExtendable = 1, opExtentBits = 6, | ||
|  |     isAsmParserOnly = 1 in | ||
|  | def TFRI64_V4 : InstHexagon<(outs DoubleRegs:$dst), | ||
|  |     (ins u64_0Imm:$src1), | ||
|  |     "$dst = #$src1", [], "", | ||
|  |     A2_combineii.Itinerary, TypeALU32_2op>, OpcodeHexagon; | ||
|  | 
 | ||
|  | // Hexagon doesn't have a vector multiply with C semantics.
 | ||
|  | // Instead, generate a pseudo instruction that gets expaneded into two
 | ||
|  | // scalar MPYI instructions.
 | ||
|  | // This is expanded by ExpandPostRAPseudos.
 | ||
|  | let isPseudo = 1 in | ||
|  | def PS_vmulw : PseudoM<(outs DoubleRegs:$Rd), | ||
|  |       (ins DoubleRegs:$Rs, DoubleRegs:$Rt), "", []>; | ||
|  | 
 | ||
|  | let isPseudo = 1 in | ||
|  | def PS_vmulw_acc : PseudoM<(outs DoubleRegs:$Rd), | ||
|  |       (ins DoubleRegs:$Rx, DoubleRegs:$Rs, DoubleRegs:$Rt), "", [], | ||
|  |       "$Rd = $Rx">; | ||
|  | 
 | ||
|  | def DuplexIClass0:  InstDuplex < 0 >; | ||
|  | def DuplexIClass1:  InstDuplex < 1 >; | ||
|  | def DuplexIClass2:  InstDuplex < 2 >; | ||
|  | let isExtendable = 1 in { | ||
|  |   def DuplexIClass3:  InstDuplex < 3 >; | ||
|  |   def DuplexIClass4:  InstDuplex < 4 >; | ||
|  |   def DuplexIClass5:  InstDuplex < 5 >; | ||
|  |   def DuplexIClass6:  InstDuplex < 6 >; | ||
|  |   def DuplexIClass7:  InstDuplex < 7 >; | ||
|  | } | ||
|  | def DuplexIClass8:  InstDuplex < 8 >; | ||
|  | def DuplexIClass9:  InstDuplex < 9 >; | ||
|  | def DuplexIClassA:  InstDuplex < 0xA >; | ||
|  | def DuplexIClassB:  InstDuplex < 0xB >; | ||
|  | def DuplexIClassC:  InstDuplex < 0xC >; | ||
|  | def DuplexIClassD:  InstDuplex < 0xD >; | ||
|  | def DuplexIClassE:  InstDuplex < 0xE >; | ||
|  | def DuplexIClassF:  InstDuplex < 0xF >; |