• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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                      ">= AMDGPUSubtarget::SEA_ISLANDS">;
11def isCIOnly : Predicate<"Subtarget->getGeneration() =="
12                         "AMDGPUSubtarget::SEA_ISLANDS">,
13  AssemblerPredicate <"FeatureSeaIslands">;
14def isVI : Predicate <
15  "Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS">,
16  AssemblerPredicate<"FeatureGCN3Encoding">;
17
18def DisableInst : Predicate <"false">, AssemblerPredicate<"FeatureDisable">;
19
20class vop {
21  field bits<9> SI3;
22  field bits<10> VI3;
23}
24
25class vopc <bits<8> si, bits<8> vi = !add(0x40, si)> : vop {
26  field bits<8> SI = si;
27  field bits<8> VI = vi;
28
29  field bits<9>  SI3 = {0, si{7-0}};
30  field bits<10> VI3 = {0, 0, vi{7-0}};
31}
32
33class vop1 <bits<8> si, bits<8> vi = si> : vop {
34  field bits<8> SI = si;
35  field bits<8> VI = vi;
36
37  field bits<9>  SI3 = {1, 1, si{6-0}};
38  field bits<10> VI3 = !add(0x140, vi);
39}
40
41class vop2 <bits<6> si, bits<6> vi = si> : vop {
42  field bits<6> SI = si;
43  field bits<6> VI = vi;
44
45  field bits<9>  SI3 = {1, 0, 0, si{5-0}};
46  field bits<10> VI3 = {0, 1, 0, 0, vi{5-0}};
47}
48
49// Specify a VOP2 opcode for SI and VOP3 opcode for VI
50// that doesn't have VOP2 encoding on VI
51class vop23 <bits<6> si, bits<10> vi> : vop2 <si> {
52  let VI3 = vi;
53}
54
55class vop3 <bits<9> si, bits<10> vi = {0, si}> : vop {
56  let SI3 = si;
57  let VI3 = vi;
58}
59
60class sop1 <bits<8> si, bits<8> vi = si> {
61  field bits<8> SI = si;
62  field bits<8> VI = vi;
63}
64
65class sop2 <bits<7> si, bits<7> vi = si> {
66  field bits<7> SI = si;
67  field bits<7> VI = vi;
68}
69
70class sopk <bits<5> si, bits<5> vi = si> {
71  field bits<5> SI = si;
72  field bits<5> VI = vi;
73}
74
75// Specify an SMRD opcode for SI and SMEM opcode for VI
76
77// FIXME: This should really be bits<5> si, Tablegen crashes if
78// parameter default value is other parameter with different bit size
79class smrd<bits<8> si, bits<8> vi = si> {
80  field bits<5> SI = si{4-0};
81  field bits<8> VI = vi;
82}
83
84// Execpt for the NONE field, this must be kept in sync with the SISubtarget enum
85// in AMDGPUInstrInfo.cpp
86def SISubtarget {
87  int NONE = -1;
88  int SI = 0;
89  int VI = 1;
90}
91
92//===----------------------------------------------------------------------===//
93// SI DAG Nodes
94//===----------------------------------------------------------------------===//
95
96def SIload_constant : SDNode<"AMDGPUISD::LOAD_CONSTANT",
97  SDTypeProfile<1, 2, [SDTCisVT<0, f32>, SDTCisVT<1, v4i32>, SDTCisVT<2, i32>]>,
98                      [SDNPMayLoad, SDNPMemOperand]
99>;
100
101def SItbuffer_store : SDNode<"AMDGPUISD::TBUFFER_STORE_FORMAT",
102  SDTypeProfile<0, 13,
103    [SDTCisVT<0, v4i32>,   // rsrc(SGPR)
104     SDTCisVT<1, iAny>,   // vdata(VGPR)
105     SDTCisVT<2, i32>,    // num_channels(imm)
106     SDTCisVT<3, i32>,    // vaddr(VGPR)
107     SDTCisVT<4, i32>,    // soffset(SGPR)
108     SDTCisVT<5, i32>,    // inst_offset(imm)
109     SDTCisVT<6, i32>,    // dfmt(imm)
110     SDTCisVT<7, i32>,    // nfmt(imm)
111     SDTCisVT<8, i32>,    // offen(imm)
112     SDTCisVT<9, i32>,    // idxen(imm)
113     SDTCisVT<10, i32>,   // glc(imm)
114     SDTCisVT<11, i32>,   // slc(imm)
115     SDTCisVT<12, i32>    // tfe(imm)
116    ]>,
117  [SDNPMayStore, SDNPMemOperand, SDNPHasChain]
118>;
119
120def SIload_input : SDNode<"AMDGPUISD::LOAD_INPUT",
121  SDTypeProfile<1, 3, [SDTCisVT<0, v4f32>, SDTCisVT<1, v4i32>, SDTCisVT<2, i16>,
122                       SDTCisVT<3, i32>]>
123>;
124
125class SDSample<string opcode> : SDNode <opcode,
126  SDTypeProfile<1, 4, [SDTCisVT<0, v4f32>, SDTCisVT<2, v32i8>,
127                       SDTCisVT<3, v4i32>, SDTCisVT<4, i32>]>
128>;
129
130def SIsample : SDSample<"AMDGPUISD::SAMPLE">;
131def SIsampleb : SDSample<"AMDGPUISD::SAMPLEB">;
132def SIsampled : SDSample<"AMDGPUISD::SAMPLED">;
133def SIsamplel : SDSample<"AMDGPUISD::SAMPLEL">;
134
135def SIconstdata_ptr : SDNode<
136  "AMDGPUISD::CONST_DATA_PTR", SDTypeProfile <1, 1, [SDTCisVT<0, i64>,
137                                                     SDTCisVT<0, i64>]>
138>;
139
140def mubuf_load : PatFrag <(ops node:$ptr), (load node:$ptr), [{
141	return isGlobalLoad(cast<LoadSDNode>(N)) ||
142         isConstantLoad(cast<LoadSDNode>(N), -1);
143}]>;
144
145def smrd_load : PatFrag <(ops node:$ptr), (load node:$ptr), [{
146  return isConstantLoad(cast<LoadSDNode>(N), -1) &&
147  static_cast<const SITargetLowering *>(getTargetLowering())->isMemOpUniform(N);
148}]>;
149
150//===----------------------------------------------------------------------===//
151// SDNodes and PatFrag for local loads and stores to enable s_mov_b32 m0, -1
152// to be glued to the memory instructions.
153//===----------------------------------------------------------------------===//
154
155def SIld_local : SDNode <"ISD::LOAD", SDTLoad,
156  [SDNPHasChain, SDNPMayLoad, SDNPMemOperand, SDNPInGlue]
157>;
158
159def si_ld_local : PatFrag <(ops node:$ptr), (SIld_local node:$ptr), [{
160  return isLocalLoad(cast<LoadSDNode>(N));
161}]>;
162
163def si_load_local : PatFrag <(ops node:$ptr), (si_ld_local node:$ptr), [{
164  return cast<LoadSDNode>(N)->getAddressingMode() == ISD::UNINDEXED &&
165         cast<LoadSDNode>(N)->getExtensionType() == ISD::NON_EXTLOAD;
166}]>;
167
168def si_load_local_align8 : Aligned8Bytes <
169  (ops node:$ptr), (si_load_local node:$ptr)
170>;
171
172def si_sextload_local : PatFrag <(ops node:$ptr), (si_ld_local node:$ptr), [{
173  return cast<LoadSDNode>(N)->getExtensionType() == ISD::SEXTLOAD;
174}]>;
175def si_az_extload_local : AZExtLoadBase <si_ld_local>;
176
177multiclass SIExtLoadLocal <PatFrag ld_node> {
178
179  def _i8 : PatFrag <(ops node:$ptr), (ld_node node:$ptr),
180                     [{return cast<LoadSDNode>(N)->getMemoryVT() == MVT::i8;}]
181  >;
182
183  def _i16 : PatFrag <(ops node:$ptr), (ld_node node:$ptr),
184                     [{return cast<LoadSDNode>(N)->getMemoryVT() == MVT::i16;}]
185  >;
186}
187
188defm si_sextload_local : SIExtLoadLocal <si_sextload_local>;
189defm si_az_extload_local : SIExtLoadLocal <si_az_extload_local>;
190
191def SIst_local : SDNode <"ISD::STORE", SDTStore,
192  [SDNPHasChain, SDNPMayStore, SDNPMemOperand, SDNPInGlue]
193>;
194
195def si_st_local : PatFrag <
196  (ops node:$val, node:$ptr), (SIst_local node:$val, node:$ptr), [{
197  return isLocalStore(cast<StoreSDNode>(N));
198}]>;
199
200def si_store_local : PatFrag <
201  (ops node:$val, node:$ptr), (si_st_local node:$val, node:$ptr), [{
202  return cast<StoreSDNode>(N)->getAddressingMode() == ISD::UNINDEXED &&
203         !cast<StoreSDNode>(N)->isTruncatingStore();
204}]>;
205
206def si_store_local_align8 : Aligned8Bytes <
207  (ops node:$val, node:$ptr), (si_store_local node:$val, node:$ptr)
208>;
209
210def si_truncstore_local : PatFrag <
211  (ops node:$val, node:$ptr), (si_st_local node:$val, node:$ptr), [{
212  return cast<StoreSDNode>(N)->isTruncatingStore();
213}]>;
214
215def si_truncstore_local_i8 : PatFrag <
216  (ops node:$val, node:$ptr), (si_truncstore_local node:$val, node:$ptr), [{
217  return cast<StoreSDNode>(N)->getMemoryVT() == MVT::i8;
218}]>;
219
220def si_truncstore_local_i16 : PatFrag <
221  (ops node:$val, node:$ptr), (si_truncstore_local node:$val, node:$ptr), [{
222  return cast<StoreSDNode>(N)->getMemoryVT() == MVT::i16;
223}]>;
224
225multiclass SIAtomicM0Glue2 <string op_name> {
226
227  def _glue : SDNode <"ISD::ATOMIC_"#op_name, SDTAtomic2,
228    [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand, SDNPInGlue]
229  >;
230
231  def _local : local_binary_atomic_op <!cast<SDNode>(NAME#"_glue")>;
232}
233
234defm si_atomic_load_add : SIAtomicM0Glue2 <"LOAD_ADD">;
235defm si_atomic_load_and : SIAtomicM0Glue2 <"LOAD_AND">;
236defm si_atomic_load_min : SIAtomicM0Glue2 <"LOAD_MIN">;
237defm si_atomic_load_max : SIAtomicM0Glue2 <"LOAD_MAX">;
238defm si_atomic_load_or : SIAtomicM0Glue2 <"LOAD_OR">;
239defm si_atomic_load_sub : SIAtomicM0Glue2 <"LOAD_SUB">;
240defm si_atomic_load_xor : SIAtomicM0Glue2 <"LOAD_XOR">;
241defm si_atomic_load_umin : SIAtomicM0Glue2 <"LOAD_UMIN">;
242defm si_atomic_load_umax : SIAtomicM0Glue2 <"LOAD_UMAX">;
243defm si_atomic_swap : SIAtomicM0Glue2 <"SWAP">;
244
245def si_atomic_cmp_swap_glue : SDNode <"ISD::ATOMIC_CMP_SWAP", SDTAtomic3,
246  [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand, SDNPInGlue]
247>;
248
249defm si_atomic_cmp_swap : AtomicCmpSwapLocal <si_atomic_cmp_swap_glue>;
250
251// Transformation function, extract the lower 32bit of a 64bit immediate
252def LO32 : SDNodeXForm<imm, [{
253  return CurDAG->getTargetConstant(N->getZExtValue() & 0xffffffff, SDLoc(N),
254                                   MVT::i32);
255}]>;
256
257def LO32f : SDNodeXForm<fpimm, [{
258  APInt V = N->getValueAPF().bitcastToAPInt().trunc(32);
259  return CurDAG->getTargetConstantFP(APFloat(APFloat::IEEEsingle, V), MVT::f32);
260}]>;
261
262// Transformation function, extract the upper 32bit of a 64bit immediate
263def HI32 : SDNodeXForm<imm, [{
264  return CurDAG->getTargetConstant(N->getZExtValue() >> 32, SDLoc(N), MVT::i32);
265}]>;
266
267def HI32f : SDNodeXForm<fpimm, [{
268  APInt V = N->getValueAPF().bitcastToAPInt().lshr(32).trunc(32);
269  return CurDAG->getTargetConstantFP(APFloat(APFloat::IEEEsingle, V), SDLoc(N),
270                                     MVT::f32);
271}]>;
272
273def IMM8bitDWORD : PatLeaf <(imm),
274  [{return (N->getZExtValue() & ~0x3FC) == 0;}]
275>;
276
277def as_dword_i32imm : SDNodeXForm<imm, [{
278  return CurDAG->getTargetConstant(N->getZExtValue() >> 2, SDLoc(N), MVT::i32);
279}]>;
280
281def as_i1imm : SDNodeXForm<imm, [{
282  return CurDAG->getTargetConstant(N->getZExtValue(), SDLoc(N), MVT::i1);
283}]>;
284
285def as_i8imm : SDNodeXForm<imm, [{
286  return CurDAG->getTargetConstant(N->getZExtValue(), SDLoc(N), MVT::i8);
287}]>;
288
289def as_i16imm : SDNodeXForm<imm, [{
290  return CurDAG->getTargetConstant(N->getSExtValue(), SDLoc(N), MVT::i16);
291}]>;
292
293def as_i32imm: SDNodeXForm<imm, [{
294  return CurDAG->getTargetConstant(N->getSExtValue(), SDLoc(N), MVT::i32);
295}]>;
296
297def as_i64imm: SDNodeXForm<imm, [{
298  return CurDAG->getTargetConstant(N->getSExtValue(), SDLoc(N), MVT::i64);
299}]>;
300
301// Copied from the AArch64 backend:
302def bitcast_fpimm_to_i32 : SDNodeXForm<fpimm, [{
303return CurDAG->getTargetConstant(
304  N->getValueAPF().bitcastToAPInt().getZExtValue(), SDLoc(N), MVT::i32);
305}]>;
306
307// Copied from the AArch64 backend:
308def bitcast_fpimm_to_i64 : SDNodeXForm<fpimm, [{
309return CurDAG->getTargetConstant(
310  N->getValueAPF().bitcastToAPInt().getZExtValue(), SDLoc(N), MVT::i64);
311}]>;
312
313def IMM8bit : PatLeaf <(imm),
314  [{return isUInt<8>(N->getZExtValue());}]
315>;
316
317def IMM12bit : PatLeaf <(imm),
318  [{return isUInt<12>(N->getZExtValue());}]
319>;
320
321def IMM16bit : PatLeaf <(imm),
322  [{return isUInt<16>(N->getZExtValue());}]
323>;
324
325def IMM20bit : PatLeaf <(imm),
326  [{return isUInt<20>(N->getZExtValue());}]
327>;
328
329def IMM32bit : PatLeaf <(imm),
330  [{return isUInt<32>(N->getZExtValue());}]
331>;
332
333def mubuf_vaddr_offset : PatFrag<
334  (ops node:$ptr, node:$offset, node:$imm_offset),
335  (add (add node:$ptr, node:$offset), node:$imm_offset)
336>;
337
338class InlineImm <ValueType vt> : PatLeaf <(vt imm), [{
339  return isInlineImmediate(N);
340}]>;
341
342class InlineFPImm <ValueType vt> : PatLeaf <(vt fpimm), [{
343  return isInlineImmediate(N);
344}]>;
345
346class SGPRImm <dag frag> : PatLeaf<frag, [{
347  if (Subtarget->getGeneration() < AMDGPUSubtarget::SOUTHERN_ISLANDS) {
348    return false;
349  }
350  const SIRegisterInfo *SIRI =
351      static_cast<const SIRegisterInfo *>(Subtarget->getRegisterInfo());
352  for (SDNode::use_iterator U = N->use_begin(), E = SDNode::use_end();
353                                                U != E; ++U) {
354    const TargetRegisterClass *RC = getOperandRegClass(*U, U.getOperandNo());
355    if (RC && SIRI->isSGPRClass(RC))
356      return true;
357  }
358  return false;
359}]>;
360
361//===----------------------------------------------------------------------===//
362// Custom Operands
363//===----------------------------------------------------------------------===//
364
365def FRAMEri32 : Operand<iPTR> {
366  let MIOperandInfo = (ops i32:$ptr, i32imm:$index);
367}
368
369def SoppBrTarget : AsmOperandClass {
370  let Name = "SoppBrTarget";
371  let ParserMethod = "parseSOppBrTarget";
372}
373
374def sopp_brtarget : Operand<OtherVT> {
375  let EncoderMethod = "getSOPPBrEncoding";
376  let OperandType = "OPERAND_PCREL";
377  let ParserMatchClass = SoppBrTarget;
378}
379
380def const_ga : Operand<iPTR>;
381
382include "SIInstrFormats.td"
383include "VIInstrFormats.td"
384
385def MubufOffsetMatchClass : AsmOperandClass {
386  let Name = "MubufOffset";
387  let ParserMethod = "parseMubufOptionalOps";
388  let RenderMethod = "addImmOperands";
389}
390
391class DSOffsetBaseMatchClass <string parser> : AsmOperandClass {
392  let Name = "DSOffset"#parser;
393  let ParserMethod = parser;
394  let RenderMethod = "addImmOperands";
395  let PredicateMethod = "isDSOffset";
396}
397
398def DSOffsetMatchClass : DSOffsetBaseMatchClass <"parseDSOptionalOps">;
399def DSOffsetGDSMatchClass : DSOffsetBaseMatchClass <"parseDSOffsetOptional">;
400
401def DSOffset01MatchClass : AsmOperandClass {
402  let Name = "DSOffset1";
403  let ParserMethod = "parseDSOff01OptionalOps";
404  let RenderMethod = "addImmOperands";
405  let PredicateMethod = "isDSOffset01";
406}
407
408class GDSBaseMatchClass <string parser> : AsmOperandClass {
409  let Name = "GDS"#parser;
410  let PredicateMethod = "isImm";
411  let ParserMethod = parser;
412  let RenderMethod = "addImmOperands";
413}
414
415def GDSMatchClass : GDSBaseMatchClass <"parseDSOptionalOps">;
416def GDS01MatchClass : GDSBaseMatchClass <"parseDSOff01OptionalOps">;
417
418class GLCBaseMatchClass <string parser> : AsmOperandClass {
419  let Name = "GLC"#parser;
420  let PredicateMethod = "isImm";
421  let ParserMethod = parser;
422  let RenderMethod = "addImmOperands";
423}
424
425def GLCMubufMatchClass : GLCBaseMatchClass <"parseMubufOptionalOps">;
426def GLCFlatMatchClass : GLCBaseMatchClass <"parseFlatOptionalOps">;
427
428class SLCBaseMatchClass <string parser> : AsmOperandClass {
429  let Name = "SLC"#parser;
430  let PredicateMethod = "isImm";
431  let ParserMethod = parser;
432  let RenderMethod = "addImmOperands";
433}
434
435def SLCMubufMatchClass : SLCBaseMatchClass <"parseMubufOptionalOps">;
436def SLCFlatMatchClass : SLCBaseMatchClass <"parseFlatOptionalOps">;
437def SLCFlatAtomicMatchClass : SLCBaseMatchClass <"parseFlatAtomicOptionalOps">;
438
439class TFEBaseMatchClass <string parser> : AsmOperandClass {
440  let Name = "TFE"#parser;
441  let PredicateMethod = "isImm";
442  let ParserMethod = parser;
443  let RenderMethod = "addImmOperands";
444}
445
446def TFEMubufMatchClass : TFEBaseMatchClass <"parseMubufOptionalOps">;
447def TFEFlatMatchClass : TFEBaseMatchClass <"parseFlatOptionalOps">;
448def TFEFlatAtomicMatchClass : TFEBaseMatchClass <"parseFlatAtomicOptionalOps">;
449
450def OModMatchClass : AsmOperandClass {
451  let Name = "OMod";
452  let PredicateMethod = "isImm";
453  let ParserMethod = "parseVOP3OptionalOps";
454  let RenderMethod = "addImmOperands";
455}
456
457def ClampMatchClass : AsmOperandClass {
458  let Name = "Clamp";
459  let PredicateMethod = "isImm";
460  let ParserMethod = "parseVOP3OptionalOps";
461  let RenderMethod = "addImmOperands";
462}
463
464class SMRDOffsetBaseMatchClass <string predicate> : AsmOperandClass {
465  let Name = "SMRDOffset"#predicate;
466  let PredicateMethod = predicate;
467  let RenderMethod = "addImmOperands";
468}
469
470def SMRDOffsetMatchClass : SMRDOffsetBaseMatchClass <"isSMRDOffset">;
471def SMRDLiteralOffsetMatchClass : SMRDOffsetBaseMatchClass <
472  "isSMRDLiteralOffset"
473>;
474
475let OperandType = "OPERAND_IMMEDIATE" in {
476
477def offen : Operand<i1> {
478  let PrintMethod = "printOffen";
479}
480def idxen : Operand<i1> {
481  let PrintMethod = "printIdxen";
482}
483def addr64 : Operand<i1> {
484  let PrintMethod = "printAddr64";
485}
486def mbuf_offset : Operand<i16> {
487  let PrintMethod = "printMBUFOffset";
488  let ParserMatchClass = MubufOffsetMatchClass;
489}
490class ds_offset_base <AsmOperandClass mc> : Operand<i16> {
491  let PrintMethod = "printDSOffset";
492  let ParserMatchClass = mc;
493}
494def ds_offset : ds_offset_base <DSOffsetMatchClass>;
495def ds_offset_gds : ds_offset_base <DSOffsetGDSMatchClass>;
496
497def ds_offset0 : Operand<i8> {
498  let PrintMethod = "printDSOffset0";
499  let ParserMatchClass = DSOffset01MatchClass;
500}
501def ds_offset1 : Operand<i8> {
502  let PrintMethod = "printDSOffset1";
503  let ParserMatchClass = DSOffset01MatchClass;
504}
505class gds_base <AsmOperandClass mc> : Operand <i1> {
506  let PrintMethod = "printGDS";
507  let ParserMatchClass = mc;
508}
509def gds : gds_base <GDSMatchClass>;
510
511def gds01 : gds_base <GDS01MatchClass>;
512
513class glc_base <AsmOperandClass mc> : Operand <i1> {
514  let PrintMethod = "printGLC";
515  let ParserMatchClass = mc;
516}
517
518def glc : glc_base <GLCMubufMatchClass>;
519def glc_flat : glc_base <GLCFlatMatchClass>;
520
521class slc_base <AsmOperandClass mc> : Operand <i1> {
522  let PrintMethod = "printSLC";
523  let ParserMatchClass = mc;
524}
525
526def slc : slc_base <SLCMubufMatchClass>;
527def slc_flat : slc_base <SLCFlatMatchClass>;
528def slc_flat_atomic : slc_base <SLCFlatAtomicMatchClass>;
529
530class tfe_base <AsmOperandClass mc> : Operand <i1> {
531  let PrintMethod = "printTFE";
532  let ParserMatchClass = mc;
533}
534
535def tfe : tfe_base <TFEMubufMatchClass>;
536def tfe_flat : tfe_base <TFEFlatMatchClass>;
537def tfe_flat_atomic : tfe_base <TFEFlatAtomicMatchClass>;
538
539def omod : Operand <i32> {
540  let PrintMethod = "printOModSI";
541  let ParserMatchClass = OModMatchClass;
542}
543
544def ClampMod : Operand <i1> {
545  let PrintMethod = "printClampSI";
546  let ParserMatchClass = ClampMatchClass;
547}
548
549def smrd_offset : Operand <i32> {
550  let PrintMethod = "printU32ImmOperand";
551  let ParserMatchClass = SMRDOffsetMatchClass;
552}
553
554def smrd_literal_offset : Operand <i32> {
555  let PrintMethod = "printU32ImmOperand";
556  let ParserMatchClass = SMRDLiteralOffsetMatchClass;
557}
558
559} // End OperandType = "OPERAND_IMMEDIATE"
560
561def VOPDstS64 : VOPDstOperand <SReg_64>;
562
563//===----------------------------------------------------------------------===//
564// Complex patterns
565//===----------------------------------------------------------------------===//
566
567def DS1Addr1Offset : ComplexPattern<i32, 2, "SelectDS1Addr1Offset">;
568def DS64Bit4ByteAligned : ComplexPattern<i32, 3, "SelectDS64Bit4ByteAligned">;
569
570def MUBUFAddr32 : ComplexPattern<i64, 9, "SelectMUBUFAddr32">;
571def MUBUFAddr64 : ComplexPattern<i64, 7, "SelectMUBUFAddr64">;
572def MUBUFAddr64Atomic : ComplexPattern<i64, 5, "SelectMUBUFAddr64">;
573def MUBUFScratch : ComplexPattern<i64, 4, "SelectMUBUFScratch">;
574def MUBUFOffset : ComplexPattern<i64, 6, "SelectMUBUFOffset">;
575def MUBUFOffsetAtomic : ComplexPattern<i64, 4, "SelectMUBUFOffset">;
576
577def SMRDImm   : ComplexPattern<i64, 2, "SelectSMRDImm">;
578def SMRDImm32 : ComplexPattern<i64, 2, "SelectSMRDImm32">;
579def SMRDSgpr  : ComplexPattern<i64, 2, "SelectSMRDSgpr">;
580def SMRDBufferImm   : ComplexPattern<i32, 1, "SelectSMRDBufferImm">;
581def SMRDBufferImm32 : ComplexPattern<i32, 1, "SelectSMRDBufferImm32">;
582def SMRDBufferSgpr  : ComplexPattern<i32, 1, "SelectSMRDBufferSgpr">;
583
584def VOP3Mods0 : ComplexPattern<untyped, 4, "SelectVOP3Mods0">;
585def VOP3NoMods0 : ComplexPattern<untyped, 4, "SelectVOP3NoMods0">;
586def VOP3Mods0Clamp : ComplexPattern<untyped, 3, "SelectVOP3Mods0Clamp">;
587def VOP3Mods0Clamp0OMod : ComplexPattern<untyped, 4, "SelectVOP3Mods0Clamp0OMod">;
588def VOP3Mods  : ComplexPattern<untyped, 2, "SelectVOP3Mods">;
589def VOP3NoMods : ComplexPattern<untyped, 2, "SelectVOP3NoMods">;
590
591//===----------------------------------------------------------------------===//
592// SI assembler operands
593//===----------------------------------------------------------------------===//
594
595def SIOperand {
596  int ZERO = 0x80;
597  int VCC = 0x6A;
598  int FLAT_SCR = 0x68;
599}
600
601def SRCMODS {
602  int NONE = 0;
603  int NEG = 1;
604}
605
606def DSTCLAMP {
607  int NONE = 0;
608}
609
610def DSTOMOD {
611  int NONE = 0;
612}
613
614//===----------------------------------------------------------------------===//
615//
616// SI Instruction multiclass helpers.
617//
618// Instructions with _32 take 32-bit operands.
619// Instructions with _64 take 64-bit operands.
620//
621// VOP_* instructions can use either a 32-bit or 64-bit encoding.  The 32-bit
622// encoding is the standard encoding, but instruction that make use of
623// any of the instruction modifiers must use the 64-bit encoding.
624//
625// Instructions with _e32 use the 32-bit encoding.
626// Instructions with _e64 use the 64-bit encoding.
627//
628//===----------------------------------------------------------------------===//
629
630class SIMCInstr <string pseudo, int subtarget> {
631  string PseudoInstr = pseudo;
632  int Subtarget = subtarget;
633}
634
635//===----------------------------------------------------------------------===//
636// EXP classes
637//===----------------------------------------------------------------------===//
638
639class EXPCommon : InstSI<
640  (outs),
641  (ins i32imm:$en, i32imm:$tgt, i32imm:$compr, i32imm:$done, i32imm:$vm,
642       VGPR_32:$src0, VGPR_32:$src1, VGPR_32:$src2, VGPR_32:$src3),
643  "exp $en, $tgt, $compr, $done, $vm, $src0, $src1, $src2, $src3",
644  [] > {
645
646  let EXP_CNT = 1;
647  let Uses = [EXEC];
648}
649
650multiclass EXP_m {
651
652  let isPseudo = 1, isCodeGenOnly = 1 in {
653    def "" : EXPCommon, SIMCInstr <"exp", SISubtarget.NONE> ;
654  }
655
656  def _si : EXPCommon, SIMCInstr <"exp", SISubtarget.SI>, EXPe;
657
658  def _vi : EXPCommon, SIMCInstr <"exp", SISubtarget.VI>, EXPe_vi;
659}
660
661//===----------------------------------------------------------------------===//
662// Scalar classes
663//===----------------------------------------------------------------------===//
664
665class SOP1_Pseudo <string opName, dag outs, dag ins, list<dag> pattern> :
666  SOP1 <outs, ins, "", pattern>,
667  SIMCInstr<opName, SISubtarget.NONE> {
668  let isPseudo = 1;
669  let isCodeGenOnly = 1;
670}
671
672class SOP1_Real_si <sop1 op, string opName, dag outs, dag ins, string asm> :
673  SOP1 <outs, ins, asm, []>,
674  SOP1e <op.SI>,
675  SIMCInstr<opName, SISubtarget.SI> {
676  let isCodeGenOnly = 0;
677  let AssemblerPredicates = [isSICI];
678}
679
680class SOP1_Real_vi <sop1 op, string opName, dag outs, dag ins, string asm> :
681  SOP1 <outs, ins, asm, []>,
682  SOP1e <op.VI>,
683  SIMCInstr<opName, SISubtarget.VI> {
684  let isCodeGenOnly = 0;
685  let AssemblerPredicates = [isVI];
686}
687
688multiclass SOP1_m <sop1 op, string opName, dag outs, dag ins, string asm,
689                   list<dag> pattern> {
690
691  def "" : SOP1_Pseudo <opName, outs, ins, pattern>;
692
693  def _si : SOP1_Real_si <op, opName, outs, ins, asm>;
694
695  def _vi : SOP1_Real_vi <op, opName, outs, ins, asm>;
696
697}
698
699multiclass SOP1_32 <sop1 op, string opName, list<dag> pattern> : SOP1_m <
700    op, opName, (outs SReg_32:$dst), (ins SSrc_32:$src0),
701    opName#" $dst, $src0", pattern
702>;
703
704multiclass SOP1_64 <sop1 op, string opName, list<dag> pattern> : SOP1_m <
705    op, opName, (outs SReg_64:$dst), (ins SSrc_64:$src0),
706    opName#" $dst, $src0", pattern
707>;
708
709// no input, 64-bit output.
710multiclass SOP1_64_0 <sop1 op, string opName, list<dag> pattern> {
711  def "" : SOP1_Pseudo <opName, (outs SReg_64:$dst), (ins), pattern>;
712
713  def _si : SOP1_Real_si <op, opName, (outs SReg_64:$dst), (ins),
714    opName#" $dst"> {
715    let ssrc0 = 0;
716  }
717
718  def _vi : SOP1_Real_vi <op, opName, (outs SReg_64:$dst), (ins),
719    opName#" $dst"> {
720    let ssrc0 = 0;
721  }
722}
723
724// 64-bit input, no output
725multiclass SOP1_1 <sop1 op, string opName, list<dag> pattern> {
726  def "" : SOP1_Pseudo <opName, (outs), (ins SReg_64:$src0), pattern>;
727
728  def _si : SOP1_Real_si <op, opName, (outs), (ins SReg_64:$src0),
729    opName#" $src0"> {
730    let sdst = 0;
731  }
732
733  def _vi : SOP1_Real_vi <op, opName, (outs), (ins SReg_64:$src0),
734    opName#" $src0"> {
735    let sdst = 0;
736  }
737}
738
739// 64-bit input, 32-bit output.
740multiclass SOP1_32_64 <sop1 op, string opName, list<dag> pattern> : SOP1_m <
741    op, opName, (outs SReg_32:$dst), (ins SSrc_64:$src0),
742    opName#" $dst, $src0", pattern
743>;
744
745class SOP2_Pseudo<string opName, dag outs, dag ins, list<dag> pattern> :
746  SOP2<outs, ins, "", pattern>,
747  SIMCInstr<opName, SISubtarget.NONE> {
748  let isPseudo = 1;
749  let isCodeGenOnly = 1;
750  let Size = 4;
751
752  // Pseudo instructions have no encodings, but adding this field here allows
753  // us to do:
754  // let sdst = xxx in {
755  // for multiclasses that include both real and pseudo instructions.
756  field bits<7> sdst = 0;
757}
758
759class SOP2_Real_si<sop2 op, string opName, dag outs, dag ins, string asm> :
760  SOP2<outs, ins, asm, []>,
761  SOP2e<op.SI>,
762  SIMCInstr<opName, SISubtarget.SI> {
763  let AssemblerPredicates = [isSICI];
764}
765
766class SOP2_Real_vi<sop2 op, string opName, dag outs, dag ins, string asm> :
767  SOP2<outs, ins, asm, []>,
768  SOP2e<op.VI>,
769  SIMCInstr<opName, SISubtarget.VI> {
770  let AssemblerPredicates = [isVI];
771}
772
773multiclass SOP2_m <sop2 op, string opName, dag outs, dag ins, string asm,
774                   list<dag> pattern> {
775
776  def "" : SOP2_Pseudo <opName, outs, ins, pattern>;
777
778  def _si : SOP2_Real_si <op, opName, outs, ins, asm>;
779
780  def _vi : SOP2_Real_vi <op, opName, outs, ins, asm>;
781
782}
783
784multiclass SOP2_32 <sop2 op, string opName, list<dag> pattern> : SOP2_m <
785    op, opName, (outs SReg_32:$dst), (ins SSrc_32:$src0, SSrc_32:$src1),
786    opName#" $dst, $src0, $src1", pattern
787>;
788
789multiclass SOP2_64 <sop2 op, string opName, list<dag> pattern> : SOP2_m <
790    op, opName, (outs SReg_64:$dst), (ins SSrc_64:$src0, SSrc_64:$src1),
791    opName#" $dst, $src0, $src1", pattern
792>;
793
794multiclass SOP2_64_32 <sop2 op, string opName, list<dag> pattern> : SOP2_m <
795    op, opName, (outs SReg_64:$dst), (ins SSrc_64:$src0, SSrc_32:$src1),
796    opName#" $dst, $src0, $src1", pattern
797>;
798
799class SOPC_Helper <bits<7> op, RegisterOperand rc, ValueType vt,
800                    string opName, PatLeaf cond> : SOPC <
801  op, (outs), (ins rc:$src0, rc:$src1),
802  opName#" $src0, $src1", []> {
803  let Defs = [SCC];
804}
805
806class SOPC_32<bits<7> op, string opName, PatLeaf cond = COND_NULL>
807  : SOPC_Helper<op, SSrc_32, i32, opName, cond>;
808
809class SOPC_64<bits<7> op, string opName, PatLeaf cond = COND_NULL>
810  : SOPC_Helper<op, SSrc_64, i64, opName, cond>;
811
812class SOPK_Pseudo <string opName, dag outs, dag ins, list<dag> pattern> :
813  SOPK <outs, ins, "", pattern>,
814  SIMCInstr<opName, SISubtarget.NONE> {
815  let isPseudo = 1;
816  let isCodeGenOnly = 1;
817}
818
819class SOPK_Real_si <sopk op, string opName, dag outs, dag ins, string asm> :
820  SOPK <outs, ins, asm, []>,
821  SOPKe <op.SI>,
822  SIMCInstr<opName, SISubtarget.SI> {
823  let AssemblerPredicates = [isSICI];
824  let isCodeGenOnly = 0;
825}
826
827class SOPK_Real_vi <sopk op, string opName, dag outs, dag ins, string asm> :
828  SOPK <outs, ins, asm, []>,
829  SOPKe <op.VI>,
830  SIMCInstr<opName, SISubtarget.VI> {
831  let AssemblerPredicates = [isVI];
832  let isCodeGenOnly = 0;
833}
834
835multiclass SOPK_m <sopk op, string opName, dag outs, dag ins, string opAsm,
836                   string asm = opName#opAsm> {
837  def "" : SOPK_Pseudo <opName, outs, ins, []>;
838
839  def _si : SOPK_Real_si <op, opName, outs, ins, asm>;
840
841  def _vi : SOPK_Real_vi <op, opName, outs, ins, asm>;
842
843}
844
845multiclass SOPK_32 <sopk op, string opName, list<dag> pattern> {
846  def "" : SOPK_Pseudo <opName, (outs SReg_32:$dst), (ins u16imm:$src0),
847    pattern>;
848
849  def _si : SOPK_Real_si <op, opName, (outs SReg_32:$dst), (ins u16imm:$src0),
850    opName#" $dst, $src0">;
851
852  def _vi : SOPK_Real_vi <op, opName, (outs SReg_32:$dst), (ins u16imm:$src0),
853    opName#" $dst, $src0">;
854}
855
856multiclass SOPK_SCC <sopk op, string opName, list<dag> pattern> {
857  def "" : SOPK_Pseudo <opName, (outs),
858    (ins SReg_32:$src0, u16imm:$src1), pattern> {
859    let Defs = [SCC];
860  }
861
862
863  def _si : SOPK_Real_si <op, opName, (outs),
864    (ins SReg_32:$sdst, u16imm:$simm16), opName#" $sdst, $simm16"> {
865    let Defs = [SCC];
866  }
867
868  def _vi : SOPK_Real_vi <op, opName, (outs),
869    (ins SReg_32:$sdst, u16imm:$simm16), opName#" $sdst, $simm16"> {
870    let Defs = [SCC];
871  }
872}
873
874multiclass SOPK_32TIE <sopk op, string opName, list<dag> pattern> : SOPK_m <
875  op, opName, (outs SReg_32:$sdst), (ins SReg_32:$src0, u16imm:$simm16),
876  " $sdst, $simm16"
877>;
878
879multiclass SOPK_IMM32 <sopk op, string opName, dag outs, dag ins,
880                       string argAsm, string asm = opName#argAsm> {
881
882  def "" : SOPK_Pseudo <opName, outs, ins, []>;
883
884  def _si : SOPK <outs, ins, asm, []>,
885            SOPK64e <op.SI>,
886            SIMCInstr<opName, SISubtarget.SI> {
887              let AssemblerPredicates = [isSICI];
888              let isCodeGenOnly = 0;
889            }
890
891  def _vi : SOPK <outs, ins, asm, []>,
892            SOPK64e <op.VI>,
893            SIMCInstr<opName, SISubtarget.VI> {
894              let AssemblerPredicates = [isVI];
895              let isCodeGenOnly = 0;
896            }
897}
898//===----------------------------------------------------------------------===//
899// SMRD classes
900//===----------------------------------------------------------------------===//
901
902class SMRD_Pseudo <string opName, dag outs, dag ins, list<dag> pattern> :
903  SMRD <outs, ins, "", pattern>,
904  SIMCInstr<opName, SISubtarget.NONE> {
905  let isPseudo = 1;
906  let isCodeGenOnly = 1;
907}
908
909class SMRD_Real_si <bits<5> op, string opName, bit imm, dag outs, dag ins,
910                    string asm> :
911  SMRD <outs, ins, asm, []>,
912  SMRDe <op, imm>,
913  SIMCInstr<opName, SISubtarget.SI> {
914  let AssemblerPredicates = [isSICI];
915}
916
917class SMRD_Real_vi <bits<8> op, string opName, bit imm, dag outs, dag ins,
918                    string asm, list<dag> pattern = []> :
919  SMRD <outs, ins, asm, pattern>,
920  SMEMe_vi <op, imm>,
921  SIMCInstr<opName, SISubtarget.VI> {
922  let AssemblerPredicates = [isVI];
923}
924
925multiclass SMRD_m <smrd op, string opName, bit imm, dag outs, dag ins,
926                   string asm, list<dag> pattern> {
927
928  def "" : SMRD_Pseudo <opName, outs, ins, pattern>;
929
930  def _si : SMRD_Real_si <op.SI, opName, imm, outs, ins, asm>;
931
932  // glc is only applicable to scalar stores, which are not yet
933  // implemented.
934  let glc = 0 in {
935    def _vi : SMRD_Real_vi <op.VI, opName, imm, outs, ins, asm>;
936  }
937}
938
939multiclass SMRD_Inval <smrd op, string opName,
940                       SDPatternOperator node> {
941  let hasSideEffects = 1, mayStore = 1 in {
942    def "" : SMRD_Pseudo <opName, (outs), (ins), [(node)]>;
943
944    let sbase = 0, offset = 0 in {
945      let sdst = 0 in {
946        def _si : SMRD_Real_si <op.SI, opName, 0, (outs), (ins), opName>;
947      }
948
949      let glc = 0, sdata = 0 in {
950        def _vi : SMRD_Real_vi <op.VI, opName, 0, (outs), (ins), opName>;
951      }
952    }
953  }
954}
955
956class SMEM_Inval <bits<8> op, string opName, SDPatternOperator node> :
957  SMRD_Real_vi<op, opName, 0, (outs), (ins), opName, [(node)]> {
958  let hasSideEffects = 1;
959  let mayStore = 1;
960  let sbase = 0;
961  let sdata = 0;
962  let glc = 0;
963  let offset = 0;
964}
965
966multiclass SMRD_Helper <smrd op, string opName, RegisterClass baseClass,
967                        RegisterClass dstClass> {
968  defm _IMM : SMRD_m <
969    op, opName#"_IMM", 1, (outs dstClass:$dst),
970    (ins baseClass:$sbase, smrd_offset:$offset),
971    opName#" $dst, $sbase, $offset", []
972  >;
973
974  def _IMM_ci : SMRD <
975    (outs dstClass:$dst), (ins baseClass:$sbase, smrd_literal_offset:$offset),
976    opName#" $dst, $sbase, $offset", []>, SMRD_IMMe_ci <op.SI> {
977    let AssemblerPredicates = [isCIOnly];
978  }
979
980  defm _SGPR : SMRD_m <
981    op, opName#"_SGPR", 0, (outs dstClass:$dst),
982    (ins baseClass:$sbase, SReg_32:$soff),
983    opName#" $dst, $sbase, $soff", []
984  >;
985}
986
987//===----------------------------------------------------------------------===//
988// Vector ALU classes
989//===----------------------------------------------------------------------===//
990
991// This must always be right before the operand being input modified.
992def InputMods : OperandWithDefaultOps <i32, (ops (i32 0))> {
993  let PrintMethod = "printOperandAndMods";
994}
995
996def InputModsMatchClass : AsmOperandClass {
997  let Name = "RegWithInputMods";
998}
999
1000def InputModsNoDefault : Operand <i32> {
1001  let PrintMethod = "printOperandAndMods";
1002  let ParserMatchClass = InputModsMatchClass;
1003}
1004
1005class getNumSrcArgs<ValueType Src0, ValueType Src1, ValueType Src2> {
1006  int ret =
1007    !if (!eq(Src0.Value, untyped.Value),      0,
1008      !if (!eq(Src1.Value, untyped.Value),    1,   // VOP1
1009         !if (!eq(Src2.Value, untyped.Value), 2,   // VOP2
1010                                              3))); // VOP3
1011}
1012
1013// Returns the register class to use for the destination of VOP[123C]
1014// instructions for the given VT.
1015class getVALUDstForVT<ValueType VT> {
1016  RegisterOperand ret = !if(!eq(VT.Size, 32), VOPDstOperand<VGPR_32>,
1017                          !if(!eq(VT.Size, 64), VOPDstOperand<VReg_64>,
1018                            !if(!eq(VT.Size, 16), VOPDstOperand<VGPR_32>,
1019                            VOPDstOperand<SReg_64>))); // else VT == i1
1020}
1021
1022// Returns the register class to use for source 0 of VOP[12C]
1023// instructions for the given VT.
1024class getVOPSrc0ForVT<ValueType VT> {
1025  RegisterOperand ret = !if(!eq(VT.Size, 64), VSrc_64, VSrc_32);
1026}
1027
1028// Returns the register class to use for source 1 of VOP[12C] for the
1029// given VT.
1030class getVOPSrc1ForVT<ValueType VT> {
1031  RegisterClass ret = !if(!eq(VT.Size, 64), VReg_64, VGPR_32);
1032}
1033
1034// Returns the register class to use for sources of VOP3 instructions for the
1035// given VT.
1036class getVOP3SrcForVT<ValueType VT> {
1037  RegisterOperand ret =
1038  !if(!eq(VT.Size, 64),
1039      VCSrc_64,
1040      !if(!eq(VT.Value, i1.Value),
1041          SCSrc_64,
1042          VCSrc_32
1043       )
1044    );
1045}
1046
1047// Returns 1 if the source arguments have modifiers, 0 if they do not.
1048// XXX - do f16 instructions?
1049class hasModifiers<ValueType SrcVT> {
1050  bit ret = !if(!eq(SrcVT.Value, f32.Value), 1,
1051            !if(!eq(SrcVT.Value, f64.Value), 1, 0));
1052}
1053
1054// Returns the input arguments for VOP[12C] instructions for the given SrcVT.
1055class getIns32 <RegisterOperand Src0RC, RegisterClass Src1RC, int NumSrcArgs> {
1056  dag ret = !if(!eq(NumSrcArgs, 1), (ins Src0RC:$src0),               // VOP1
1057            !if(!eq(NumSrcArgs, 2), (ins Src0RC:$src0, Src1RC:$src1), // VOP2
1058                                    (ins)));
1059}
1060
1061// Returns the input arguments for VOP3 instructions for the given SrcVT.
1062class getIns64 <RegisterOperand Src0RC, RegisterOperand Src1RC,
1063                RegisterOperand Src2RC, int NumSrcArgs,
1064                bit HasModifiers> {
1065
1066  dag ret =
1067    !if (!eq(NumSrcArgs, 1),
1068      !if (!eq(HasModifiers, 1),
1069        // VOP1 with modifiers
1070        (ins InputModsNoDefault:$src0_modifiers, Src0RC:$src0,
1071             ClampMod:$clamp, omod:$omod)
1072      /* else */,
1073        // VOP1 without modifiers
1074        (ins Src0RC:$src0)
1075      /* endif */ ),
1076    !if (!eq(NumSrcArgs, 2),
1077      !if (!eq(HasModifiers, 1),
1078        // VOP 2 with modifiers
1079        (ins InputModsNoDefault:$src0_modifiers, Src0RC:$src0,
1080             InputModsNoDefault:$src1_modifiers, Src1RC:$src1,
1081             ClampMod:$clamp, omod:$omod)
1082      /* else */,
1083        // VOP2 without modifiers
1084        (ins Src0RC:$src0, Src1RC:$src1)
1085      /* endif */ )
1086    /* NumSrcArgs == 3 */,
1087      !if (!eq(HasModifiers, 1),
1088        // VOP3 with modifiers
1089        (ins InputModsNoDefault:$src0_modifiers, Src0RC:$src0,
1090             InputModsNoDefault:$src1_modifiers, Src1RC:$src1,
1091             InputModsNoDefault:$src2_modifiers, Src2RC:$src2,
1092             ClampMod:$clamp, omod:$omod)
1093      /* else */,
1094        // VOP3 without modifiers
1095        (ins Src0RC:$src0, Src1RC:$src1, Src2RC:$src2)
1096      /* endif */ )));
1097}
1098
1099// Returns the assembly string for the inputs and outputs of a VOP[12C]
1100// instruction.  This does not add the _e32 suffix, so it can be reused
1101// by getAsm64.
1102class getAsm32 <bit HasDst, int NumSrcArgs> {
1103  string dst = "$dst";
1104  string src0 = ", $src0";
1105  string src1 = ", $src1";
1106  string src2 = ", $src2";
1107  string ret = !if(HasDst, dst, "") #
1108               !if(!eq(NumSrcArgs, 1), src0, "") #
1109               !if(!eq(NumSrcArgs, 2), src0#src1, "") #
1110               !if(!eq(NumSrcArgs, 3), src0#src1#src2, "");
1111}
1112
1113// Returns the assembly string for the inputs and outputs of a VOP3
1114// instruction.
1115class getAsm64 <bit HasDst, int NumSrcArgs, bit HasModifiers> {
1116  string src0 = !if(!eq(NumSrcArgs, 1), "$src0_modifiers", "$src0_modifiers,");
1117  string src1 = !if(!eq(NumSrcArgs, 1), "",
1118                   !if(!eq(NumSrcArgs, 2), " $src1_modifiers",
1119                                           " $src1_modifiers,"));
1120  string src2 = !if(!eq(NumSrcArgs, 3), " $src2_modifiers", "");
1121  string ret =
1122  !if(!eq(HasModifiers, 0),
1123      getAsm32<HasDst, NumSrcArgs>.ret,
1124      "$dst, "#src0#src1#src2#"$clamp"#"$omod");
1125}
1126
1127class VOPProfile <list<ValueType> _ArgVT> {
1128
1129  field list<ValueType> ArgVT = _ArgVT;
1130
1131  field ValueType DstVT = ArgVT[0];
1132  field ValueType Src0VT = ArgVT[1];
1133  field ValueType Src1VT = ArgVT[2];
1134  field ValueType Src2VT = ArgVT[3];
1135  field RegisterOperand DstRC = getVALUDstForVT<DstVT>.ret;
1136  field RegisterOperand Src0RC32 = getVOPSrc0ForVT<Src0VT>.ret;
1137  field RegisterClass Src1RC32 = getVOPSrc1ForVT<Src1VT>.ret;
1138  field RegisterOperand Src0RC64 = getVOP3SrcForVT<Src0VT>.ret;
1139  field RegisterOperand Src1RC64 = getVOP3SrcForVT<Src1VT>.ret;
1140  field RegisterOperand Src2RC64 = getVOP3SrcForVT<Src2VT>.ret;
1141
1142  field bit HasDst = !if(!eq(DstVT.Value, untyped.Value), 0, 1);
1143  field bit HasDst32 = HasDst;
1144  field int NumSrcArgs = getNumSrcArgs<Src0VT, Src1VT, Src2VT>.ret;
1145  field bit HasModifiers = hasModifiers<Src0VT>.ret;
1146
1147  field dag Outs = !if(HasDst,(outs DstRC:$dst),(outs));
1148
1149  // VOP3b instructions are a special case with a second explicit
1150  // output. This is manually overridden for them.
1151  field dag Outs32 = Outs;
1152  field dag Outs64 = Outs;
1153
1154  field dag Ins32 = getIns32<Src0RC32, Src1RC32, NumSrcArgs>.ret;
1155  field dag Ins64 = getIns64<Src0RC64, Src1RC64, Src2RC64, NumSrcArgs,
1156                             HasModifiers>.ret;
1157
1158  field string Asm32 = getAsm32<HasDst, NumSrcArgs>.ret;
1159  field string Asm64 = getAsm64<HasDst, NumSrcArgs, HasModifiers>.ret;
1160}
1161
1162// FIXME: I think these F16/I16 profiles will need to use f16/i16 types in order
1163//        for the instruction patterns to work.
1164def VOP_F16_F16 : VOPProfile <[f16, f16, untyped, untyped]>;
1165def VOP_F16_I16 : VOPProfile <[f16, i32, untyped, untyped]>;
1166def VOP_I16_F16 : VOPProfile <[i32, f16, untyped, untyped]>;
1167
1168def VOP_F16_F16_F16 : VOPProfile <[f16, f16, f16, untyped]>;
1169def VOP_F16_F16_I16 : VOPProfile <[f16, f16, i32, untyped]>;
1170def VOP_I16_I16_I16 : VOPProfile <[i32, i32, i32, untyped]>;
1171
1172def VOP_NONE : VOPProfile <[untyped, untyped, untyped, untyped]>;
1173
1174def VOP_F32_F32 : VOPProfile <[f32, f32, untyped, untyped]>;
1175def VOP_F32_F64 : VOPProfile <[f32, f64, untyped, untyped]>;
1176def VOP_F32_I32 : VOPProfile <[f32, i32, untyped, untyped]>;
1177def VOP_F64_F32 : VOPProfile <[f64, f32, untyped, untyped]>;
1178def VOP_F64_F64 : VOPProfile <[f64, f64, untyped, untyped]>;
1179def VOP_F64_I32 : VOPProfile <[f64, i32, untyped, untyped]>;
1180def VOP_I32_F32 : VOPProfile <[i32, f32, untyped, untyped]>;
1181def VOP_I32_F64 : VOPProfile <[i32, f64, untyped, untyped]>;
1182def VOP_I32_I32 : VOPProfile <[i32, i32, untyped, untyped]>;
1183
1184def VOP_F32_F32_F32 : VOPProfile <[f32, f32, f32, untyped]>;
1185def VOP_F32_F32_I32 : VOPProfile <[f32, f32, i32, untyped]>;
1186def VOP_F64_F64_F64 : VOPProfile <[f64, f64, f64, untyped]>;
1187def VOP_F64_F64_I32 : VOPProfile <[f64, f64, i32, untyped]>;
1188def VOP_I32_F32_F32 : VOPProfile <[i32, f32, f32, untyped]>;
1189def VOP_I32_F32_I32 : VOPProfile <[i32, f32, i32, untyped]>;
1190def VOP_I32_I32_I32 : VOPProfile <[i32, i32, i32, untyped]>;
1191
1192// Write out to vcc or arbitrary SGPR.
1193def VOP2b_I32_I1_I32_I32 : VOPProfile<[i32, i32, i32, untyped]> {
1194  let Asm32 = "$dst, vcc, $src0, $src1";
1195  let Asm64 = "$dst, $sdst, $src0, $src1";
1196  let Outs32 = (outs DstRC:$dst);
1197  let Outs64 = (outs DstRC:$dst, SReg_64:$sdst);
1198}
1199
1200// Write out to vcc or arbitrary SGPR and read in from vcc or
1201// arbitrary SGPR.
1202def VOP2b_I32_I1_I32_I32_I1 : VOPProfile<[i32, i32, i32, i1]> {
1203  // We use VCSrc_32 to exclude literal constants, even though the
1204  // encoding normally allows them since the implicit VCC use means
1205  // using one would always violate the constant bus
1206  // restriction. SGPRs are still allowed because it should
1207  // technically be possible to use VCC again as src0.
1208  let Src0RC32 = VCSrc_32;
1209  let Asm32 = "$dst, vcc, $src0, $src1, vcc";
1210  let Asm64 = "$dst, $sdst, $src0, $src1, $src2";
1211  let Outs32 = (outs DstRC:$dst);
1212  let Outs64 = (outs DstRC:$dst, SReg_64:$sdst);
1213
1214  // Suppress src2 implied by type since the 32-bit encoding uses an
1215  // implicit VCC use.
1216  let Ins32 = (ins Src0RC32:$src0, Src1RC32:$src1);
1217}
1218
1219class VOP3b_Profile<ValueType vt> : VOPProfile<[vt, vt, vt, vt]> {
1220  let Outs64 = (outs DstRC:$vdst, SReg_64:$sdst);
1221  let Asm64 = "$vdst, $sdst, $src0_modifiers, $src1_modifiers, $src2_modifiers"#"$clamp"#"$omod";
1222}
1223
1224def VOP3b_F32_I1_F32_F32_F32 : VOP3b_Profile<f32> {
1225  // FIXME: Hack to stop printing _e64
1226  let DstRC = RegisterOperand<VGPR_32>;
1227}
1228
1229def VOP3b_F64_I1_F64_F64_F64 : VOP3b_Profile<f64> {
1230  // FIXME: Hack to stop printing _e64
1231  let DstRC = RegisterOperand<VReg_64>;
1232}
1233
1234// VOPC instructions are a special case because for the 32-bit
1235// encoding, we want to display the implicit vcc write as if it were
1236// an explicit $dst.
1237class VOPC_Profile<ValueType vt0, ValueType vt1 = vt0> : VOPProfile <[i1, vt0, vt1, untyped]> {
1238  let Asm32 = "vcc, $src0, $src1";
1239  // The destination for 32-bit encoding is implicit.
1240  let HasDst32 = 0;
1241}
1242
1243class VOPC_Class_Profile<ValueType vt> : VOPC_Profile<vt, i32> {
1244  let Ins64 = (ins InputModsNoDefault:$src0_modifiers, Src0RC64:$src0, Src1RC64:$src1);
1245  let Asm64 = "$dst, $src0_modifiers, $src1";
1246}
1247
1248def VOPC_I1_F32_F32 : VOPC_Profile<f32>;
1249def VOPC_I1_F64_F64 : VOPC_Profile<f64>;
1250def VOPC_I1_I32_I32 : VOPC_Profile<i32>;
1251def VOPC_I1_I64_I64 : VOPC_Profile<i64>;
1252
1253def VOPC_I1_F32_I32 : VOPC_Class_Profile<f32>;
1254def VOPC_I1_F64_I32 : VOPC_Class_Profile<f64>;
1255
1256def VOP_I64_I64_I32 : VOPProfile <[i64, i64, i32, untyped]>;
1257def VOP_I64_I32_I64 : VOPProfile <[i64, i32, i64, untyped]>;
1258def VOP_I64_I64_I64 : VOPProfile <[i64, i64, i64, untyped]>;
1259def VOP_CNDMASK : VOPProfile <[i32, i32, i32, untyped]> {
1260  let Ins32 = (ins Src0RC32:$src0, Src1RC32:$src1);
1261  let Ins64 = (ins Src0RC64:$src0, Src1RC64:$src1, SSrc_64:$src2);
1262  let Asm64 = "$dst, $src0, $src1, $src2";
1263}
1264
1265def VOP_F32_F32_F32_F32 : VOPProfile <[f32, f32, f32, f32]>;
1266def VOP_MADK : VOPProfile <[f32, f32, f32, f32]> {
1267  field dag Ins = (ins VCSrc_32:$src0, VGPR_32:$vsrc1, u32imm:$src2);
1268  field string Asm = "$dst, $src0, $vsrc1, $src2";
1269}
1270def VOP_MAC : VOPProfile <[f32, f32, f32, f32]> {
1271  let Ins32 = (ins Src0RC32:$src0, Src1RC32:$src1, VGPR_32:$src2);
1272  let Ins64 = getIns64<Src0RC64, Src1RC64, RegisterOperand<VGPR_32>, 3,
1273                             HasModifiers>.ret;
1274  let Asm32 = getAsm32<1, 2>.ret;
1275  let Asm64 = getAsm64<1, 2, HasModifiers>.ret;
1276}
1277def VOP_F64_F64_F64_F64 : VOPProfile <[f64, f64, f64, f64]>;
1278def VOP_I32_I32_I32_I32 : VOPProfile <[i32, i32, i32, i32]>;
1279def VOP_I64_I32_I32_I64 : VOPProfile <[i64, i32, i32, i64]>;
1280
1281class SIInstAlias <string asm, Instruction inst, VOPProfile p> :
1282    InstAlias <asm, (inst)>, PredicateControl {
1283
1284  field bit isCompare;
1285  field bit isCommutable;
1286
1287  let ResultInst =
1288    !if (p.HasDst32,
1289      !if (!eq(p.NumSrcArgs, 0),
1290        // 1 dst, 0 src
1291        (inst p.DstRC:$dst),
1292      !if (!eq(p.NumSrcArgs, 1),
1293        // 1 dst, 1 src
1294        (inst p.DstRC:$dst, p.Src0RC32:$src0),
1295      !if (!eq(p.NumSrcArgs, 2),
1296        // 1 dst, 2 src
1297        (inst p.DstRC:$dst, p.Src0RC32:$src0, p.Src1RC32:$src1),
1298      // else - unreachable
1299        (inst)))),
1300    // else
1301      !if (!eq(p.NumSrcArgs, 2),
1302        // 0 dst, 2 src
1303        (inst p.Src0RC32:$src0, p.Src1RC32:$src1),
1304      !if (!eq(p.NumSrcArgs, 1),
1305        // 0 dst, 1 src
1306        (inst p.Src0RC32:$src1),
1307      // else
1308        // 0 dst, 0 src
1309        (inst))));
1310}
1311
1312class SIInstAliasSI <string asm, string op_name, VOPProfile p> :
1313  SIInstAlias <asm, !cast<Instruction>(op_name#"_e32_si"), p> {
1314  let AssemblerPredicate = SIAssemblerPredicate;
1315}
1316
1317class SIInstAliasVI <string asm, string op_name, VOPProfile p> :
1318  SIInstAlias <asm, !cast<Instruction>(op_name#"_e32_vi"), p> {
1319  let AssemblerPredicates = [isVI];
1320}
1321
1322multiclass SIInstAliasBuilder <string asm, VOPProfile p> {
1323
1324  def : SIInstAliasSI <asm, NAME, p>;
1325
1326  def : SIInstAliasVI <asm, NAME, p>;
1327}
1328
1329class VOP <string opName> {
1330  string OpName = opName;
1331}
1332
1333class VOP2_REV <string revOp, bit isOrig> {
1334  string RevOp = revOp;
1335  bit IsOrig = isOrig;
1336}
1337
1338class AtomicNoRet <string noRetOp, bit isRet> {
1339  string NoRetOp = noRetOp;
1340  bit IsRet = isRet;
1341}
1342
1343class VOP1_Pseudo <dag outs, dag ins, list<dag> pattern, string opName> :
1344  VOP1Common <outs, ins, "", pattern>,
1345  VOP <opName>,
1346  SIMCInstr <opName#"_e32", SISubtarget.NONE>,
1347  MnemonicAlias<opName#"_e32", opName> {
1348  let isPseudo = 1;
1349  let isCodeGenOnly = 1;
1350
1351  field bits<8> vdst;
1352  field bits<9> src0;
1353}
1354
1355class VOP1_Real_si <string opName, vop1 op, dag outs, dag ins, string asm> :
1356  VOP1<op.SI, outs, ins, asm, []>,
1357  SIMCInstr <opName#"_e32", SISubtarget.SI> {
1358  let AssemblerPredicate = SIAssemblerPredicate;
1359}
1360
1361class VOP1_Real_vi <string opName, vop1 op, dag outs, dag ins, string asm> :
1362  VOP1<op.VI, outs, ins, asm, []>,
1363  SIMCInstr <opName#"_e32", SISubtarget.VI> {
1364  let AssemblerPredicates = [isVI];
1365}
1366
1367multiclass VOP1_m <vop1 op, string opName, VOPProfile p, list<dag> pattern,
1368                   string asm = opName#p.Asm32> {
1369  def "" : VOP1_Pseudo <p.Outs, p.Ins32, pattern, opName>;
1370
1371  def _si : VOP1_Real_si <opName, op, p.Outs, p.Ins32, asm>;
1372
1373  def _vi : VOP1_Real_vi <opName, op, p.Outs, p.Ins32, asm>;
1374
1375}
1376
1377multiclass VOP1SI_m <vop1 op, string opName, VOPProfile p, list<dag> pattern,
1378                     string asm = opName#p.Asm32> {
1379
1380  def "" : VOP1_Pseudo <p.Outs, p.Ins32, pattern, opName>;
1381
1382  def _si : VOP1_Real_si <opName, op, p.Outs, p.Ins32, asm>;
1383}
1384
1385class VOP2_Pseudo <dag outs, dag ins, list<dag> pattern, string opName> :
1386  VOP2Common <outs, ins, "", pattern>,
1387  VOP <opName>,
1388  SIMCInstr<opName#"_e32", SISubtarget.NONE>,
1389  MnemonicAlias<opName#"_e32", opName> {
1390  let isPseudo = 1;
1391  let isCodeGenOnly = 1;
1392}
1393
1394class VOP2_Real_si <string opName, vop2 op, dag outs, dag ins, string asm> :
1395  VOP2 <op.SI, outs, ins, opName#asm, []>,
1396  SIMCInstr <opName#"_e32", SISubtarget.SI> {
1397  let AssemblerPredicates = [isSICI];
1398}
1399
1400class VOP2_Real_vi <string opName, vop2 op, dag outs, dag ins, string asm> :
1401  VOP2 <op.VI, outs, ins, opName#asm, []>,
1402  SIMCInstr <opName#"_e32", SISubtarget.VI> {
1403  let AssemblerPredicates = [isVI];
1404}
1405
1406multiclass VOP2SI_m <vop2 op, string opName, VOPProfile p, list<dag> pattern,
1407                     string revOp> {
1408
1409  def "" : VOP2_Pseudo <p.Outs32, p.Ins32, pattern, opName>,
1410           VOP2_REV<revOp#"_e32", !eq(revOp, opName)>;
1411
1412  def _si : VOP2_Real_si <opName, op, p.Outs32, p.Ins32, p.Asm32>;
1413}
1414
1415multiclass VOP2_m <vop2 op, string opName, VOPProfile p, list <dag> pattern,
1416                   string revOp> {
1417
1418  def "" : VOP2_Pseudo <p.Outs32, p.Ins32, pattern, opName>,
1419           VOP2_REV<revOp#"_e32", !eq(revOp, opName)>;
1420
1421  def _si : VOP2_Real_si <opName, op, p.Outs32, p.Ins32, p.Asm32>;
1422
1423  def _vi : VOP2_Real_vi <opName, op, p.Outs32, p.Ins32, p.Asm32>;
1424
1425}
1426
1427class VOP3DisableFields <bit HasSrc1, bit HasSrc2, bit HasModifiers> {
1428
1429  bits<2> src0_modifiers = !if(HasModifiers, ?, 0);
1430  bits<2> src1_modifiers = !if(HasModifiers, !if(HasSrc1, ?, 0), 0);
1431  bits<2> src2_modifiers = !if(HasModifiers, !if(HasSrc2, ?, 0), 0);
1432  bits<2> omod = !if(HasModifiers, ?, 0);
1433  bits<1> clamp = !if(HasModifiers, ?, 0);
1434  bits<9> src1 = !if(HasSrc1, ?, 0);
1435  bits<9> src2 = !if(HasSrc2, ?, 0);
1436}
1437
1438class VOP3DisableModFields <bit HasSrc0Mods,
1439                            bit HasSrc1Mods = 0,
1440                            bit HasSrc2Mods = 0,
1441                            bit HasOutputMods = 0> {
1442  bits<2> src0_modifiers = !if(HasSrc0Mods, ?, 0);
1443  bits<2> src1_modifiers = !if(HasSrc1Mods, ?, 0);
1444  bits<2> src2_modifiers = !if(HasSrc2Mods, ?, 0);
1445  bits<2> omod = !if(HasOutputMods, ?, 0);
1446  bits<1> clamp = !if(HasOutputMods, ?, 0);
1447}
1448
1449class VOP3_Pseudo <dag outs, dag ins, list<dag> pattern, string opName> :
1450  VOP3Common <outs, ins, "", pattern>,
1451  VOP <opName>,
1452  SIMCInstr<opName#"_e64", SISubtarget.NONE>,
1453  MnemonicAlias<opName#"_e64", opName> {
1454  let isPseudo = 1;
1455  let isCodeGenOnly = 1;
1456
1457  field bit vdst;
1458  field bit src0;
1459}
1460
1461class VOP3_Real_si <bits<9> op, dag outs, dag ins, string asm, string opName> :
1462  VOP3Common <outs, ins, asm, []>,
1463  VOP3e <op>,
1464  SIMCInstr<opName#"_e64", SISubtarget.SI> {
1465  let AssemblerPredicates = [isSICI];
1466}
1467
1468class VOP3_Real_vi <bits<10> op, dag outs, dag ins, string asm, string opName> :
1469  VOP3Common <outs, ins, asm, []>,
1470  VOP3e_vi <op>,
1471  SIMCInstr <opName#"_e64", SISubtarget.VI> {
1472  let AssemblerPredicates = [isVI];
1473}
1474
1475class VOP3b_Real_si <bits<9> op, dag outs, dag ins, string asm, string opName> :
1476  VOP3Common <outs, ins, asm, []>,
1477  VOP3be <op>,
1478  SIMCInstr<opName#"_e64", SISubtarget.SI> {
1479  let AssemblerPredicates = [isSICI];
1480}
1481
1482class VOP3b_Real_vi <bits<10> op, dag outs, dag ins, string asm, string opName> :
1483  VOP3Common <outs, ins, asm, []>,
1484  VOP3be_vi <op>,
1485  SIMCInstr <opName#"_e64", SISubtarget.VI> {
1486  let AssemblerPredicates = [isVI];
1487}
1488
1489multiclass VOP3_m <vop op, dag outs, dag ins, string asm, list<dag> pattern,
1490                   string opName, int NumSrcArgs, bit HasMods = 1> {
1491
1492  def "" : VOP3_Pseudo <outs, ins, pattern, opName>;
1493
1494  def _si : VOP3_Real_si <op.SI3, outs, ins, asm, opName>,
1495            VOP3DisableFields<!if(!eq(NumSrcArgs, 1), 0, 1),
1496                              !if(!eq(NumSrcArgs, 2), 0, 1),
1497                              HasMods>;
1498  def _vi : VOP3_Real_vi <op.VI3, outs, ins, asm, opName>,
1499            VOP3DisableFields<!if(!eq(NumSrcArgs, 1), 0, 1),
1500                              !if(!eq(NumSrcArgs, 2), 0, 1),
1501                              HasMods>;
1502}
1503
1504multiclass VOP3_1_m <vop op, dag outs, dag ins, string asm,
1505                     list<dag> pattern, string opName, bit HasMods = 1> {
1506
1507  def "" : VOP3_Pseudo <outs, ins, pattern, opName>;
1508
1509  def _si : VOP3_Real_si <op.SI3, outs, ins, asm, opName>,
1510            VOP3DisableFields<0, 0, HasMods>;
1511
1512  def _vi : VOP3_Real_vi <op.VI3, outs, ins, asm, opName>,
1513            VOP3DisableFields<0, 0, HasMods>;
1514}
1515
1516multiclass VOP3SI_1_m <vop op, dag outs, dag ins, string asm,
1517                     list<dag> pattern, string opName, bit HasMods = 1> {
1518
1519  def "" : VOP3_Pseudo <outs, ins, pattern, opName>;
1520
1521  def _si : VOP3_Real_si <op.SI3, outs, ins, asm, opName>,
1522            VOP3DisableFields<0, 0, HasMods>;
1523  // No VI instruction. This class is for SI only.
1524}
1525
1526multiclass VOP3_2_m <vop op, dag outs, dag ins, string asm,
1527                     list<dag> pattern, string opName, string revOp,
1528                     bit HasMods = 1> {
1529
1530  def "" : VOP3_Pseudo <outs, ins, pattern, opName>,
1531           VOP2_REV<revOp#"_e64", !eq(revOp, opName)>;
1532
1533  def _si : VOP3_Real_si <op.SI3, outs, ins, asm, opName>,
1534            VOP3DisableFields<1, 0, HasMods>;
1535
1536  def _vi : VOP3_Real_vi <op.VI3, outs, ins, asm, opName>,
1537            VOP3DisableFields<1, 0, HasMods>;
1538}
1539
1540multiclass VOP3SI_2_m <vop op, dag outs, dag ins, string asm,
1541                     list<dag> pattern, string opName, string revOp,
1542                     bit HasMods = 1> {
1543
1544  def "" : VOP3_Pseudo <outs, ins, pattern, opName>,
1545           VOP2_REV<revOp#"_e64", !eq(revOp, opName)>;
1546
1547  def _si : VOP3_Real_si <op.SI3, outs, ins, asm, opName>,
1548            VOP3DisableFields<1, 0, HasMods>;
1549
1550  // No VI instruction. This class is for SI only.
1551}
1552
1553// Two operand VOP3b instruction that may have a 3rd SGPR bool operand
1554// instead of an implicit VCC as in the VOP2b format.
1555multiclass VOP3b_2_3_m <vop op, dag outs, dag ins, string asm,
1556                        list<dag> pattern, string opName, string revOp,
1557                        bit HasMods = 1, bit useSrc2Input = 0> {
1558  def "" : VOP3_Pseudo <outs, ins, pattern, opName>;
1559
1560  def _si : VOP3b_Real_si <op.SI3, outs, ins, asm, opName>,
1561            VOP3DisableFields<1, useSrc2Input, HasMods>;
1562
1563  def _vi : VOP3b_Real_vi <op.VI3, outs, ins, asm, opName>,
1564            VOP3DisableFields<1, useSrc2Input, HasMods>;
1565}
1566
1567multiclass VOP3_C_m <vop op, dag outs, dag ins, string asm,
1568                     list<dag> pattern, string opName,
1569                     bit HasMods, bit defExec,
1570                     string revOp, list<SchedReadWrite> sched> {
1571
1572  def "" : VOP3_Pseudo <outs, ins, pattern, opName>,
1573           VOP2_REV<revOp#"_e64", !eq(revOp, opName)> {
1574    let Defs = !if(defExec, [EXEC], []);
1575    let SchedRW = sched;
1576  }
1577
1578  def _si : VOP3_Real_si <op.SI3, outs, ins, asm, opName>,
1579            VOP3DisableFields<1, 0, HasMods> {
1580    let Defs = !if(defExec, [EXEC], []);
1581    let SchedRW = sched;
1582  }
1583
1584  def _vi : VOP3_Real_vi <op.VI3, outs, ins, asm, opName>,
1585            VOP3DisableFields<1, 0, HasMods> {
1586    let Defs = !if(defExec, [EXEC], []);
1587    let SchedRW = sched;
1588  }
1589}
1590
1591// An instruction that is VOP2 on SI and VOP3 on VI, no modifiers.
1592multiclass VOP2SI_3VI_m <vop3 op, string opName, dag outs, dag ins,
1593                         string asm, list<dag> pattern = []> {
1594  let isPseudo = 1, isCodeGenOnly = 1 in {
1595    def "" : VOPAnyCommon <outs, ins, "", pattern>,
1596             SIMCInstr<opName, SISubtarget.NONE>;
1597  }
1598
1599  def _si : VOP2 <op.SI3{5-0}, outs, ins, asm, []>,
1600            SIMCInstr <opName, SISubtarget.SI> {
1601            let AssemblerPredicates = [isSICI];
1602  }
1603
1604  def _vi : VOP3Common <outs, ins, asm, []>,
1605            VOP3e_vi <op.VI3>,
1606            VOP3DisableFields <1, 0, 0>,
1607            SIMCInstr <opName, SISubtarget.VI> {
1608            let AssemblerPredicates = [isVI];
1609  }
1610}
1611
1612multiclass VOP1_Helper <vop1 op, string opName, VOPProfile p, list<dag> pat32,
1613                        list<dag> pat64> {
1614
1615  defm _e32 : VOP1_m <op, opName, p, pat32>;
1616
1617  defm _e64 : VOP3_1_m <op, p.Outs, p.Ins64, opName#p.Asm64, pat64, opName,
1618                        p.HasModifiers>;
1619}
1620
1621multiclass VOP1Inst <vop1 op, string opName, VOPProfile P,
1622                     SDPatternOperator node = null_frag> : VOP1_Helper <
1623  op, opName, P, [],
1624  !if(P.HasModifiers,
1625      [(set P.DstVT:$dst, (node (P.Src0VT (VOP3Mods0 P.Src0VT:$src0,
1626                                i32:$src0_modifiers, i1:$clamp, i32:$omod))))],
1627      [(set P.DstVT:$dst, (node P.Src0VT:$src0))])
1628>;
1629
1630multiclass VOP1InstSI <vop1 op, string opName, VOPProfile P,
1631                       SDPatternOperator node = null_frag> {
1632
1633  defm _e32 : VOP1SI_m <op, opName, P, []>;
1634
1635  defm _e64 : VOP3SI_1_m <op, P.Outs, P.Ins64, opName#P.Asm64,
1636    !if(P.HasModifiers,
1637      [(set P.DstVT:$dst, (node (P.Src0VT (VOP3Mods0 P.Src0VT:$src0,
1638                                i32:$src0_modifiers, i1:$clamp, i32:$omod))))],
1639      [(set P.DstVT:$dst, (node P.Src0VT:$src0))]),
1640    opName, P.HasModifiers>;
1641}
1642
1643multiclass VOP2_Helper <vop2 op, string opName, VOPProfile p, list<dag> pat32,
1644                        list<dag> pat64, string revOp> {
1645
1646  defm _e32 : VOP2_m <op, opName, p, pat32, revOp>;
1647
1648  defm _e64 : VOP3_2_m <op, p.Outs, p.Ins64, opName#p.Asm64, pat64, opName,
1649                        revOp, p.HasModifiers>;
1650}
1651
1652multiclass VOP2Inst <vop2 op, string opName, VOPProfile P,
1653                     SDPatternOperator node = null_frag,
1654                     string revOp = opName> : VOP2_Helper <
1655  op, opName, P, [],
1656  !if(P.HasModifiers,
1657      [(set P.DstVT:$dst,
1658           (node (P.Src0VT (VOP3Mods0 P.Src0VT:$src0, i32:$src0_modifiers,
1659                                      i1:$clamp, i32:$omod)),
1660                 (P.Src1VT (VOP3Mods P.Src1VT:$src1, i32:$src1_modifiers))))],
1661      [(set P.DstVT:$dst, (node P.Src0VT:$src0, P.Src1VT:$src1))]),
1662  revOp
1663>;
1664
1665multiclass VOP2InstSI <vop2 op, string opName, VOPProfile P,
1666                       SDPatternOperator node = null_frag,
1667                       string revOp = opName> {
1668
1669  defm _e32 : VOP2SI_m <op, opName, P, [], revOp>;
1670
1671  defm _e64 : VOP3SI_2_m <op, P.Outs, P.Ins64, opName#P.Asm64,
1672    !if(P.HasModifiers,
1673        [(set P.DstVT:$dst,
1674             (node (P.Src0VT (VOP3Mods0 P.Src0VT:$src0, i32:$src0_modifiers,
1675                                        i1:$clamp, i32:$omod)),
1676                   (P.Src1VT (VOP3Mods P.Src1VT:$src1, i32:$src1_modifiers))))],
1677        [(set P.DstVT:$dst, (node P.Src0VT:$src0, P.Src1VT:$src1))]),
1678    opName, revOp, P.HasModifiers>;
1679}
1680
1681multiclass VOP2b_Helper <vop2 op, string opName, VOPProfile p,
1682                         list<dag> pat32, list<dag> pat64,
1683                         string revOp, bit useSGPRInput> {
1684
1685  let SchedRW = [Write32Bit, WriteSALU] in {
1686    let Uses = !if(useSGPRInput, [VCC, EXEC], [EXEC]), Defs = [VCC] in {
1687      defm _e32 : VOP2_m <op, opName, p, pat32, revOp>;
1688    }
1689
1690    defm _e64 : VOP3b_2_3_m <op, p.Outs64, p.Ins64, opName#p.Asm64, pat64,
1691                             opName, revOp, p.HasModifiers, useSGPRInput>;
1692  }
1693}
1694
1695multiclass VOP2bInst <vop2 op, string opName, VOPProfile P,
1696                      SDPatternOperator node = null_frag,
1697                      string revOp = opName> : VOP2b_Helper <
1698  op, opName, P, [],
1699  !if(P.HasModifiers,
1700      [(set P.DstVT:$dst,
1701           (node (P.Src0VT (VOP3Mods0 P.Src0VT:$src0, i32:$src0_modifiers,
1702                                      i1:$clamp, i32:$omod)),
1703                 (P.Src1VT (VOP3Mods P.Src1VT:$src1, i32:$src1_modifiers))))],
1704      [(set P.DstVT:$dst, (node P.Src0VT:$src0, P.Src1VT:$src1))]),
1705  revOp, !eq(P.NumSrcArgs, 3)
1706>;
1707
1708// A VOP2 instruction that is VOP3-only on VI.
1709multiclass VOP2_VI3_Helper <vop23 op, string opName, VOPProfile p,
1710                            list<dag> pat32, list<dag> pat64, string revOp> {
1711
1712  defm _e32 : VOP2SI_m <op, opName, p, pat32, revOp>;
1713
1714  defm _e64 : VOP3_2_m <op, p.Outs, p.Ins64, opName#p.Asm64, pat64, opName,
1715                        revOp, p.HasModifiers>;
1716}
1717
1718multiclass VOP2_VI3_Inst <vop23 op, string opName, VOPProfile P,
1719                          SDPatternOperator node = null_frag,
1720                          string revOp = opName>
1721                          : VOP2_VI3_Helper <
1722  op, opName, P, [],
1723  !if(P.HasModifiers,
1724      [(set P.DstVT:$dst,
1725           (node (P.Src0VT (VOP3Mods0 P.Src0VT:$src0, i32:$src0_modifiers,
1726                                      i1:$clamp, i32:$omod)),
1727                 (P.Src1VT (VOP3Mods P.Src1VT:$src1, i32:$src1_modifiers))))],
1728      [(set P.DstVT:$dst, (node P.Src0VT:$src0, P.Src1VT:$src1))]),
1729  revOp
1730>;
1731
1732multiclass VOP2MADK <vop2 op, string opName, list<dag> pattern = []> {
1733
1734  def "" : VOP2_Pseudo <VOP_MADK.Outs, VOP_MADK.Ins, pattern, opName>;
1735
1736let isCodeGenOnly = 0 in {
1737  def _si : VOP2Common <VOP_MADK.Outs, VOP_MADK.Ins,
1738                        !strconcat(opName, VOP_MADK.Asm), []>,
1739            SIMCInstr <opName#"_e32", SISubtarget.SI>,
1740            VOP2_MADKe <op.SI> {
1741            let AssemblerPredicates = [isSICI];
1742            }
1743
1744  def _vi : VOP2Common <VOP_MADK.Outs, VOP_MADK.Ins,
1745                        !strconcat(opName, VOP_MADK.Asm), []>,
1746            SIMCInstr <opName#"_e32", SISubtarget.VI>,
1747            VOP2_MADKe <op.VI> {
1748            let AssemblerPredicates = [isVI];
1749            }
1750} // End isCodeGenOnly = 0
1751}
1752
1753class VOPC_Pseudo <dag ins, list<dag> pattern, string opName> :
1754  VOPCCommon <ins, "", pattern>,
1755  VOP <opName>,
1756  SIMCInstr<opName#"_e32", SISubtarget.NONE> {
1757  let isPseudo = 1;
1758  let isCodeGenOnly = 1;
1759}
1760
1761multiclass VOPC_m <vopc op, dag ins, string op_asm, list<dag> pattern,
1762                   string opName, bit DefExec, VOPProfile p,
1763                   list<SchedReadWrite> sched,
1764                   string revOpName = "", string asm = opName#"_e32 "#op_asm,
1765                   string alias_asm = opName#" "#op_asm> {
1766  def "" : VOPC_Pseudo <ins, pattern, opName> {
1767    let Defs = !if(DefExec, [VCC, EXEC], [VCC]);
1768    let SchedRW = sched;
1769  }
1770
1771  let AssemblerPredicates = [isSICI] in {
1772    def _si : VOPC<op.SI, ins, asm, []>,
1773              SIMCInstr <opName#"_e32", SISubtarget.SI> {
1774      let Defs = !if(DefExec, [VCC, EXEC], [VCC]);
1775      let hasSideEffects = DefExec;
1776      let SchedRW = sched;
1777    }
1778
1779  } // End AssemblerPredicates = [isSICI]
1780
1781  let AssemblerPredicates = [isVI] in {
1782    def _vi : VOPC<op.VI, ins, asm, []>,
1783              SIMCInstr <opName#"_e32", SISubtarget.VI> {
1784      let Defs = !if(DefExec, [VCC, EXEC], [VCC]);
1785      let hasSideEffects = DefExec;
1786      let SchedRW = sched;
1787    }
1788
1789  } // End AssemblerPredicates = [isVI]
1790
1791  defm : SIInstAliasBuilder<alias_asm, p>;
1792}
1793
1794multiclass VOPC_Helper <vopc op, string opName, list<dag> pat32,
1795                        list<dag> pat64, bit DefExec, string revOp,
1796                        VOPProfile p, list<SchedReadWrite> sched> {
1797  defm _e32 : VOPC_m <op, p.Ins32, p.Asm32, pat32, opName, DefExec, p, sched>;
1798
1799  defm _e64 : VOP3_C_m <op, (outs VOPDstS64:$dst), p.Ins64, opName#p.Asm64, pat64,
1800                        opName, p.HasModifiers, DefExec, revOp, sched>;
1801}
1802
1803// Special case for class instructions which only have modifiers on
1804// the 1st source operand.
1805multiclass VOPC_Class_Helper <vopc op, string opName, list<dag> pat32,
1806                              list<dag> pat64, bit DefExec, string revOp,
1807                              VOPProfile p, list<SchedReadWrite> sched> {
1808  defm _e32 : VOPC_m <op, p.Ins32, p.Asm32, pat32, opName, DefExec, p, sched>;
1809
1810  defm _e64 : VOP3_C_m <op, (outs VOPDstS64:$dst), p.Ins64, opName#p.Asm64, pat64,
1811                        opName, p.HasModifiers, DefExec, revOp, sched>,
1812                        VOP3DisableModFields<1, 0, 0>;
1813}
1814
1815multiclass VOPCInst <vopc op, string opName,
1816                     VOPProfile P, PatLeaf cond = COND_NULL,
1817                     string revOp = opName,
1818                     bit DefExec = 0,
1819                     list<SchedReadWrite> sched = [Write32Bit]> :
1820                     VOPC_Helper <
1821  op, opName, [],
1822  !if(P.HasModifiers,
1823      [(set i1:$dst,
1824          (setcc (P.Src0VT (VOP3Mods0 P.Src0VT:$src0, i32:$src0_modifiers,
1825                                      i1:$clamp, i32:$omod)),
1826                 (P.Src1VT (VOP3Mods P.Src1VT:$src1, i32:$src1_modifiers)),
1827                 cond))],
1828      [(set i1:$dst, (setcc P.Src0VT:$src0, P.Src1VT:$src1, cond))]),
1829  DefExec, revOp, P, sched
1830>;
1831
1832multiclass VOPCClassInst <vopc op, string opName, VOPProfile P,
1833                     bit DefExec = 0,
1834                     list<SchedReadWrite> sched> : VOPC_Class_Helper <
1835  op, opName, [],
1836  !if(P.HasModifiers,
1837      [(set i1:$dst,
1838          (AMDGPUfp_class (P.Src0VT (VOP3Mods0Clamp0OMod P.Src0VT:$src0, i32:$src0_modifiers)), P.Src1VT:$src1))],
1839      [(set i1:$dst, (AMDGPUfp_class P.Src0VT:$src0, P.Src1VT:$src1))]),
1840  DefExec, opName, P, sched
1841>;
1842
1843
1844multiclass VOPC_F32 <vopc op, string opName, PatLeaf cond = COND_NULL, string revOp = opName> :
1845  VOPCInst <op, opName, VOPC_I1_F32_F32, cond, revOp>;
1846
1847multiclass VOPC_F64 <vopc op, string opName, PatLeaf cond = COND_NULL, string revOp = opName> :
1848  VOPCInst <op, opName, VOPC_I1_F64_F64, cond, revOp, 0, [WriteDoubleAdd]>;
1849
1850multiclass VOPC_I32 <vopc op, string opName, PatLeaf cond = COND_NULL, string revOp = opName> :
1851  VOPCInst <op, opName, VOPC_I1_I32_I32, cond, revOp>;
1852
1853multiclass VOPC_I64 <vopc op, string opName, PatLeaf cond = COND_NULL, string revOp = opName> :
1854  VOPCInst <op, opName, VOPC_I1_I64_I64, cond, revOp, 0, [Write64Bit]>;
1855
1856
1857multiclass VOPCX <vopc op, string opName, VOPProfile P,
1858                  PatLeaf cond = COND_NULL,
1859                  list<SchedReadWrite> sched,
1860                  string revOp = "">
1861  : VOPCInst <op, opName, P, cond, revOp, 1, sched>;
1862
1863multiclass VOPCX_F32 <vopc op, string opName, string revOp = opName> :
1864  VOPCX <op, opName, VOPC_I1_F32_F32, COND_NULL, [Write32Bit], revOp>;
1865
1866multiclass VOPCX_F64 <vopc op, string opName, string revOp = opName> :
1867  VOPCX <op, opName, VOPC_I1_F64_F64, COND_NULL, [WriteDoubleAdd], revOp>;
1868
1869multiclass VOPCX_I32 <vopc op, string opName, string revOp = opName> :
1870  VOPCX <op, opName, VOPC_I1_I32_I32, COND_NULL, [Write32Bit], revOp>;
1871
1872multiclass VOPCX_I64 <vopc op, string opName, string revOp = opName> :
1873  VOPCX <op, opName, VOPC_I1_I64_I64, COND_NULL, [Write64Bit], revOp>;
1874
1875multiclass VOP3_Helper <vop3 op, string opName, dag outs, dag ins, string asm,
1876                        list<dag> pat, int NumSrcArgs, bit HasMods> : VOP3_m <
1877    op, outs, ins, opName#" "#asm, pat, opName, NumSrcArgs, HasMods
1878>;
1879
1880multiclass VOPC_CLASS_F32 <vopc op, string opName> :
1881  VOPCClassInst <op, opName, VOPC_I1_F32_I32, 0, [Write32Bit]>;
1882
1883multiclass VOPCX_CLASS_F32 <vopc op, string opName> :
1884  VOPCClassInst <op, opName, VOPC_I1_F32_I32, 1, [Write32Bit]>;
1885
1886multiclass VOPC_CLASS_F64 <vopc op, string opName> :
1887  VOPCClassInst <op, opName, VOPC_I1_F64_I32, 0, [WriteDoubleAdd]>;
1888
1889multiclass VOPCX_CLASS_F64 <vopc op, string opName> :
1890  VOPCClassInst <op, opName, VOPC_I1_F64_I32, 1, [WriteDoubleAdd]>;
1891
1892multiclass VOP3Inst <vop3 op, string opName, VOPProfile P,
1893                     SDPatternOperator node = null_frag> : VOP3_Helper <
1894  op, opName, (outs P.DstRC.RegClass:$dst), P.Ins64, P.Asm64,
1895  !if(!eq(P.NumSrcArgs, 3),
1896    !if(P.HasModifiers,
1897        [(set P.DstVT:$dst,
1898            (node (P.Src0VT (VOP3Mods0 P.Src0VT:$src0, i32:$src0_modifiers,
1899                                       i1:$clamp, i32:$omod)),
1900                  (P.Src1VT (VOP3Mods P.Src1VT:$src1, i32:$src1_modifiers)),
1901                  (P.Src2VT (VOP3Mods P.Src2VT:$src2, i32:$src2_modifiers))))],
1902        [(set P.DstVT:$dst, (node P.Src0VT:$src0, P.Src1VT:$src1,
1903                                  P.Src2VT:$src2))]),
1904  !if(!eq(P.NumSrcArgs, 2),
1905    !if(P.HasModifiers,
1906        [(set P.DstVT:$dst,
1907            (node (P.Src0VT (VOP3Mods0 P.Src0VT:$src0, i32:$src0_modifiers,
1908                                       i1:$clamp, i32:$omod)),
1909                  (P.Src1VT (VOP3Mods P.Src1VT:$src1, i32:$src1_modifiers))))],
1910        [(set P.DstVT:$dst, (node P.Src0VT:$src0, P.Src1VT:$src1))])
1911  /* P.NumSrcArgs == 1 */,
1912    !if(P.HasModifiers,
1913        [(set P.DstVT:$dst,
1914            (node (P.Src0VT (VOP3Mods0 P.Src0VT:$src0, i32:$src0_modifiers,
1915                                       i1:$clamp, i32:$omod))))],
1916        [(set P.DstVT:$dst, (node P.Src0VT:$src0))]))),
1917  P.NumSrcArgs, P.HasModifiers
1918>;
1919
1920// Special case for v_div_fmas_{f32|f64}, since it seems to be the
1921// only VOP instruction that implicitly reads VCC.
1922multiclass VOP3_VCC_Inst <vop3 op, string opName,
1923                          VOPProfile P,
1924                          SDPatternOperator node = null_frag> : VOP3_Helper <
1925  op, opName,
1926  (outs P.DstRC.RegClass:$dst),
1927  (ins InputModsNoDefault:$src0_modifiers, P.Src0RC64:$src0,
1928       InputModsNoDefault:$src1_modifiers, P.Src1RC64:$src1,
1929       InputModsNoDefault:$src2_modifiers, P.Src2RC64:$src2,
1930       ClampMod:$clamp,
1931       omod:$omod),
1932  "$dst, $src0_modifiers, $src1_modifiers, $src2_modifiers"#"$clamp"#"$omod",
1933  [(set P.DstVT:$dst,
1934            (node (P.Src0VT (VOP3Mods0 P.Src0VT:$src0, i32:$src0_modifiers,
1935                                       i1:$clamp, i32:$omod)),
1936                  (P.Src1VT (VOP3Mods P.Src1VT:$src1, i32:$src1_modifiers)),
1937                  (P.Src2VT (VOP3Mods P.Src2VT:$src2, i32:$src2_modifiers)),
1938                  (i1 VCC)))],
1939  3, 1
1940>;
1941
1942multiclass VOP3bInst <vop op, string opName, VOPProfile P, list<dag> pattern = []> :
1943  VOP3b_2_3_m <
1944  op, P.Outs64, P.Ins64,
1945  opName#" "#P.Asm64, pattern,
1946  opName, "", 1, 1
1947>;
1948
1949class Vop3ModPat<Instruction Inst, VOPProfile P, SDPatternOperator node> : Pat<
1950  (node (P.Src0VT (VOP3Mods0 P.Src0VT:$src0, i32:$src0_modifiers, i1:$clamp, i32:$omod)),
1951        (P.Src1VT (VOP3Mods P.Src1VT:$src1, i32:$src1_modifiers)),
1952        (P.Src2VT (VOP3Mods P.Src2VT:$src2, i32:$src2_modifiers))),
1953  (Inst i32:$src0_modifiers, P.Src0VT:$src0,
1954        i32:$src1_modifiers, P.Src1VT:$src1,
1955        i32:$src2_modifiers, P.Src2VT:$src2,
1956        i1:$clamp,
1957        i32:$omod)>;
1958
1959//===----------------------------------------------------------------------===//
1960// Interpolation opcodes
1961//===----------------------------------------------------------------------===//
1962
1963class VINTRP_Pseudo <string opName, dag outs, dag ins, list<dag> pattern> :
1964  VINTRPCommon <outs, ins, "", pattern>,
1965  SIMCInstr<opName, SISubtarget.NONE> {
1966  let isPseudo = 1;
1967  let isCodeGenOnly = 1;
1968}
1969
1970class VINTRP_Real_si <bits <2> op, string opName, dag outs, dag ins,
1971                      string asm> :
1972  VINTRPCommon <outs, ins, asm, []>,
1973  VINTRPe <op>,
1974  SIMCInstr<opName, SISubtarget.SI>;
1975
1976class VINTRP_Real_vi <bits <2> op, string opName, dag outs, dag ins,
1977                      string asm> :
1978  VINTRPCommon <outs, ins, asm, []>,
1979  VINTRPe_vi <op>,
1980  SIMCInstr<opName, SISubtarget.VI>;
1981
1982multiclass VINTRP_m <bits <2> op, dag outs, dag ins, string asm,
1983                     list<dag> pattern = []> {
1984  def "" : VINTRP_Pseudo <NAME, outs, ins, pattern>;
1985
1986  def _si : VINTRP_Real_si <op, NAME, outs, ins, asm>;
1987
1988  def _vi : VINTRP_Real_vi <op, NAME, outs, ins, asm>;
1989}
1990
1991//===----------------------------------------------------------------------===//
1992// Vector I/O classes
1993//===----------------------------------------------------------------------===//
1994
1995class DS_Pseudo <string opName, dag outs, dag ins, list<dag> pattern> :
1996  DS <outs, ins, "", pattern>,
1997  SIMCInstr <opName, SISubtarget.NONE> {
1998  let isPseudo = 1;
1999  let isCodeGenOnly = 1;
2000}
2001
2002class DS_Real_si <bits<8> op, string opName, dag outs, dag ins, string asm> :
2003  DS <outs, ins, asm, []>,
2004  DSe <op>,
2005  SIMCInstr <opName, SISubtarget.SI> {
2006  let isCodeGenOnly = 0;
2007}
2008
2009class DS_Real_vi <bits<8> op, string opName, dag outs, dag ins, string asm> :
2010  DS <outs, ins, asm, []>,
2011  DSe_vi <op>,
2012  SIMCInstr <opName, SISubtarget.VI>;
2013
2014class DS_Off16_Real_si <bits<8> op, string opName, dag outs, dag ins, string asm> :
2015  DS_Real_si <op,opName, outs, ins, asm> {
2016
2017  // Single load interpret the 2 i8imm operands as a single i16 offset.
2018  bits<16> offset;
2019  let offset0 = offset{7-0};
2020  let offset1 = offset{15-8};
2021  let isCodeGenOnly = 0;
2022}
2023
2024class DS_Off16_Real_vi <bits<8> op, string opName, dag outs, dag ins, string asm> :
2025  DS_Real_vi <op, opName, outs, ins, asm> {
2026
2027  // Single load interpret the 2 i8imm operands as a single i16 offset.
2028  bits<16> offset;
2029  let offset0 = offset{7-0};
2030  let offset1 = offset{15-8};
2031}
2032
2033multiclass DS_1A_RET <bits<8> op, string opName, RegisterClass rc,
2034  dag outs = (outs rc:$vdst),
2035  dag ins = (ins VGPR_32:$addr, ds_offset:$offset, gds:$gds),
2036  string asm = opName#" $vdst, $addr"#"$offset$gds"> {
2037
2038  def "" : DS_Pseudo <opName, outs, ins, []>;
2039
2040  let data0 = 0, data1 = 0 in {
2041    def _si : DS_Off16_Real_si <op, opName, outs, ins, asm>;
2042    def _vi : DS_Off16_Real_vi <op, opName, outs, ins, asm>;
2043  }
2044}
2045
2046multiclass DS_1A_Off8_RET <bits<8> op, string opName, RegisterClass rc,
2047  dag outs = (outs rc:$vdst),
2048  dag ins = (ins VGPR_32:$addr, ds_offset0:$offset0, ds_offset1:$offset1,
2049                 gds01:$gds),
2050  string asm = opName#" $vdst, $addr"#"$offset0"#"$offset1$gds"> {
2051
2052  def "" : DS_Pseudo <opName, outs, ins, []>;
2053
2054  let data0 = 0, data1 = 0, AsmMatchConverter = "cvtDSOffset01" in {
2055    def _si : DS_Real_si <op, opName, outs, ins, asm>;
2056    def _vi : DS_Real_vi <op, opName, outs, ins, asm>;
2057  }
2058}
2059
2060multiclass DS_1A1D_NORET <bits<8> op, string opName, RegisterClass rc,
2061  dag outs = (outs),
2062  dag ins = (ins VGPR_32:$addr, rc:$data0, ds_offset:$offset, gds:$gds),
2063  string asm = opName#" $addr, $data0"#"$offset$gds"> {
2064
2065  def "" : DS_Pseudo <opName, outs, ins, []>,
2066           AtomicNoRet<opName, 0>;
2067
2068  let data1 = 0, vdst = 0 in {
2069    def _si : DS_Off16_Real_si <op, opName, outs, ins, asm>;
2070    def _vi : DS_Off16_Real_vi <op, opName, outs, ins, asm>;
2071  }
2072}
2073
2074multiclass DS_1A1D_Off8_NORET <bits<8> op, string opName, RegisterClass rc,
2075  dag outs = (outs),
2076  dag ins = (ins VGPR_32:$addr, rc:$data0, rc:$data1,
2077              ds_offset0:$offset0, ds_offset1:$offset1, gds01:$gds),
2078  string asm = opName#" $addr, $data0, $data1"#"$offset0"#"$offset1"#"$gds"> {
2079
2080  def "" : DS_Pseudo <opName, outs, ins, []>;
2081
2082  let vdst = 0, AsmMatchConverter = "cvtDSOffset01" in {
2083    def _si : DS_Real_si <op, opName, outs, ins, asm>;
2084    def _vi : DS_Real_vi <op, opName, outs, ins, asm>;
2085  }
2086}
2087
2088multiclass DS_1A1D_RET <bits<8> op, string opName, RegisterClass rc,
2089                        string noRetOp = "",
2090  dag outs = (outs rc:$vdst),
2091  dag ins = (ins VGPR_32:$addr, rc:$data0, ds_offset:$offset, gds:$gds),
2092  string asm = opName#" $vdst, $addr, $data0"#"$offset$gds"> {
2093
2094  let hasPostISelHook = 1 in {
2095    def "" : DS_Pseudo <opName, outs, ins, []>,
2096             AtomicNoRet<noRetOp, 1>;
2097
2098    let data1 = 0 in {
2099      def _si : DS_Off16_Real_si <op, opName, outs, ins, asm>;
2100      def _vi : DS_Off16_Real_vi <op, opName, outs, ins, asm>;
2101    }
2102  }
2103}
2104
2105multiclass DS_1A2D_RET_m <bits<8> op, string opName, RegisterClass rc,
2106                          string noRetOp = "", dag ins,
2107  dag outs = (outs rc:$vdst),
2108  string asm = opName#" $vdst, $addr, $data0, $data1"#"$offset"#"$gds"> {
2109
2110  let hasPostISelHook = 1 in {
2111    def "" : DS_Pseudo <opName, outs, ins, []>,
2112             AtomicNoRet<noRetOp, 1>;
2113
2114    def _si : DS_Off16_Real_si <op, opName, outs, ins, asm>;
2115    def _vi : DS_Off16_Real_vi <op, opName, outs, ins, asm>;
2116  }
2117}
2118
2119multiclass DS_1A2D_RET <bits<8> op, string asm, RegisterClass rc,
2120                        string noRetOp = "", RegisterClass src = rc> :
2121  DS_1A2D_RET_m <op, asm, rc, noRetOp,
2122                 (ins VGPR_32:$addr, src:$data0, src:$data1,
2123                      ds_offset:$offset, gds:$gds)
2124>;
2125
2126multiclass DS_1A2D_NORET <bits<8> op, string opName, RegisterClass rc,
2127                          string noRetOp = opName,
2128  dag outs = (outs),
2129  dag ins = (ins VGPR_32:$addr, rc:$data0, rc:$data1,
2130                 ds_offset:$offset, gds:$gds),
2131  string asm = opName#" $addr, $data0, $data1"#"$offset"#"$gds"> {
2132
2133  def "" : DS_Pseudo <opName, outs, ins, []>,
2134           AtomicNoRet<noRetOp, 0>;
2135
2136  let vdst = 0 in {
2137    def _si : DS_Off16_Real_si <op, opName, outs, ins, asm>;
2138    def _vi : DS_Off16_Real_vi <op, opName, outs, ins, asm>;
2139  }
2140}
2141
2142multiclass DS_0A_RET <bits<8> op, string opName,
2143  dag outs = (outs VGPR_32:$vdst),
2144  dag ins = (ins ds_offset:$offset, gds:$gds),
2145  string asm = opName#" $vdst"#"$offset"#"$gds"> {
2146
2147  let mayLoad = 1, mayStore = 1 in {
2148    def "" : DS_Pseudo <opName, outs, ins, []>;
2149
2150    let addr = 0, data0 = 0, data1 = 0 in {
2151      def _si : DS_Off16_Real_si <op, opName, outs, ins, asm>;
2152      def _vi : DS_Off16_Real_vi <op, opName, outs, ins, asm>;
2153    } // end addr = 0, data0 = 0, data1 = 0
2154  } // end mayLoad = 1, mayStore = 1
2155}
2156
2157multiclass DS_1A_RET_GDS <bits<8> op, string opName,
2158  dag outs = (outs VGPR_32:$vdst),
2159  dag ins = (ins VGPR_32:$addr, ds_offset_gds:$offset),
2160  string asm = opName#" $vdst, $addr"#"$offset gds"> {
2161
2162  def "" : DS_Pseudo <opName, outs, ins, []>;
2163
2164  let data0 = 0, data1 = 0, gds = 1 in {
2165    def _si : DS_Off16_Real_si <op, opName, outs, ins, asm>;
2166    def _vi : DS_Off16_Real_vi <op, opName, outs, ins, asm>;
2167  } // end data0 = 0, data1 = 0, gds = 1
2168}
2169
2170multiclass DS_1A_GDS <bits<8> op, string opName,
2171  dag outs = (outs),
2172  dag ins = (ins VGPR_32:$addr),
2173  string asm = opName#" $addr gds"> {
2174
2175  def "" : DS_Pseudo <opName, outs, ins, []>;
2176
2177  let vdst = 0, data0 = 0, data1 = 0, offset0 = 0, offset1 = 0, gds = 1 in {
2178    def _si : DS_Real_si <op, opName, outs, ins, asm>;
2179    def _vi : DS_Real_vi <op, opName, outs, ins, asm>;
2180  } // end vdst = 0, data = 0, data1 = 0, gds = 1
2181}
2182
2183multiclass DS_1A <bits<8> op, string opName,
2184  dag outs = (outs),
2185  dag ins = (ins VGPR_32:$addr, ds_offset:$offset, gds:$gds),
2186  string asm = opName#" $addr"#"$offset"#"$gds"> {
2187
2188  let mayLoad = 1, mayStore = 1 in {
2189    def "" : DS_Pseudo <opName, outs, ins, []>;
2190
2191    let vdst = 0, data0 = 0, data1 = 0 in {
2192      def _si : DS_Off16_Real_si <op, opName, outs, ins, asm>;
2193      def _vi : DS_Off16_Real_vi <op, opName, outs, ins, asm>;
2194    } // let vdst = 0, data0 = 0, data1 = 0
2195  } // end mayLoad = 1, mayStore = 1
2196}
2197
2198//===----------------------------------------------------------------------===//
2199// MTBUF classes
2200//===----------------------------------------------------------------------===//
2201
2202class MTBUF_Pseudo <string opName, dag outs, dag ins, list<dag> pattern> :
2203  MTBUF <outs, ins, "", pattern>,
2204  SIMCInstr<opName, SISubtarget.NONE> {
2205  let isPseudo = 1;
2206  let isCodeGenOnly = 1;
2207}
2208
2209class MTBUF_Real_si <bits<3> op, string opName, dag outs, dag ins,
2210                    string asm> :
2211  MTBUF <outs, ins, asm, []>,
2212  MTBUFe <op>,
2213  SIMCInstr<opName, SISubtarget.SI>;
2214
2215class MTBUF_Real_vi <bits<4> op, string opName, dag outs, dag ins, string asm> :
2216  MTBUF <outs, ins, asm, []>,
2217  MTBUFe_vi <op>,
2218  SIMCInstr <opName, SISubtarget.VI>;
2219
2220multiclass MTBUF_m <bits<3> op, string opName, dag outs, dag ins, string asm,
2221                    list<dag> pattern> {
2222
2223  def "" : MTBUF_Pseudo <opName, outs, ins, pattern>;
2224
2225  def _si : MTBUF_Real_si <op, opName, outs, ins, asm>;
2226
2227  def _vi : MTBUF_Real_vi <{0, op{2}, op{1}, op{0}}, opName, outs, ins, asm>;
2228
2229}
2230
2231let mayStore = 1, mayLoad = 0 in {
2232
2233multiclass MTBUF_Store_Helper <bits<3> op, string opName,
2234                               RegisterClass regClass> : MTBUF_m <
2235  op, opName, (outs),
2236  (ins regClass:$vdata, u16imm:$offset, i1imm:$offen, i1imm:$idxen, i1imm:$glc,
2237   i1imm:$addr64, i8imm:$dfmt, i8imm:$nfmt, VGPR_32:$vaddr,
2238   SReg_128:$srsrc, i1imm:$slc, i1imm:$tfe, SCSrc_32:$soffset),
2239  opName#" $vdata, $offset, $offen, $idxen, $glc, $addr64, $dfmt,"
2240        #" $nfmt, $vaddr, $srsrc, $slc, $tfe, $soffset", []
2241>;
2242
2243} // mayStore = 1, mayLoad = 0
2244
2245let mayLoad = 1, mayStore = 0 in {
2246
2247multiclass MTBUF_Load_Helper <bits<3> op, string opName,
2248                              RegisterClass regClass> : MTBUF_m <
2249  op, opName, (outs regClass:$dst),
2250  (ins u16imm:$offset, i1imm:$offen, i1imm:$idxen, i1imm:$glc, i1imm:$addr64,
2251       i8imm:$dfmt, i8imm:$nfmt, VGPR_32:$vaddr, SReg_128:$srsrc,
2252       i1imm:$slc, i1imm:$tfe, SCSrc_32:$soffset),
2253  opName#" $dst, $offset, $offen, $idxen, $glc, $addr64, $dfmt,"
2254        #" $nfmt, $vaddr, $srsrc, $slc, $tfe, $soffset", []
2255>;
2256
2257} // mayLoad = 1, mayStore = 0
2258
2259//===----------------------------------------------------------------------===//
2260// MUBUF classes
2261//===----------------------------------------------------------------------===//
2262
2263class mubuf <bits<7> si, bits<7> vi = si> {
2264  field bits<7> SI = si;
2265  field bits<7> VI = vi;
2266}
2267
2268let isCodeGenOnly = 0 in {
2269
2270class MUBUF_si <bits<7> op, dag outs, dag ins, string asm, list<dag> pattern> :
2271  MUBUF <outs, ins, asm, pattern>, MUBUFe <op> {
2272  let lds  = 0;
2273}
2274
2275} // End let isCodeGenOnly = 0
2276
2277class MUBUF_vi <bits<7> op, dag outs, dag ins, string asm, list<dag> pattern> :
2278  MUBUF <outs, ins, asm, pattern>, MUBUFe_vi <op> {
2279  let lds = 0;
2280}
2281
2282class MUBUFAddr64Table <bit is_addr64, string suffix = ""> {
2283  bit IsAddr64 = is_addr64;
2284  string OpName = NAME # suffix;
2285}
2286
2287class MUBUF_Pseudo <string opName, dag outs, dag ins, list<dag> pattern> :
2288  MUBUF <outs, ins, "", pattern>,
2289  SIMCInstr<opName, SISubtarget.NONE> {
2290  let isPseudo = 1;
2291  let isCodeGenOnly = 1;
2292
2293  // dummy fields, so that we can use let statements around multiclasses
2294  bits<1> offen;
2295  bits<1> idxen;
2296  bits<8> vaddr;
2297  bits<1> glc;
2298  bits<1> slc;
2299  bits<1> tfe;
2300  bits<8> soffset;
2301}
2302
2303class MUBUF_Real_si <mubuf op, string opName, dag outs, dag ins,
2304                     string asm> :
2305  MUBUF <outs, ins, asm, []>,
2306  MUBUFe <op.SI>,
2307  SIMCInstr<opName, SISubtarget.SI> {
2308  let lds = 0;
2309}
2310
2311class MUBUF_Real_vi <mubuf op, string opName, dag outs, dag ins,
2312                     string asm> :
2313  MUBUF <outs, ins, asm, []>,
2314  MUBUFe_vi <op.VI>,
2315  SIMCInstr<opName, SISubtarget.VI> {
2316  let lds = 0;
2317}
2318
2319multiclass MUBUF_m <mubuf op, string opName, dag outs, dag ins, string asm,
2320                    list<dag> pattern> {
2321
2322  def "" : MUBUF_Pseudo <opName, outs, ins, pattern>,
2323           MUBUFAddr64Table <0>;
2324
2325  let addr64 = 0, isCodeGenOnly = 0 in {
2326    def _si : MUBUF_Real_si <op, opName, outs, ins, asm>;
2327  }
2328
2329  def _vi : MUBUF_Real_vi <op, opName, outs, ins, asm>;
2330}
2331
2332multiclass MUBUFAddr64_m <mubuf op, string opName, dag outs,
2333                          dag ins, string asm, list<dag> pattern> {
2334
2335  def "" : MUBUF_Pseudo <opName, outs, ins, pattern>,
2336           MUBUFAddr64Table <1>;
2337
2338  let addr64 = 1, isCodeGenOnly = 0 in {
2339    def _si : MUBUF_Real_si <op, opName, outs, ins, asm>;
2340  }
2341
2342  // There is no VI version. If the pseudo is selected, it should be lowered
2343  // for VI appropriately.
2344}
2345
2346multiclass MUBUFAtomicOffset_m <mubuf op, string opName, dag outs, dag ins,
2347                                string asm, list<dag> pattern, bit is_return> {
2348
2349  def "" : MUBUF_Pseudo <opName, outs, ins, pattern>,
2350           MUBUFAddr64Table <0, !if(is_return, "_RTN", "")>,
2351           AtomicNoRet<NAME#"_OFFSET", is_return>;
2352
2353  let offen = 0, idxen = 0, tfe = 0, vaddr = 0 in {
2354    let addr64 = 0 in {
2355      def _si : MUBUF_Real_si <op, opName, outs, ins, asm>;
2356    }
2357
2358    def _vi : MUBUF_Real_vi <op, opName, outs, ins, asm>;
2359  }
2360}
2361
2362multiclass MUBUFAtomicAddr64_m <mubuf op, string opName, dag outs, dag ins,
2363                                string asm, list<dag> pattern, bit is_return> {
2364
2365  def "" : MUBUF_Pseudo <opName, outs, ins, pattern>,
2366           MUBUFAddr64Table <1, !if(is_return, "_RTN", "")>,
2367           AtomicNoRet<NAME#"_ADDR64", is_return>;
2368
2369  let offen = 0, idxen = 0, addr64 = 1, tfe = 0 in {
2370    def _si : MUBUF_Real_si <op, opName, outs, ins, asm>;
2371  }
2372
2373  // There is no VI version. If the pseudo is selected, it should be lowered
2374  // for VI appropriately.
2375}
2376
2377multiclass MUBUF_Atomic <mubuf op, string name, RegisterClass rc,
2378                         ValueType vt, SDPatternOperator atomic> {
2379
2380  let mayStore = 1, mayLoad = 1, hasPostISelHook = 1 in {
2381
2382    // No return variants
2383    let glc = 0 in {
2384
2385      defm _ADDR64 : MUBUFAtomicAddr64_m <
2386        op, name#"_addr64", (outs),
2387        (ins rc:$vdata, VReg_64:$vaddr, SReg_128:$srsrc,
2388             SCSrc_32:$soffset, mbuf_offset:$offset, slc:$slc),
2389        name#" $vdata, $vaddr, $srsrc, $soffset addr64"#"$offset"#"$slc", [], 0
2390      >;
2391
2392      defm _OFFSET : MUBUFAtomicOffset_m <
2393        op, name#"_offset", (outs),
2394        (ins rc:$vdata, SReg_128:$srsrc, SCSrc_32:$soffset, mbuf_offset:$offset,
2395             slc:$slc),
2396        name#" $vdata, $srsrc, $soffset"#"$offset"#"$slc", [], 0
2397      >;
2398    } // glc = 0
2399
2400    // Variant that return values
2401    let glc = 1, Constraints = "$vdata = $vdata_in",
2402        DisableEncoding = "$vdata_in"  in {
2403
2404      defm _RTN_ADDR64 : MUBUFAtomicAddr64_m <
2405        op, name#"_rtn_addr64", (outs rc:$vdata),
2406        (ins rc:$vdata_in, VReg_64:$vaddr, SReg_128:$srsrc,
2407             SCSrc_32:$soffset, mbuf_offset:$offset, slc:$slc),
2408        name#" $vdata, $vaddr, $srsrc, $soffset addr64"#"$offset"#" glc"#"$slc",
2409        [(set vt:$vdata,
2410         (atomic (MUBUFAddr64Atomic v4i32:$srsrc, i64:$vaddr, i32:$soffset,
2411	                            i16:$offset, i1:$slc), vt:$vdata_in))], 1
2412      >;
2413
2414      defm _RTN_OFFSET : MUBUFAtomicOffset_m <
2415        op, name#"_rtn_offset", (outs rc:$vdata),
2416        (ins rc:$vdata_in, SReg_128:$srsrc, SCSrc_32:$soffset,
2417             mbuf_offset:$offset, slc:$slc),
2418        name#" $vdata, $srsrc, $soffset"#"$offset"#" glc$slc",
2419        [(set vt:$vdata,
2420         (atomic (MUBUFOffsetAtomic v4i32:$srsrc, i32:$soffset, i16:$offset,
2421                                    i1:$slc), vt:$vdata_in))], 1
2422      >;
2423
2424    } // glc = 1
2425
2426  } // mayStore = 1, mayLoad = 1, hasPostISelHook = 1
2427}
2428
2429// FIXME: tfe can't be an operand because it requires a separate
2430// opcode because it needs an N+1 register class dest register.
2431multiclass MUBUF_Load_Helper <mubuf op, string name, RegisterClass regClass,
2432                              ValueType load_vt = i32,
2433                              SDPatternOperator ld = null_frag> {
2434
2435  let mayLoad = 1, mayStore = 0 in {
2436    let offen = 0, idxen = 0, vaddr = 0 in {
2437      defm _OFFSET : MUBUF_m <op, name#"_offset", (outs regClass:$vdata),
2438                           (ins SReg_128:$srsrc, SCSrc_32:$soffset,
2439                           mbuf_offset:$offset, glc:$glc, slc:$slc, tfe:$tfe),
2440                           name#" $vdata, $srsrc, $soffset"#"$offset"#"$glc"#"$slc"#"$tfe",
2441                           [(set load_vt:$vdata, (ld (MUBUFOffset v4i32:$srsrc,
2442                                                     i32:$soffset, i16:$offset,
2443                                                     i1:$glc, i1:$slc, i1:$tfe)))]>;
2444    }
2445
2446    let offen = 1, idxen = 0  in {
2447      defm _OFFEN  : MUBUF_m <op, name#"_offen", (outs regClass:$vdata),
2448                           (ins VGPR_32:$vaddr, SReg_128:$srsrc,
2449                           SCSrc_32:$soffset, mbuf_offset:$offset, glc:$glc, slc:$slc,
2450                           tfe:$tfe),
2451                           name#" $vdata, $vaddr, $srsrc, $soffset offen"#"$offset"#"$glc"#"$slc"#"$tfe", []>;
2452    }
2453
2454    let offen = 0, idxen = 1 in {
2455      defm _IDXEN  : MUBUF_m <op, name#"_idxen", (outs regClass:$vdata),
2456                           (ins VGPR_32:$vaddr, SReg_128:$srsrc,
2457                           SCSrc_32:$soffset, mbuf_offset:$offset, glc:$glc,
2458                           slc:$slc, tfe:$tfe),
2459                           name#" $vdata, $vaddr, $srsrc, $soffset idxen"#"$offset"#"$glc"#"$slc"#"$tfe", []>;
2460    }
2461
2462    let offen = 1, idxen = 1 in {
2463      defm _BOTHEN : MUBUF_m <op, name#"_bothen", (outs regClass:$vdata),
2464                           (ins VReg_64:$vaddr, SReg_128:$srsrc, SCSrc_32:$soffset,
2465                           mbuf_offset:$offset, glc:$glc, slc:$slc, tfe:$tfe),
2466                           name#" $vdata, $vaddr, $srsrc, $soffset idxen offen"#"$offset"#"$glc"#"$slc"#"$tfe", []>;
2467    }
2468
2469    let offen = 0, idxen = 0 in {
2470      defm _ADDR64 : MUBUFAddr64_m <op, name#"_addr64", (outs regClass:$vdata),
2471                           (ins VReg_64:$vaddr, SReg_128:$srsrc,
2472                                SCSrc_32:$soffset, mbuf_offset:$offset,
2473				glc:$glc, slc:$slc, tfe:$tfe),
2474                           name#" $vdata, $vaddr, $srsrc, $soffset addr64"#"$offset"#
2475                                "$glc"#"$slc"#"$tfe",
2476                           [(set load_vt:$vdata, (ld (MUBUFAddr64 v4i32:$srsrc,
2477                                                  i64:$vaddr, i32:$soffset,
2478                                                  i16:$offset, i1:$glc, i1:$slc,
2479						  i1:$tfe)))]>;
2480    }
2481  }
2482}
2483
2484multiclass MUBUF_Store_Helper <mubuf op, string name, RegisterClass vdataClass,
2485                          ValueType store_vt = i32, SDPatternOperator st = null_frag> {
2486  let mayLoad = 0, mayStore = 1 in {
2487    defm : MUBUF_m <op, name, (outs),
2488                    (ins vdataClass:$vdata, VGPR_32:$vaddr, SReg_128:$srsrc, SCSrc_32:$soffset,
2489                    mbuf_offset:$offset, offen:$offen, idxen:$idxen, glc:$glc, slc:$slc,
2490                    tfe:$tfe),
2491                    name#" $vdata, $vaddr, $srsrc, $soffset"#"$offen"#"$idxen"#"$offset"#
2492                         "$glc"#"$slc"#"$tfe", []>;
2493
2494    let offen = 0, idxen = 0, vaddr = 0 in {
2495      defm _OFFSET : MUBUF_m <op, name#"_offset",(outs),
2496                              (ins vdataClass:$vdata, SReg_128:$srsrc, SCSrc_32:$soffset,
2497                              mbuf_offset:$offset, glc:$glc, slc:$slc, tfe:$tfe),
2498                              name#" $vdata, $srsrc, $soffset"#"$offset"#"$glc"#"$slc"#"$tfe",
2499                              [(st store_vt:$vdata, (MUBUFOffset v4i32:$srsrc, i32:$soffset,
2500                                   i16:$offset, i1:$glc, i1:$slc, i1:$tfe))]>;
2501    } // offen = 0, idxen = 0, vaddr = 0
2502
2503    let offen = 1, idxen = 0  in {
2504      defm _OFFEN : MUBUF_m <op, name#"_offen", (outs),
2505                             (ins vdataClass:$vdata, VGPR_32:$vaddr, SReg_128:$srsrc,
2506                              SCSrc_32:$soffset, mbuf_offset:$offset, glc:$glc,
2507                              slc:$slc, tfe:$tfe),
2508                             name#" $vdata, $vaddr, $srsrc, $soffset offen"#"$offset"#
2509                             "$glc"#"$slc"#"$tfe", []>;
2510    } // end offen = 1, idxen = 0
2511
2512    let offen = 0, idxen = 1 in {
2513      defm _IDXEN  : MUBUF_m <op, name#"_idxen", (outs),
2514                           (ins vdataClass:$vdata, VGPR_32:$vaddr, SReg_128:$srsrc,
2515                           SCSrc_32:$soffset, mbuf_offset:$offset, glc:$glc,
2516                           slc:$slc, tfe:$tfe),
2517                           name#" $vdata, $vaddr, $srsrc, $soffset idxen"#"$offset"#"$glc"#"$slc"#"$tfe", []>;
2518    }
2519
2520    let offen = 1, idxen = 1 in {
2521      defm _BOTHEN : MUBUF_m <op, name#"_bothen", (outs),
2522                           (ins vdataClass:$vdata, VReg_64:$vaddr, SReg_128:$srsrc, SCSrc_32:$soffset,
2523                           mbuf_offset:$offset, glc:$glc, slc:$slc, tfe:$tfe),
2524                           name#" $vdata, $vaddr, $srsrc, $soffset idxen offen"#"$offset"#"$glc"#"$slc"#"$tfe", []>;
2525    }
2526
2527    let offen = 0, idxen = 0 in {
2528      defm _ADDR64 : MUBUFAddr64_m <op, name#"_addr64", (outs),
2529                                    (ins vdataClass:$vdata, VReg_64:$vaddr, SReg_128:$srsrc,
2530                                         SCSrc_32:$soffset,
2531                                         mbuf_offset:$offset, glc:$glc, slc:$slc,
2532                                         tfe:$tfe),
2533                                    name#" $vdata, $vaddr, $srsrc, $soffset addr64"#
2534                                         "$offset"#"$glc"#"$slc"#"$tfe",
2535                                    [(st store_vt:$vdata,
2536                                      (MUBUFAddr64 v4i32:$srsrc, i64:$vaddr,
2537                                                   i32:$soffset, i16:$offset,
2538                                                   i1:$glc, i1:$slc, i1:$tfe))]>;
2539    }
2540  } // End mayLoad = 0, mayStore = 1
2541}
2542
2543// For cache invalidation instructions.
2544multiclass MUBUF_Invalidate <mubuf op, string opName, SDPatternOperator node> {
2545  let hasSideEffects = 1, mayStore = 1, AsmMatchConverter = "" in {
2546    def "" : MUBUF_Pseudo <opName, (outs), (ins), [(node)]>;
2547
2548    // Set everything to 0.
2549    let offset = 0, offen = 0, idxen = 0, glc = 0, vaddr = 0,
2550        vdata = 0, srsrc = 0, slc = 0, tfe = 0, soffset = 0 in {
2551      let addr64 = 0 in {
2552        def _si : MUBUF_Real_si <op, opName, (outs), (ins), opName>;
2553      }
2554
2555      def _vi : MUBUF_Real_vi <op, opName, (outs), (ins), opName>;
2556    }
2557  } // End hasSideEffects = 1, mayStore = 1, AsmMatchConverter = ""
2558}
2559
2560class FLAT_Load_Helper <bits<7> op, string asm, RegisterClass regClass> :
2561      FLAT <op, (outs regClass:$vdst),
2562                (ins VReg_64:$addr, glc_flat:$glc, slc_flat:$slc, tfe_flat:$tfe),
2563            asm#" $vdst, $addr"#"$glc"#"$slc"#"$tfe", []> {
2564  let data = 0;
2565  let mayLoad = 1;
2566}
2567
2568class FLAT_Store_Helper <bits<7> op, string name, RegisterClass vdataClass> :
2569      FLAT <op, (outs), (ins vdataClass:$data, VReg_64:$addr,
2570                             glc_flat:$glc, slc_flat:$slc, tfe_flat:$tfe),
2571          name#" $data, $addr"#"$glc"#"$slc"#"$tfe",
2572         []> {
2573
2574  let mayLoad = 0;
2575  let mayStore = 1;
2576
2577  // Encoding
2578  let vdst = 0;
2579}
2580
2581multiclass FLAT_ATOMIC <bits<7> op, string name, RegisterClass vdst_rc,
2582                        RegisterClass data_rc = vdst_rc> {
2583
2584  let mayLoad = 1, mayStore = 1 in {
2585    def "" : FLAT <op, (outs),
2586                  (ins VReg_64:$addr, data_rc:$data, slc_flat_atomic:$slc,
2587                       tfe_flat_atomic:$tfe),
2588                   name#" $addr, $data"#"$slc"#"$tfe", []>,
2589             AtomicNoRet <NAME, 0> {
2590      let glc = 0;
2591      let vdst = 0;
2592    }
2593
2594    def _RTN : FLAT <op, (outs vdst_rc:$vdst),
2595                     (ins VReg_64:$addr, data_rc:$data, slc_flat_atomic:$slc,
2596                          tfe_flat_atomic:$tfe),
2597                     name#" $vdst, $addr, $data glc"#"$slc"#"$tfe", []>,
2598               AtomicNoRet <NAME, 1> {
2599      let glc = 1;
2600      let hasPostISelHook = 1;
2601    }
2602  }
2603}
2604
2605class MIMG_Mask <string op, int channels> {
2606  string Op = op;
2607  int Channels = channels;
2608}
2609
2610class MIMG_NoSampler_Helper <bits<7> op, string asm,
2611                             RegisterClass dst_rc,
2612                             RegisterClass src_rc> : MIMG <
2613  op,
2614  (outs dst_rc:$vdata),
2615  (ins i32imm:$dmask, i1imm:$unorm, i1imm:$glc, i1imm:$da, i1imm:$r128,
2616       i1imm:$tfe, i1imm:$lwe, i1imm:$slc, src_rc:$vaddr,
2617       SReg_256:$srsrc),
2618  asm#" $vdata, $dmask, $unorm, $glc, $da, $r128,"
2619     #" $tfe, $lwe, $slc, $vaddr, $srsrc",
2620  []> {
2621  let ssamp = 0;
2622  let mayLoad = 1;
2623  let mayStore = 0;
2624  let hasPostISelHook = 1;
2625}
2626
2627multiclass MIMG_NoSampler_Src_Helper <bits<7> op, string asm,
2628                                      RegisterClass dst_rc,
2629                                      int channels> {
2630  def _V1 : MIMG_NoSampler_Helper <op, asm, dst_rc, VGPR_32>,
2631            MIMG_Mask<asm#"_V1", channels>;
2632  def _V2 : MIMG_NoSampler_Helper <op, asm, dst_rc, VReg_64>,
2633            MIMG_Mask<asm#"_V2", channels>;
2634  def _V4 : MIMG_NoSampler_Helper <op, asm, dst_rc, VReg_128>,
2635            MIMG_Mask<asm#"_V4", channels>;
2636}
2637
2638multiclass MIMG_NoSampler <bits<7> op, string asm> {
2639  defm _V1 : MIMG_NoSampler_Src_Helper <op, asm, VGPR_32, 1>;
2640  defm _V2 : MIMG_NoSampler_Src_Helper <op, asm, VReg_64, 2>;
2641  defm _V3 : MIMG_NoSampler_Src_Helper <op, asm, VReg_96, 3>;
2642  defm _V4 : MIMG_NoSampler_Src_Helper <op, asm, VReg_128, 4>;
2643}
2644
2645class MIMG_Sampler_Helper <bits<7> op, string asm,
2646                           RegisterClass dst_rc,
2647                           RegisterClass src_rc, int wqm> : MIMG <
2648  op,
2649  (outs dst_rc:$vdata),
2650  (ins i32imm:$dmask, i1imm:$unorm, i1imm:$glc, i1imm:$da, i1imm:$r128,
2651       i1imm:$tfe, i1imm:$lwe, i1imm:$slc, src_rc:$vaddr,
2652       SReg_256:$srsrc, SReg_128:$ssamp),
2653  asm#" $vdata, $dmask, $unorm, $glc, $da, $r128,"
2654     #" $tfe, $lwe, $slc, $vaddr, $srsrc, $ssamp",
2655  []> {
2656  let mayLoad = 1;
2657  let mayStore = 0;
2658  let hasPostISelHook = 1;
2659  let WQM = wqm;
2660}
2661
2662multiclass MIMG_Sampler_Src_Helper <bits<7> op, string asm,
2663                                    RegisterClass dst_rc,
2664                                    int channels, int wqm> {
2665  def _V1 : MIMG_Sampler_Helper <op, asm, dst_rc, VGPR_32, wqm>,
2666            MIMG_Mask<asm#"_V1", channels>;
2667  def _V2 : MIMG_Sampler_Helper <op, asm, dst_rc, VReg_64, wqm>,
2668            MIMG_Mask<asm#"_V2", channels>;
2669  def _V4 : MIMG_Sampler_Helper <op, asm, dst_rc, VReg_128, wqm>,
2670            MIMG_Mask<asm#"_V4", channels>;
2671  def _V8 : MIMG_Sampler_Helper <op, asm, dst_rc, VReg_256, wqm>,
2672            MIMG_Mask<asm#"_V8", channels>;
2673  def _V16 : MIMG_Sampler_Helper <op, asm, dst_rc, VReg_512, wqm>,
2674            MIMG_Mask<asm#"_V16", channels>;
2675}
2676
2677multiclass MIMG_Sampler <bits<7> op, string asm> {
2678  defm _V1 : MIMG_Sampler_Src_Helper<op, asm, VGPR_32, 1, 0>;
2679  defm _V2 : MIMG_Sampler_Src_Helper<op, asm, VReg_64, 2, 0>;
2680  defm _V3 : MIMG_Sampler_Src_Helper<op, asm, VReg_96, 3, 0>;
2681  defm _V4 : MIMG_Sampler_Src_Helper<op, asm, VReg_128, 4, 0>;
2682}
2683
2684multiclass MIMG_Sampler_WQM <bits<7> op, string asm> {
2685  defm _V1 : MIMG_Sampler_Src_Helper<op, asm, VGPR_32, 1, 1>;
2686  defm _V2 : MIMG_Sampler_Src_Helper<op, asm, VReg_64, 2, 1>;
2687  defm _V3 : MIMG_Sampler_Src_Helper<op, asm, VReg_96, 3, 1>;
2688  defm _V4 : MIMG_Sampler_Src_Helper<op, asm, VReg_128, 4, 1>;
2689}
2690
2691class MIMG_Gather_Helper <bits<7> op, string asm,
2692                          RegisterClass dst_rc,
2693                          RegisterClass src_rc, int wqm> : MIMG <
2694  op,
2695  (outs dst_rc:$vdata),
2696  (ins i32imm:$dmask, i1imm:$unorm, i1imm:$glc, i1imm:$da, i1imm:$r128,
2697       i1imm:$tfe, i1imm:$lwe, i1imm:$slc, src_rc:$vaddr,
2698       SReg_256:$srsrc, SReg_128:$ssamp),
2699  asm#" $vdata, $dmask, $unorm, $glc, $da, $r128,"
2700     #" $tfe, $lwe, $slc, $vaddr, $srsrc, $ssamp",
2701  []> {
2702  let mayLoad = 1;
2703  let mayStore = 0;
2704
2705  // DMASK was repurposed for GATHER4. 4 components are always
2706  // returned and DMASK works like a swizzle - it selects
2707  // the component to fetch. The only useful DMASK values are
2708  // 1=red, 2=green, 4=blue, 8=alpha. (e.g. 1 returns
2709  // (red,red,red,red) etc.) The ISA document doesn't mention
2710  // this.
2711  // Therefore, disable all code which updates DMASK by setting these two:
2712  let MIMG = 0;
2713  let hasPostISelHook = 0;
2714  let WQM = wqm;
2715}
2716
2717multiclass MIMG_Gather_Src_Helper <bits<7> op, string asm,
2718                                    RegisterClass dst_rc,
2719                                    int channels, int wqm> {
2720  def _V1 : MIMG_Gather_Helper <op, asm, dst_rc, VGPR_32, wqm>,
2721            MIMG_Mask<asm#"_V1", channels>;
2722  def _V2 : MIMG_Gather_Helper <op, asm, dst_rc, VReg_64, wqm>,
2723            MIMG_Mask<asm#"_V2", channels>;
2724  def _V4 : MIMG_Gather_Helper <op, asm, dst_rc, VReg_128, wqm>,
2725            MIMG_Mask<asm#"_V4", channels>;
2726  def _V8 : MIMG_Gather_Helper <op, asm, dst_rc, VReg_256, wqm>,
2727            MIMG_Mask<asm#"_V8", channels>;
2728  def _V16 : MIMG_Gather_Helper <op, asm, dst_rc, VReg_512, wqm>,
2729            MIMG_Mask<asm#"_V16", channels>;
2730}
2731
2732multiclass MIMG_Gather <bits<7> op, string asm> {
2733  defm _V1 : MIMG_Gather_Src_Helper<op, asm, VGPR_32, 1, 0>;
2734  defm _V2 : MIMG_Gather_Src_Helper<op, asm, VReg_64, 2, 0>;
2735  defm _V3 : MIMG_Gather_Src_Helper<op, asm, VReg_96, 3, 0>;
2736  defm _V4 : MIMG_Gather_Src_Helper<op, asm, VReg_128, 4, 0>;
2737}
2738
2739multiclass MIMG_Gather_WQM <bits<7> op, string asm> {
2740  defm _V1 : MIMG_Gather_Src_Helper<op, asm, VGPR_32, 1, 1>;
2741  defm _V2 : MIMG_Gather_Src_Helper<op, asm, VReg_64, 2, 1>;
2742  defm _V3 : MIMG_Gather_Src_Helper<op, asm, VReg_96, 3, 1>;
2743  defm _V4 : MIMG_Gather_Src_Helper<op, asm, VReg_128, 4, 1>;
2744}
2745
2746//===----------------------------------------------------------------------===//
2747// Vector instruction mappings
2748//===----------------------------------------------------------------------===//
2749
2750// Maps an opcode in e32 form to its e64 equivalent
2751def getVOPe64 : InstrMapping {
2752  let FilterClass = "VOP";
2753  let RowFields = ["OpName"];
2754  let ColFields = ["Size"];
2755  let KeyCol = ["4"];
2756  let ValueCols = [["8"]];
2757}
2758
2759// Maps an opcode in e64 form to its e32 equivalent
2760def getVOPe32 : InstrMapping {
2761  let FilterClass = "VOP";
2762  let RowFields = ["OpName"];
2763  let ColFields = ["Size"];
2764  let KeyCol = ["8"];
2765  let ValueCols = [["4"]];
2766}
2767
2768def getMaskedMIMGOp : InstrMapping {
2769  let FilterClass = "MIMG_Mask";
2770  let RowFields = ["Op"];
2771  let ColFields = ["Channels"];
2772  let KeyCol = ["4"];
2773  let ValueCols = [["1"], ["2"], ["3"] ];
2774}
2775
2776// Maps an commuted opcode to its original version
2777def getCommuteOrig : InstrMapping {
2778  let FilterClass = "VOP2_REV";
2779  let RowFields = ["RevOp"];
2780  let ColFields = ["IsOrig"];
2781  let KeyCol = ["0"];
2782  let ValueCols = [["1"]];
2783}
2784
2785// Maps an original opcode to its commuted version
2786def getCommuteRev : InstrMapping {
2787  let FilterClass = "VOP2_REV";
2788  let RowFields = ["RevOp"];
2789  let ColFields = ["IsOrig"];
2790  let KeyCol = ["1"];
2791  let ValueCols = [["0"]];
2792}
2793
2794def getCommuteCmpOrig : InstrMapping {
2795  let FilterClass = "VOP2_REV";
2796  let RowFields = ["RevOp"];
2797  let ColFields = ["IsOrig"];
2798  let KeyCol = ["0"];
2799  let ValueCols = [["1"]];
2800}
2801
2802// Maps an original opcode to its commuted version
2803def getCommuteCmpRev : InstrMapping {
2804  let FilterClass = "VOP2_REV";
2805  let RowFields = ["RevOp"];
2806  let ColFields = ["IsOrig"];
2807  let KeyCol = ["1"];
2808  let ValueCols = [["0"]];
2809}
2810
2811
2812def getMCOpcodeGen : InstrMapping {
2813  let FilterClass = "SIMCInstr";
2814  let RowFields = ["PseudoInstr"];
2815  let ColFields = ["Subtarget"];
2816  let KeyCol = [!cast<string>(SISubtarget.NONE)];
2817  let ValueCols = [[!cast<string>(SISubtarget.SI)],[!cast<string>(SISubtarget.VI)]];
2818}
2819
2820def getAddr64Inst : InstrMapping {
2821  let FilterClass = "MUBUFAddr64Table";
2822  let RowFields = ["OpName"];
2823  let ColFields = ["IsAddr64"];
2824  let KeyCol = ["0"];
2825  let ValueCols = [["1"]];
2826}
2827
2828// Maps an atomic opcode to its version with a return value.
2829def getAtomicRetOp : InstrMapping {
2830  let FilterClass = "AtomicNoRet";
2831  let RowFields = ["NoRetOp"];
2832  let ColFields = ["IsRet"];
2833  let KeyCol = ["0"];
2834  let ValueCols = [["1"]];
2835}
2836
2837// Maps an atomic opcode to its returnless version.
2838def getAtomicNoRetOp : InstrMapping {
2839  let FilterClass = "AtomicNoRet";
2840  let RowFields = ["NoRetOp"];
2841  let ColFields = ["IsRet"];
2842  let KeyCol = ["1"];
2843  let ValueCols = [["0"]];
2844}
2845
2846include "SIInstructions.td"
2847include "CIInstructions.td"
2848include "VIInstructions.td"
2849