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