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-exception 6// 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. The 11// 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 in 25def 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 in 34def 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 Instructions 40let isReMaterializable = 1, isMoveImm = 1, hasSideEffects = 0, 41 hasNewValue = 1, opNewValue = 0 in 42class 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 in 73def 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 in 78def 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 in 82def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 83 ".error \"should not emit\" ", []>; 84 85let Defs = [R29, R30, R31], Uses = [R29], isPseudo = 1 in 86def 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 in 113class 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 in 133class 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.lpcfg 156let 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 in 164class 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 in 179def CALLProfile : T_Call<"">; 180 181let isCodeGenOnly = 1, isCall = 1, hasSideEffects = 1, 182 Defs = [PC, R31, R6, R7, P0] in 183def PS_call_stk : T_Call<"">; 184 185// This pseudo instruction is used to replace int_hexagon_instrprof_custom intrinsic 186// with a call to custom handler passed as the first argument to the intrinsic. 187 188// Pleae Note: 189// 1) The call to the custom handler is being treated as a special one as the 190// callee is responsible for saving and restoring all the registers it needs 191// to modify. This includes caller saved registers as well as r0-r5 argument 192// registers. This is done to reduce the impact of instrumentation on the 193// code being instrumented/profiled. 194// 2) R14, R15 and R28 are reserved for PLT handling and therefore are 195// part of the def list. 196// 3) R0 is used to pass the unique id associated with an instrumentation site 197// to the handler. 198// 4) All the other registers (R29, R30, R31, PC) get modified by the call 199// instruction. 200 201// TODO: It may be a good idea to add a separate pseudo instruction for 202// 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] in 205def 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 in 209def 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 in 223class 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 in 244class 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 in 257def 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 in 262def 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 in 268def PS_tailcall_i : Pseudo<(outs), (ins a30_2Imm:$dst), "", []>; 269 270let isCodeGenOnly = 1, isPseudo = 1, Uses = [R30], hasSideEffects = 0 in 271def PS_aligna : Pseudo<(outs IntRegs:$Rd), (ins u32_0Imm:$A), "", []>; 272 273// Generate frameindex addresses. The main reason for the offset operand is 274// that every instruction that is allowed to have frame index as an operand 275// 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 in 282 def PS_fi : Pseudo<(outs IntRegs:$Rd), 283 (ins IntRegs:$fi, s32_0Imm:$off), "">; 284 let opExtendable = 3 in 285 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 in 297class 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 instructions 333// in MachineFunctionInfo. 334let Defs = [R29], hasSideEffects = 1 in 335def 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 in 341def 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 in 348def 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 in 354def 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" in 362class 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 in 379 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 in 385 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 in 394 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 in 400 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 in 409 def SAVE_REGISTERS_CALL_V4_EXT : T_Call<"">, PredRel; 410 411 let Defs = [P0] in 412 def SAVE_REGISTERS_CALL_V4STK : T_Call<"">, PredRel; 413 414 let Defs = [P0], isExtended = 1, opExtendable = 0 in 415 def SAVE_REGISTERS_CALL_V4STK_EXT : T_Call<"">, PredRel; 416 417 let Defs = [R14, R15, R28] in 418 def SAVE_REGISTERS_CALL_V4_PIC : T_Call<"">, PredRel; 419 420 let Defs = [R14, R15, R28], isExtended = 1, opExtendable = 0 in 421 def SAVE_REGISTERS_CALL_V4_EXT_PIC : T_Call<"">, PredRel; 422 423 let Defs = [R14, R15, R28, P0] in 424 def SAVE_REGISTERS_CALL_V4STK_PIC : T_Call<"">, PredRel; 425 426 let Defs = [R14, R15, R28, P0], isExtended = 1, opExtendable = 0 in 427 def SAVE_REGISTERS_CALL_V4STK_EXT_PIC : T_Call<"">, PredRel; 428} 429 430let Predicates = [UseHVX], isPseudo = 1, isCodeGenOnly = 1, 431 hasSideEffects = 0, hasPostISelHook = 1 in 432class 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 in 440class 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 pseudos 447let Predicates = [HasV60,UseHVX], isPseudo = 1, isCodeGenOnly = 1, 448 mayStore = 1, accessSize = HVXVectorAccess, hasSideEffects = 0 in 449class 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 in 463def PS_vstorerq_ai: Pseudo<(outs), 464 (ins IntRegs:$Rs, s32_0Imm:$Off, HvxQR:$Qt), "", []>, 465 Requires<[HasV60,UseHVX]>; 466 467// Vector load pseudos 468let Predicates = [HasV60, UseHVX], isPseudo = 1, isCodeGenOnly = 1, 469 mayLoad = 1, accessSize = HVXVectorAccess, hasSideEffects = 0 in 470class 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 in 484def 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 in 490class 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 in 513def 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 in 519def 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 in 525def 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 two 532// scalar MPYI instructions. 533// This is expanded by ExpandPostRAPseudos. 534let isPseudo = 1 in 535def PS_vmulw : PseudoM<(outs DoubleRegs:$Rd), 536 (ins DoubleRegs:$Rs, DoubleRegs:$Rt), "", []>; 537 538let isPseudo = 1 in 539def 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 to 563// 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 implement 610// __builtin_trap. 611let hasSideEffects = 1, isPseudo = 1, isCodeGenOnly = 1, isSolo = 1 in 612def PS_crash: InstHexagon<(outs), (ins), "", [], "", PSEUDO, TypePSEUDO>; 613 614// This is actual trap1 instruction from before v65. It's here since it is 615// 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