1//===-- VOPInstructions.td - Vector Instruction Definitions ---------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9// dummies for outer let
10class LetDummies {
11  bit TRANS;
12  bit ReadsModeReg;
13  bit mayRaiseFPException;
14  bit isCommutable;
15  bit isConvertibleToThreeAddress;
16  bit isMoveImm;
17  bit isReMaterializable;
18  bit isAsCheapAsAMove;
19  bit VOPAsmPrefer32Bit;
20  bit FPDPRounding;
21  Predicate SubtargetPredicate;
22  string Constraints;
23  string DisableEncoding;
24  list<SchedReadWrite> SchedRW;
25  list<Register> Uses;
26  list<Register> Defs;
27}
28
29class VOP <string opName> {
30  string OpName = opName;
31}
32
33class VOPAnyCommon <dag outs, dag ins, string asm, list<dag> pattern> :
34    InstSI <outs, ins, asm, pattern> {
35
36  let mayLoad = 0;
37  let mayStore = 0;
38  let hasSideEffects = 0;
39  let UseNamedOperandTable = 1;
40  let VALU = 1;
41  let Uses = !if(ReadsModeReg, [MODE, EXEC], [EXEC]);
42}
43
44class VOP_Pseudo <string opName, string suffix, VOPProfile P, dag outs, dag ins,
45                  string asm, list<dag> pattern> :
46  InstSI <outs, ins, asm, pattern>,
47  VOP <opName>,
48  SIMCInstr <opName#suffix, SIEncodingFamily.NONE> {
49  let isPseudo = 1;
50  let isCodeGenOnly = 1;
51  let UseNamedOperandTable = 1;
52
53  string Mnemonic = opName;
54  VOPProfile Pfl = P;
55
56  string AsmOperands;
57}
58
59class VOP3Common <dag outs, dag ins, string asm = "",
60                  list<dag> pattern = [], bit HasMods = 0> :
61  VOPAnyCommon <outs, ins, asm, pattern> {
62
63  // Using complex patterns gives VOP3 patterns a very high complexity rating,
64  // but standalone patterns are almost always preferred, so we need to adjust the
65  // priority lower.  The goal is to use a high number to reduce complexity to
66  // zero (or less than zero).
67  let AddedComplexity = -1000;
68
69  let VOP3 = 1;
70
71  let AsmVariantName = AMDGPUAsmVariants.VOP3;
72  let AsmMatchConverter = !if(HasMods, "cvtVOP3", "");
73
74  let isCodeGenOnly = 0;
75
76  int Size = 8;
77
78  // Because SGPRs may be allowed if there are multiple operands, we
79  // need a post-isel hook to insert copies in order to avoid
80  // violating constant bus requirements.
81  let hasPostISelHook = 1;
82}
83
84class VOP3_Pseudo <string opName, VOPProfile P, list<dag> pattern = [],
85                   bit isVOP3P = 0, bit isVop3OpSel = 0> :
86  VOP_Pseudo <opName, "_e64", P, P.Outs64,
87              !if(isVop3OpSel,
88                  P.InsVOP3OpSel,
89                  !if(!and(isVOP3P, P.IsPacked), P.InsVOP3P, P.Ins64)),
90              "", pattern> {
91
92  let VOP3_OPSEL = isVop3OpSel;
93  let IsPacked = P.IsPacked;
94  let IsMAI = P.IsMAI;
95
96  let AsmOperands = !if(isVop3OpSel,
97                        P.AsmVOP3OpSel,
98                        !if(!and(isVOP3P, P.IsPacked), P.AsmVOP3P, P.Asm64));
99
100  let Size = 8;
101  let mayLoad = 0;
102  let mayStore = 0;
103  let hasSideEffects = 0;
104
105  // Because SGPRs may be allowed if there are multiple operands, we
106  // need a post-isel hook to insert copies in order to avoid
107  // violating constant bus requirements.
108  let hasPostISelHook = 1;
109
110  // Using complex patterns gives VOP3 patterns a very high complexity rating,
111  // but standalone patterns are almost always preferred, so we need to adjust the
112  // priority lower.  The goal is to use a high number to reduce complexity to
113  // zero (or less than zero).
114  let AddedComplexity = -1000;
115
116  let VOP3 = 1;
117  let VALU = 1;
118  let FPClamp = P.HasFPClamp;
119  let IntClamp = P.HasIntClamp;
120  let ClampLo = P.HasClampLo;
121  let ClampHi = P.HasClampHi;
122
123  let ReadsModeReg = !or(isFloatType<P.DstVT>.ret, isFloatType<P.Src0VT>.ret);
124
125  let mayRaiseFPException = ReadsModeReg;
126  let Uses = !if(ReadsModeReg, [MODE, EXEC], [EXEC]);
127
128  let AsmVariantName = AMDGPUAsmVariants.VOP3;
129  let AsmMatchConverter =
130    !if(isVOP3P,
131        "cvtVOP3P",
132        !if(!or(P.HasModifiers, P.HasOMod, P.HasIntClamp),
133            "cvtVOP3",
134            ""));
135}
136
137class VOP3P_Pseudo <string opName, VOPProfile P, list<dag> pattern = []> :
138  VOP3_Pseudo<opName, P, pattern, 1> {
139  let VOP3P = 1;
140}
141
142class VOP_Real<VOP_Pseudo ps> {
143  Instruction Opcode = !cast<Instruction>(NAME);
144  bit IsSingle = ps.Pfl.IsSingle;
145}
146
147class VOP3_Real <VOP_Pseudo ps, int EncodingFamily> :
148  VOP_Real <ps>,
149  InstSI <ps.OutOperandList, ps.InOperandList, ps.Mnemonic # ps.AsmOperands, []>,
150  SIMCInstr <ps.PseudoInstr, EncodingFamily> {
151
152  let VALU = 1;
153  let VOP3 = 1;
154  let isPseudo = 0;
155  let isCodeGenOnly = 0;
156  let UseNamedOperandTable = 1;
157
158  let Constraints     = ps.Constraints;
159  let DisableEncoding = ps.DisableEncoding;
160
161  // copy relevant pseudo op flags
162  let SubtargetPredicate = ps.SubtargetPredicate;
163  let OtherPredicates    = ps.OtherPredicates;
164  let AsmMatchConverter  = ps.AsmMatchConverter;
165  let AsmVariantName     = ps.AsmVariantName;
166  let Constraints        = ps.Constraints;
167  let DisableEncoding    = ps.DisableEncoding;
168  let TSFlags            = ps.TSFlags;
169  let UseNamedOperandTable = ps.UseNamedOperandTable;
170  let Uses                 = ps.Uses;
171  let Defs                 = ps.Defs;
172  let SchedRW              = ps.SchedRW;
173  let mayLoad              = ps.mayLoad;
174  let mayStore             = ps.mayStore;
175  let TRANS                = ps.TRANS;
176
177  VOPProfile Pfl = ps.Pfl;
178}
179
180// XXX - Is there any reason to distinguish this from regular VOP3
181// here?
182class VOP3P_Real<VOP_Pseudo ps, int EncodingFamily> :
183  VOP3_Real<ps, EncodingFamily>;
184
185class VOP3a<VOPProfile P> : Enc64 {
186  bits<4> src0_modifiers;
187  bits<9> src0;
188  bits<3> src1_modifiers;
189  bits<9> src1;
190  bits<3> src2_modifiers;
191  bits<9> src2;
192  bits<1> clamp;
193  bits<2> omod;
194
195  let Inst{8}     = !if(P.HasSrc0Mods, src0_modifiers{1}, 0);
196  let Inst{9}     = !if(P.HasSrc1Mods, src1_modifiers{1}, 0);
197  let Inst{10}    = !if(P.HasSrc2Mods, src2_modifiers{1}, 0);
198
199  let Inst{31-26} = 0x34; //encoding
200  let Inst{40-32} = !if(P.HasSrc0, src0, 0);
201  let Inst{49-41} = !if(P.HasSrc1, src1, 0);
202  let Inst{58-50} = !if(P.HasSrc2, src2, 0);
203  let Inst{60-59} = !if(P.HasOMod, omod, 0);
204  let Inst{61}    = !if(P.HasSrc0Mods, src0_modifiers{0}, 0);
205  let Inst{62}    = !if(P.HasSrc1Mods, src1_modifiers{0}, 0);
206  let Inst{63}    = !if(P.HasSrc2Mods, src2_modifiers{0}, 0);
207}
208
209class VOP3a_gfx6_gfx7<bits<9> op, VOPProfile p> : VOP3a<p> {
210  let Inst{11}    = !if(p.HasClamp, clamp{0}, 0);
211  let Inst{25-17} = op;
212}
213
214class VOP3a_gfx10<bits<10> op, VOPProfile p> : VOP3a<p> {
215  let Inst{15}    = !if(p.HasClamp, clamp{0}, 0);
216  let Inst{25-16} = op;
217  let Inst{31-26} = 0x35;
218}
219
220class VOP3a_vi <bits<10> op, VOPProfile P> : VOP3a<P> {
221  let Inst{25-16} = op;
222  let Inst{15}    = !if(P.HasClamp, clamp{0}, 0);
223}
224
225class VOP3e_gfx6_gfx7<bits<9> op, VOPProfile p> : VOP3a_gfx6_gfx7<op, p> {
226  bits<8> vdst;
227  let Inst{7-0} = !if(p.EmitDst, vdst{7-0}, 0);
228}
229
230class VOP3e_gfx10<bits<10> op, VOPProfile p> : VOP3a_gfx10<op, p> {
231  bits<8> vdst;
232  let Inst{7-0} = !if(p.EmitDst, vdst{7-0}, 0);
233}
234
235class VOP3e_vi <bits<10> op, VOPProfile P> : VOP3a_vi <op, P> {
236  bits<8> vdst;
237  let Inst{7-0} = !if(P.EmitDst, vdst{7-0}, 0);
238}
239
240class VOP3OpSel_gfx9 <bits<10> op, VOPProfile P> : VOP3e_vi <op, P> {
241  let Inst{11} = !if(P.HasSrc0, src0_modifiers{2}, 0);
242  let Inst{12} = !if(P.HasSrc1, src1_modifiers{2}, 0);
243  let Inst{13} = !if(P.HasSrc2, src2_modifiers{2}, 0);
244  let Inst{14} = !if(P.HasDst,  src0_modifiers{3}, 0);
245}
246
247class VOP3OpSel_gfx10<bits<10> op, VOPProfile p> : VOP3e_gfx10<op, p> {
248  let Inst{11} = !if(p.HasSrc0, src0_modifiers{2}, 0);
249  let Inst{12} = !if(p.HasSrc1, src1_modifiers{2}, 0);
250  let Inst{13} = !if(p.HasSrc2, src2_modifiers{2}, 0);
251  let Inst{14} = !if(p.HasDst,  src0_modifiers{3}, 0);
252}
253
254// NB: For V_INTERP* opcodes, src0 is encoded as src1 and vice versa
255class VOP3Interp_vi <bits<10> op, VOPProfile P> : VOP3e_vi <op, P> {
256  bits<2> attrchan;
257  bits<6> attr;
258  bits<1> high;
259
260  let Inst{8}     = 0; // No modifiers for src0
261  let Inst{61}    = 0;
262
263  let Inst{9}     = !if(P.HasSrc0Mods, src0_modifiers{1}, 0);
264  let Inst{62}    = !if(P.HasSrc0Mods, src0_modifiers{0}, 0);
265
266  let Inst{37-32} = attr;
267  let Inst{39-38} = attrchan;
268  let Inst{40}    = !if(P.HasHigh, high, 0);
269
270  let Inst{49-41} = src0;
271}
272
273class VOP3Interp_gfx10<bits<10> op, VOPProfile p> : VOP3e_gfx10<op, p> {
274  bits<6> attr;
275  bits<2> attrchan;
276  bits<1> high;
277
278  let Inst{8}     = 0;
279  let Inst{9}     = !if(p.HasSrc0Mods, src0_modifiers{1}, 0);
280  let Inst{37-32} = attr;
281  let Inst{39-38} = attrchan;
282  let Inst{40}    = !if(p.HasHigh, high, 0);
283  let Inst{49-41} = src0;
284  let Inst{61}    = 0;
285  let Inst{62}    = !if(p.HasSrc0Mods, src0_modifiers{0}, 0);
286}
287
288class VOP3be <VOPProfile P> : Enc64 {
289  bits<8> vdst;
290  bits<2> src0_modifiers;
291  bits<9> src0;
292  bits<2> src1_modifiers;
293  bits<9> src1;
294  bits<2> src2_modifiers;
295  bits<9> src2;
296  bits<7> sdst;
297  bits<2> omod;
298
299  let Inst{7-0}   = vdst;
300  let Inst{14-8}  = sdst;
301  let Inst{31-26} = 0x34; //encoding
302  let Inst{40-32} = !if(P.HasSrc0, src0, 0);
303  let Inst{49-41} = !if(P.HasSrc1, src1, 0);
304  let Inst{58-50} = !if(P.HasSrc2, src2, 0);
305  let Inst{60-59} = !if(P.HasOMod, omod, 0);
306  let Inst{61}    = !if(P.HasSrc0Mods, src0_modifiers{0}, 0);
307  let Inst{62}    = !if(P.HasSrc1Mods, src1_modifiers{0}, 0);
308  let Inst{63}    = !if(P.HasSrc2Mods, src2_modifiers{0}, 0);
309}
310
311class VOP3Pe <bits<7> op, VOPProfile P> : Enc64 {
312  bits<8> vdst;
313  // neg, neg_hi, op_sel put in srcN_modifiers
314  bits<4> src0_modifiers;
315  bits<9> src0;
316  bits<4> src1_modifiers;
317  bits<9> src1;
318  bits<4> src2_modifiers;
319  bits<9> src2;
320  bits<1> clamp;
321
322  let Inst{7-0} = vdst;
323  let Inst{8} = !if(P.HasSrc0Mods, src0_modifiers{1}, 0); // neg_hi src0
324  let Inst{9} = !if(P.HasSrc1Mods, src1_modifiers{1}, 0); // neg_hi src1
325  let Inst{10} = !if(P.HasSrc2Mods, src2_modifiers{1}, 0); // neg_hi src2
326
327  let Inst{11} = !if(!and(P.HasSrc0, P.HasOpSel), src0_modifiers{2}, 0); // op_sel(0)
328  let Inst{12} = !if(!and(P.HasSrc1, P.HasOpSel), src1_modifiers{2}, 0); // op_sel(1)
329  let Inst{13} = !if(!and(P.HasSrc2, P.HasOpSel), src2_modifiers{2}, 0); // op_sel(2)
330
331  let Inst{14} = !if(!and(P.HasSrc2, P.HasOpSel), src2_modifiers{3}, ?); // op_sel_hi(2)
332
333  let Inst{15} = !if(P.HasClamp, clamp{0}, 0);
334
335  let Inst{22-16} = op;
336  let Inst{31-23} = 0x1a7; //encoding
337  let Inst{40-32} = !if(P.HasSrc0, src0, 0);
338  let Inst{49-41} = !if(P.HasSrc1, src1, 0);
339  let Inst{58-50} = !if(P.HasSrc2, src2, 0);
340  let Inst{59}    = !if(!and(P.HasSrc0, P.HasOpSel), src0_modifiers{3}, ?); // op_sel_hi(0)
341  let Inst{60}    = !if(!and(P.HasSrc1, P.HasOpSel), src1_modifiers{3}, ?); // op_sel_hi(1)
342  let Inst{61}    = !if(P.HasSrc0Mods, src0_modifiers{0}, 0); // neg (lo)
343  let Inst{62}    = !if(P.HasSrc1Mods, src1_modifiers{0}, 0); // neg (lo)
344  let Inst{63}    = !if(P.HasSrc2Mods, src2_modifiers{0}, 0); // neg (lo)
345}
346
347class VOP3Pe_MAI <bits<7> op, VOPProfile P, bit acc_cd = 0> : Enc64 {
348  bits<8> vdst;
349  bits<10> src0;
350  bits<10> src1;
351  bits<9> src2;
352  bits<3> blgp;
353  bits<3> cbsz;
354  bits<4> abid;
355
356  let Inst{7-0} = vdst;
357
358  let Inst{10-8}  = !if(P.HasSrc1, cbsz, 0);
359  let Inst{14-11} = !if(P.HasSrc1, abid, 0);
360
361  let Inst{15} = acc_cd;
362
363  let Inst{22-16} = op;
364  let Inst{31-23} = 0x1a7; //encoding
365  let Inst{40-32} = !if(P.HasSrc0, src0{8-0}, 0);
366  let Inst{49-41} = !if(P.HasSrc1, src1{8-0}, 0);
367  let Inst{58-50} = !if(P.HasSrc2, src2, 0);
368
369  let Inst{59}    = !if(P.HasSrc0, src0{9}, 0); // acc(0)
370  let Inst{60}    = !if(P.HasSrc1, src1{9}, 0); // acc(1)
371
372  let Inst{63-61} = !if(P.HasSrc1, blgp, 0);
373}
374
375class VOP3Pe_SMFMAC <bits<7> op> : Enc64 {
376  bits<10> vdst; // VGPR or AGPR, but not SGPR. vdst{8} is not encoded in the instruction.
377  bits<10> src0;
378  bits<10> src1;
379  bits<9> idx;
380  bits<3> blgp;
381  bits<3> cbsz;
382  bits<4> abid;
383
384  let blgp = 0;
385
386  let Inst{7-0} = vdst{7-0};
387
388  let Inst{10-8}  = cbsz;
389  let Inst{14-11} = abid;
390
391  let Inst{15} = vdst{9}; // acc(vdst)
392
393  let Inst{22-16} = op;
394  let Inst{31-23} = 0x1a7; // encoding
395  let Inst{40-32} = src0{8-0};
396  let Inst{49-41} = src1{8-0};
397  let Inst{58-50} = idx;
398
399  let Inst{59}    = src0{9}; // acc(0)
400  let Inst{60}    = src1{9}; // acc(1)
401
402  let Inst{63-61} = blgp;
403}
404
405class VOP3Pe_gfx10 <bits<7> op, VOPProfile P> : VOP3Pe<op, P> {
406  let Inst{31-23} = 0x198; //encoding
407}
408
409class VOP3be_gfx6_gfx7<bits<9> op, VOPProfile p> : VOP3be<p> {
410  let Inst{25-17} = op;
411}
412
413class VOP3be_gfx10<bits<10> op, VOPProfile p> : VOP3be<p> {
414  bits<1> clamp;
415  let Inst{15}    = !if(p.HasClamp, clamp{0}, 0);
416  let Inst{25-16} = op;
417  let Inst{31-26} = 0x35;
418}
419
420class VOP3be_vi <bits<10> op, VOPProfile P> : VOP3be<P> {
421  bits<1> clamp;
422  let Inst{25-16} = op;
423  let Inst{15}    = !if(P.HasClamp, clamp{0}, 0);
424}
425
426def SDWA {
427  // sdwa_sel
428  int BYTE_0 = 0;
429  int BYTE_1 = 1;
430  int BYTE_2 = 2;
431  int BYTE_3 = 3;
432  int WORD_0 = 4;
433  int WORD_1 = 5;
434  int DWORD = 6;
435
436  // dst_unused
437  int UNUSED_PAD = 0;
438  int UNUSED_SEXT = 1;
439  int UNUSED_PRESERVE = 2;
440}
441
442class VOP_SDWAe<VOPProfile P> : Enc64 {
443  bits<8> src0;
444  bits<3> src0_sel;
445  bits<2> src0_modifiers; // float: {abs,neg}, int {sext}
446  bits<3> src1_sel;
447  bits<2> src1_modifiers;
448  bits<3> dst_sel;
449  bits<2> dst_unused;
450  bits<1> clamp;
451
452  let Inst{39-32} = !if(P.HasSrc0, src0{7-0}, 0);
453  let Inst{42-40} = !if(P.EmitDstSel, dst_sel{2-0}, ?);
454  let Inst{44-43} = !if(P.EmitDstSel, dst_unused{1-0}, ?);
455  let Inst{45}    = !if(P.HasSDWAClamp, clamp{0}, 0);
456  let Inst{50-48} = !if(P.HasSrc0, src0_sel{2-0}, 0);
457  let Inst{51}    = !if(P.HasSrc0IntMods, src0_modifiers{0}, 0);
458  let Inst{53-52} = !if(P.HasSrc0FloatMods, src0_modifiers{1-0}, 0);
459  let Inst{58-56} = !if(P.HasSrc1, src1_sel{2-0}, 0);
460  let Inst{59}    = !if(P.HasSrc1IntMods, src1_modifiers{0}, 0);
461  let Inst{61-60} = !if(P.HasSrc1FloatMods, src1_modifiers{1-0}, 0);
462}
463
464// GFX9 adds two features to SDWA:
465// 1.	Add 3 fields to the SDWA microcode word: S0, S1 and OMOD.
466//    a. S0 and S1 indicate that source 0 and 1 respectively are SGPRs rather
467//       than VGPRs (at most 1 can be an SGPR);
468//    b. OMOD is the standard output modifier (result *2, *4, /2)
469// 2.	Add a new version of the SDWA microcode word for VOPC: SDWAB. This
470//    replaces OMOD and the dest fields with SD and SDST (SGPR destination)
471//    field.
472//    a. When SD=1, the SDST is used as the destination for the compare result;
473//    b. When SD=0, VCC is used.
474//
475// In GFX9, V_MAC_F16, V_MAC_F32 opcodes cannot be used with SDWA
476
477// gfx9 SDWA basic encoding
478class VOP_SDWA9e<VOPProfile P> : Enc64 {
479  bits<9> src0; // {src0_sgpr{0}, src0{7-0}}
480  bits<3> src0_sel;
481  bits<2> src0_modifiers; // float: {abs,neg}, int {sext}
482  bits<3> src1_sel;
483  bits<2> src1_modifiers;
484  bits<1> src1_sgpr;
485
486  let Inst{39-32} = !if(P.HasSrc0, src0{7-0}, 0);
487  let Inst{50-48} = !if(P.HasSrc0, src0_sel{2-0}, 0);
488  let Inst{51}    = !if(P.HasSrc0IntMods, src0_modifiers{0}, 0);
489  let Inst{53-52} = !if(P.HasSrc0FloatMods, src0_modifiers{1-0}, 0);
490  let Inst{55}    = !if(P.HasSrc0, src0{8}, 0);
491  let Inst{58-56} = !if(P.HasSrc1, src1_sel{2-0}, 0);
492  let Inst{59}    = !if(P.HasSrc1IntMods, src1_modifiers{0}, 0);
493  let Inst{61-60} = !if(P.HasSrc1FloatMods, src1_modifiers{1-0}, 0);
494  let Inst{63}    = 0; // src1_sgpr - should be specified in subclass
495}
496
497// gfx9 SDWA-A
498class VOP_SDWA9Ae<VOPProfile P> : VOP_SDWA9e<P> {
499  bits<3> dst_sel;
500  bits<2> dst_unused;
501  bits<1> clamp;
502  bits<2> omod;
503
504  let Inst{42-40} = !if(P.EmitDstSel, dst_sel{2-0}, ?);
505  let Inst{44-43} = !if(P.EmitDstSel, dst_unused{1-0}, ?);
506  let Inst{45}    = !if(P.HasSDWAClamp, clamp{0}, 0);
507  let Inst{47-46} = !if(P.HasSDWAOMod, omod{1-0}, 0);
508}
509
510// gfx9 SDWA-B
511class VOP_SDWA9Be<VOPProfile P> : VOP_SDWA9e<P> {
512  bits<8> sdst; // {vcc_sdst{0}, sdst{6-0}}
513
514  let Inst{46-40} = !if(P.EmitDst, sdst{6-0}, ?);
515  let Inst{47} = !if(P.EmitDst, sdst{7}, 0);
516}
517
518class VOP_SDWA_Pseudo <string opName, VOPProfile P, list<dag> pattern=[]> :
519  InstSI <P.OutsSDWA, P.InsSDWA, "", pattern>,
520  VOP <opName>,
521  SIMCInstr <opName#"_sdwa", SIEncodingFamily.NONE> {
522
523  let isPseudo = 1;
524  let isCodeGenOnly = 1;
525  let UseNamedOperandTable = 1;
526
527  string Mnemonic = opName;
528  string AsmOperands = P.AsmSDWA;
529  string AsmOperands9 = P.AsmSDWA9;
530
531  let Size = 8;
532  let mayLoad = 0;
533  let mayStore = 0;
534  let hasSideEffects = 0;
535
536  let VALU = 1;
537  let SDWA = 1;
538
539  let ReadsModeReg = !or(isFloatType<P.DstVT>.ret, isFloatType<P.Src0VT>.ret);
540
541  let mayRaiseFPException = ReadsModeReg;
542  let Uses = !if(ReadsModeReg, [MODE, EXEC], [EXEC]);
543
544  let SubtargetPredicate = HasSDWA;
545  let AssemblerPredicate = HasSDWA;
546  let AsmVariantName = !if(P.HasExtSDWA, AMDGPUAsmVariants.SDWA,
547                                         AMDGPUAsmVariants.Disable);
548  let DecoderNamespace = "SDWA";
549
550  VOPProfile Pfl = P;
551}
552
553class VOP_SDWA_Real <VOP_SDWA_Pseudo ps> :
554  InstSI <ps.OutOperandList, ps.InOperandList, ps.Mnemonic # ps.AsmOperands, []>,
555  SIMCInstr <ps.PseudoInstr, SIEncodingFamily.SDWA> {
556
557  let VALU = 1;
558  let SDWA = 1;
559  let isPseudo = 0;
560  let isCodeGenOnly = 0;
561
562  let Defs = ps.Defs;
563  let Uses = ps.Uses;
564  let hasSideEffects = ps.hasSideEffects;
565
566  let Constraints     = ps.Constraints;
567  let DisableEncoding = ps.DisableEncoding;
568
569  // Copy relevant pseudo op flags
570  let SubtargetPredicate   = ps.SubtargetPredicate;
571  let AssemblerPredicate   = ps.AssemblerPredicate;
572  let AsmMatchConverter    = ps.AsmMatchConverter;
573  let AsmVariantName       = ps.AsmVariantName;
574  let UseNamedOperandTable = ps.UseNamedOperandTable;
575  let DecoderNamespace     = ps.DecoderNamespace;
576  let Constraints          = ps.Constraints;
577  let DisableEncoding      = ps.DisableEncoding;
578  let TSFlags              = ps.TSFlags;
579  let SchedRW              = ps.SchedRW;
580  let mayLoad              = ps.mayLoad;
581  let mayStore             = ps.mayStore;
582  let TRANS                = ps.TRANS;
583}
584
585class Base_VOP_SDWA9_Real <VOP_SDWA_Pseudo ps> :
586  InstSI <ps.OutOperandList, ps.InOperandList, ps.Mnemonic # ps.AsmOperands9, []> {
587
588  let VALU = 1;
589  let SDWA = 1;
590  let isPseudo = 0;
591  let isCodeGenOnly = 0;
592
593  let Defs = ps.Defs;
594  let Uses = ps.Uses;
595  let hasSideEffects = ps.hasSideEffects;
596
597  let Constraints     = ps.Constraints;
598  let DisableEncoding = ps.DisableEncoding;
599
600  let SubtargetPredicate = HasSDWA9;
601  let AssemblerPredicate = HasSDWA9;
602  let AsmVariantName = !if(ps.Pfl.HasExtSDWA9, AMDGPUAsmVariants.SDWA9,
603                                               AMDGPUAsmVariants.Disable);
604  let DecoderNamespace = "SDWA9";
605
606  // Copy relevant pseudo op flags
607  let AsmMatchConverter    = ps.AsmMatchConverter;
608  let UseNamedOperandTable = ps.UseNamedOperandTable;
609  let Constraints          = ps.Constraints;
610  let DisableEncoding      = ps.DisableEncoding;
611  let TSFlags              = ps.TSFlags;
612  let SchedRW              = ps.SchedRW;
613  let mayLoad              = ps.mayLoad;
614  let mayStore             = ps.mayStore;
615  let TRANS                = ps.TRANS;
616}
617
618class VOP_SDWA9_Real <VOP_SDWA_Pseudo ps> :
619  Base_VOP_SDWA9_Real <ps >,
620  SIMCInstr <ps.PseudoInstr, SIEncodingFamily.SDWA9>;
621
622class Base_VOP_SDWA10_Real<VOP_SDWA_Pseudo ps> : Base_VOP_SDWA9_Real<ps> {
623  let SubtargetPredicate = HasSDWA10;
624  let AssemblerPredicate = HasSDWA10;
625  let DecoderNamespace = "SDWA10";
626}
627
628class VOP_SDWA10_Real<VOP_SDWA_Pseudo ps> :
629  Base_VOP_SDWA10_Real<ps>, SIMCInstr<ps.PseudoInstr, SIEncodingFamily.SDWA10>;
630
631class VOP_DPPe<VOPProfile P, bit IsDPP16=0> : Enc64 {
632  bits<2> src0_modifiers;
633  bits<8> src0;
634  bits<2> src1_modifiers;
635  bits<9> dpp_ctrl;
636  bits<1> bound_ctrl;
637  bits<4> bank_mask;
638  bits<4> row_mask;
639  bit     fi;
640
641  let Inst{39-32} = !if(P.HasSrc0, src0{7-0}, 0);
642  let Inst{48-40} = dpp_ctrl;
643  let Inst{50}    = !if(IsDPP16, fi, ?);
644  let Inst{51}    = bound_ctrl;
645  let Inst{52}    = !if(P.HasSrc0Mods, src0_modifiers{0}, 0); // src0_neg
646  let Inst{53}    = !if(P.HasSrc0Mods, src0_modifiers{1}, 0); // src0_abs
647  let Inst{54}    = !if(P.HasSrc1Mods, src1_modifiers{0}, 0); // src1_neg
648  let Inst{55}    = !if(P.HasSrc1Mods, src1_modifiers{1}, 0); // src1_abs
649  let Inst{59-56} = bank_mask;
650  let Inst{63-60} = row_mask;
651}
652
653class VOP_DPP_Pseudo <string OpName, VOPProfile P, list<dag> pattern=[]> :
654  InstSI <P.OutsDPP, P.InsDPP, OpName#P.AsmDPP, pattern>,
655  VOP <OpName>,
656  SIMCInstr <OpName#"_dpp", SIEncodingFamily.NONE> {
657
658  let isPseudo = 1;
659  let isCodeGenOnly = 1;
660
661  let mayLoad = 0;
662  let mayStore = 0;
663  let hasSideEffects = 0;
664  let UseNamedOperandTable = 1;
665
666  let VALU = 1;
667  let DPP = 1;
668  let Size = 8;
669
670  let ReadsModeReg = !or(isFloatType<P.DstVT>.ret, isFloatType<P.Src0VT>.ret);
671
672  let mayRaiseFPException = ReadsModeReg;
673  let Uses = !if(ReadsModeReg, [MODE, EXEC], [EXEC]);
674  let isConvergent = 1;
675
676  string Mnemonic = OpName;
677  string AsmOperands = P.AsmDPP;
678
679  let AsmMatchConverter = !if(P.HasModifiers, "cvtDPP", "");
680  let SubtargetPredicate = !if(P.HasExt64BitDPP, Has64BitDPP, HasDPP);
681  let AssemblerPredicate = !if(P.HasExt64BitDPP, Has64BitDPP, HasDPP);
682  let AsmVariantName = !if(P.HasExtDPP, AMDGPUAsmVariants.DPP,
683                                        AMDGPUAsmVariants.Disable);
684  let Constraints = !if(P.NumSrcArgs, P.TieRegDPP # " = $vdst", "");
685  let DisableEncoding = !if(P.NumSrcArgs, P.TieRegDPP, "");
686  let DecoderNamespace = "DPP";
687
688  VOPProfile Pfl = P;
689}
690
691class VOP_DPP_Real <VOP_DPP_Pseudo ps, int EncodingFamily> :
692  InstSI <ps.OutOperandList, ps.InOperandList, ps.Mnemonic # ps.AsmOperands, []>,
693  SIMCInstr <ps.PseudoInstr, EncodingFamily> {
694
695  let VALU = 1;
696  let DPP = 1;
697  let isPseudo = 0;
698  let isCodeGenOnly = 0;
699
700  let Defs = ps.Defs;
701  let Uses = ps.Uses;
702  let hasSideEffects = ps.hasSideEffects;
703
704  let Constraints     = ps.Constraints;
705  let DisableEncoding = ps.DisableEncoding;
706
707  // Copy relevant pseudo op flags
708  let isConvergent         = ps.isConvergent;
709  let SubtargetPredicate   = ps.SubtargetPredicate;
710  let AssemblerPredicate   = ps.AssemblerPredicate;
711  let OtherPredicates      = ps.OtherPredicates;
712  let AsmMatchConverter    = ps.AsmMatchConverter;
713  let AsmVariantName       = ps.AsmVariantName;
714  let UseNamedOperandTable = ps.UseNamedOperandTable;
715  let DecoderNamespace     = ps.DecoderNamespace;
716  let Constraints          = ps.Constraints;
717  let DisableEncoding      = ps.DisableEncoding;
718  let TSFlags              = ps.TSFlags;
719  let SchedRW              = ps.SchedRW;
720  let mayLoad              = ps.mayLoad;
721  let mayStore             = ps.mayStore;
722  let TRANS                = ps.TRANS;
723}
724
725class VOP_DPP <string OpName, VOPProfile P, bit IsDPP16,
726               dag InsDPP = !if(IsDPP16, P.InsDPP16, P.InsDPP),
727               string AsmDPP = !if(IsDPP16, P.AsmDPP16, P.AsmDPP)> :
728  InstSI <P.OutsDPP, InsDPP, OpName#AsmDPP, []>,
729  VOP_DPPe<P, IsDPP16> {
730
731  let mayLoad = 0;
732  let mayStore = 0;
733  let hasSideEffects = 0;
734  let UseNamedOperandTable = 1;
735
736  let VALU = 1;
737  let DPP = 1;
738  let Size = 8;
739
740  let AsmMatchConverter = !if(P.HasModifiers, "cvtDPP", "");
741  let SubtargetPredicate = !if(P.HasExt64BitDPP, Has64BitDPP, HasDPP);
742  let AssemblerPredicate = !if(P.HasExt64BitDPP, Has64BitDPP, HasDPP);
743  let AsmVariantName = !if(P.HasExtDPP, AMDGPUAsmVariants.DPP,
744                                        AMDGPUAsmVariants.Disable);
745  let Constraints = !if(P.NumSrcArgs, P.TieRegDPP # " = $vdst", "");
746  let DisableEncoding = !if(P.NumSrcArgs, P.TieRegDPP, "");
747  let DecoderNamespace = "DPP";
748}
749
750class VOP_DPP8e<VOPProfile P> : Enc64 {
751  bits<8> src0;
752  bits<24> dpp8;
753  bits<9> fi;
754
755  let Inst{39-32} = !if(P.HasSrc0, src0{7-0}, 0);
756  let Inst{63-40} = dpp8{23-0};
757}
758
759class VOP_DPP8<string OpName, VOPProfile P> :
760  InstSI<P.OutsDPP8, P.InsDPP8, OpName#P.AsmDPP8, []>,
761  VOP_DPP8e<P> {
762
763  let mayLoad = 0;
764  let mayStore = 0;
765  let hasSideEffects = 0;
766  let UseNamedOperandTable = 1;
767
768  let VALU = 1;
769  let DPP = 1;
770  let Size = 8;
771
772  let AsmMatchConverter = "cvtDPP8";
773  let SubtargetPredicate = HasDPP8;
774  let AssemblerPredicate = HasDPP8;
775  let AsmVariantName = !if(P.HasExt, AMDGPUAsmVariants.DPP,
776                                     AMDGPUAsmVariants.Disable);
777  let Constraints = !if(P.NumSrcArgs, P.TieRegDPP # " = $vdst", "");
778  let DisableEncoding = !if(P.NumSrcArgs, P.TieRegDPP, "");
779}
780
781def DPP8Mode {
782  int FI_0 = 0xE9;
783  int FI_1 = 0xEA;
784}
785
786class getNumNodeArgs<SDPatternOperator Op> {
787  SDNode N = !cast<SDNode>(Op);
788  SDTypeProfile TP = N.TypeProfile;
789  int ret = TP.NumOperands;
790}
791
792class getDivergentFrag<SDPatternOperator Op> {
793  assert !or(!isa<SDNode>(Op), !isa<PatFrags>(Op)), "Expected SDNode or PatFrags";
794
795  int NumSrcArgs = !if(!isa<SDNode>(Op), getNumNodeArgs<Op>.ret,
796    !size(!cast<PatFrags>(Op).Operands));
797  PatFrag ret = PatFrag <
798    !if(!eq(NumSrcArgs, 1),
799             (ops node:$src0),
800             !if(!eq(NumSrcArgs, 2),
801               (ops node:$src0, node:$src1),
802               (ops node:$src0, node:$src1, node:$src2))),
803    !if(!eq(NumSrcArgs, 1),
804             (Op $src0),
805             !if(!eq(NumSrcArgs, 2),
806               (Op $src0, $src1),
807               (Op $src0, $src1, $src2))),
808    [{ return N->isDivergent(); }]
809  >;
810}
811
812class VOPPatGen<SDPatternOperator Op, VOPProfile P> {
813
814  PatFrag Operator = getDivergentFrag < Op >.ret;
815
816  dag Ins = !foreach(tmp, P.Ins32, !subst(ins, Operator,
817                                         !subst(P.Src0RC32, P.Src0VT,
818                                               !subst(P.Src1RC32, P.Src1VT, tmp))));
819
820
821  dag Outs = !foreach(tmp, P.Outs32, !subst(outs, set,
822                                           !subst(P.DstRC, P.DstVT, tmp)));
823
824  list<dag> ret =  [!con(Outs, (set Ins))];
825}
826
827class DivergentUnaryFrag<SDPatternOperator Op> : PatFrag <
828  (ops node:$src0),
829  (Op $src0),
830  [{ return N->isDivergent(); }]> {
831  // This check is unnecessary as it's captured by the result register
832  // bank constraint.
833  //
834  // FIXME: Should add a way for the emitter to recognize this is a
835  // trivially true predicate to eliminate the check.
836  let GISelPredicateCode = [{return true;}];
837}
838
839class VOPPatOrNull<SDPatternOperator Op, VOPProfile P> {
840  list<dag> ret = !if(!ne(P.NeedPatGen,PatGenMode.NoPattern), VOPPatGen<Op, P>.ret, []);
841}
842
843class DivergentFragOrOp<SDPatternOperator Op, VOPProfile P> {
844  SDPatternOperator ret = !if(!eq(P.NeedPatGen,PatGenMode.Pattern),
845   !if(!isa<SDNode>(Op), getDivergentFrag<Op>.ret, Op), Op);
846}
847
848class getVSrcOp<ValueType vt> {
849  RegisterOperand ret = !if(!eq(vt.Size, 32), VSrc_b32, VSrc_b16);
850}
851
852// Class for binary integer operations with the clamp bit set for saturation
853// TODO: Add sub with negated inline constant pattern.
854class VOPBinOpClampPat<SDPatternOperator node, Instruction inst, ValueType vt> :
855  GCNPat<(node vt:$src0, vt:$src1),
856         (inst getVSrcOp<vt>.ret:$src0, getVSrcOp<vt>.ret:$src1,
857               DSTCLAMP.ENABLE)
858>;
859
860//===----------------------------------------------------------------------===//
861// VOP3 Classes
862//===----------------------------------------------------------------------===//
863
864class getVOP3ModPat<VOPProfile P, SDPatternOperator node> {
865  dag src0 = !if(P.HasOMod,
866    (VOP3Mods0 P.Src0VT:$src0, i32:$src0_modifiers, i1:$clamp, i32:$omod),
867    (VOP3Mods0 P.Src0VT:$src0, i32:$src0_modifiers, i1:$clamp));
868
869  list<dag> ret3 = [(set P.DstVT:$vdst,
870    (DivergentFragOrOp<node, P>.ret (P.Src0VT src0),
871          (P.Src1VT (VOP3Mods P.Src1VT:$src1, i32:$src1_modifiers)),
872          (P.Src2VT (VOP3Mods P.Src2VT:$src2, i32:$src2_modifiers))))];
873
874  list<dag> ret2 = [(set P.DstVT:$vdst,
875    (DivergentFragOrOp<node, P>.ret (P.Src0VT src0),
876          (P.Src1VT (VOP3Mods P.Src1VT:$src1, i32:$src1_modifiers))))];
877
878  list<dag> ret1 = [(set P.DstVT:$vdst,
879    (DivergentFragOrOp<node, P>.ret (P.Src0VT src0)))];
880
881  list<dag> ret = !if(!eq(P.NumSrcArgs, 3), ret3,
882                  !if(!eq(P.NumSrcArgs, 2), ret2,
883                  ret1));
884}
885
886class getVOP3PModPat<VOPProfile P, SDPatternOperator node, bit HasExplicitClamp,
887                     bit IsDOT = 0,
888                     ComplexPattern SrcPat = !if(IsDOT, VOP3PModsDOT, VOP3PMods)> {
889  dag src0_dag = (P.Src0VT (SrcPat P.Src0VT:$src0, i32:$src0_modifiers));
890  dag src1_dag = (P.Src1VT (SrcPat P.Src1VT:$src1, i32:$src1_modifiers));
891  dag src2_dag = (P.Src2VT (SrcPat P.Src2VT:$src2, i32:$src2_modifiers));
892  dag clamp_dag = (i1 timm:$clamp);
893
894  list<dag> ret3 = [(set P.DstVT:$vdst,
895    !if(HasExplicitClamp,
896        (DivergentFragOrOp<node, P>.ret src0_dag, src1_dag, src2_dag, clamp_dag),
897        (DivergentFragOrOp<node, P>.ret src0_dag, src1_dag, src2_dag)))];
898
899  list<dag> ret2 = [(set P.DstVT:$vdst,
900    !if(HasExplicitClamp,
901        (DivergentFragOrOp<node, P>.ret src0_dag, src1_dag, clamp_dag),
902        (DivergentFragOrOp<node, P>.ret src0_dag, src1_dag)))];
903
904  list<dag> ret1 = [(set P.DstVT:$vdst,
905    !if(HasExplicitClamp,
906        (DivergentFragOrOp<node, P>.ret src0_dag, clamp_dag),
907        (DivergentFragOrOp<node, P>.ret src0_dag)))];
908
909  list<dag> ret = !if(!eq(P.NumSrcArgs, 3), ret3,
910                  !if(!eq(P.NumSrcArgs, 2), ret2,
911                  ret1));
912}
913
914class getVOP3OpSelPat<VOPProfile P, SDPatternOperator node> {
915  list<dag> ret3 = [(set P.DstVT:$vdst,
916        (DivergentFragOrOp<node, P>.ret (P.Src0VT (VOP3OpSel P.Src0VT:$src0, i32:$src0_modifiers)),
917          (P.Src1VT (VOP3OpSel P.Src1VT:$src1, i32:$src1_modifiers)),
918          (P.Src2VT (VOP3OpSel P.Src2VT:$src2, i32:$src2_modifiers))))];
919
920  list<dag> ret2 = [(set P.DstVT:$vdst,
921    (DivergentFragOrOp<node, P>.ret (P.Src0VT (VOP3OpSel P.Src0VT:$src0, i32:$src0_modifiers)),
922                                    (P.Src1VT (VOP3OpSel P.Src1VT:$src1, i32:$src1_modifiers))))];
923
924  list<dag> ret1 = [(set P.DstVT:$vdst,
925    (DivergentFragOrOp<node, P>.ret (P.Src0VT (VOP3OpSel P.Src0VT:$src0, i32:$src0_modifiers))))];
926
927  list<dag> ret = !if(!eq(P.NumSrcArgs, 3), ret3,
928                  !if(!eq(P.NumSrcArgs, 2), ret2,
929                  ret1));
930}
931
932class getVOP3OpSelModPat<VOPProfile P, SDPatternOperator node> {
933  list<dag> ret3 = [(set P.DstVT:$vdst,
934    (DivergentFragOrOp<node, P>.ret (P.Src0VT !if(P.HasClamp, (VOP3OpSelMods P.Src0VT:$src0, i32:$src0_modifiers),
935                                    (VOP3OpSelMods P.Src0VT:$src0, i32:$src0_modifiers))),
936          (P.Src1VT (VOP3OpSelMods P.Src1VT:$src1, i32:$src1_modifiers)),
937          (P.Src2VT (VOP3OpSelMods P.Src2VT:$src2, i32:$src2_modifiers))))];
938
939  list<dag> ret2 = [(set P.DstVT:$vdst,
940    (DivergentFragOrOp<node, P>.ret !if(P.HasClamp, (P.Src0VT (VOP3OpSelMods P.Src0VT:$src0, i32:$src0_modifiers)),
941                          (P.Src0VT (VOP3OpSelMods P.Src0VT:$src0, i32:$src0_modifiers))),
942          (P.Src1VT (VOP3OpSelMods P.Src1VT:$src1, i32:$src1_modifiers))))];
943
944  list<dag> ret1 = [(set P.DstVT:$vdst,
945    (DivergentFragOrOp<node, P>.ret (P.Src0VT (VOP3OpSelMods P.Src0VT:$src0, i32:$src0_modifiers))))];
946
947  list<dag> ret = !if(!eq(P.NumSrcArgs, 3), ret3,
948                  !if(!eq(P.NumSrcArgs, 2), ret2,
949                  ret1));
950}
951
952class getVOP3Pat<VOPProfile P, SDPatternOperator node> {
953  list<dag> ret3 = [(set P.DstVT:$vdst, (DivergentFragOrOp<node, P>.ret P.Src0VT:$src0, P.Src1VT:$src1, P.Src2VT:$src2))];
954  list<dag> ret2 = [(set P.DstVT:$vdst, (DivergentFragOrOp<node, P>.ret P.Src0VT:$src0, P.Src1VT:$src1))];
955  list<dag> ret1 = [(set P.DstVT:$vdst, (DivergentFragOrOp<node, P>.ret P.Src0VT:$src0))];
956  list<dag> ret = !if(!eq(P.NumSrcArgs, 3), ret3,
957                  !if(!eq(P.NumSrcArgs, 2), ret2,
958                  ret1));
959}
960
961class getVOP3ClampPat<VOPProfile P, SDPatternOperator node> {
962  list<dag> ret3 = [(set P.DstVT:$vdst, (node P.Src0VT:$src0, P.Src1VT:$src1, P.Src2VT:$src2, i1:$clamp))];
963  list<dag> ret2 = [(set P.DstVT:$vdst, (node P.Src0VT:$src0, P.Src1VT:$src1, i1:$clamp))];
964  list<dag> ret1 = [(set P.DstVT:$vdst, (node P.Src0VT:$src0, i1:$clamp))];
965  list<dag> ret = !if(!eq(P.NumSrcArgs, 3), ret3,
966                  !if(!eq(P.NumSrcArgs, 2), ret2,
967                  ret1));
968}
969
970class getVOP3MAIPat<VOPProfile P, SDPatternOperator node> {
971  list<dag> ret = !if(!eq(P.Src0VT, P.Src1VT),
972                      // mfma
973                      [(set P.DstVT:$vdst, (node P.Src0VT:$src0, P.Src1VT:$src1, P.Src2VT:$src2,
974                                            timm:$cbsz, timm:$abid, timm:$blgp))],
975                      // smfmac
976                      [(set P.DstVT:$vdst, (node P.Src0VT:$src0, P.Src1VT:$src1, P.Src2VT:$src2, i32:$idx,
977                                            timm:$cbsz, timm:$abid))]);
978}
979
980class VOP3Features<bit Clamp, bit OpSel, bit Packed, bit MAI> {
981  bit HasClamp = Clamp;
982  bit HasOpSel = OpSel;
983  bit IsPacked = Packed;
984  bit IsMAI = MAI;
985}
986
987def VOP3_REGULAR : VOP3Features<0, 0, 0, 0>;
988def VOP3_CLAMP   : VOP3Features<1, 0, 0, 0>;
989def VOP3_OPSEL   : VOP3Features<1, 1, 0, 0>;
990def VOP3_PACKED  : VOP3Features<1, 1, 1, 0>;
991def VOP3_MAI     : VOP3Features<0, 0, 0, 1>;
992
993class VOP3_Profile<VOPProfile P, VOP3Features Features = VOP3_REGULAR> : VOPProfile<P.ArgVT> {
994
995  let HasClamp = !if(Features.HasClamp, 1, P.HasClamp);
996  let HasOpSel = !if(Features.HasOpSel, 1, P.HasOpSel);
997  let IsMAI    = !if(Features.IsMAI,    1, P.IsMAI);
998  let IsPacked = !if(Features.IsPacked, 1, P.IsPacked);
999
1000  let HasModifiers = !if(Features.IsMAI, 0, !or(Features.IsPacked, P.HasModifiers));
1001  let IsSingle = 1;
1002}
1003
1004// Consistently gives instructions a _e64 suffix.
1005multiclass VOP3Inst_Pseudo_Wrapper<string opName, VOPProfile P, list<dag> pattern = []> {
1006  def _e64 : VOP3_Pseudo<opName, P, pattern>;
1007}
1008
1009class VOP3InstBase<string OpName, VOPProfile P, SDPatternOperator node = null_frag> :
1010  VOP3_Pseudo<OpName, P,
1011  !if(P.HasOpSel,
1012      !if(P.HasModifiers,
1013          getVOP3OpSelModPat<P, node>.ret,
1014          getVOP3OpSelPat<P, node>.ret),
1015      !if(P.HasModifiers,
1016          getVOP3ModPat<P, node>.ret,
1017          !if(P.HasIntClamp,
1018              getVOP3ClampPat<P, node>.ret,
1019              !if (P.IsMAI,
1020                  getVOP3MAIPat<P, node>.ret,
1021                  getVOP3Pat<P, node>.ret)))),
1022  0, P.HasOpSel> {
1023
1024  let IntClamp = P.HasIntClamp;
1025  let AsmMatchConverter =
1026  !if(P.HasOpSel,
1027      "cvtVOP3OpSel",
1028      !if(!or(P.HasModifiers, P.HasOMod, P.HasIntClamp),
1029          "cvtVOP3",
1030          ""));
1031}
1032
1033multiclass VOP3Inst<string OpName, VOPProfile P, SDPatternOperator node = null_frag> {
1034  def _e64 : VOP3InstBase<OpName, P, node>;
1035}
1036
1037
1038include "VOPCInstructions.td"
1039include "VOP1Instructions.td"
1040include "VOP2Instructions.td"
1041include "VOP3Instructions.td"
1042include "VOP3PInstructions.td"
1043
1044
1045class VOPInfoTable <string Format> : GenericTable {
1046  let FilterClass = Format # "_Real";
1047  let CppTypeName = "VOPInfo";
1048  let Fields = ["Opcode", "IsSingle"];
1049
1050  let PrimaryKey = ["Opcode"];
1051  let PrimaryKeyName = "get" # Format # "OpcodeHelper";
1052}
1053
1054def VOP1InfoTable : VOPInfoTable<"VOP1">;
1055def VOP2InfoTable : VOPInfoTable<"VOP2">;
1056def VOP3InfoTable : VOPInfoTable<"VOP3">;
1057