1//===-- VOPDInstructions.td - Vector Instruction Definitions --------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9//===----------------------------------------------------------------------===//
10// Encodings
11//===----------------------------------------------------------------------===//
12
13class VOPDe<bits<4> opX, bits<5> opY> : Enc64 {
14  bits<9> src0X;
15  bits<8> vsrc1X;
16  bits<8> vdstX;
17  bits<9> src0Y;
18  bits<8> vsrc1Y;
19  bits<8> vdstY;
20
21  let Inst{8-0} = src0X;
22  let Inst{16-9} = vsrc1X;
23  let Inst{21-17} = opY;
24  let Inst{25-22} = opX;
25  let Inst{31-26} = 0x32; // encoding
26  let Inst{40-32} = src0Y;
27  let Inst{48-41} = vsrc1Y;
28  let Inst{55-49} = vdstY{7-1};
29  let Inst{63-56} = vdstX;
30}
31
32class VOPD_MADKe<bits<4> opX, bits<5> opY> : Enc96 {
33  bits<9> src0X;
34  bits<8> vsrc1X;
35  bits<8> vdstX;
36  bits<9> src0Y;
37  bits<8> vsrc1Y;
38  bits<8> vdstY;
39  bits<32> imm;
40
41  let Inst{8-0} = src0X;
42  let Inst{16-9} = vsrc1X;
43  let Inst{21-17} = opY;
44  let Inst{25-22} = opX;
45  let Inst{31-26} = 0x32; // encoding
46  let Inst{40-32} = src0Y;
47  let Inst{48-41} = vsrc1Y;
48  let Inst{55-49} = vdstY{7-1};
49  let Inst{63-56} = vdstX;
50  let Inst{95-64} = imm;
51}
52
53//===----------------------------------------------------------------------===//
54// VOPD classes
55//===----------------------------------------------------------------------===//
56
57class VOPD_Base<dag outs, dag ins, string asm, VOP_Pseudo VDX, VOP_Pseudo VDY,
58                VOPD_Component XasVC, VOPD_Component YasVC>
59    : VOPAnyCommon<outs, ins, asm, []>,
60      VOP<NAME>,
61      SIMCInstr<NAME, SIEncodingFamily.GFX11> {
62  // Fields for table indexing
63  Instruction Opcode = !cast<Instruction>(NAME);
64  bits<5> OpX = XasVC.VOPDOp;
65  bits<5> OpY = YasVC.VOPDOp;
66
67  let VALU = 1;
68
69  let DecoderNamespace = "GFX11";
70  let AssemblerPredicate = isGFX11Plus;
71  let WaveSizePredicate = isWave32;
72  let isCodeGenOnly = 0;
73  let SubtargetPredicate = isGFX11Plus;
74  let AsmMatchConverter  = "cvtVOPD";
75  let Size = 8;
76  let ReadsModeReg = !or(VDX.ReadsModeReg, VDY.ReadsModeReg);
77  let mayRaiseFPException = ReadsModeReg;
78
79  let Uses = RegListUnion<VDX.Uses, VDY.Uses>.ret;
80  let Defs = RegListUnion<VDX.Defs, VDY.Defs>.ret;
81  let SchedRW = !listconcat(VDX.SchedRW, VDY.SchedRW);
82}
83
84class VOPD<dag outs, dag ins, string asm, VOP_Pseudo VDX, VOP_Pseudo VDY,
85           VOPD_Component XasVC, VOPD_Component YasVC>
86    : VOPD_Base<outs, ins, asm, VDX, VDY, XasVC, YasVC>,
87      VOPDe<XasVC.VOPDOp{3-0}, YasVC.VOPDOp> {
88  let Inst{16-9} = !if (!eq(VDX.Mnemonic, "v_mov_b32"), 0x0, vsrc1X);
89  let Inst{48-41} = !if (!eq(VDY.Mnemonic, "v_mov_b32"), 0x0, vsrc1Y);
90}
91
92class VOPD_MADK<dag outs, dag ins, string asm, VOP_Pseudo VDX, VOP_Pseudo VDY,
93                VOPD_Component XasVC, VOPD_Component YasVC>
94    : VOPD_Base<outs, ins, asm, VDX, VDY, XasVC, YasVC>,
95      VOPD_MADKe<XasVC.VOPDOp{3-0}, YasVC.VOPDOp> {
96  let Inst{16-9} = !if (!eq(VDX.Mnemonic, "v_mov_b32"), 0x0, vsrc1X);
97  let Inst{48-41} = !if (!eq(VDY.Mnemonic, "v_mov_b32"), 0x0, vsrc1Y);
98  let Size = 12;
99}
100
101// V_DUAL_DOT2ACC_F32_BF16 is a legal instruction, but V_DOT2ACC_F32_BF16 is
102// not. Since we generate the DUAL form by converting from the normal form we
103// will never generate it.
104defvar VOPDYPseudos = [
105  "V_FMAC_F32_e32", "V_FMAAK_F32", "V_FMAMK_F32", "V_MUL_F32_e32",
106  "V_ADD_F32_e32", "V_SUB_F32_e32", "V_SUBREV_F32_e32", "V_MUL_LEGACY_F32_e32",
107  "V_MOV_B32_e32", "V_CNDMASK_B32_e32", "V_MAX_F32_e32", "V_MIN_F32_e32",
108  "V_DOT2C_F32_F16_e32", "V_ADD_U32_e32", "V_LSHLREV_B32_e32", "V_AND_B32_e32"
109];
110defvar VOPDXPseudos = VOPDYPseudos[0...VOPDX_Max_Index];
111
112def VOPDDstYOperand : RegisterOperand<VGPR_32, "printRegularOperand"> {
113  let DecoderMethod = "decodeOperandVOPDDstY";
114}
115
116foreach x = VOPDXPseudos in {
117  foreach y = VOPDYPseudos in {
118    defvar xInst = !cast<VOP_Pseudo>(x);
119    defvar yInst = !cast<VOP_Pseudo>(y);
120    defvar XasVC = !cast<VOPD_Component>(x);
121    defvar YasVC = !cast<VOPD_Component>(y);
122    defvar isMADK = !or(!eq(x, "V_FMAAK_F32"), !eq(x, "V_FMAMK_F32"),
123                        !eq(y, "V_FMAAK_F32"), !eq(y, "V_FMAMK_F32"));
124    // If X or Y is MADK (have a mandatory immediate), all src operands which
125    // may contain an optional literal must use the VSrc_*_Deferred operand
126    // type. Optional literal operands in MADK VOPD components always use this
127    // operand form. If Both X and Y are MADK, the mandatory literal of X
128    // additionally must use an alternate operand format which defers to the
129    // 'real' Y literal
130    defvar isOpXMADK = !or(!eq(x, "V_FMAAK_F32"), !eq(x, "V_FMAMK_F32"));
131    defvar isOpYMADK = !or(!eq(y, "V_FMAAK_F32"), !eq(y, "V_FMAMK_F32"));
132    defvar OpName = "V_DUAL_" # !substr(x,2) # "_X_" # !substr(y,2);
133    defvar outs = (outs VGPRSrc_32:$vdstX, VOPDDstYOperand:$vdstY);
134    if !or(isOpXMADK, isOpYMADK) then {
135      if !and(isOpXMADK, isOpYMADK) then {
136        defvar X_MADK_Pfl = !cast<VOP_MADK_Base>(xInst.Pfl);
137        defvar ins = !con(xInst.Pfl.InsVOPDXDeferred, yInst.Pfl.InsVOPDY);
138        defvar asm = XasVC.VOPDName #" "# X_MADK_Pfl.AsmVOPDXDeferred #" :: "# YasVC.VOPDName #" "# yInst.Pfl.AsmVOPDY;
139        def OpName : VOPD_MADK<outs, ins, asm, xInst, yInst, XasVC, YasVC>;
140      } else {
141        defvar asm = XasVC.VOPDName #" "# xInst.Pfl.AsmVOPDX #" :: "# YasVC.VOPDName #" "# yInst.Pfl.AsmVOPDY;
142        if isOpXMADK then {
143          assert !not(isOpYMADK), "Expected only OpX as MADK";
144          defvar ins = !con(xInst.Pfl.InsVOPDX, yInst.Pfl.InsVOPDYDeferred);
145          def OpName : VOPD_MADK<outs, ins, asm, xInst, yInst, XasVC, YasVC>;
146        } else {
147          assert !not(isOpXMADK), "Expected only OpY as MADK";
148          defvar ins = !con(xInst.Pfl.InsVOPDXDeferred, yInst.Pfl.InsVOPDY);
149          def OpName : VOPD_MADK<outs, ins, asm, xInst, yInst, XasVC, YasVC>;
150        }
151      }
152    } else {
153      defvar ins = !con(xInst.Pfl.InsVOPDX, yInst.Pfl.InsVOPDY);
154      defvar asm = XasVC.VOPDName #" "# xInst.Pfl.AsmVOPDX #" :: "# YasVC.VOPDName #" "# yInst.Pfl.AsmVOPDY;
155      def OpName : VOPD<outs, ins, asm, xInst, yInst, XasVC, YasVC>;
156    }
157  }
158}
159
160