1//===-- SIInstrInfo.td - SI Instruction Infos -------------*- tablegen -*--===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9def isCI : Predicate<"Subtarget->getGeneration() " 10 ">= SISubtarget::SEA_ISLANDS">; 11def isCIOnly : Predicate<"Subtarget->getGeneration() ==" 12 "SISubtarget::SEA_ISLANDS">, 13 AssemblerPredicate <"FeatureSeaIslands">; 14def isVIOnly : Predicate<"Subtarget->getGeneration() ==" 15 "SISubtarget::VOLCANIC_ISLANDS">, 16 AssemblerPredicate <"FeatureVolcanicIslands">; 17 18def DisableInst : Predicate <"false">, AssemblerPredicate<"FeatureDisable">; 19 20// Execpt for the NONE field, this must be kept in sync with the 21// SIEncodingFamily enum in AMDGPUInstrInfo.cpp 22def SIEncodingFamily { 23 int NONE = -1; 24 int SI = 0; 25 int VI = 1; 26 int SDWA = 2; 27 int SDWA9 = 3; 28 int GFX9 = 4; 29} 30 31//===----------------------------------------------------------------------===// 32// SI DAG Nodes 33//===----------------------------------------------------------------------===// 34 35def SIload_constant : SDNode<"AMDGPUISD::LOAD_CONSTANT", 36 SDTypeProfile<1, 2, [SDTCisVT<0, f32>, SDTCisVT<1, v4i32>, SDTCisVT<2, i32>]>, 37 [SDNPMayLoad, SDNPMemOperand] 38>; 39 40def SIatomic_inc : SDNode<"AMDGPUISD::ATOMIC_INC", SDTAtomic2, 41 [SDNPMayLoad, SDNPMayStore, SDNPMemOperand, SDNPHasChain] 42>; 43 44def SIatomic_dec : SDNode<"AMDGPUISD::ATOMIC_DEC", SDTAtomic2, 45 [SDNPMayLoad, SDNPMayStore, SDNPMemOperand, SDNPHasChain] 46>; 47 48def SItbuffer_load : SDNode<"AMDGPUISD::TBUFFER_LOAD_FORMAT", 49 SDTypeProfile<1, 9, 50 [ // vdata 51 SDTCisVT<1, v4i32>, // rsrc 52 SDTCisVT<2, i32>, // vindex(VGPR) 53 SDTCisVT<3, i32>, // voffset(VGPR) 54 SDTCisVT<4, i32>, // soffset(SGPR) 55 SDTCisVT<5, i32>, // offset(imm) 56 SDTCisVT<6, i32>, // dfmt(imm) 57 SDTCisVT<7, i32>, // nfmt(imm) 58 SDTCisVT<8, i32>, // glc(imm) 59 SDTCisVT<9, i32> // slc(imm) 60 ]>, 61 [SDNPMayLoad, SDNPMemOperand, SDNPHasChain] 62>; 63 64def SDTtbuffer_store : SDTypeProfile<0, 10, 65 [ // vdata 66 SDTCisVT<1, v4i32>, // rsrc 67 SDTCisVT<2, i32>, // vindex(VGPR) 68 SDTCisVT<3, i32>, // voffset(VGPR) 69 SDTCisVT<4, i32>, // soffset(SGPR) 70 SDTCisVT<5, i32>, // offset(imm) 71 SDTCisVT<6, i32>, // dfmt(imm) 72 SDTCisVT<7, i32>, // nfmt(imm) 73 SDTCisVT<8, i32>, // glc(imm) 74 SDTCisVT<9, i32> // slc(imm) 75 ]>; 76 77def SItbuffer_store : SDNode<"AMDGPUISD::TBUFFER_STORE_FORMAT", SDTtbuffer_store, 78 [SDNPMayStore, SDNPMemOperand, SDNPHasChain]>; 79def SItbuffer_store_x3 : SDNode<"AMDGPUISD::TBUFFER_STORE_FORMAT_X3", 80 SDTtbuffer_store, 81 [SDNPMayStore, SDNPMemOperand, SDNPHasChain]>; 82 83def SDTBufferLoad : SDTypeProfile<1, 5, 84 [ // vdata 85 SDTCisVT<1, v4i32>, // rsrc 86 SDTCisVT<2, i32>, // vindex 87 SDTCisVT<3, i32>, // offset 88 SDTCisVT<4, i1>, // glc 89 SDTCisVT<5, i1>]>; // slc 90 91def SIbuffer_load : SDNode <"AMDGPUISD::BUFFER_LOAD", SDTBufferLoad, 92 [SDNPMemOperand, SDNPHasChain, SDNPMayLoad]>; 93def SIbuffer_load_format : SDNode <"AMDGPUISD::BUFFER_LOAD_FORMAT", SDTBufferLoad, 94 [SDNPMemOperand, SDNPHasChain, SDNPMayLoad]>; 95 96class SDSample<string opcode> : SDNode <opcode, 97 SDTypeProfile<1, 4, [SDTCisVT<0, v4f32>, SDTCisVT<2, v8i32>, 98 SDTCisVT<3, v4i32>, SDTCisVT<4, i32>]> 99>; 100 101def SIsample : SDSample<"AMDGPUISD::SAMPLE">; 102def SIsampleb : SDSample<"AMDGPUISD::SAMPLEB">; 103def SIsampled : SDSample<"AMDGPUISD::SAMPLED">; 104def SIsamplel : SDSample<"AMDGPUISD::SAMPLEL">; 105 106def SIpc_add_rel_offset : SDNode<"AMDGPUISD::PC_ADD_REL_OFFSET", 107 SDTypeProfile<1, 2, [SDTCisVT<0, iPTR>, SDTCisSameAs<0,1>, SDTCisSameAs<0,2>]> 108>; 109 110//===----------------------------------------------------------------------===// 111// PatFrags for global memory operations 112//===----------------------------------------------------------------------===// 113 114defm atomic_inc_global : global_binary_atomic_op<SIatomic_inc>; 115defm atomic_dec_global : global_binary_atomic_op<SIatomic_dec>; 116 117//===----------------------------------------------------------------------===// 118// SDNodes PatFrags for loads/stores with a glue input. 119// This is for SDNodes and PatFrag for local loads and stores to 120// enable s_mov_b32 m0, -1 to be glued to the memory instructions. 121// 122// These mirror the regular load/store PatFrags and rely on special 123// processing during Select() to add the glued copy. 124// 125//===----------------------------------------------------------------------===// 126 127def AMDGPUld_glue : SDNode <"ISD::LOAD", SDTLoad, 128 [SDNPHasChain, SDNPMayLoad, SDNPMemOperand, SDNPInGlue] 129>; 130 131def unindexedload_glue : PatFrag <(ops node:$ptr), (AMDGPUld_glue node:$ptr), [{ 132 return cast<LoadSDNode>(N)->getAddressingMode() == ISD::UNINDEXED; 133}]>; 134 135def load_glue : PatFrag <(ops node:$ptr), (unindexedload_glue node:$ptr), [{ 136 return cast<LoadSDNode>(N)->getExtensionType() == ISD::NON_EXTLOAD; 137}]>; 138 139def extload_glue : PatFrag<(ops node:$ptr), (load_glue node:$ptr), [{ 140 return cast<LoadSDNode>(N)->getExtensionType() == ISD::EXTLOAD; 141}]>; 142 143def sextload_glue : PatFrag<(ops node:$ptr), (unindexedload_glue node:$ptr), [{ 144 return cast<LoadSDNode>(N)->getExtensionType() == ISD::SEXTLOAD; 145}]>; 146 147def zextload_glue : PatFrag<(ops node:$ptr), (unindexedload_glue node:$ptr), [{ 148 return cast<LoadSDNode>(N)->getExtensionType() == ISD::ZEXTLOAD; 149}]>; 150 151def az_extload_glue : AZExtLoadBase <unindexedload_glue>; 152 153def az_extloadi8_glue : PatFrag<(ops node:$ptr), (az_extload_glue node:$ptr), [{ 154 return cast<LoadSDNode>(N)->getMemoryVT() == MVT::i8; 155}]>; 156 157def az_extloadi16_glue : PatFrag<(ops node:$ptr), (az_extload_glue node:$ptr), [{ 158 return cast<LoadSDNode>(N)->getMemoryVT() == MVT::i16; 159}]>; 160 161def sextloadi8_glue : PatFrag<(ops node:$ptr), (sextload_glue node:$ptr), [{ 162 return cast<LoadSDNode>(N)->getMemoryVT() == MVT::i8; 163}]>; 164 165def sextloadi16_glue : PatFrag<(ops node:$ptr), (sextload_glue node:$ptr), [{ 166 return cast<LoadSDNode>(N)->getMemoryVT() == MVT::i16; 167}]>; 168 169def load_glue_align8 : Aligned8Bytes < 170 (ops node:$ptr), (load_glue node:$ptr) 171>; 172 173 174def load_local_m0 : LoadFrag<load_glue>, LocalAddress; 175def sextloadi8_local_m0 : LoadFrag<sextloadi8_glue>, LocalAddress; 176def sextloadi16_local_m0 : LoadFrag<sextloadi16_glue>, LocalAddress; 177def az_extloadi8_local_m0 : LoadFrag<az_extloadi8_glue>, LocalAddress; 178def az_extloadi16_local_m0 : LoadFrag<az_extloadi16_glue>, LocalAddress; 179def load_align8_local_m0 : LoadFrag <load_glue_align8>, LocalAddress; 180 181 182def AMDGPUst_glue : SDNode <"ISD::STORE", SDTStore, 183 [SDNPHasChain, SDNPMayStore, SDNPMemOperand, SDNPInGlue] 184>; 185 186def unindexedstore_glue : PatFrag<(ops node:$val, node:$ptr), 187 (AMDGPUst_glue node:$val, node:$ptr), [{ 188 return cast<StoreSDNode>(N)->getAddressingMode() == ISD::UNINDEXED; 189}]>; 190 191def store_glue : PatFrag<(ops node:$val, node:$ptr), 192 (unindexedstore_glue node:$val, node:$ptr), [{ 193 return !cast<StoreSDNode>(N)->isTruncatingStore(); 194}]>; 195 196def truncstore_glue : PatFrag<(ops node:$val, node:$ptr), 197 (unindexedstore_glue node:$val, node:$ptr), [{ 198 return cast<StoreSDNode>(N)->isTruncatingStore(); 199}]>; 200 201def truncstorei8_glue : PatFrag<(ops node:$val, node:$ptr), 202 (truncstore_glue node:$val, node:$ptr), [{ 203 return cast<StoreSDNode>(N)->getMemoryVT() == MVT::i8; 204}]>; 205 206def truncstorei16_glue : PatFrag<(ops node:$val, node:$ptr), 207 (truncstore_glue node:$val, node:$ptr), [{ 208 return cast<StoreSDNode>(N)->getMemoryVT() == MVT::i16; 209}]>; 210 211def store_glue_align8 : Aligned8Bytes < 212 (ops node:$value, node:$ptr), (store_glue node:$value, node:$ptr) 213>; 214 215def store_local_m0 : StoreFrag<store_glue>, LocalAddress; 216def truncstorei8_local_m0 : StoreFrag<truncstorei8_glue>, LocalAddress; 217def truncstorei16_local_m0 : StoreFrag<truncstorei16_glue>, LocalAddress; 218 219def store_align8_local_m0 : StoreFrag<store_glue_align8>, LocalAddress; 220 221def si_setcc_uniform : PatFrag < 222 (ops node:$lhs, node:$rhs, node:$cond), 223 (setcc node:$lhs, node:$rhs, node:$cond), [{ 224 for (SDNode *Use : N->uses()) { 225 if (Use->isMachineOpcode() || Use->getOpcode() != ISD::CopyToReg) 226 return false; 227 228 unsigned Reg = cast<RegisterSDNode>(Use->getOperand(1))->getReg(); 229 if (Reg != AMDGPU::SCC) 230 return false; 231 } 232 return true; 233}]>; 234 235def lshr_rev : PatFrag < 236 (ops node:$src1, node:$src0), 237 (srl $src0, $src1) 238>; 239 240def ashr_rev : PatFrag < 241 (ops node:$src1, node:$src0), 242 (sra $src0, $src1) 243>; 244 245def lshl_rev : PatFrag < 246 (ops node:$src1, node:$src0), 247 (shl $src0, $src1) 248>; 249 250multiclass SIAtomicM0Glue2 <string op_name, bit is_amdgpu = 0> { 251 252 def _glue : SDNode < 253 !if(is_amdgpu, "AMDGPUISD", "ISD")#"::ATOMIC_"#op_name, SDTAtomic2, 254 [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand, SDNPInGlue] 255 >; 256 257 def _local : local_binary_atomic_op <!cast<SDNode>(NAME#"_glue")>; 258} 259 260defm si_atomic_load_add : SIAtomicM0Glue2 <"LOAD_ADD">; 261defm si_atomic_load_sub : SIAtomicM0Glue2 <"LOAD_SUB">; 262defm si_atomic_inc : SIAtomicM0Glue2 <"INC", 1>; 263defm si_atomic_dec : SIAtomicM0Glue2 <"DEC", 1>; 264defm si_atomic_load_and : SIAtomicM0Glue2 <"LOAD_AND">; 265defm si_atomic_load_min : SIAtomicM0Glue2 <"LOAD_MIN">; 266defm si_atomic_load_max : SIAtomicM0Glue2 <"LOAD_MAX">; 267defm si_atomic_load_or : SIAtomicM0Glue2 <"LOAD_OR">; 268defm si_atomic_load_xor : SIAtomicM0Glue2 <"LOAD_XOR">; 269defm si_atomic_load_umin : SIAtomicM0Glue2 <"LOAD_UMIN">; 270defm si_atomic_load_umax : SIAtomicM0Glue2 <"LOAD_UMAX">; 271defm si_atomic_swap : SIAtomicM0Glue2 <"SWAP">; 272 273def si_atomic_cmp_swap_glue : SDNode <"ISD::ATOMIC_CMP_SWAP", SDTAtomic3, 274 [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand, SDNPInGlue] 275>; 276 277defm si_atomic_cmp_swap : AtomicCmpSwapLocal <si_atomic_cmp_swap_glue>; 278 279def as_i1imm : SDNodeXForm<imm, [{ 280 return CurDAG->getTargetConstant(N->getZExtValue(), SDLoc(N), MVT::i1); 281}]>; 282 283def as_i8imm : SDNodeXForm<imm, [{ 284 return CurDAG->getTargetConstant(N->getZExtValue(), SDLoc(N), MVT::i8); 285}]>; 286 287def as_i16imm : SDNodeXForm<imm, [{ 288 return CurDAG->getTargetConstant(N->getSExtValue(), SDLoc(N), MVT::i16); 289}]>; 290 291def as_i32imm: SDNodeXForm<imm, [{ 292 return CurDAG->getTargetConstant(N->getSExtValue(), SDLoc(N), MVT::i32); 293}]>; 294 295def as_i64imm: SDNodeXForm<imm, [{ 296 return CurDAG->getTargetConstant(N->getSExtValue(), SDLoc(N), MVT::i64); 297}]>; 298 299// Copied from the AArch64 backend: 300def bitcast_fpimm_to_i32 : SDNodeXForm<fpimm, [{ 301return CurDAG->getTargetConstant( 302 N->getValueAPF().bitcastToAPInt().getZExtValue(), SDLoc(N), MVT::i32); 303}]>; 304 305def frameindex_to_targetframeindex : SDNodeXForm<frameindex, [{ 306 auto FI = cast<FrameIndexSDNode>(N); 307 return CurDAG->getTargetFrameIndex(FI->getIndex(), MVT::i32); 308}]>; 309 310// Copied from the AArch64 backend: 311def bitcast_fpimm_to_i64 : SDNodeXForm<fpimm, [{ 312return CurDAG->getTargetConstant( 313 N->getValueAPF().bitcastToAPInt().getZExtValue(), SDLoc(N), MVT::i64); 314}]>; 315 316def SIMM16bit : PatLeaf <(imm), 317 [{return isInt<16>(N->getSExtValue());}] 318>; 319 320class InlineImm <ValueType vt> : PatLeaf <(vt imm), [{ 321 return isInlineImmediate(N); 322}]>; 323 324class InlineFPImm <ValueType vt> : PatLeaf <(vt fpimm), [{ 325 return isInlineImmediate(N); 326}]>; 327 328class VGPRImm <dag frag> : PatLeaf<frag, [{ 329 if (Subtarget->getGeneration() < SISubtarget::SOUTHERN_ISLANDS) { 330 return false; 331 } 332 const SIRegisterInfo *SIRI = 333 static_cast<const SIRegisterInfo *>(Subtarget->getRegisterInfo()); 334 unsigned Limit = 0; 335 for (SDNode::use_iterator U = N->use_begin(), E = SDNode::use_end(); 336 Limit < 10 && U != E; ++U, ++Limit) { 337 const TargetRegisterClass *RC = getOperandRegClass(*U, U.getOperandNo()); 338 339 // If the register class is unknown, it could be an unknown 340 // register class that needs to be an SGPR, e.g. an inline asm 341 // constraint 342 if (!RC || SIRI->isSGPRClass(RC)) 343 return false; 344 } 345 346 return Limit < 10; 347}]>; 348 349def NegateImm : SDNodeXForm<imm, [{ 350 return CurDAG->getConstant(-N->getSExtValue(), SDLoc(N), MVT::i32); 351}]>; 352 353// TODO: When FP inline imm values work? 354def NegSubInlineConst32 : ImmLeaf<i32, [{ 355 return Imm < -16 && Imm >= -64; 356}], NegateImm>; 357 358def NegSubInlineConst16 : ImmLeaf<i16, [{ 359 return Imm < -16 && Imm >= -64; 360}], NegateImm>; 361 362def ShiftAmt32Imm : PatLeaf <(imm), [{ 363 return N->getZExtValue() < 32; 364}]>; 365 366//===----------------------------------------------------------------------===// 367// Custom Operands 368//===----------------------------------------------------------------------===// 369 370def SoppBrTarget : AsmOperandClass { 371 let Name = "SoppBrTarget"; 372 let ParserMethod = "parseSOppBrTarget"; 373} 374 375def sopp_brtarget : Operand<OtherVT> { 376 let EncoderMethod = "getSOPPBrEncoding"; 377 let DecoderMethod = "decodeSoppBrTarget"; 378 let OperandType = "OPERAND_PCREL"; 379 let ParserMatchClass = SoppBrTarget; 380} 381 382def si_ga : Operand<iPTR>; 383 384def InterpSlotMatchClass : AsmOperandClass { 385 let Name = "InterpSlot"; 386 let PredicateMethod = "isInterpSlot"; 387 let ParserMethod = "parseInterpSlot"; 388 let RenderMethod = "addImmOperands"; 389} 390 391def InterpSlot : Operand<i32> { 392 let PrintMethod = "printInterpSlot"; 393 let ParserMatchClass = InterpSlotMatchClass; 394 let OperandType = "OPERAND_IMMEDIATE"; 395} 396 397def AttrMatchClass : AsmOperandClass { 398 let Name = "Attr"; 399 let PredicateMethod = "isInterpAttr"; 400 let ParserMethod = "parseInterpAttr"; 401 let RenderMethod = "addImmOperands"; 402} 403 404// It appears to be necessary to create a separate operand for this to 405// be able to parse attr<num> with no space. 406def Attr : Operand<i32> { 407 let PrintMethod = "printInterpAttr"; 408 let ParserMatchClass = AttrMatchClass; 409 let OperandType = "OPERAND_IMMEDIATE"; 410} 411 412def AttrChanMatchClass : AsmOperandClass { 413 let Name = "AttrChan"; 414 let PredicateMethod = "isAttrChan"; 415 let RenderMethod = "addImmOperands"; 416} 417 418def AttrChan : Operand<i32> { 419 let PrintMethod = "printInterpAttrChan"; 420 let ParserMatchClass = AttrChanMatchClass; 421 let OperandType = "OPERAND_IMMEDIATE"; 422} 423 424def SendMsgMatchClass : AsmOperandClass { 425 let Name = "SendMsg"; 426 let PredicateMethod = "isSendMsg"; 427 let ParserMethod = "parseSendMsgOp"; 428 let RenderMethod = "addImmOperands"; 429} 430 431def SwizzleMatchClass : AsmOperandClass { 432 let Name = "Swizzle"; 433 let PredicateMethod = "isSwizzle"; 434 let ParserMethod = "parseSwizzleOp"; 435 let RenderMethod = "addImmOperands"; 436 let IsOptional = 1; 437} 438 439def ExpTgtMatchClass : AsmOperandClass { 440 let Name = "ExpTgt"; 441 let PredicateMethod = "isExpTgt"; 442 let ParserMethod = "parseExpTgt"; 443 let RenderMethod = "printExpTgt"; 444} 445 446def SendMsgImm : Operand<i32> { 447 let PrintMethod = "printSendMsg"; 448 let ParserMatchClass = SendMsgMatchClass; 449} 450 451def SwizzleImm : Operand<i16> { 452 let PrintMethod = "printSwizzle"; 453 let ParserMatchClass = SwizzleMatchClass; 454} 455 456def SWaitMatchClass : AsmOperandClass { 457 let Name = "SWaitCnt"; 458 let RenderMethod = "addImmOperands"; 459 let ParserMethod = "parseSWaitCntOps"; 460} 461 462def VReg32OrOffClass : AsmOperandClass { 463 let Name = "VReg32OrOff"; 464 let ParserMethod = "parseVReg32OrOff"; 465} 466 467def WAIT_FLAG : Operand <i32> { 468 let ParserMatchClass = SWaitMatchClass; 469 let PrintMethod = "printWaitFlag"; 470} 471 472include "SIInstrFormats.td" 473include "VIInstrFormats.td" 474 475// ===----------------------------------------------------------------------===// 476// ExpSrc* Special cases for exp src operands which are printed as 477// "off" depending on en operand. 478// ===----------------------------------------------------------------------===// 479 480def ExpSrc0 : RegisterOperand<VGPR_32> { 481 let PrintMethod = "printExpSrc0"; 482 let ParserMatchClass = VReg32OrOffClass; 483} 484 485def ExpSrc1 : RegisterOperand<VGPR_32> { 486 let PrintMethod = "printExpSrc1"; 487 let ParserMatchClass = VReg32OrOffClass; 488} 489 490def ExpSrc2 : RegisterOperand<VGPR_32> { 491 let PrintMethod = "printExpSrc2"; 492 let ParserMatchClass = VReg32OrOffClass; 493} 494 495def ExpSrc3 : RegisterOperand<VGPR_32> { 496 let PrintMethod = "printExpSrc3"; 497 let ParserMatchClass = VReg32OrOffClass; 498} 499 500class SDWASrc : RegisterOperand<VS_32> { 501 let OperandNamespace = "AMDGPU"; 502 let OperandType = "OPERAND_SDWA_SRC"; 503 let EncoderMethod = "getSDWASrcEncoding"; 504} 505 506def SDWASrc32 : SDWASrc { 507 let DecoderMethod = "decodeSDWASrc32"; 508} 509 510def SDWASrc16 : SDWASrc { 511 let DecoderMethod = "decodeSDWASrc16"; 512} 513 514def SDWAVopcDst : VOPDstOperand<SReg_64> { 515 let OperandNamespace = "AMDGPU"; 516 let OperandType = "OPERAND_SDWA_VOPC_DST"; 517 let EncoderMethod = "getSDWAVopcDstEncoding"; 518 let DecoderMethod = "decodeSDWAVopcDst"; 519} 520 521class NamedMatchClass<string CName, bit Optional = 1> : AsmOperandClass { 522 let Name = "Imm"#CName; 523 let PredicateMethod = "is"#CName; 524 let ParserMethod = !if(Optional, "parseOptionalOperand", "parse"#CName); 525 let RenderMethod = "addImmOperands"; 526 let IsOptional = Optional; 527 let DefaultMethod = !if(Optional, "default"#CName, ?); 528} 529 530class NamedOperandBit<string Name, AsmOperandClass MatchClass> : Operand<i1> { 531 let PrintMethod = "print"#Name; 532 let ParserMatchClass = MatchClass; 533} 534 535class NamedOperandU8<string Name, AsmOperandClass MatchClass> : Operand<i8> { 536 let PrintMethod = "print"#Name; 537 let ParserMatchClass = MatchClass; 538} 539 540class NamedOperandU12<string Name, AsmOperandClass MatchClass> : Operand<i16> { 541 let PrintMethod = "print"#Name; 542 let ParserMatchClass = MatchClass; 543} 544 545class NamedOperandU16<string Name, AsmOperandClass MatchClass> : Operand<i16> { 546 let PrintMethod = "print"#Name; 547 let ParserMatchClass = MatchClass; 548} 549 550class NamedOperandS13<string Name, AsmOperandClass MatchClass> : Operand<i16> { 551 let PrintMethod = "print"#Name; 552 let ParserMatchClass = MatchClass; 553} 554 555class NamedOperandU32<string Name, AsmOperandClass MatchClass> : Operand<i32> { 556 let PrintMethod = "print"#Name; 557 let ParserMatchClass = MatchClass; 558} 559 560class NamedOperandU32Default0<string Name, AsmOperandClass MatchClass> : 561 OperandWithDefaultOps<i32, (ops (i32 0))> { 562 let PrintMethod = "print"#Name; 563 let ParserMatchClass = MatchClass; 564} 565 566let OperandType = "OPERAND_IMMEDIATE" in { 567 568def offen : NamedOperandBit<"Offen", NamedMatchClass<"Offen">>; 569def idxen : NamedOperandBit<"Idxen", NamedMatchClass<"Idxen">>; 570def addr64 : NamedOperandBit<"Addr64", NamedMatchClass<"Addr64">>; 571 572def offset_u12 : NamedOperandU12<"Offset", NamedMatchClass<"OffsetU12">>; 573def offset_s13 : NamedOperandS13<"OffsetS13", NamedMatchClass<"OffsetS13">>; 574def offset : NamedOperandU16<"Offset", NamedMatchClass<"Offset">>; 575def offset0 : NamedOperandU8<"Offset0", NamedMatchClass<"Offset0">>; 576def offset1 : NamedOperandU8<"Offset1", NamedMatchClass<"Offset1">>; 577 578def gds : NamedOperandBit<"GDS", NamedMatchClass<"GDS">>; 579 580def omod : NamedOperandU32<"OModSI", NamedMatchClass<"OModSI">>; 581def clampmod : NamedOperandBit<"ClampSI", NamedMatchClass<"ClampSI">>; 582def highmod : NamedOperandBit<"High", NamedMatchClass<"High">>; 583 584def GLC : NamedOperandBit<"GLC", NamedMatchClass<"GLC">>; 585def slc : NamedOperandBit<"SLC", NamedMatchClass<"SLC">>; 586def tfe : NamedOperandBit<"TFE", NamedMatchClass<"TFE">>; 587def unorm : NamedOperandBit<"UNorm", NamedMatchClass<"UNorm">>; 588def da : NamedOperandBit<"DA", NamedMatchClass<"DA">>; 589def r128 : NamedOperandBit<"R128", NamedMatchClass<"R128">>; 590def lwe : NamedOperandBit<"LWE", NamedMatchClass<"LWE">>; 591def exp_compr : NamedOperandBit<"ExpCompr", NamedMatchClass<"ExpCompr">>; 592def exp_vm : NamedOperandBit<"ExpVM", NamedMatchClass<"ExpVM">>; 593 594def DFMT : NamedOperandU8<"DFMT", NamedMatchClass<"DFMT">>; 595def NFMT : NamedOperandU8<"NFMT", NamedMatchClass<"NFMT">>; 596 597def dmask : NamedOperandU16<"DMask", NamedMatchClass<"DMask">>; 598 599def dpp_ctrl : NamedOperandU32<"DPPCtrl", NamedMatchClass<"DPPCtrl", 0>>; 600def row_mask : NamedOperandU32<"RowMask", NamedMatchClass<"RowMask">>; 601def bank_mask : NamedOperandU32<"BankMask", NamedMatchClass<"BankMask">>; 602def bound_ctrl : NamedOperandBit<"BoundCtrl", NamedMatchClass<"BoundCtrl">>; 603 604def dst_sel : NamedOperandU32<"SDWADstSel", NamedMatchClass<"SDWADstSel">>; 605def src0_sel : NamedOperandU32<"SDWASrc0Sel", NamedMatchClass<"SDWASrc0Sel">>; 606def src1_sel : NamedOperandU32<"SDWASrc1Sel", NamedMatchClass<"SDWASrc1Sel">>; 607def dst_unused : NamedOperandU32<"SDWADstUnused", NamedMatchClass<"SDWADstUnused">>; 608 609def op_sel : NamedOperandU32Default0<"OpSel", NamedMatchClass<"OpSel">>; 610def op_sel_hi : NamedOperandU32Default0<"OpSelHi", NamedMatchClass<"OpSelHi">>; 611def neg_lo : NamedOperandU32Default0<"NegLo", NamedMatchClass<"NegLo">>; 612def neg_hi : NamedOperandU32Default0<"NegHi", NamedMatchClass<"NegHi">>; 613 614def hwreg : NamedOperandU16<"Hwreg", NamedMatchClass<"Hwreg", 0>>; 615 616def exp_tgt : NamedOperandU8<"ExpTgt", NamedMatchClass<"ExpTgt", 0>> { 617 618} 619 620} // End OperandType = "OPERAND_IMMEDIATE" 621 622class KImmMatchClass<int size> : AsmOperandClass { 623 let Name = "KImmFP"#size; 624 let PredicateMethod = "isKImmFP"#size; 625 let ParserMethod = "parseImm"; 626 let RenderMethod = "addKImmFP"#size#"Operands"; 627} 628 629class kimmOperand<ValueType vt> : Operand<vt> { 630 let OperandNamespace = "AMDGPU"; 631 let OperandType = "OPERAND_KIMM"#vt.Size; 632 let PrintMethod = "printU"#vt.Size#"ImmOperand"; 633 let ParserMatchClass = !cast<AsmOperandClass>("KImmFP"#vt.Size#"MatchClass"); 634} 635 636// 32-bit VALU immediate operand that uses the constant bus. 637def KImmFP32MatchClass : KImmMatchClass<32>; 638def f32kimm : kimmOperand<i32>; 639 640// 32-bit VALU immediate operand with a 16-bit value that uses the 641// constant bus. 642def KImmFP16MatchClass : KImmMatchClass<16>; 643def f16kimm : kimmOperand<i16>; 644 645 646def VOPDstS64 : VOPDstOperand <SReg_64>; 647 648class FPInputModsMatchClass <int opSize> : AsmOperandClass { 649 let Name = "RegOrImmWithFP"#opSize#"InputMods"; 650 let ParserMethod = "parseRegOrImmWithFPInputMods"; 651 let PredicateMethod = "isRegOrImmWithFP"#opSize#"InputMods"; 652} 653 654def FP16InputModsMatchClass : FPInputModsMatchClass<16>; 655def FP32InputModsMatchClass : FPInputModsMatchClass<32>; 656def FP64InputModsMatchClass : FPInputModsMatchClass<64>; 657 658class InputMods <AsmOperandClass matchClass> : Operand <i32> { 659 let OperandNamespace = "AMDGPU"; 660 let OperandType = "OPERAND_INPUT_MODS"; 661 let ParserMatchClass = matchClass; 662} 663 664class FPInputMods <FPInputModsMatchClass matchClass> : InputMods <matchClass> { 665 let PrintMethod = "printOperandAndFPInputMods"; 666} 667 668def FP16InputMods : FPInputMods<FP16InputModsMatchClass>; 669def FP32InputMods : FPInputMods<FP32InputModsMatchClass>; 670def FP64InputMods : FPInputMods<FP64InputModsMatchClass>; 671 672class IntInputModsMatchClass <int opSize> : AsmOperandClass { 673 let Name = "RegOrImmWithInt"#opSize#"InputMods"; 674 let ParserMethod = "parseRegOrImmWithIntInputMods"; 675 let PredicateMethod = "isRegOrImmWithInt"#opSize#"InputMods"; 676} 677def Int32InputModsMatchClass : IntInputModsMatchClass<32>; 678def Int64InputModsMatchClass : IntInputModsMatchClass<64>; 679 680class IntInputMods <IntInputModsMatchClass matchClass> : InputMods <matchClass> { 681 let PrintMethod = "printOperandAndIntInputMods"; 682} 683def Int32InputMods : IntInputMods<Int32InputModsMatchClass>; 684def Int64InputMods : IntInputMods<Int64InputModsMatchClass>; 685 686class OpSelModsMatchClass : AsmOperandClass { 687 let Name = "OpSelMods"; 688 let ParserMethod = "parseRegOrImm"; 689 let PredicateMethod = "isRegOrImm"; 690} 691 692def IntOpSelModsMatchClass : OpSelModsMatchClass; 693def IntOpSelMods : InputMods<IntOpSelModsMatchClass>; 694 695def FPRegSDWAInputModsMatchClass : AsmOperandClass { 696 let Name = "SDWARegWithFPInputMods"; 697 let ParserMethod = "parseRegWithFPInputMods"; 698 let PredicateMethod = "isSDWARegKind"; 699} 700 701def FPRegSDWAInputMods : InputMods <FPRegSDWAInputModsMatchClass> { 702 let PrintMethod = "printOperandAndFPInputMods"; 703} 704 705def FPVRegInputModsMatchClass : AsmOperandClass { 706 let Name = "VRegWithFPInputMods"; 707 let ParserMethod = "parseRegWithFPInputMods"; 708 let PredicateMethod = "isVReg"; 709} 710 711def FPVRegInputMods : InputMods <FPVRegInputModsMatchClass> { 712 let PrintMethod = "printOperandAndFPInputMods"; 713} 714 715 716def IntRegSDWAInputModsMatchClass : AsmOperandClass { 717 let Name = "SDWARegWithIntInputMods"; 718 let ParserMethod = "parseRegWithIntInputMods"; 719 let PredicateMethod = "isSDWARegKind"; 720} 721 722def IntRegSDWAInputMods : InputMods <IntRegSDWAInputModsMatchClass> { 723 let PrintMethod = "printOperandAndIntInputMods"; 724} 725 726def IntVRegInputModsMatchClass : AsmOperandClass { 727 let Name = "VRegWithIntInputMods"; 728 let ParserMethod = "parseRegWithIntInputMods"; 729 let PredicateMethod = "isVReg"; 730} 731 732def IntVRegInputMods : InputMods <IntVRegInputModsMatchClass> { 733 let PrintMethod = "printOperandAndIntInputMods"; 734} 735 736class PackedFPInputModsMatchClass <int opSize> : AsmOperandClass { 737 let Name = "PackedFP"#opSize#"InputMods"; 738 let ParserMethod = "parseRegOrImm"; 739 let PredicateMethod = "isRegOrImm"; 740// let PredicateMethod = "isPackedFP"#opSize#"InputMods"; 741} 742 743class PackedIntInputModsMatchClass <int opSize> : AsmOperandClass { 744 let Name = "PackedInt"#opSize#"InputMods"; 745 let ParserMethod = "parseRegOrImm"; 746 let PredicateMethod = "isRegOrImm"; 747// let PredicateMethod = "isPackedInt"#opSize#"InputMods"; 748} 749 750def PackedF16InputModsMatchClass : PackedFPInputModsMatchClass<16>; 751def PackedI16InputModsMatchClass : PackedIntInputModsMatchClass<16>; 752 753class PackedFPInputMods <PackedFPInputModsMatchClass matchClass> : InputMods <matchClass> { 754// let PrintMethod = "printPackedFPInputMods"; 755} 756 757class PackedIntInputMods <PackedIntInputModsMatchClass matchClass> : InputMods <matchClass> { 758 //let PrintMethod = "printPackedIntInputMods"; 759} 760 761def PackedF16InputMods : PackedFPInputMods<PackedF16InputModsMatchClass>; 762def PackedI16InputMods : PackedIntInputMods<PackedI16InputModsMatchClass>; 763 764//===----------------------------------------------------------------------===// 765// Complex patterns 766//===----------------------------------------------------------------------===// 767 768def DS1Addr1Offset : ComplexPattern<i32, 2, "SelectDS1Addr1Offset">; 769def DS64Bit4ByteAligned : ComplexPattern<i32, 3, "SelectDS64Bit4ByteAligned">; 770 771def MOVRELOffset : ComplexPattern<i32, 2, "SelectMOVRELOffset">; 772 773def VOP3Mods0 : ComplexPattern<untyped, 4, "SelectVOP3Mods0">; 774def VOP3Mods0Clamp : ComplexPattern<untyped, 3, "SelectVOP3Mods0Clamp">; 775def VOP3Mods0Clamp0OMod : ComplexPattern<untyped, 4, "SelectVOP3Mods0Clamp0OMod">; 776def VOP3Mods : ComplexPattern<untyped, 2, "SelectVOP3Mods">; 777def VOP3NoMods : ComplexPattern<untyped, 1, "SelectVOP3NoMods">; 778// VOP3Mods, but the input source is known to never be NaN. 779def VOP3Mods_nnan : ComplexPattern<fAny, 2, "SelectVOP3Mods_NNaN">; 780 781def VOP3OMods : ComplexPattern<untyped, 3, "SelectVOP3OMods">; 782 783def VOP3PMods : ComplexPattern<untyped, 2, "SelectVOP3PMods">; 784def VOP3PMods0 : ComplexPattern<untyped, 3, "SelectVOP3PMods0">; 785 786def VOP3OpSel : ComplexPattern<untyped, 2, "SelectVOP3OpSel">; 787def VOP3OpSel0 : ComplexPattern<untyped, 3, "SelectVOP3OpSel0">; 788 789def VOP3OpSelMods : ComplexPattern<untyped, 2, "SelectVOP3OpSelMods">; 790def VOP3OpSelMods0 : ComplexPattern<untyped, 3, "SelectVOP3OpSelMods0">; 791 792def VOP3PMadMixMods : ComplexPattern<untyped, 2, "SelectVOP3PMadMixMods">; 793 794//===----------------------------------------------------------------------===// 795// SI assembler operands 796//===----------------------------------------------------------------------===// 797 798def SIOperand { 799 int ZERO = 0x80; 800 int VCC = 0x6A; 801 int FLAT_SCR = 0x68; 802} 803 804// This should be kept in sync with SISrcMods enum 805def SRCMODS { 806 int NONE = 0; 807 int NEG = 1; 808 int ABS = 2; 809 int NEG_ABS = 3; 810 811 int NEG_HI = ABS; 812 int OP_SEL_0 = 4; 813 int OP_SEL_1 = 8; 814 int DST_OP_SEL = 8; 815} 816 817def DSTCLAMP { 818 int NONE = 0; 819 int ENABLE = 1; 820} 821 822def DSTOMOD { 823 int NONE = 0; 824} 825 826def TRAPID{ 827 int LLVM_TRAP = 2; 828 int LLVM_DEBUG_TRAP = 3; 829} 830 831//===----------------------------------------------------------------------===// 832// 833// SI Instruction multiclass helpers. 834// 835// Instructions with _32 take 32-bit operands. 836// Instructions with _64 take 64-bit operands. 837// 838// VOP_* instructions can use either a 32-bit or 64-bit encoding. The 32-bit 839// encoding is the standard encoding, but instruction that make use of 840// any of the instruction modifiers must use the 64-bit encoding. 841// 842// Instructions with _e32 use the 32-bit encoding. 843// Instructions with _e64 use the 64-bit encoding. 844// 845//===----------------------------------------------------------------------===// 846 847class SIMCInstr <string pseudo, int subtarget> { 848 string PseudoInstr = pseudo; 849 int Subtarget = subtarget; 850} 851 852//===----------------------------------------------------------------------===// 853// EXP classes 854//===----------------------------------------------------------------------===// 855 856class EXP_Helper<bit done, SDPatternOperator node = null_frag> : EXPCommon< 857 (outs), 858 (ins exp_tgt:$tgt, 859 ExpSrc0:$src0, ExpSrc1:$src1, ExpSrc2:$src2, ExpSrc3:$src3, 860 exp_vm:$vm, exp_compr:$compr, i8imm:$en), 861 "exp$tgt $src0, $src1, $src2, $src3"#!if(done, " done", "")#"$compr$vm", 862 [(node (i8 timm:$tgt), (i8 timm:$en), 863 f32:$src0, f32:$src1, f32:$src2, f32:$src3, 864 (i1 timm:$compr), (i1 timm:$vm))]> { 865 let AsmMatchConverter = "cvtExp"; 866} 867 868// Split EXP instruction into EXP and EXP_DONE so we can set 869// mayLoad for done=1. 870multiclass EXP_m<bit done, SDPatternOperator node> { 871 let mayLoad = done, DisableWQM = 1 in { 872 let isPseudo = 1, isCodeGenOnly = 1 in { 873 def "" : EXP_Helper<done, node>, 874 SIMCInstr <"exp"#!if(done, "_done", ""), SIEncodingFamily.NONE>; 875 } 876 877 let done = done in { 878 def _si : EXP_Helper<done>, 879 SIMCInstr <"exp"#!if(done, "_done", ""), SIEncodingFamily.SI>, 880 EXPe { 881 let AssemblerPredicates = [isSICI]; 882 let DecoderNamespace = "SICI"; 883 let DisableDecoder = DisableSIDecoder; 884 } 885 886 def _vi : EXP_Helper<done>, 887 SIMCInstr <"exp"#!if(done, "_done", ""), SIEncodingFamily.VI>, 888 EXPe_vi { 889 let AssemblerPredicates = [isVI]; 890 let DecoderNamespace = "VI"; 891 let DisableDecoder = DisableVIDecoder; 892 } 893 } 894 } 895} 896 897//===----------------------------------------------------------------------===// 898// Vector ALU classes 899//===----------------------------------------------------------------------===// 900 901class getNumSrcArgs<ValueType Src0, ValueType Src1, ValueType Src2> { 902 int ret = 903 !if (!eq(Src0.Value, untyped.Value), 0, 904 !if (!eq(Src1.Value, untyped.Value), 1, // VOP1 905 !if (!eq(Src2.Value, untyped.Value), 2, // VOP2 906 3))); // VOP3 907} 908 909// Returns the register class to use for the destination of VOP[123C] 910// instructions for the given VT. 911class getVALUDstForVT<ValueType VT> { 912 RegisterOperand ret = !if(!eq(VT.Size, 32), VOPDstOperand<VGPR_32>, 913 !if(!eq(VT.Size, 128), VOPDstOperand<VReg_128>, 914 !if(!eq(VT.Size, 64), VOPDstOperand<VReg_64>, 915 !if(!eq(VT.Size, 16), VOPDstOperand<VGPR_32>, 916 VOPDstOperand<SReg_64>)))); // else VT == i1 917} 918 919// Returns the register class to use for the destination of VOP[12C] 920// instructions with SDWA extension 921class getSDWADstForVT<ValueType VT> { 922 RegisterOperand ret = !if(!eq(VT.Size, 1), 923 SDWAVopcDst, // VOPC 924 VOPDstOperand<VGPR_32>); // VOP1/2 32-bit dst 925} 926 927// Returns the register class to use for source 0 of VOP[12C] 928// instructions for the given VT. 929class getVOPSrc0ForVT<ValueType VT> { 930 bit isFP = !if(!eq(VT.Value, f16.Value), 1, 931 !if(!eq(VT.Value, v2f16.Value), 1, 932 !if(!eq(VT.Value, f32.Value), 1, 933 !if(!eq(VT.Value, f64.Value), 1, 934 0)))); 935 936 RegisterOperand ret = 937 !if(isFP, 938 !if(!eq(VT.Size, 64), 939 VSrc_f64, 940 !if(!eq(VT.Value, f16.Value), 941 VSrc_f16, 942 !if(!eq(VT.Value, v2f16.Value), 943 VCSrc_v2f16, 944 VSrc_f32 945 ) 946 ) 947 ), 948 !if(!eq(VT.Size, 64), 949 VSrc_b64, 950 !if(!eq(VT.Value, i16.Value), 951 VSrc_b16, 952 !if(!eq(VT.Value, v2i16.Value), 953 VCSrc_v2b16, 954 VSrc_b32 955 ) 956 ) 957 ) 958 ); 959} 960 961// Returns the vreg register class to use for source operand given VT 962class getVregSrcForVT<ValueType VT> { 963 RegisterClass ret = !if(!eq(VT.Size, 128), VReg_128, 964 !if(!eq(VT.Size, 64), VReg_64, VGPR_32)); 965} 966 967class getSDWASrcForVT <ValueType VT> { 968 RegisterOperand ret = !if(!eq(VT.Size, 16), SDWASrc16, SDWASrc32); 969} 970 971// Returns the register class to use for sources of VOP3 instructions for the 972// given VT. 973class getVOP3SrcForVT<ValueType VT> { 974 bit isFP = !if(!eq(VT.Value, f16.Value), 1, 975 !if(!eq(VT.Value, v2f16.Value), 1, 976 !if(!eq(VT.Value, f32.Value), 1, 977 !if(!eq(VT.Value, f64.Value), 1, 978 0)))); 979 RegisterOperand ret = 980 !if(!eq(VT.Size, 128), 981 VSrc_128, 982 !if(!eq(VT.Size, 64), 983 !if(isFP, 984 VCSrc_f64, 985 VCSrc_b64), 986 !if(!eq(VT.Value, i1.Value), 987 SCSrc_i1, 988 !if(isFP, 989 !if(!eq(VT.Value, f16.Value), 990 VCSrc_f16, 991 !if(!eq(VT.Value, v2f16.Value), 992 VCSrc_v2f16, 993 VCSrc_f32 994 ) 995 ), 996 !if(!eq(VT.Value, i16.Value), 997 VCSrc_b16, 998 !if(!eq(VT.Value, v2i16.Value), 999 VCSrc_v2b16, 1000 VCSrc_b32 1001 ) 1002 ) 1003 ) 1004 ) 1005 ) 1006 ); 1007} 1008 1009// Returns 1 if the source arguments have modifiers, 0 if they do not. 1010// XXX - do f16 instructions? 1011class isFloatType<ValueType SrcVT> { 1012 bit ret = 1013 !if(!eq(SrcVT.Value, f16.Value), 1, 1014 !if(!eq(SrcVT.Value, f32.Value), 1, 1015 !if(!eq(SrcVT.Value, f64.Value), 1, 1016 !if(!eq(SrcVT.Value, v2f16.Value), 1, 1017 0)))); 1018} 1019 1020class isIntType<ValueType SrcVT> { 1021 bit ret = 1022 !if(!eq(SrcVT.Value, i16.Value), 1, 1023 !if(!eq(SrcVT.Value, i32.Value), 1, 1024 !if(!eq(SrcVT.Value, i64.Value), 1, 1025 0))); 1026} 1027 1028class isPackedType<ValueType SrcVT> { 1029 bit ret = 1030 !if(!eq(SrcVT.Value, v2i16.Value), 1, 1031 !if(!eq(SrcVT.Value, v2f16.Value), 1, 0) 1032 ); 1033} 1034 1035// Float or packed int 1036class isModifierType<ValueType SrcVT> { 1037 bit ret = 1038 !if(!eq(SrcVT.Value, f16.Value), 1, 1039 !if(!eq(SrcVT.Value, f32.Value), 1, 1040 !if(!eq(SrcVT.Value, f64.Value), 1, 1041 !if(!eq(SrcVT.Value, v2f16.Value), 1, 1042 !if(!eq(SrcVT.Value, v2i16.Value), 1, 1043 0))))); 1044} 1045 1046// Return type of input modifiers operand for specified input operand 1047class getSrcMod <ValueType VT> { 1048 bit isFP = !if(!eq(VT.Value, f16.Value), 1, 1049 !if(!eq(VT.Value, f32.Value), 1, 1050 !if(!eq(VT.Value, f64.Value), 1, 1051 0))); 1052 bit isPacked = isPackedType<VT>.ret; 1053 Operand ret = !if(!eq(VT.Size, 64), 1054 !if(isFP, FP64InputMods, Int64InputMods), 1055 !if(isFP, 1056 !if(!eq(VT.Value, f16.Value), 1057 FP16InputMods, 1058 FP32InputMods 1059 ), 1060 Int32InputMods) 1061 ); 1062} 1063 1064class getOpSelMod <ValueType VT> { 1065 Operand ret = !if(!eq(VT.Value, f16.Value), FP16InputMods, IntOpSelMods); 1066} 1067 1068// Return type of input modifiers operand specified input operand for DPP 1069class getSrcModExt <ValueType VT> { 1070 bit isFP = !if(!eq(VT.Value, f16.Value), 1, 1071 !if(!eq(VT.Value, f32.Value), 1, 1072 !if(!eq(VT.Value, f64.Value), 1, 1073 0))); 1074 Operand ret = !if(isFP, FPVRegInputMods, IntVRegInputMods); 1075} 1076 1077// Return type of input modifiers operand specified input operand for SDWA 1078class getSrcModSDWA <ValueType VT> { 1079 bit isFP = !if(!eq(VT.Value, f16.Value), 1, 1080 !if(!eq(VT.Value, f32.Value), 1, 1081 !if(!eq(VT.Value, f64.Value), 1, 1082 0))); 1083 Operand ret = !if(isFP, FPRegSDWAInputMods, IntRegSDWAInputMods); 1084} 1085 1086// Returns the input arguments for VOP[12C] instructions for the given SrcVT. 1087class getIns32 <RegisterOperand Src0RC, RegisterClass Src1RC, int NumSrcArgs> { 1088 dag ret = !if(!eq(NumSrcArgs, 1), (ins Src0RC:$src0), // VOP1 1089 !if(!eq(NumSrcArgs, 2), (ins Src0RC:$src0, Src1RC:$src1), // VOP2 1090 (ins))); 1091} 1092 1093// Returns the input arguments for VOP3 instructions for the given SrcVT. 1094class getIns64 <RegisterOperand Src0RC, RegisterOperand Src1RC, 1095 RegisterOperand Src2RC, int NumSrcArgs, 1096 bit HasIntClamp, bit HasModifiers, bit HasOMod, 1097 Operand Src0Mod, Operand Src1Mod, Operand Src2Mod> { 1098 1099 dag ret = 1100 !if (!eq(NumSrcArgs, 0), 1101 // VOP1 without input operands (V_NOP, V_CLREXCP) 1102 (ins), 1103 /* else */ 1104 !if (!eq(NumSrcArgs, 1), 1105 !if (!eq(HasModifiers, 1), 1106 // VOP1 with modifiers 1107 (ins Src0Mod:$src0_modifiers, Src0RC:$src0, 1108 clampmod:$clamp, omod:$omod) 1109 /* else */, 1110 // VOP1 without modifiers 1111 !if (!eq(HasIntClamp, 1), 1112 (ins Src0RC:$src0, clampmod:$clamp), 1113 (ins Src0RC:$src0)) 1114 /* endif */ ), 1115 !if (!eq(NumSrcArgs, 2), 1116 !if (!eq(HasModifiers, 1), 1117 // VOP 2 with modifiers 1118 !if( !eq(HasOMod, 1), 1119 (ins Src0Mod:$src0_modifiers, Src0RC:$src0, 1120 Src1Mod:$src1_modifiers, Src1RC:$src1, 1121 clampmod:$clamp, omod:$omod), 1122 (ins Src0Mod:$src0_modifiers, Src0RC:$src0, 1123 Src1Mod:$src1_modifiers, Src1RC:$src1, 1124 clampmod:$clamp)) 1125 /* else */, 1126 // VOP2 without modifiers 1127 !if (!eq(HasIntClamp, 1), 1128 (ins Src0RC:$src0, Src1RC:$src1, clampmod:$clamp), 1129 (ins Src0RC:$src0, Src1RC:$src1)) 1130 1131 /* endif */ ) 1132 /* NumSrcArgs == 3 */, 1133 !if (!eq(HasModifiers, 1), 1134 // VOP3 with modifiers 1135 !if (!eq(HasOMod, 1), 1136 (ins Src0Mod:$src0_modifiers, Src0RC:$src0, 1137 Src1Mod:$src1_modifiers, Src1RC:$src1, 1138 Src2Mod:$src2_modifiers, Src2RC:$src2, 1139 clampmod:$clamp, omod:$omod), 1140 (ins Src0Mod:$src0_modifiers, Src0RC:$src0, 1141 Src1Mod:$src1_modifiers, Src1RC:$src1, 1142 Src2Mod:$src2_modifiers, Src2RC:$src2, 1143 clampmod:$clamp)) 1144 /* else */, 1145 // VOP3 without modifiers 1146 !if (!eq(HasIntClamp, 1), 1147 (ins Src0RC:$src0, Src1RC:$src1, Src2RC:$src2, clampmod:$clamp), 1148 (ins Src0RC:$src0, Src1RC:$src1, Src2RC:$src2)) 1149 /* endif */ )))); 1150} 1151 1152/// XXX - src1 may only allow VGPRs? 1153 1154// The modifiers (except clamp) are dummy operands for the benefit of 1155// printing and parsing. They defer their values to looking at the 1156// srcN_modifiers for what to print. 1157class getInsVOP3P <RegisterOperand Src0RC, RegisterOperand Src1RC, 1158 RegisterOperand Src2RC, int NumSrcArgs, 1159 bit HasClamp, 1160 Operand Src0Mod, Operand Src1Mod, Operand Src2Mod> { 1161 dag ret = !if (!eq(NumSrcArgs, 2), 1162 !if (HasClamp, 1163 (ins Src0Mod:$src0_modifiers, Src0RC:$src0, 1164 Src1Mod:$src1_modifiers, Src1RC:$src1, 1165 clampmod:$clamp, 1166 op_sel:$op_sel, op_sel_hi:$op_sel_hi, 1167 neg_lo:$neg_lo, neg_hi:$neg_hi), 1168 (ins Src0Mod:$src0_modifiers, Src0RC:$src0, 1169 Src1Mod:$src1_modifiers, Src1RC:$src1, 1170 op_sel:$op_sel, op_sel_hi:$op_sel_hi, 1171 neg_lo:$neg_lo, neg_hi:$neg_hi)), 1172 // else NumSrcArgs == 3 1173 !if (HasClamp, 1174 (ins Src0Mod:$src0_modifiers, Src0RC:$src0, 1175 Src1Mod:$src1_modifiers, Src1RC:$src1, 1176 Src2Mod:$src2_modifiers, Src2RC:$src2, 1177 clampmod:$clamp, 1178 op_sel:$op_sel, op_sel_hi:$op_sel_hi, 1179 neg_lo:$neg_lo, neg_hi:$neg_hi), 1180 (ins Src0Mod:$src0_modifiers, Src0RC:$src0, 1181 Src1Mod:$src1_modifiers, Src1RC:$src1, 1182 Src2Mod:$src2_modifiers, Src2RC:$src2, 1183 op_sel:$op_sel, op_sel_hi:$op_sel_hi, 1184 neg_lo:$neg_lo, neg_hi:$neg_hi)) 1185 ); 1186} 1187 1188class getInsVOP3OpSel <RegisterOperand Src0RC, 1189 RegisterOperand Src1RC, 1190 RegisterOperand Src2RC, 1191 int NumSrcArgs, 1192 bit HasClamp, 1193 Operand Src0Mod, 1194 Operand Src1Mod, 1195 Operand Src2Mod> { 1196 dag ret = !if (!eq(NumSrcArgs, 2), 1197 !if (HasClamp, 1198 (ins Src0Mod:$src0_modifiers, Src0RC:$src0, 1199 Src1Mod:$src1_modifiers, Src1RC:$src1, 1200 clampmod:$clamp, 1201 op_sel:$op_sel), 1202 (ins Src0Mod:$src0_modifiers, Src0RC:$src0, 1203 Src1Mod:$src1_modifiers, Src1RC:$src1, 1204 op_sel:$op_sel)), 1205 // else NumSrcArgs == 3 1206 !if (HasClamp, 1207 (ins Src0Mod:$src0_modifiers, Src0RC:$src0, 1208 Src1Mod:$src1_modifiers, Src1RC:$src1, 1209 Src2Mod:$src2_modifiers, Src2RC:$src2, 1210 clampmod:$clamp, 1211 op_sel:$op_sel), 1212 (ins Src0Mod:$src0_modifiers, Src0RC:$src0, 1213 Src1Mod:$src1_modifiers, Src1RC:$src1, 1214 Src2Mod:$src2_modifiers, Src2RC:$src2, 1215 op_sel:$op_sel)) 1216 ); 1217} 1218 1219class getInsDPP <RegisterOperand DstRC, RegisterClass Src0RC, RegisterClass Src1RC, 1220 int NumSrcArgs, bit HasModifiers, 1221 Operand Src0Mod, Operand Src1Mod> { 1222 1223 dag ret = !if (!eq(NumSrcArgs, 0), 1224 // VOP1 without input operands (V_NOP) 1225 (ins dpp_ctrl:$dpp_ctrl, row_mask:$row_mask, 1226 bank_mask:$bank_mask, bound_ctrl:$bound_ctrl), 1227 !if (!eq(NumSrcArgs, 1), 1228 !if (!eq(HasModifiers, 1), 1229 // VOP1_DPP with modifiers 1230 (ins DstRC:$old, Src0Mod:$src0_modifiers, 1231 Src0RC:$src0, dpp_ctrl:$dpp_ctrl, row_mask:$row_mask, 1232 bank_mask:$bank_mask, bound_ctrl:$bound_ctrl) 1233 /* else */, 1234 // VOP1_DPP without modifiers 1235 (ins DstRC:$old, Src0RC:$src0, 1236 dpp_ctrl:$dpp_ctrl, row_mask:$row_mask, 1237 bank_mask:$bank_mask, bound_ctrl:$bound_ctrl) 1238 /* endif */) 1239 /* NumSrcArgs == 2 */, 1240 !if (!eq(HasModifiers, 1), 1241 // VOP2_DPP with modifiers 1242 (ins DstRC:$old, 1243 Src0Mod:$src0_modifiers, Src0RC:$src0, 1244 Src1Mod:$src1_modifiers, Src1RC:$src1, 1245 dpp_ctrl:$dpp_ctrl, row_mask:$row_mask, 1246 bank_mask:$bank_mask, bound_ctrl:$bound_ctrl) 1247 /* else */, 1248 // VOP2_DPP without modifiers 1249 (ins DstRC:$old, 1250 Src0RC:$src0, Src1RC:$src1, dpp_ctrl:$dpp_ctrl, 1251 row_mask:$row_mask, bank_mask:$bank_mask, 1252 bound_ctrl:$bound_ctrl) 1253 /* endif */))); 1254} 1255 1256 1257 1258// Ins for SDWA 1259class getInsSDWA <RegisterOperand Src0RC, RegisterOperand Src1RC, int NumSrcArgs, 1260 bit HasSDWAOMod, Operand Src0Mod, Operand Src1Mod, 1261 ValueType DstVT> { 1262 1263 dag ret = !if(!eq(NumSrcArgs, 0), 1264 // VOP1 without input operands (V_NOP) 1265 (ins), 1266 !if(!eq(NumSrcArgs, 1), 1267 // VOP1 1268 !if(!eq(HasSDWAOMod, 0), 1269 // VOP1_SDWA without omod 1270 (ins Src0Mod:$src0_modifiers, Src0RC:$src0, 1271 clampmod:$clamp, 1272 dst_sel:$dst_sel, dst_unused:$dst_unused, 1273 src0_sel:$src0_sel), 1274 // VOP1_SDWA with omod 1275 (ins Src0Mod:$src0_modifiers, Src0RC:$src0, 1276 clampmod:$clamp, omod:$omod, 1277 dst_sel:$dst_sel, dst_unused:$dst_unused, 1278 src0_sel:$src0_sel)), 1279 !if(!eq(NumSrcArgs, 2), 1280 !if(!eq(DstVT.Size, 1), 1281 // VOPC_SDWA 1282 (ins Src0Mod:$src0_modifiers, Src0RC:$src0, 1283 Src1Mod:$src1_modifiers, Src1RC:$src1, 1284 clampmod:$clamp, src0_sel:$src0_sel, src1_sel:$src1_sel), 1285 // VOP2_SDWA 1286 !if(!eq(HasSDWAOMod, 0), 1287 // VOP2_SDWA without omod 1288 (ins Src0Mod:$src0_modifiers, Src0RC:$src0, 1289 Src1Mod:$src1_modifiers, Src1RC:$src1, 1290 clampmod:$clamp, 1291 dst_sel:$dst_sel, dst_unused:$dst_unused, 1292 src0_sel:$src0_sel, src1_sel:$src1_sel), 1293 // VOP2_SDWA with omod 1294 (ins Src0Mod:$src0_modifiers, Src0RC:$src0, 1295 Src1Mod:$src1_modifiers, Src1RC:$src1, 1296 clampmod:$clamp, omod:$omod, 1297 dst_sel:$dst_sel, dst_unused:$dst_unused, 1298 src0_sel:$src0_sel, src1_sel:$src1_sel))), 1299 (ins)/* endif */))); 1300} 1301 1302// Outs for DPP and SDWA 1303class getOutsExt <bit HasDst, ValueType DstVT, RegisterOperand DstRCExt> { 1304 dag ret = !if(HasDst, 1305 !if(!eq(DstVT.Size, 1), 1306 (outs), // no dst for VOPC, we use "vcc"-token as dst in SDWA VOPC instructions 1307 (outs DstRCExt:$vdst)), 1308 (outs)); // V_NOP 1309} 1310 1311// Outs for SDWA 1312class getOutsSDWA <bit HasDst, ValueType DstVT, RegisterOperand DstRCSDWA> { 1313 dag ret = !if(HasDst, 1314 !if(!eq(DstVT.Size, 1), 1315 (outs DstRCSDWA:$sdst), 1316 (outs DstRCSDWA:$vdst)), 1317 (outs)); // V_NOP 1318} 1319 1320// Returns the assembly string for the inputs and outputs of a VOP[12C] 1321// instruction. This does not add the _e32 suffix, so it can be reused 1322// by getAsm64. 1323class getAsm32 <bit HasDst, int NumSrcArgs, ValueType DstVT = i32> { 1324 string dst = !if(!eq(DstVT.Size, 1), "$sdst", "$vdst"); // use $sdst for VOPC 1325 string src0 = ", $src0"; 1326 string src1 = ", $src1"; 1327 string src2 = ", $src2"; 1328 string ret = !if(HasDst, dst, "") # 1329 !if(!eq(NumSrcArgs, 1), src0, "") # 1330 !if(!eq(NumSrcArgs, 2), src0#src1, "") # 1331 !if(!eq(NumSrcArgs, 3), src0#src1#src2, ""); 1332} 1333 1334// Returns the assembly string for the inputs and outputs of a VOP3 1335// instruction. 1336class getAsm64 <bit HasDst, int NumSrcArgs, bit HasIntClamp, bit HasModifiers, 1337 bit HasOMod, ValueType DstVT = i32> { 1338 string dst = !if(!eq(DstVT.Size, 1), "$sdst", "$vdst"); // use $sdst for VOPC 1339 string src0 = !if(!eq(NumSrcArgs, 1), "$src0_modifiers", "$src0_modifiers,"); 1340 string src1 = !if(!eq(NumSrcArgs, 1), "", 1341 !if(!eq(NumSrcArgs, 2), " $src1_modifiers", 1342 " $src1_modifiers,")); 1343 string src2 = !if(!eq(NumSrcArgs, 3), " $src2_modifiers", ""); 1344 string iclamp = !if(HasIntClamp, "$clamp", ""); 1345 string ret = 1346 !if(!eq(HasModifiers, 0), 1347 getAsm32<HasDst, NumSrcArgs, DstVT>.ret # iclamp, 1348 dst#", "#src0#src1#src2#"$clamp"#!if(HasOMod, "$omod", "")); 1349} 1350 1351// Returns the assembly string for the inputs and outputs of a VOP3P 1352// instruction. 1353class getAsmVOP3P <bit HasDst, int NumSrcArgs, bit HasModifiers, 1354 bit HasClamp, ValueType DstVT = i32> { 1355 string dst = " $vdst"; 1356 string src0 = !if(!eq(NumSrcArgs, 1), "$src0", "$src0,"); 1357 string src1 = !if(!eq(NumSrcArgs, 1), "", 1358 !if(!eq(NumSrcArgs, 2), " $src1", 1359 " $src1,")); 1360 string src2 = !if(!eq(NumSrcArgs, 3), " $src2", ""); 1361 1362 string mods = !if(HasModifiers, "$neg_lo$neg_hi", ""); 1363 string clamp = !if(HasClamp, "$clamp", ""); 1364 1365 // Each modifier is printed as an array of bits for each operand, so 1366 // all operands are printed as part of src0_modifiers. 1367 string ret = dst#", "#src0#src1#src2#"$op_sel$op_sel_hi"#mods#clamp; 1368} 1369 1370class getAsmVOP3OpSel <int NumSrcArgs, 1371 bit HasClamp, 1372 bit Src0HasMods, 1373 bit Src1HasMods, 1374 bit Src2HasMods> { 1375 string dst = " $vdst"; 1376 1377 string isrc0 = !if(!eq(NumSrcArgs, 1), "$src0", "$src0,"); 1378 string isrc1 = !if(!eq(NumSrcArgs, 1), "", 1379 !if(!eq(NumSrcArgs, 2), " $src1", 1380 " $src1,")); 1381 string isrc2 = !if(!eq(NumSrcArgs, 3), " $src2", ""); 1382 1383 string fsrc0 = !if(!eq(NumSrcArgs, 1), "$src0_modifiers", "$src0_modifiers,"); 1384 string fsrc1 = !if(!eq(NumSrcArgs, 1), "", 1385 !if(!eq(NumSrcArgs, 2), " $src1_modifiers", 1386 " $src1_modifiers,")); 1387 string fsrc2 = !if(!eq(NumSrcArgs, 3), " $src2_modifiers", ""); 1388 1389 string src0 = !if(Src0HasMods, fsrc0, isrc0); 1390 string src1 = !if(Src1HasMods, fsrc1, isrc1); 1391 string src2 = !if(Src2HasMods, fsrc2, isrc2); 1392 1393 string clamp = !if(HasClamp, "$clamp", ""); 1394 1395 string ret = dst#", "#src0#src1#src2#"$op_sel"#clamp; 1396} 1397 1398class getAsmDPP <bit HasDst, int NumSrcArgs, bit HasModifiers, ValueType DstVT = i32> { 1399 string dst = !if(HasDst, 1400 !if(!eq(DstVT.Size, 1), 1401 "$sdst", 1402 "$vdst"), 1403 ""); // use $sdst for VOPC 1404 string src0 = !if(!eq(NumSrcArgs, 1), "$src0_modifiers", "$src0_modifiers,"); 1405 string src1 = !if(!eq(NumSrcArgs, 1), "", 1406 !if(!eq(NumSrcArgs, 2), " $src1_modifiers", 1407 " $src1_modifiers,")); 1408 string args = !if(!eq(HasModifiers, 0), 1409 getAsm32<0, NumSrcArgs, DstVT>.ret, 1410 ", "#src0#src1); 1411 string ret = dst#args#" $dpp_ctrl$row_mask$bank_mask$bound_ctrl"; 1412} 1413 1414class getAsmSDWA <bit HasDst, int NumSrcArgs, ValueType DstVT = i32> { 1415 string dst = !if(HasDst, 1416 !if(!eq(DstVT.Size, 1), 1417 " vcc", // use vcc token as dst for VOPC instructioins 1418 "$vdst"), 1419 ""); 1420 string src0 = "$src0_modifiers"; 1421 string src1 = "$src1_modifiers"; 1422 string args = !if(!eq(NumSrcArgs, 0), 1423 "", 1424 !if(!eq(NumSrcArgs, 1), 1425 ", "#src0#"$clamp", 1426 ", "#src0#", "#src1#"$clamp" 1427 ) 1428 ); 1429 string sdwa = !if(!eq(NumSrcArgs, 0), 1430 "", 1431 !if(!eq(NumSrcArgs, 1), 1432 " $dst_sel $dst_unused $src0_sel", 1433 !if(!eq(DstVT.Size, 1), 1434 " $src0_sel $src1_sel", // No dst_sel and dst_unused for VOPC 1435 " $dst_sel $dst_unused $src0_sel $src1_sel" 1436 ) 1437 ) 1438 ); 1439 string ret = dst#args#sdwa; 1440} 1441 1442class getAsmSDWA9 <bit HasDst, bit HasOMod, int NumSrcArgs, 1443 ValueType DstVT = i32> { 1444 string dst = !if(HasDst, 1445 !if(!eq(DstVT.Size, 1), 1446 "$sdst", // VOPC 1447 "$vdst"), // VOP1/2 1448 ""); 1449 string src0 = "$src0_modifiers"; 1450 string src1 = "$src1_modifiers"; 1451 string out_mods = !if(!eq(HasOMod, 0), "$clamp", "$clamp$omod"); 1452 string args = !if(!eq(NumSrcArgs, 0), "", 1453 !if(!eq(NumSrcArgs, 1), 1454 ", "#src0, 1455 ", "#src0#", "#src1 1456 ) 1457 ); 1458 string sdwa = !if(!eq(NumSrcArgs, 0), "", 1459 !if(!eq(NumSrcArgs, 1), 1460 out_mods#" $dst_sel $dst_unused $src0_sel", 1461 !if(!eq(DstVT.Size, 1), 1462 " $src0_sel $src1_sel", // No dst_sel, dst_unused and output modifiers for VOPC 1463 out_mods#" $dst_sel $dst_unused $src0_sel $src1_sel" 1464 ) 1465 ) 1466 ); 1467 string ret = dst#args#sdwa; 1468} 1469 1470 1471// Function that checks if instruction supports DPP and SDWA 1472class getHasExt <int NumSrcArgs, ValueType DstVT = i32, ValueType Src0VT = i32, 1473 ValueType Src1VT = i32> { 1474 bit ret = !if(!eq(NumSrcArgs, 3), 1475 0, // NumSrcArgs == 3 - No DPP or SDWA for VOP3 1476 !if(!eq(DstVT.Size, 64), 1477 0, // 64-bit dst - No DPP or SDWA for 64-bit operands 1478 !if(!eq(Src0VT.Size, 64), 1479 0, // 64-bit src0 1480 !if(!eq(Src0VT.Size, 64), 1481 0, // 64-bit src2 1482 1 1483 ) 1484 ) 1485 ) 1486 ); 1487} 1488 1489class BitOr<bit a, bit b> { 1490 bit ret = !if(a, 1, !if(b, 1, 0)); 1491} 1492 1493class BitAnd<bit a, bit b> { 1494 bit ret = !if(a, !if(b, 1, 0), 0); 1495} 1496 1497class VOPProfile <list<ValueType> _ArgVT> { 1498 1499 field list<ValueType> ArgVT = _ArgVT; 1500 1501 field ValueType DstVT = ArgVT[0]; 1502 field ValueType Src0VT = ArgVT[1]; 1503 field ValueType Src1VT = ArgVT[2]; 1504 field ValueType Src2VT = ArgVT[3]; 1505 field RegisterOperand DstRC = getVALUDstForVT<DstVT>.ret; 1506 field RegisterOperand DstRCDPP = getVALUDstForVT<DstVT>.ret; 1507 field RegisterOperand DstRCSDWA = getSDWADstForVT<DstVT>.ret; 1508 field RegisterOperand Src0RC32 = getVOPSrc0ForVT<Src0VT>.ret; 1509 field RegisterClass Src1RC32 = getVregSrcForVT<Src1VT>.ret; 1510 field RegisterOperand Src0RC64 = getVOP3SrcForVT<Src0VT>.ret; 1511 field RegisterOperand Src1RC64 = getVOP3SrcForVT<Src1VT>.ret; 1512 field RegisterOperand Src2RC64 = getVOP3SrcForVT<Src2VT>.ret; 1513 field RegisterClass Src0DPP = getVregSrcForVT<Src0VT>.ret; 1514 field RegisterClass Src1DPP = getVregSrcForVT<Src1VT>.ret; 1515 field RegisterOperand Src0SDWA = getSDWASrcForVT<Src0VT>.ret; 1516 field RegisterOperand Src1SDWA = getSDWASrcForVT<Src0VT>.ret; 1517 field Operand Src0Mod = getSrcMod<Src0VT>.ret; 1518 field Operand Src1Mod = getSrcMod<Src1VT>.ret; 1519 field Operand Src2Mod = getSrcMod<Src2VT>.ret; 1520 field Operand Src0ModDPP = getSrcModExt<Src0VT>.ret; 1521 field Operand Src1ModDPP = getSrcModExt<Src1VT>.ret; 1522 field Operand Src0ModSDWA = getSrcModSDWA<Src0VT>.ret; 1523 field Operand Src1ModSDWA = getSrcModSDWA<Src1VT>.ret; 1524 1525 1526 field bit HasDst = !if(!eq(DstVT.Value, untyped.Value), 0, 1); 1527 field bit HasDst32 = HasDst; 1528 field bit EmitDst = HasDst; // force dst encoding, see v_movreld_b32 special case 1529 field int NumSrcArgs = getNumSrcArgs<Src0VT, Src1VT, Src2VT>.ret; 1530 field bit HasSrc0 = !if(!eq(Src0VT.Value, untyped.Value), 0, 1); 1531 field bit HasSrc1 = !if(!eq(Src1VT.Value, untyped.Value), 0, 1); 1532 field bit HasSrc2 = !if(!eq(Src2VT.Value, untyped.Value), 0, 1); 1533 1534 // TODO: Modifiers logic is somewhat adhoc here, to be refined later 1535 field bit HasModifiers = isModifierType<Src0VT>.ret; 1536 1537 field bit HasSrc0FloatMods = isFloatType<Src0VT>.ret; 1538 field bit HasSrc1FloatMods = isFloatType<Src1VT>.ret; 1539 field bit HasSrc2FloatMods = isFloatType<Src2VT>.ret; 1540 1541 field bit HasSrc0IntMods = isIntType<Src0VT>.ret; 1542 field bit HasSrc1IntMods = isIntType<Src1VT>.ret; 1543 field bit HasSrc2IntMods = isIntType<Src2VT>.ret; 1544 1545 field bit HasSrc0Mods = HasModifiers; 1546 field bit HasSrc1Mods = !if(HasModifiers, BitOr<HasSrc1FloatMods, HasSrc1IntMods>.ret, 0); 1547 field bit HasSrc2Mods = !if(HasModifiers, BitOr<HasSrc2FloatMods, HasSrc2IntMods>.ret, 0); 1548 1549 field bit HasClamp = HasModifiers; 1550 field bit HasSDWAClamp = EmitDst; 1551 field bit HasFPClamp = BitAnd<isFloatType<DstVT>.ret, HasClamp>.ret; 1552 field bit HasIntClamp = !if(isFloatType<DstVT>.ret, 0, HasClamp); 1553 field bit HasClampLo = HasClamp; 1554 field bit HasClampHi = BitAnd<isPackedType<DstVT>.ret, HasClamp>.ret; 1555 field bit HasHigh = 0; 1556 1557 field bit IsPacked = isPackedType<Src0VT>.ret; 1558 field bit HasOpSel = IsPacked; 1559 field bit HasOMod = !if(HasOpSel, 0, isFloatType<DstVT>.ret); 1560 field bit HasSDWAOMod = isFloatType<DstVT>.ret; 1561 1562 field bit HasExt = getHasExt<NumSrcArgs, DstVT, Src0VT, Src1VT>.ret; 1563 field bit HasSDWA9 = HasExt; 1564 1565 field Operand Src0PackedMod = !if(HasSrc0FloatMods, PackedF16InputMods, PackedI16InputMods); 1566 field Operand Src1PackedMod = !if(HasSrc1FloatMods, PackedF16InputMods, PackedI16InputMods); 1567 field Operand Src2PackedMod = !if(HasSrc2FloatMods, PackedF16InputMods, PackedI16InputMods); 1568 1569 field dag Outs = !if(HasDst,(outs DstRC:$vdst),(outs)); 1570 1571 // VOP3b instructions are a special case with a second explicit 1572 // output. This is manually overridden for them. 1573 field dag Outs32 = Outs; 1574 field dag Outs64 = Outs; 1575 field dag OutsDPP = getOutsExt<HasDst, DstVT, DstRCDPP>.ret; 1576 field dag OutsSDWA = getOutsSDWA<HasDst, DstVT, DstRCSDWA>.ret; 1577 1578 field dag Ins32 = getIns32<Src0RC32, Src1RC32, NumSrcArgs>.ret; 1579 field dag Ins64 = getIns64<Src0RC64, Src1RC64, Src2RC64, NumSrcArgs, 1580 HasIntClamp, HasModifiers, HasOMod, Src0Mod, Src1Mod, 1581 Src2Mod>.ret; 1582 field dag InsVOP3P = getInsVOP3P<Src0RC64, Src1RC64, Src2RC64, 1583 NumSrcArgs, HasClamp, 1584 Src0PackedMod, Src1PackedMod, Src2PackedMod>.ret; 1585 field dag InsVOP3OpSel = getInsVOP3OpSel<Src0RC64, Src1RC64, Src2RC64, 1586 NumSrcArgs, 1587 HasClamp, 1588 getOpSelMod<Src0VT>.ret, 1589 getOpSelMod<Src1VT>.ret, 1590 getOpSelMod<Src2VT>.ret>.ret; 1591 field dag InsDPP = getInsDPP<DstRCDPP, Src0DPP, Src1DPP, NumSrcArgs, 1592 HasModifiers, Src0ModDPP, Src1ModDPP>.ret; 1593 field dag InsSDWA = getInsSDWA<Src0SDWA, Src1SDWA, NumSrcArgs, 1594 HasSDWAOMod, Src0ModSDWA, Src1ModSDWA, 1595 DstVT>.ret; 1596 1597 1598 field string Asm32 = getAsm32<HasDst, NumSrcArgs, DstVT>.ret; 1599 field string Asm64 = getAsm64<HasDst, NumSrcArgs, HasIntClamp, HasModifiers, HasOMod, DstVT>.ret; 1600 field string AsmVOP3P = getAsmVOP3P<HasDst, NumSrcArgs, HasModifiers, HasClamp, DstVT>.ret; 1601 field string AsmVOP3OpSel = getAsmVOP3OpSel<NumSrcArgs, 1602 HasClamp, 1603 HasSrc0FloatMods, 1604 HasSrc1FloatMods, 1605 HasSrc2FloatMods>.ret; 1606 field string AsmDPP = getAsmDPP<HasDst, NumSrcArgs, HasModifiers, DstVT>.ret; 1607 field string AsmSDWA = getAsmSDWA<HasDst, NumSrcArgs, DstVT>.ret; 1608 field string AsmSDWA9 = getAsmSDWA9<HasDst, HasSDWAOMod, NumSrcArgs, DstVT>.ret; 1609} 1610 1611class VOP_NO_EXT <VOPProfile p> : VOPProfile <p.ArgVT> { 1612 let HasExt = 0; 1613 let HasSDWA9 = 0; 1614} 1615 1616def VOP_F16_F16 : VOPProfile <[f16, f16, untyped, untyped]>; 1617def VOP_F16_I16 : VOPProfile <[f16, i16, untyped, untyped]>; 1618def VOP_I16_F16 : VOPProfile <[i16, f16, untyped, untyped]>; 1619 1620def VOP_F16_F16_F16 : VOPProfile <[f16, f16, f16, untyped]>; 1621def VOP_F16_F16_I16 : VOPProfile <[f16, f16, i16, untyped]>; 1622def VOP_F16_F16_I32 : VOPProfile <[f16, f16, i32, untyped]>; 1623def VOP_I16_I16_I16 : VOPProfile <[i16, i16, i16, untyped]>; 1624 1625def VOP_I16_I16_I16_I16 : VOPProfile <[i16, i16, i16, i16, untyped]>; 1626def VOP_F16_F16_F16_F16 : VOPProfile <[f16, f16, f16, f16, untyped]>; 1627 1628def VOP_I32_I16_I16_I32 : VOPProfile <[i32, i16, i16, i32, untyped]>; 1629 1630def VOP_V2F16_V2F16_V2F16 : VOPProfile <[v2f16, v2f16, v2f16, untyped]>; 1631def VOP_V2I16_V2I16_V2I16 : VOPProfile <[v2i16, v2i16, v2i16, untyped]>; 1632def VOP_B32_F16_F16 : VOPProfile <[i32, f16, f16, untyped]>; 1633 1634def VOP_V2F16_V2F16_V2F16_V2F16 : VOPProfile <[v2f16, v2f16, v2f16, v2f16]>; 1635def VOP_V2I16_V2I16_V2I16_V2I16 : VOPProfile <[v2i16, v2i16, v2i16, v2i16]>; 1636 1637def VOP_F32_V2F16_V2F16_V2F16 : VOPProfile <[f32, v2f16, v2f16, v2f16]>; 1638 1639def VOP_NONE : VOPProfile <[untyped, untyped, untyped, untyped]>; 1640 1641def VOP_F32_F32 : VOPProfile <[f32, f32, untyped, untyped]>; 1642def VOP_F32_F64 : VOPProfile <[f32, f64, untyped, untyped]>; 1643def VOP_F32_I32 : VOPProfile <[f32, i32, untyped, untyped]>; 1644def VOP_F64_F32 : VOPProfile <[f64, f32, untyped, untyped]>; 1645def VOP_F64_F64 : VOPProfile <[f64, f64, untyped, untyped]>; 1646def VOP_F64_I32 : VOPProfile <[f64, i32, untyped, untyped]>; 1647def VOP_I32_F32 : VOPProfile <[i32, f32, untyped, untyped]>; 1648def VOP_I32_F64 : VOPProfile <[i32, f64, untyped, untyped]>; 1649def VOP_I32_I32 : VOPProfile <[i32, i32, untyped, untyped]>; 1650def VOP_F16_F32 : VOPProfile <[f16, f32, untyped, untyped]>; 1651def VOP_F32_F16 : VOPProfile <[f32, f16, untyped, untyped]>; 1652 1653def VOP_F32_F32_F16 : VOPProfile <[f32, f32, f16, untyped]>; 1654def VOP_F32_F32_F32 : VOPProfile <[f32, f32, f32, untyped]>; 1655def VOP_F32_F32_I32 : VOPProfile <[f32, f32, i32, untyped]>; 1656def VOP_F64_F64_F64 : VOPProfile <[f64, f64, f64, untyped]>; 1657def VOP_F64_F64_I32 : VOPProfile <[f64, f64, i32, untyped]>; 1658def VOP_I32_F32_F32 : VOPProfile <[i32, f32, f32, untyped]>; 1659def VOP_I32_F32_I32 : VOPProfile <[i32, f32, i32, untyped]>; 1660def VOP_I32_I32_I32 : VOPProfile <[i32, i32, i32, untyped]>; 1661def VOP_V2F16_F32_F32 : VOPProfile <[v2f16, f32, f32, untyped]>; 1662def VOP_F32_F16_F16_F16 : VOPProfile <[f32, f16, f16, f16]>; 1663 1664def VOP_I64_I64_I32 : VOPProfile <[i64, i64, i32, untyped]>; 1665def VOP_I64_I32_I64 : VOPProfile <[i64, i32, i64, untyped]>; 1666def VOP_I64_I64_I64 : VOPProfile <[i64, i64, i64, untyped]>; 1667 1668def VOP_F16_F32_F16_F32 : VOPProfile <[f16, f32, f16, f32]>; 1669def VOP_F32_F32_F16_F16 : VOPProfile <[f32, f32, f16, f16]>; 1670def VOP_F32_F32_F32_F32 : VOPProfile <[f32, f32, f32, f32]>; 1671def VOP_F64_F64_F64_F64 : VOPProfile <[f64, f64, f64, f64]>; 1672def VOP_I32_I32_I32_I32 : VOPProfile <[i32, i32, i32, i32]>; 1673def VOP_I64_I32_I32_I64 : VOPProfile <[i64, i32, i32, i64]>; 1674def VOP_I32_F32_I32_I32 : VOPProfile <[i32, f32, i32, i32]>; 1675def VOP_I64_I64_I32_I64 : VOPProfile <[i64, i64, i32, i64]>; 1676def VOP_V4I32_I64_I32_V4I32 : VOPProfile <[v4i32, i64, i32, v4i32]>; 1677 1678class Commutable_REV <string revOp, bit isOrig> { 1679 string RevOp = revOp; 1680 bit IsOrig = isOrig; 1681} 1682 1683class AtomicNoRet <string noRetOp, bit isRet> { 1684 string NoRetOp = noRetOp; 1685 bit IsRet = isRet; 1686} 1687 1688//===----------------------------------------------------------------------===// 1689// Interpolation opcodes 1690//===----------------------------------------------------------------------===// 1691 1692class VINTRP_Pseudo <string opName, dag outs, dag ins, list<dag> pattern> : 1693 VINTRPCommon <outs, ins, "", pattern>, 1694 SIMCInstr<opName, SIEncodingFamily.NONE> { 1695 let isPseudo = 1; 1696 let isCodeGenOnly = 1; 1697} 1698 1699class VINTRP_Real_si <bits <2> op, string opName, dag outs, dag ins, 1700 string asm> : 1701 VINTRPCommon <outs, ins, asm, []>, 1702 VINTRPe <op>, 1703 SIMCInstr<opName, SIEncodingFamily.SI> { 1704 let AssemblerPredicate = SIAssemblerPredicate; 1705 let DecoderNamespace = "SICI"; 1706 let DisableDecoder = DisableSIDecoder; 1707} 1708 1709class VINTRP_Real_vi <bits <2> op, string opName, dag outs, dag ins, 1710 string asm> : 1711 VINTRPCommon <outs, ins, asm, []>, 1712 VINTRPe_vi <op>, 1713 SIMCInstr<opName, SIEncodingFamily.VI> { 1714 let AssemblerPredicate = VIAssemblerPredicate; 1715 let DecoderNamespace = "VI"; 1716 let DisableDecoder = DisableVIDecoder; 1717} 1718 1719multiclass VINTRP_m <bits <2> op, dag outs, dag ins, string asm, 1720 list<dag> pattern = []> { 1721 def "" : VINTRP_Pseudo <NAME, outs, ins, pattern>; 1722 1723 def _si : VINTRP_Real_si <op, NAME, outs, ins, asm>; 1724 1725 def _vi : VINTRP_Real_vi <op, NAME, outs, ins, asm>; 1726} 1727 1728//===----------------------------------------------------------------------===// 1729// Vector instruction mappings 1730//===----------------------------------------------------------------------===// 1731 1732// Maps an opcode in e32 form to its e64 equivalent 1733def getVOPe64 : InstrMapping { 1734 let FilterClass = "VOP"; 1735 let RowFields = ["OpName"]; 1736 let ColFields = ["Size", "VOP3"]; 1737 let KeyCol = ["4", "0"]; 1738 let ValueCols = [["8", "1"]]; 1739} 1740 1741// Maps an opcode in e64 form to its e32 equivalent 1742def getVOPe32 : InstrMapping { 1743 let FilterClass = "VOP"; 1744 let RowFields = ["OpName"]; 1745 let ColFields = ["Size", "VOP3"]; 1746 let KeyCol = ["8", "1"]; 1747 let ValueCols = [["4", "0"]]; 1748} 1749 1750// Maps ordinary instructions to their SDWA counterparts 1751def getSDWAOp : InstrMapping { 1752 let FilterClass = "VOP"; 1753 let RowFields = ["OpName"]; 1754 let ColFields = ["AsmVariantName"]; 1755 let KeyCol = ["Default"]; 1756 let ValueCols = [["SDWA"]]; 1757} 1758 1759// Maps SDWA instructions to their ordinary counterparts 1760def getBasicFromSDWAOp : InstrMapping { 1761 let FilterClass = "VOP"; 1762 let RowFields = ["OpName"]; 1763 let ColFields = ["AsmVariantName"]; 1764 let KeyCol = ["SDWA"]; 1765 let ValueCols = [["Default"]]; 1766} 1767 1768def getMaskedMIMGOp : InstrMapping { 1769 let FilterClass = "MIMG_Mask"; 1770 let RowFields = ["Op"]; 1771 let ColFields = ["Channels"]; 1772 let KeyCol = ["4"]; 1773 let ValueCols = [["1"], ["2"], ["3"] ]; 1774} 1775 1776// Maps an commuted opcode to its original version 1777def getCommuteOrig : InstrMapping { 1778 let FilterClass = "Commutable_REV"; 1779 let RowFields = ["RevOp"]; 1780 let ColFields = ["IsOrig"]; 1781 let KeyCol = ["0"]; 1782 let ValueCols = [["1"]]; 1783} 1784 1785// Maps an original opcode to its commuted version 1786def getCommuteRev : InstrMapping { 1787 let FilterClass = "Commutable_REV"; 1788 let RowFields = ["RevOp"]; 1789 let ColFields = ["IsOrig"]; 1790 let KeyCol = ["1"]; 1791 let ValueCols = [["0"]]; 1792} 1793 1794def getMCOpcodeGen : InstrMapping { 1795 let FilterClass = "SIMCInstr"; 1796 let RowFields = ["PseudoInstr"]; 1797 let ColFields = ["Subtarget"]; 1798 let KeyCol = [!cast<string>(SIEncodingFamily.NONE)]; 1799 let ValueCols = [[!cast<string>(SIEncodingFamily.SI)], 1800 [!cast<string>(SIEncodingFamily.VI)], 1801 [!cast<string>(SIEncodingFamily.SDWA)], 1802 [!cast<string>(SIEncodingFamily.SDWA9)], 1803 [!cast<string>(SIEncodingFamily.GFX9)]]; 1804} 1805 1806// Get equivalent SOPK instruction. 1807def getSOPKOp : InstrMapping { 1808 let FilterClass = "SOPKInstTable"; 1809 let RowFields = ["BaseCmpOp"]; 1810 let ColFields = ["IsSOPK"]; 1811 let KeyCol = ["0"]; 1812 let ValueCols = [["1"]]; 1813} 1814 1815def getAddr64Inst : InstrMapping { 1816 let FilterClass = "MUBUFAddr64Table"; 1817 let RowFields = ["OpName"]; 1818 let ColFields = ["IsAddr64"]; 1819 let KeyCol = ["0"]; 1820 let ValueCols = [["1"]]; 1821} 1822 1823// Maps an atomic opcode to its version with a return value. 1824def getAtomicRetOp : InstrMapping { 1825 let FilterClass = "AtomicNoRet"; 1826 let RowFields = ["NoRetOp"]; 1827 let ColFields = ["IsRet"]; 1828 let KeyCol = ["0"]; 1829 let ValueCols = [["1"]]; 1830} 1831 1832// Maps an atomic opcode to its returnless version. 1833def getAtomicNoRetOp : InstrMapping { 1834 let FilterClass = "AtomicNoRet"; 1835 let RowFields = ["NoRetOp"]; 1836 let ColFields = ["IsRet"]; 1837 let KeyCol = ["1"]; 1838 let ValueCols = [["0"]]; 1839} 1840 1841include "SIInstructions.td" 1842 1843include "DSInstructions.td" 1844include "MIMGInstructions.td" 1845