624 lines · plain
1//===--- HexagonPseudo.td -------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// The pat frags in the definitions below need to have a named register,10// otherwise i32 will be assumed regardless of the register class. The11// name of the register does not matter.12def I1 : PatLeaf<(i1 PredRegs:$R)>;13def I32 : PatLeaf<(i32 IntRegs:$R)>;14def I64 : PatLeaf<(i64 DoubleRegs:$R)>;15def F32 : PatLeaf<(f32 IntRegs:$R)>;16def F64 : PatLeaf<(f64 DoubleRegs:$R)>;17 18let PrintMethod = "printGlobalOperand" in {19 def globaladdress : Operand<i32>;20 def globaladdressExt : Operand<i32>;21}22 23let isPseudo = 1 in {24let isCodeGenOnly = 0 in25def A2_iconst : Pseudo<(outs IntRegs:$Rd32),26 (ins s27_2Imm:$Ii), "${Rd32} = iconst(#${Ii})">;27 28def DUPLEX_Pseudo : InstHexagon<(outs),29 (ins s32_0Imm:$offset), "DUPLEX", [], "", DUPLEX, TypePSEUDO>;30}31 32let isExtendable = 1, opExtendable = 1, opExtentBits = 6,33 isAsmParserOnly = 1 in34def TFRI64_V2_ext : InstHexagon<(outs DoubleRegs:$dst),35 (ins s32_0Imm:$src1, s8_0Imm:$src2),36 "$dst = combine(#$src1,#$src2)", [], "",37 A2_combineii.Itinerary, TypeALU32_2op>, OpcodeHexagon;38 39// HI/LO Instructions40let isReMaterializable = 1, isMoveImm = 1, hasSideEffects = 0,41 hasNewValue = 1, opNewValue = 0 in42class REG_IMMED<string RegHalf, bit Rs, bits<3> MajOp, bit MinOp,43 InstHexagon rootInst>44 : InstHexagon<(outs IntRegs:$dst),45 (ins u16_0Imm:$imm_value),46 "$dst"#RegHalf#" = #$imm_value", [], "",47 rootInst.Itinerary, rootInst.Type>, OpcodeHexagon {48 bits<5> dst;49 bits<32> imm_value;50 51 let Inst{27} = Rs;52 let Inst{26-24} = MajOp;53 let Inst{21} = MinOp;54 let Inst{20-16} = dst;55 let Inst{23-22} = imm_value{15-14};56 let Inst{13-0} = imm_value{13-0};57}58 59let isAsmParserOnly = 1 in {60 def LO : REG_IMMED<".l", 0b0, 0b001, 0b1, A2_tfril>;61 def HI : REG_IMMED<".h", 0b0, 0b010, 0b1, A2_tfrih>;62}63 64let isReMaterializable = 1, isMoveImm = 1, isAsmParserOnly = 1 in {65 def CONST32 : CONSTLDInst<(outs IntRegs:$Rd), (ins i32imm:$v),66 "$Rd = CONST32(#$v)", []>;67 def CONST64 : CONSTLDInst<(outs DoubleRegs:$Rd), (ins i64imm:$v),68 "$Rd = CONST64(#$v)", []>;69}70 71let hasSideEffects = 0, isReMaterializable = 1, isPseudo = 1,72 isCodeGenOnly = 1 in73def PS_true : InstHexagon<(outs PredRegs:$dst), (ins), "",74 [(set I1:$dst, 1)], "", C2_orn.Itinerary, TypeCR>;75 76let hasSideEffects = 0, isReMaterializable = 1, isPseudo = 1,77 isCodeGenOnly = 1 in78def PS_false : InstHexagon<(outs PredRegs:$dst), (ins), "",79 [(set I1:$dst, 0)], "", C2_andn.Itinerary, TypeCR>;80 81let Defs = [R29, R30], Uses = [R31, R30, R29], isPseudo = 1 in82def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),83 ".error \"should not emit\" ", []>;84 85let Defs = [R29, R30, R31], Uses = [R29], isPseudo = 1 in86def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),87 ".error \"should not emit\" ", []>;88 89 90let isBranch = 1, isTerminator = 1, hasSideEffects = 0,91 Defs = [PC, LC0], Uses = [SA0, LC0] in {92def ENDLOOP0 : Endloop<(outs), (ins b30_2Imm:$offset),93 ":endloop0",94 []>;95}96 97let isBranch = 1, isTerminator = 1, hasSideEffects = 0,98 Defs = [PC, LC1], Uses = [SA1, LC1] in {99def ENDLOOP1 : Endloop<(outs), (ins b30_2Imm:$offset),100 ":endloop1",101 []>;102}103 104let isBranch = 1, isTerminator = 1, hasSideEffects = 0,105 Defs = [PC, LC0, LC1], Uses = [SA0, SA1, LC0, LC1] in {106def ENDLOOP01 : Endloop<(outs), (ins b30_2Imm:$offset),107 ":endloop01",108 []>;109}110 111let isExtendable = 1, isExtentSigned = 1, opExtentBits = 9, opExtentAlign = 2,112 opExtendable = 0, hasSideEffects = 0 in113class LOOP_iBase<string mnemonic, InstHexagon rootInst>114 : InstHexagon <(outs), (ins b30_2Imm:$offset, u10_0Imm:$src2),115 mnemonic#"($offset,#$src2)",116 [], "", rootInst.Itinerary, rootInst.Type>, OpcodeHexagon {117 bits<9> offset;118 bits<10> src2;119 120 let IClass = 0b0110;121 122 let Inst{27-22} = 0b100100;123 let Inst{21} = !if (!eq(mnemonic, "loop0"), 0b0, 0b1);124 let Inst{20-16} = src2{9-5};125 let Inst{12-8} = offset{8-4};126 let Inst{7-5} = src2{4-2};127 let Inst{4-3} = offset{3-2};128 let Inst{1-0} = src2{1-0};129}130 131let isExtendable = 1, isExtentSigned = 1, opExtentBits = 9, opExtentAlign = 2,132 opExtendable = 0, hasSideEffects = 0 in133class LOOP_rBase<string mnemonic, InstHexagon rootInst>134 : InstHexagon<(outs), (ins b30_2Imm:$offset, IntRegs:$src2),135 mnemonic#"($offset,$src2)",136 [], "", rootInst.Itinerary, rootInst.Type>, OpcodeHexagon {137 bits<9> offset;138 bits<5> src2;139 140 let IClass = 0b0110;141 142 let Inst{27-22} = 0b000000;143 let Inst{21} = !if (!eq(mnemonic, "loop0"), 0b0, 0b1);144 let Inst{20-16} = src2;145 let Inst{12-8} = offset{8-4};146 let Inst{4-3} = offset{3-2};147 }148 149let Defs = [SA0, LC0, USR], isCodeGenOnly = 1, isExtended = 1,150 opExtendable = 0 in {151 def J2_loop0iext : LOOP_iBase<"loop0", J2_loop0i>;152 def J2_loop1iext : LOOP_iBase<"loop1", J2_loop1i>;153}154 155// Interestingly only loop0's appear to set usr.lpcfg156let Defs = [SA1, LC1], isCodeGenOnly = 1, isExtended = 1, opExtendable = 0 in {157 def J2_loop0rext : LOOP_rBase<"loop0", J2_loop0r>;158 def J2_loop1rext : LOOP_rBase<"loop1", J2_loop1r>;159}160 161let isCall = 1, hasSideEffects = 1, isPredicable = 0,162 isExtended = 0, isExtendable = 1, opExtendable = 0,163 isExtentSigned = 1, opExtentBits = 24, opExtentAlign = 2 in164class T_Call<string ExtStr>165 : InstHexagon<(outs), (ins a30_2Imm:$dst),166 "call " # ExtStr # "$dst", [], "", J2_call.Itinerary, TypeJ>,167 OpcodeHexagon {168 let BaseOpcode = "call";169 bits<24> dst;170 171 let IClass = 0b0101;172 let Inst{27-25} = 0b101;173 let Inst{24-16,13-1} = dst{23-2};174 let Inst{0} = 0b0;175}176 177let isCodeGenOnly = 1, isCall = 1, hasSideEffects = 1, Defs = [R16],178 isPredicable = 0 in179def CALLProfile : T_Call<"">;180 181let isCodeGenOnly = 1, isCall = 1, hasSideEffects = 1,182 Defs = [PC, R31, R6, R7, P0] in183def PS_call_stk : T_Call<"">;184 185// This pseudo instruction is used to replace int_hexagon_instrprof_custom intrinsic186// with a call to custom handler passed as the first argument to the intrinsic.187 188// Please Note:189// 1) The call to the custom handler is being treated as a special one as the190// callee is responsible for saving and restoring all the registers it needs191// to modify. This includes caller saved registers as well as r0-r5 argument192// registers. This is done to reduce the impact of instrumentation on the193// code being instrumented/profiled.194// 2) R14, R15 and R28 are reserved for PLT handling and therefore are195// part of the def list.196// 3) R0 is used to pass the unique id associated with an instrumentation site197// to the handler.198// 4) All the other registers (R29, R30, R31, PC) get modified by the call199// instruction.200 201// TODO: It may be a good idea to add a separate pseudo instruction for202// static relocation which doesn't need to reserve r14, r15 and r28.203 204let hasSideEffects = 1, isCall = 1, Defs = [R0, R14, R15, R28, R29, R30, R31, PC] in205def PS_call_instrprof_custom : Pseudo<(outs), (ins s32_0Imm:$dst, u32_0Imm:$Ii), "">;206 207// Call, no return.208let isCall = 1, hasSideEffects = 1, cofMax1 = 1, isCodeGenOnly = 1 in209def PS_callr_nr: InstHexagon<(outs), (ins IntRegs:$Rs),210 "callr $Rs", [], "", J2_callr.Itinerary, TypeJ>, OpcodeHexagon {211 bits<5> Rs;212 bits<2> Pu;213 let isPredicatedFalse = 1;214 215 let IClass = 0b0101;216 let Inst{27-21} = 0b0000101;217 let Inst{20-16} = Rs;218 }219 220let isCall = 1, hasSideEffects = 1,221 isExtended = 0, isExtendable = 1, opExtendable = 0, isCodeGenOnly = 1,222 BaseOpcode = "PS_call_nr", isExtentSigned = 1, opExtentAlign = 2 in223class Call_nr<bits<5> nbits, bit isFalse, dag iops,224 InstrItinClass itin>225 : Pseudo<(outs), iops, "">, PredRel {226 bits<2> Pu;227 bits<17> dst;228 let opExtentBits = nbits;229 let isPredicable = 0; // !if(isPred, 0, 1);230 let isPredicated = 0; // isPred;231 let isPredicatedFalse = isFalse;232 let Itinerary = itin;233}234 235def PS_call_nr : Call_nr<24, 0, (ins s32_0Imm:$Ii), J2_call.Itinerary>;236//def PS_call_nrt: Call_nr<17, 1, 0, (ins PredRegs:$Pu, s32_0Imm:$dst),237// J2_callt.Itinerary>;238//def PS_call_nrf: Call_nr<17, 1, 1, (ins PredRegs:$Pu, s32_0Imm:$dst),239// J2_callf.Itinerary>;240 241let isBranch = 1, isIndirectBranch = 1, isBarrier = 1, Defs = [PC],242 isPredicable = 1, hasSideEffects = 0, InputType = "reg",243 cofMax1 = 1 in244class T_JMPr <InstHexagon rootInst>245 : InstHexagon<(outs), (ins IntRegs:$dst), "jumpr $dst", [],246 "", rootInst.Itinerary, rootInst.Type>, OpcodeHexagon {247 bits<5> dst;248 249 let IClass = 0b0101;250 let Inst{27-21} = 0b0010100;251 let Inst{20-16} = dst;252}253 254// A return through builtin_eh_return.255let isReturn = 1, isTerminator = 1, isBarrier = 1, hasSideEffects = 0,256 isCodeGenOnly = 1, Defs = [PC], Uses = [R28], isPredicable = 0 in257def EH_RETURN_JMPR : T_JMPr<J2_jumpr>;258 259// Indirect tail-call.260let isPseudo = 1, isCall = 1, isReturn = 1, isBarrier = 1, isPredicable = 0,261 isTerminator = 1, isCodeGenOnly = 1 in262def PS_tailcall_r : T_JMPr<J2_jumpr>;263 264//265// Direct tail-calls.266let isPseudo = 1, isCall = 1, isReturn = 1, isBarrier = 1, isPredicable = 0,267 isTerminator = 1, isCodeGenOnly = 1 in268def PS_tailcall_i : Pseudo<(outs), (ins a30_2Imm:$dst), "", []>;269 270let isCodeGenOnly = 1, isPseudo = 1, Uses = [R30], hasSideEffects = 0 in271def PS_aligna : Pseudo<(outs IntRegs:$Rd), (ins u32_0Imm:$A), "", []>;272 273// Generate frameindex addresses. The main reason for the offset operand is274// that every instruction that is allowed to have frame index as an operand275// will then have that operand followed by an immediate operand (the offset).276// This simplifies the frame-index elimination code.277//278let isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1,279 isPseudo = 1, isCodeGenOnly = 1, hasSideEffects = 0, isExtendable = 1,280 isExtentSigned = 1, opExtentBits = 16, opExtentAlign = 0 in {281 let opExtendable = 2 in282 def PS_fi : Pseudo<(outs IntRegs:$Rd),283 (ins IntRegs:$fi, s32_0Imm:$off), "">;284 let opExtendable = 3 in285 def PS_fia : Pseudo<(outs IntRegs:$Rd),286 (ins IntRegs:$Rs, IntRegs:$fi, s32_0Imm:$off), "">;287}288 289class CondStr<string CReg, bit True, bit New> {290 string S = "if (" # !if(True,"","!") # CReg # !if(New,".new","") # ") ";291}292class JumpOpcStr<string Mnemonic, bit Taken> {293 string S = Mnemonic # !if(Taken, ":t", ":nt");294}295let isBranch = 1, isIndirectBranch = 1, Defs = [PC], isPredicated = 1,296 hasSideEffects = 0, InputType = "reg", cofMax1 = 1 in297class T_JMPr_c <bit PredNot, bit isPredNew, bit isTak, InstHexagon rootInst>298 : InstHexagon<(outs), (ins PredRegs:$src, IntRegs:$dst),299 CondStr<"$src", !if(PredNot,0,1), isPredNew>.S #300 JumpOpcStr<"jumpr", isTak>.S # " $dst",301 [], "", rootInst.Itinerary, rootInst.Type>, OpcodeHexagon {302 303 let isTaken = isTak;304 let isPredicatedFalse = PredNot;305 let isPredicatedNew = isPredNew;306 bits<2> src;307 bits<5> dst;308 309 let IClass = 0b0101;310 311 let Inst{27-22} = 0b001101;312 let Inst{21} = PredNot;313 let Inst{20-16} = dst;314 let Inst{12} = isTak;315 let Inst{11} = isPredNew;316 let Inst{9-8} = src;317}318 319let isTerminator = 1, hasSideEffects = 0, isReturn = 1, isCodeGenOnly = 1,320 isBarrier = 1, BaseOpcode = "JMPret" in {321 def PS_jmpret : T_JMPr<J2_jumpr>, PredNewRel;322 def PS_jmprett : T_JMPr_c<0, 0, 0, J2_jumprt>, PredNewRel;323 def PS_jmpretf : T_JMPr_c<1, 0, 0, J2_jumprf>, PredNewRel;324 def PS_jmprettnew : T_JMPr_c<0, 1, 0, J2_jumprtnew>, PredNewRel;325 def PS_jmpretfnew : T_JMPr_c<1, 1, 0, J2_jumprfnew>, PredNewRel;326 def PS_jmprettnewpt : T_JMPr_c<0, 1, 1, J2_jumprtnewpt>, PredNewRel;327 def PS_jmpretfnewpt : T_JMPr_c<1, 1, 1, J2_jumprfnewpt>, PredNewRel;328}329 330//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)>;331 332// The reason for the custom inserter is to record all ALLOCA instructions333// in MachineFunctionInfo.334let Defs = [R29], hasSideEffects = 1 in335def PS_alloca: Pseudo <(outs IntRegs:$Rd),336 (ins IntRegs:$Rs, u32_0Imm:$A), "", []>;337 338// Load predicate.339let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 13,340 isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in341def LDriw_pred : LDInst<(outs PredRegs:$dst),342 (ins IntRegs:$addr, s32_0Imm:$off),343 ".error \"should not emit\"", []>;344 345// Load modifier.346let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 13,347 isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in348def LDriw_ctr : LDInst<(outs CtrRegs:$dst),349 (ins IntRegs:$addr, s32_0Imm:$off),350 ".error \"should not emit\"", []>;351 352 353let isCodeGenOnly = 1, isPseudo = 1 in354def PS_pselect: InstHexagon<(outs DoubleRegs:$Rd),355 (ins PredRegs:$Pu, DoubleRegs:$Rs, DoubleRegs:$Rt),356 ".error \"should not emit\" ", [], "", A2_tfrpt.Itinerary, TypeALU32_2op>;357 358let isBranch = 1, isBarrier = 1, Defs = [PC], hasSideEffects = 0,359 isPredicable = 1,360 isExtendable = 1, opExtendable = 0, isExtentSigned = 1,361 opExtentBits = 24, opExtentAlign = 2, InputType = "imm" in362class T_JMP: InstHexagon<(outs), (ins b30_2Imm:$dst),363 "jump $dst",364 [], "", J2_jump.Itinerary, TypeJ>, OpcodeHexagon {365 bits<24> dst;366 let IClass = 0b0101;367 368 let Inst{27-25} = 0b100;369 let Inst{24-16} = dst{23-15};370 let Inst{13-1} = dst{14-2};371}372 373// Restore registers and dealloc return function call.374let isCall = 1, isBarrier = 1, isReturn = 1, isTerminator = 1,375 Defs = [R29, R30, R31, PC], isPredicable = 0, isAsmParserOnly = 1 in {376 def RESTORE_DEALLOC_RET_JMP_V4 : T_JMP;377 378 let isExtended = 1, opExtendable = 0 in379 def RESTORE_DEALLOC_RET_JMP_V4_EXT : T_JMP;380 381 let Defs = [R14, R15, R28, R29, R30, R31, PC] in {382 def RESTORE_DEALLOC_RET_JMP_V4_PIC : T_JMP;383 384 let isExtended = 1, opExtendable = 0 in385 def RESTORE_DEALLOC_RET_JMP_V4_EXT_PIC : T_JMP;386 }387}388 389// Restore registers and dealloc frame before a tail call.390let isCall = 1, Defs = [R29, R30, R31, PC], isAsmParserOnly = 1 in {391 def RESTORE_DEALLOC_BEFORE_TAILCALL_V4 : T_Call<"">, PredRel;392 393 let isExtended = 1, opExtendable = 0 in394 def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT : T_Call<"">, PredRel;395 396 let Defs = [R14, R15, R28, R29, R30, R31, PC] in {397 def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC : T_Call<"">, PredRel;398 399 let isExtended = 1, opExtendable = 0 in400 def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC : T_Call<"">, PredRel;401 }402}403 404// Save registers function call.405let isCall = 1, Uses = [R29, R31], isAsmParserOnly = 1 in {406 def SAVE_REGISTERS_CALL_V4 : T_Call<"">, PredRel;407 408 let isExtended = 1, opExtendable = 0 in409 def SAVE_REGISTERS_CALL_V4_EXT : T_Call<"">, PredRel;410 411 let Defs = [P0] in412 def SAVE_REGISTERS_CALL_V4STK : T_Call<"">, PredRel;413 414 let Defs = [P0], isExtended = 1, opExtendable = 0 in415 def SAVE_REGISTERS_CALL_V4STK_EXT : T_Call<"">, PredRel;416 417 let Defs = [R14, R15, R28] in418 def SAVE_REGISTERS_CALL_V4_PIC : T_Call<"">, PredRel;419 420 let Defs = [R14, R15, R28], isExtended = 1, opExtendable = 0 in421 def SAVE_REGISTERS_CALL_V4_EXT_PIC : T_Call<"">, PredRel;422 423 let Defs = [R14, R15, R28, P0] in424 def SAVE_REGISTERS_CALL_V4STK_PIC : T_Call<"">, PredRel;425 426 let Defs = [R14, R15, R28, P0], isExtended = 1, opExtendable = 0 in427 def SAVE_REGISTERS_CALL_V4STK_EXT_PIC : T_Call<"">, PredRel;428}429 430let Predicates = [UseHVX], isPseudo = 1, isCodeGenOnly = 1,431 hasSideEffects = 0, hasPostISelHook = 1 in432class Vsplatr_template : InstHexagon<(outs HvxVR:$Vd), (ins IntRegs:$Rs),433 "", [], "", V6_lvsplatw.Itinerary, V6_lvsplatw.Type>;434def PS_vsplatrb: Vsplatr_template;435def PS_vsplatrh: Vsplatr_template;436def PS_vsplatrw: Vsplatr_template;437 438let Predicates = [UseHVX], isPseudo = 1, isCodeGenOnly = 1,439 hasSideEffects = 0, hasPostISelHook = 1 in440class Vsplati_template : InstHexagon<(outs HvxVR:$Vd), (ins s32_0Imm:$Val),441 "", [], "", V6_lvsplatw.Itinerary, V6_lvsplatw.Type>;442def PS_vsplatib: Vsplati_template;443def PS_vsplatih: Vsplati_template;444def PS_vsplatiw: Vsplati_template;445 446// Vector store pseudos447let Predicates = [HasV60,UseHVX], isPseudo = 1, isCodeGenOnly = 1,448 mayStore = 1, accessSize = HVXVectorAccess, hasSideEffects = 0 in449class STriv_template<RegisterClass RC, InstHexagon rootInst>450 : InstHexagon<(outs), (ins IntRegs:$addr, s32_0Imm:$off, RC:$src),451 "", [], "", rootInst.Itinerary, rootInst.Type>;452 453def PS_vstorerv_ai: STriv_template<HvxVR, V6_vS32b_ai>,454 Requires<[HasV60,UseHVX]>;455def PS_vstorerv_nt_ai: STriv_template<HvxVR, V6_vS32b_nt_ai>,456 Requires<[HasV60,UseHVX]>;457def PS_vstorerw_ai: STriv_template<HvxWR, V6_vS32b_ai>,458 Requires<[HasV60,UseHVX]>;459def PS_vstorerw_nt_ai: STriv_template<HvxWR, V6_vS32b_nt_ai>,460 Requires<[HasV60,UseHVX]>;461 462let isPseudo = 1, isCodeGenOnly = 1, mayStore = 1, hasSideEffects = 0 in463def PS_vstorerq_ai: Pseudo<(outs),464 (ins IntRegs:$Rs, s32_0Imm:$Off, HvxQR:$Qt), "", []>,465 Requires<[HasV60,UseHVX]>;466 467// Vector load pseudos468let Predicates = [HasV60, UseHVX], isPseudo = 1, isCodeGenOnly = 1,469 mayLoad = 1, accessSize = HVXVectorAccess, hasSideEffects = 0 in470class LDriv_template<RegisterClass RC, InstHexagon rootInst>471 : InstHexagon<(outs RC:$dst), (ins IntRegs:$addr, s32_0Imm:$off),472 "", [], "", rootInst.Itinerary, rootInst.Type>;473 474def PS_vloadrv_ai: LDriv_template<HvxVR, V6_vL32b_ai>,475 Requires<[HasV60,UseHVX]>;476def PS_vloadrv_nt_ai: LDriv_template<HvxVR, V6_vL32b_nt_ai>,477 Requires<[HasV60,UseHVX]>;478def PS_vloadrw_ai: LDriv_template<HvxWR, V6_vL32b_ai>,479 Requires<[HasV60,UseHVX]>;480def PS_vloadrw_nt_ai: LDriv_template<HvxWR, V6_vL32b_nt_ai>,481 Requires<[HasV60,UseHVX]>;482 483let isPseudo = 1, isCodeGenOnly = 1, mayLoad = 1, hasSideEffects = 0 in484def PS_vloadrq_ai: Pseudo<(outs HvxQR:$Qd),485 (ins IntRegs:$Rs, s32_0Imm:$Off), "", []>,486 Requires<[HasV60,UseHVX]>;487 488 489let isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in490class VSELInst<dag outs, dag ins, InstHexagon rootInst>491 : InstHexagon<outs, ins, "", [], "", rootInst.Itinerary, rootInst.Type>;492 493def PS_vselect: VSELInst<(outs HvxVR:$dst),494 (ins PredRegs:$src1, HvxVR:$src2, HvxVR:$src3), V6_vcmov>,495 Requires<[HasV60,UseHVX]>;496def PS_wselect: VSELInst<(outs HvxWR:$dst),497 (ins PredRegs:$src1, HvxWR:$src2, HvxWR:$src3), V6_vccombine>,498 Requires<[HasV60,UseHVX]>;499 500let hasSideEffects = 0, isReMaterializable = 1, isPseudo = 1,501 isCodeGenOnly = 1 in {502 def PS_qtrue: InstHexagon<(outs HvxQR:$Qd), (ins), "", [], "",503 V6_veqw.Itinerary, TypeCVI_VA>;504 def PS_qfalse: InstHexagon<(outs HvxQR:$Qd), (ins), "", [], "",505 V6_vgtw.Itinerary, TypeCVI_VA>;506 def PS_vdd0: InstHexagon<(outs HvxWR:$Vd), (ins), "", [], "",507 V6_vsubw_dv.Itinerary, TypeCVI_VA_DV>;508}509 510// Store predicate.511let isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 13,512 isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in513def STriw_pred : STInst<(outs),514 (ins IntRegs:$addr, s32_0Imm:$off, PredRegs:$src1),515 ".error \"should not emit\"", []>;516// Store modifier.517let isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 13,518 isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in519def STriw_ctr : STInst<(outs),520 (ins IntRegs:$addr, s32_0Imm:$off, CtrRegs:$src1),521 ".error \"should not emit\"", []>;522 523let isExtendable = 1, opExtendable = 1, opExtentBits = 6,524 isAsmParserOnly = 1 in525def TFRI64_V4 : InstHexagon<(outs DoubleRegs:$dst),526 (ins u64_0Imm:$src1),527 "$dst = #$src1", [], "",528 A2_combineii.Itinerary, TypeALU32_2op>, OpcodeHexagon;529 530// Hexagon doesn't have a vector multiply with C semantics.531// Instead, generate a pseudo instruction that gets expanded into two532// scalar MPYI instructions.533// This is expanded by ExpandPostRAPseudos.534let isPseudo = 1 in535def PS_vmulw : PseudoM<(outs DoubleRegs:$Rd),536 (ins DoubleRegs:$Rs, DoubleRegs:$Rt), "", []>;537 538let isPseudo = 1 in539def PS_vmulw_acc : PseudoM<(outs DoubleRegs:$Rd),540 (ins DoubleRegs:$Rx, DoubleRegs:$Rs, DoubleRegs:$Rt), "", [],541 "$Rd = $Rx">;542 543def DuplexIClass0: InstDuplex < 0 >;544def DuplexIClass1: InstDuplex < 1 >;545def DuplexIClass2: InstDuplex < 2 >;546let isExtendable = 1 in {547 def DuplexIClass3: InstDuplex < 3 >;548 def DuplexIClass4: InstDuplex < 4 >;549 def DuplexIClass5: InstDuplex < 5 >;550 def DuplexIClass6: InstDuplex < 6 >;551 def DuplexIClass7: InstDuplex < 7 >;552}553def DuplexIClass8: InstDuplex < 8 >;554def DuplexIClass9: InstDuplex < 9 >;555def DuplexIClassA: InstDuplex < 0xA >;556def DuplexIClassB: InstDuplex < 0xB >;557def DuplexIClassC: InstDuplex < 0xC >;558def DuplexIClassD: InstDuplex < 0xD >;559def DuplexIClassE: InstDuplex < 0xE >;560def DuplexIClassF: InstDuplex < 0xF >;561 562// Pseudos for circular buffer instructions. These are needed in order to563// allocate the correct pair of CSx and Mx registers.564multiclass NewCircularLoad<RegisterClass RC, MemAccessSize MS> {565 566let isCodeGenOnly = 1, isPseudo = 1, Defs = [CS], Uses = [CS],567 addrMode = PostInc, accessSize = MS, hasSideEffects = 0 in {568 // Use timing class of L2_loadrb_pci.569 def NAME#_pci : LDInst<(outs RC:$Rd32, IntRegs:$Rx32),570 (ins IntRegs:$Rx32in, s4_0Imm:$Ii, ModRegs:$Mu2, IntRegs:$Cs),571 ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_5ceb2f9e>;572 573 // Use timing class of L2_loadrb_pcr.574 def NAME#_pcr : LDInst<(outs RC:$Rd32, IntRegs:$Rx32),575 (ins IntRegs:$Rx32in, ModRegs:$Mu2, IntRegs:$Cs),576 ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_075c8dd8>;577}578}579 580defm PS_loadrub : NewCircularLoad<IntRegs, ByteAccess>;581defm PS_loadrb : NewCircularLoad<IntRegs, ByteAccess>;582defm PS_loadruh : NewCircularLoad<IntRegs, HalfWordAccess>;583defm PS_loadrh : NewCircularLoad<IntRegs, HalfWordAccess>;584defm PS_loadri : NewCircularLoad<IntRegs, WordAccess>;585defm PS_loadrd : NewCircularLoad<DoubleRegs, DoubleWordAccess>;586 587multiclass NewCircularStore<RegisterClass RC, MemAccessSize MS> {588 589let isCodeGenOnly = 1, isPseudo = 1, Defs = [CS], Uses = [CS],590 addrMode = PostInc, accessSize = MS, hasSideEffects = 0 in {591 // Use timing class of S2_storerb_pci.592 def NAME#_pci : STInst<(outs IntRegs:$Rx32),593 (ins IntRegs:$Rx32in, s4_0Imm:$Ii, ModRegs:$Mu2, RC:$Rt32, IntRegs:$Cs),594 ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_b4dc7630>;595 596 // Use timing class of S2_storerb_pcr.597 def NAME#_pcr : STInst<(outs IntRegs:$Rx32),598 (ins IntRegs:$Rx32in, ModRegs:$Mu2, RC:$Rt32, IntRegs:$Cs),599 ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_a2b365d2>;600}601}602 603defm PS_storerb : NewCircularStore<IntRegs, ByteAccess>;604defm PS_storerh : NewCircularStore<IntRegs, HalfWordAccess>;605defm PS_storerf : NewCircularStore<IntRegs, HalfWordAccess>;606defm PS_storeri : NewCircularStore<IntRegs, WordAccess>;607defm PS_storerd : NewCircularStore<DoubleRegs, WordAccess>;608 609// A pseudo that generates a runtime crash. This is used to implement610// __builtin_trap.611let hasSideEffects = 1, isPseudo = 1, isCodeGenOnly = 1, isSolo = 1 in612def PS_crash: InstHexagon<(outs), (ins), "", [], "", PSEUDO, TypePSEUDO>;613 614// This is actual trap1 instruction from before v65. It's here since it is615// no longer included in DepInstrInfo.td.616def PS_trap1 : HInst<(outs), (ins u8_0Imm:$Ii), "trap1(#$Ii)", tc_53c851ab,617 TypeJ>, Enc_a51a9a, Requires<[HasPreV65]> {618 let Inst{1-0} = 0b00;619 let Inst{7-5} = 0b000;620 let Inst{13-13} = 0b0;621 let Inst{31-16} = 0b0101010010000000;622}623 624