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// Call, no return. 186let isCall = 1, hasSideEffects = 1, cofMax1 = 1, isCodeGenOnly = 1 in 187def PS_callr_nr: InstHexagon<(outs), (ins IntRegs:$Rs), 188 "callr $Rs", [], "", J2_callr.Itinerary, TypeJ>, OpcodeHexagon { 189 bits<5> Rs; 190 bits<2> Pu; 191 let isPredicatedFalse = 1; 192 193 let IClass = 0b0101; 194 let Inst{27-21} = 0b0000101; 195 let Inst{20-16} = Rs; 196 } 197 198let isCall = 1, hasSideEffects = 1, 199 isExtended = 0, isExtendable = 1, opExtendable = 0, isCodeGenOnly = 1, 200 BaseOpcode = "PS_call_nr", isExtentSigned = 1, opExtentAlign = 2 in 201class Call_nr<bits<5> nbits, bit isPred, bit isFalse, dag iops, 202 InstrItinClass itin> 203 : Pseudo<(outs), iops, "">, PredRel { 204 bits<2> Pu; 205 bits<17> dst; 206 let opExtentBits = nbits; 207 let isPredicable = 0; // !if(isPred, 0, 1); 208 let isPredicated = 0; // isPred; 209 let isPredicatedFalse = isFalse; 210 let Itinerary = itin; 211} 212 213def PS_call_nr : Call_nr<24, 0, 0, (ins s32_0Imm:$Ii), J2_call.Itinerary>; 214//def PS_call_nrt: Call_nr<17, 1, 0, (ins PredRegs:$Pu, s32_0Imm:$dst), 215// J2_callt.Itinerary>; 216//def PS_call_nrf: Call_nr<17, 1, 1, (ins PredRegs:$Pu, s32_0Imm:$dst), 217// J2_callf.Itinerary>; 218 219let isBranch = 1, isIndirectBranch = 1, isBarrier = 1, Defs = [PC], 220 isPredicable = 1, hasSideEffects = 0, InputType = "reg", 221 cofMax1 = 1 in 222class T_JMPr <InstHexagon rootInst> 223 : InstHexagon<(outs), (ins IntRegs:$dst), "jumpr $dst", [], 224 "", rootInst.Itinerary, rootInst.Type>, OpcodeHexagon { 225 bits<5> dst; 226 227 let IClass = 0b0101; 228 let Inst{27-21} = 0b0010100; 229 let Inst{20-16} = dst; 230} 231 232// A return through builtin_eh_return. 233let isReturn = 1, isTerminator = 1, isBarrier = 1, hasSideEffects = 0, 234 isCodeGenOnly = 1, Defs = [PC], Uses = [R28], isPredicable = 0 in 235def EH_RETURN_JMPR : T_JMPr<J2_jumpr>; 236 237// Indirect tail-call. 238let isPseudo = 1, isCall = 1, isReturn = 1, isBarrier = 1, isPredicable = 0, 239 isTerminator = 1, isCodeGenOnly = 1 in 240def PS_tailcall_r : T_JMPr<J2_jumpr>; 241 242// 243// Direct tail-calls. 244let isPseudo = 1, isCall = 1, isReturn = 1, isBarrier = 1, isPredicable = 0, 245 isTerminator = 1, isCodeGenOnly = 1 in 246def PS_tailcall_i : Pseudo<(outs), (ins a30_2Imm:$dst), "", []>; 247 248let isCodeGenOnly = 1, isPseudo = 1, Uses = [R30], hasSideEffects = 0 in 249def PS_aligna : Pseudo<(outs IntRegs:$Rd), (ins u32_0Imm:$A), "", []>; 250 251// Generate frameindex addresses. The main reason for the offset operand is 252// that every instruction that is allowed to have frame index as an operand 253// will then have that operand followed by an immediate operand (the offset). 254// This simplifies the frame-index elimination code. 255// 256let isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1, 257 isPseudo = 1, isCodeGenOnly = 1, hasSideEffects = 0, isExtendable = 1, 258 isExtentSigned = 1, opExtentBits = 16, opExtentAlign = 0 in { 259 let opExtendable = 2 in 260 def PS_fi : Pseudo<(outs IntRegs:$Rd), 261 (ins IntRegs:$fi, s32_0Imm:$off), "">; 262 let opExtendable = 3 in 263 def PS_fia : Pseudo<(outs IntRegs:$Rd), 264 (ins IntRegs:$Rs, IntRegs:$fi, s32_0Imm:$off), "">; 265} 266 267class CondStr<string CReg, bit True, bit New> { 268 string S = "if (" # !if(True,"","!") # CReg # !if(New,".new","") # ") "; 269} 270class JumpOpcStr<string Mnemonic, bit New, bit Taken> { 271 string S = Mnemonic # !if(Taken, ":t", ":nt"); 272} 273let isBranch = 1, isIndirectBranch = 1, Defs = [PC], isPredicated = 1, 274 hasSideEffects = 0, InputType = "reg", cofMax1 = 1 in 275class T_JMPr_c <bit PredNot, bit isPredNew, bit isTak, InstHexagon rootInst> 276 : InstHexagon<(outs), (ins PredRegs:$src, IntRegs:$dst), 277 CondStr<"$src", !if(PredNot,0,1), isPredNew>.S # 278 JumpOpcStr<"jumpr", isPredNew, isTak>.S # " $dst", 279 [], "", rootInst.Itinerary, rootInst.Type>, OpcodeHexagon { 280 281 let isTaken = isTak; 282 let isPredicatedFalse = PredNot; 283 let isPredicatedNew = isPredNew; 284 bits<2> src; 285 bits<5> dst; 286 287 let IClass = 0b0101; 288 289 let Inst{27-22} = 0b001101; 290 let Inst{21} = PredNot; 291 let Inst{20-16} = dst; 292 let Inst{12} = isTak; 293 let Inst{11} = isPredNew; 294 let Inst{9-8} = src; 295} 296 297let isTerminator = 1, hasSideEffects = 0, isReturn = 1, isCodeGenOnly = 1, 298 isBarrier = 1, BaseOpcode = "JMPret" in { 299 def PS_jmpret : T_JMPr<J2_jumpr>, PredNewRel; 300 def PS_jmprett : T_JMPr_c<0, 0, 0, J2_jumprt>, PredNewRel; 301 def PS_jmpretf : T_JMPr_c<1, 0, 0, J2_jumprf>, PredNewRel; 302 def PS_jmprettnew : T_JMPr_c<0, 1, 0, J2_jumprtnew>, PredNewRel; 303 def PS_jmpretfnew : T_JMPr_c<1, 1, 0, J2_jumprfnew>, PredNewRel; 304 def PS_jmprettnewpt : T_JMPr_c<0, 1, 1, J2_jumprtnewpt>, PredNewRel; 305 def PS_jmpretfnewpt : T_JMPr_c<1, 1, 1, J2_jumprfnewpt>, PredNewRel; 306} 307 308//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)>; 309 310// The reason for the custom inserter is to record all ALLOCA instructions 311// in MachineFunctionInfo. 312let Defs = [R29], hasSideEffects = 1 in 313def PS_alloca: Pseudo <(outs IntRegs:$Rd), 314 (ins IntRegs:$Rs, u32_0Imm:$A), "", []>; 315 316// Load predicate. 317let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 13, 318 isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in 319def LDriw_pred : LDInst<(outs PredRegs:$dst), 320 (ins IntRegs:$addr, s32_0Imm:$off), 321 ".error \"should not emit\"", []>; 322 323// Load modifier. 324let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 13, 325 isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in 326def LDriw_ctr : LDInst<(outs CtrRegs:$dst), 327 (ins IntRegs:$addr, s32_0Imm:$off), 328 ".error \"should not emit\"", []>; 329 330 331let isCodeGenOnly = 1, isPseudo = 1 in 332def PS_pselect: InstHexagon<(outs DoubleRegs:$Rd), 333 (ins PredRegs:$Pu, DoubleRegs:$Rs, DoubleRegs:$Rt), 334 ".error \"should not emit\" ", [], "", A2_tfrpt.Itinerary, TypeALU32_2op>; 335 336let isBranch = 1, isBarrier = 1, Defs = [PC], hasSideEffects = 0, 337 isPredicable = 1, 338 isExtendable = 1, opExtendable = 0, isExtentSigned = 1, 339 opExtentBits = 24, opExtentAlign = 2, InputType = "imm" in 340class T_JMP: InstHexagon<(outs), (ins b30_2Imm:$dst), 341 "jump $dst", 342 [], "", J2_jump.Itinerary, TypeJ>, OpcodeHexagon { 343 bits<24> dst; 344 let IClass = 0b0101; 345 346 let Inst{27-25} = 0b100; 347 let Inst{24-16} = dst{23-15}; 348 let Inst{13-1} = dst{14-2}; 349} 350 351// Restore registers and dealloc return function call. 352let isCall = 1, isBarrier = 1, isReturn = 1, isTerminator = 1, 353 Defs = [R29, R30, R31, PC], isPredicable = 0, isAsmParserOnly = 1 in { 354 def RESTORE_DEALLOC_RET_JMP_V4 : T_JMP; 355 356 let isExtended = 1, opExtendable = 0 in 357 def RESTORE_DEALLOC_RET_JMP_V4_EXT : T_JMP; 358 359 let Defs = [R14, R15, R28, R29, R30, R31, PC] in { 360 def RESTORE_DEALLOC_RET_JMP_V4_PIC : T_JMP; 361 362 let isExtended = 1, opExtendable = 0 in 363 def RESTORE_DEALLOC_RET_JMP_V4_EXT_PIC : T_JMP; 364 } 365} 366 367// Restore registers and dealloc frame before a tail call. 368let isCall = 1, Defs = [R29, R30, R31, PC], isAsmParserOnly = 1 in { 369 def RESTORE_DEALLOC_BEFORE_TAILCALL_V4 : T_Call<"">, PredRel; 370 371 let isExtended = 1, opExtendable = 0 in 372 def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT : T_Call<"">, PredRel; 373 374 let Defs = [R14, R15, R28, R29, R30, R31, PC] in { 375 def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC : T_Call<"">, PredRel; 376 377 let isExtended = 1, opExtendable = 0 in 378 def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC : T_Call<"">, PredRel; 379 } 380} 381 382// Save registers function call. 383let isCall = 1, Uses = [R29, R31], isAsmParserOnly = 1 in { 384 def SAVE_REGISTERS_CALL_V4 : T_Call<"">, PredRel; 385 386 let isExtended = 1, opExtendable = 0 in 387 def SAVE_REGISTERS_CALL_V4_EXT : T_Call<"">, PredRel; 388 389 let Defs = [P0] in 390 def SAVE_REGISTERS_CALL_V4STK : T_Call<"">, PredRel; 391 392 let Defs = [P0], isExtended = 1, opExtendable = 0 in 393 def SAVE_REGISTERS_CALL_V4STK_EXT : T_Call<"">, PredRel; 394 395 let Defs = [R14, R15, R28] in 396 def SAVE_REGISTERS_CALL_V4_PIC : T_Call<"">, PredRel; 397 398 let Defs = [R14, R15, R28], isExtended = 1, opExtendable = 0 in 399 def SAVE_REGISTERS_CALL_V4_EXT_PIC : T_Call<"">, PredRel; 400 401 let Defs = [R14, R15, R28, P0] in 402 def SAVE_REGISTERS_CALL_V4STK_PIC : T_Call<"">, PredRel; 403 404 let Defs = [R14, R15, R28, P0], isExtended = 1, opExtendable = 0 in 405 def SAVE_REGISTERS_CALL_V4STK_EXT_PIC : T_Call<"">, PredRel; 406} 407 408// Vector store pseudos 409let Predicates = [HasV60,UseHVX], isPseudo = 1, isCodeGenOnly = 1, 410 mayStore = 1, accessSize = HVXVectorAccess, hasSideEffects = 0 in 411class STriv_template<RegisterClass RC, InstHexagon rootInst> 412 : InstHexagon<(outs), (ins IntRegs:$addr, s32_0Imm:$off, RC:$src), 413 "", [], "", rootInst.Itinerary, rootInst.Type>; 414 415def PS_vstorerv_ai: STriv_template<HvxVR, V6_vS32b_ai>, 416 Requires<[HasV60,UseHVX]>; 417def PS_vstorerv_nt_ai: STriv_template<HvxVR, V6_vS32b_nt_ai>, 418 Requires<[HasV60,UseHVX]>; 419def PS_vstorerw_ai: STriv_template<HvxWR, V6_vS32b_ai>, 420 Requires<[HasV60,UseHVX]>; 421def PS_vstorerw_nt_ai: STriv_template<HvxWR, V6_vS32b_nt_ai>, 422 Requires<[HasV60,UseHVX]>; 423 424let isPseudo = 1, isCodeGenOnly = 1, mayStore = 1, hasSideEffects = 0 in 425def PS_vstorerq_ai: Pseudo<(outs), 426 (ins IntRegs:$Rs, s32_0Imm:$Off, HvxQR:$Qt), "", []>, 427 Requires<[HasV60,UseHVX]>; 428 429// Vector load pseudos 430let Predicates = [HasV60, UseHVX], isPseudo = 1, isCodeGenOnly = 1, 431 mayLoad = 1, accessSize = HVXVectorAccess, hasSideEffects = 0 in 432class LDriv_template<RegisterClass RC, InstHexagon rootInst> 433 : InstHexagon<(outs RC:$dst), (ins IntRegs:$addr, s32_0Imm:$off), 434 "", [], "", rootInst.Itinerary, rootInst.Type>; 435 436def PS_vloadrv_ai: LDriv_template<HvxVR, V6_vL32b_ai>, 437 Requires<[HasV60,UseHVX]>; 438def PS_vloadrv_nt_ai: LDriv_template<HvxVR, V6_vL32b_nt_ai>, 439 Requires<[HasV60,UseHVX]>; 440def PS_vloadrw_ai: LDriv_template<HvxWR, V6_vL32b_ai>, 441 Requires<[HasV60,UseHVX]>; 442def PS_vloadrw_nt_ai: LDriv_template<HvxWR, V6_vL32b_nt_ai>, 443 Requires<[HasV60,UseHVX]>; 444 445let isPseudo = 1, isCodeGenOnly = 1, mayLoad = 1, hasSideEffects = 0 in 446def PS_vloadrq_ai: Pseudo<(outs HvxQR:$Qd), 447 (ins IntRegs:$Rs, s32_0Imm:$Off), "", []>, 448 Requires<[HasV60,UseHVX]>; 449 450 451let isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in 452class VSELInst<dag outs, dag ins, InstHexagon rootInst> 453 : InstHexagon<outs, ins, "", [], "", rootInst.Itinerary, rootInst.Type>; 454 455def PS_vselect: VSELInst<(outs HvxVR:$dst), 456 (ins PredRegs:$src1, HvxVR:$src2, HvxVR:$src3), V6_vcmov>, 457 Requires<[HasV60,UseHVX]>; 458def PS_wselect: VSELInst<(outs HvxWR:$dst), 459 (ins PredRegs:$src1, HvxWR:$src2, HvxWR:$src3), V6_vccombine>, 460 Requires<[HasV60,UseHVX]>; 461 462let hasSideEffects = 0, isReMaterializable = 1, isPseudo = 1, 463 isCodeGenOnly = 1 in { 464 def PS_qtrue: InstHexagon<(outs HvxQR:$Qd), (ins), "", [], "", 465 V6_veqw.Itinerary, TypeCVI_VA>; 466 def PS_qfalse: InstHexagon<(outs HvxQR:$Qd), (ins), "", [], "", 467 V6_vgtw.Itinerary, TypeCVI_VA>; 468 def PS_vdd0: InstHexagon<(outs HvxWR:$Vd), (ins), "", [], "", 469 V6_vsubw_dv.Itinerary, TypeCVI_VA_DV>; 470} 471 472// Store predicate. 473let isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 13, 474 isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in 475def STriw_pred : STInst<(outs), 476 (ins IntRegs:$addr, s32_0Imm:$off, PredRegs:$src1), 477 ".error \"should not emit\"", []>; 478// Store modifier. 479let isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 13, 480 isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in 481def STriw_ctr : STInst<(outs), 482 (ins IntRegs:$addr, s32_0Imm:$off, CtrRegs:$src1), 483 ".error \"should not emit\"", []>; 484 485let isExtendable = 1, opExtendable = 1, opExtentBits = 6, 486 isAsmParserOnly = 1 in 487def TFRI64_V4 : InstHexagon<(outs DoubleRegs:$dst), 488 (ins u64_0Imm:$src1), 489 "$dst = #$src1", [], "", 490 A2_combineii.Itinerary, TypeALU32_2op>, OpcodeHexagon; 491 492// Hexagon doesn't have a vector multiply with C semantics. 493// Instead, generate a pseudo instruction that gets expaneded into two 494// scalar MPYI instructions. 495// This is expanded by ExpandPostRAPseudos. 496let isPseudo = 1 in 497def PS_vmulw : PseudoM<(outs DoubleRegs:$Rd), 498 (ins DoubleRegs:$Rs, DoubleRegs:$Rt), "", []>; 499 500let isPseudo = 1 in 501def PS_vmulw_acc : PseudoM<(outs DoubleRegs:$Rd), 502 (ins DoubleRegs:$Rx, DoubleRegs:$Rs, DoubleRegs:$Rt), "", [], 503 "$Rd = $Rx">; 504 505def DuplexIClass0: InstDuplex < 0 >; 506def DuplexIClass1: InstDuplex < 1 >; 507def DuplexIClass2: InstDuplex < 2 >; 508let isExtendable = 1 in { 509 def DuplexIClass3: InstDuplex < 3 >; 510 def DuplexIClass4: InstDuplex < 4 >; 511 def DuplexIClass5: InstDuplex < 5 >; 512 def DuplexIClass6: InstDuplex < 6 >; 513 def DuplexIClass7: InstDuplex < 7 >; 514} 515def DuplexIClass8: InstDuplex < 8 >; 516def DuplexIClass9: InstDuplex < 9 >; 517def DuplexIClassA: InstDuplex < 0xA >; 518def DuplexIClassB: InstDuplex < 0xB >; 519def DuplexIClassC: InstDuplex < 0xC >; 520def DuplexIClassD: InstDuplex < 0xD >; 521def DuplexIClassE: InstDuplex < 0xE >; 522def DuplexIClassF: InstDuplex < 0xF >; 523 524// Pseudos for circular buffer instructions. These are needed in order to 525// allocate the correct pair of CSx and Mx registers. 526multiclass NewCircularLoad<RegisterClass RC, MemAccessSize MS> { 527 528let isCodeGenOnly = 1, isPseudo = 1, Defs = [CS], Uses = [CS], 529 addrMode = PostInc, accessSize = MS, hasSideEffects = 0 in { 530 def NAME#_pci : LDInst<(outs RC:$Rd32, IntRegs:$Rx32), 531 (ins IntRegs:$Rx32in, s4_0Imm:$Ii, ModRegs:$Mu2, IntRegs:$Cs), 532 ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_e93a3d71>; 533 534 def NAME#_pcr : LDInst<(outs RC:$Rd32, IntRegs:$Rx32), 535 (ins IntRegs:$Rx32in, ModRegs:$Mu2, IntRegs:$Cs), 536 ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_44d3da28>; 537} 538} 539 540defm PS_loadrub : NewCircularLoad<IntRegs, ByteAccess>; 541defm PS_loadrb : NewCircularLoad<IntRegs, ByteAccess>; 542defm PS_loadruh : NewCircularLoad<IntRegs, HalfWordAccess>; 543defm PS_loadrh : NewCircularLoad<IntRegs, HalfWordAccess>; 544defm PS_loadri : NewCircularLoad<IntRegs, WordAccess>; 545defm PS_loadrd : NewCircularLoad<DoubleRegs, DoubleWordAccess>; 546 547multiclass NewCircularStore<RegisterClass RC, MemAccessSize MS> { 548 549let isCodeGenOnly = 1, isPseudo = 1, Defs = [CS], Uses = [CS], 550 addrMode = PostInc, accessSize = MS, hasSideEffects = 0 in { 551 def NAME#_pci : STInst<(outs IntRegs:$Rx32), 552 (ins IntRegs:$Rx32in, s4_0Imm:$Ii, ModRegs:$Mu2, RC:$Rt32, IntRegs:$Cs), 553 ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_e86aa961>; 554 555 def NAME#_pcr : STInst<(outs IntRegs:$Rx32), 556 (ins IntRegs:$Rx32in, ModRegs:$Mu2, RC:$Rt32, IntRegs:$Cs), 557 ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_da97ee82>; 558} 559} 560 561defm PS_storerb : NewCircularStore<IntRegs, ByteAccess>; 562defm PS_storerh : NewCircularStore<IntRegs, HalfWordAccess>; 563defm PS_storerf : NewCircularStore<IntRegs, HalfWordAccess>; 564defm PS_storeri : NewCircularStore<IntRegs, WordAccess>; 565defm PS_storerd : NewCircularStore<DoubleRegs, WordAccess>; 566 567// A pseudo that generates a runtime crash. This is used to implement 568// __builtin_trap. 569let hasSideEffects = 1, isPseudo = 1, isCodeGenOnly = 1, isSolo = 1 in 570def PS_crash: InstHexagon<(outs), (ins), "", [], "", PSEUDO, TypePSEUDO>; 571