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