xref: /minix3/external/bsd/llvm/dist/llvm/lib/Target/X86/X86InstrFMA.td (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc//===-- X86InstrFMA.td - FMA Instruction Set ---------------*- tablegen -*-===//
2f4a2713aSLionel Sambuc//
3f4a2713aSLionel Sambuc//                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc//
5f4a2713aSLionel Sambuc// This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc// License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc//
8f4a2713aSLionel Sambuc//===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc//
10f4a2713aSLionel Sambuc// This file describes FMA (Fused Multiply-Add) instructions.
11f4a2713aSLionel Sambuc//
12f4a2713aSLionel Sambuc//===----------------------------------------------------------------------===//
13f4a2713aSLionel Sambuc
14f4a2713aSLionel Sambuc//===----------------------------------------------------------------------===//
15f4a2713aSLionel Sambuc// FMA3 - Intel 3 operand Fused Multiply-Add instructions
16f4a2713aSLionel Sambuc//===----------------------------------------------------------------------===//
17f4a2713aSLionel Sambuc
18f4a2713aSLionel Sambuclet Constraints = "$src1 = $dst" in {
19f4a2713aSLionel Sambucmulticlass fma3p_rm<bits<8> opc, string OpcodeStr,
20f4a2713aSLionel Sambuc                    PatFrag MemFrag128, PatFrag MemFrag256,
21f4a2713aSLionel Sambuc                    ValueType OpVT128, ValueType OpVT256,
22*0a6a1f1dSLionel Sambuc                    bit IsRVariantCommutable = 0, bit IsMVariantCommutable = 0,
23f4a2713aSLionel Sambuc                    SDPatternOperator Op = null_frag> {
24*0a6a1f1dSLionel Sambuc  let usesCustomInserter = 1, isCommutable = IsRVariantCommutable in
25f4a2713aSLionel Sambuc  def r     : FMA3<opc, MRMSrcReg, (outs VR128:$dst),
26f4a2713aSLionel Sambuc                   (ins VR128:$src1, VR128:$src2, VR128:$src3),
27f4a2713aSLionel Sambuc                   !strconcat(OpcodeStr,
28f4a2713aSLionel Sambuc                              "\t{$src3, $src2, $dst|$dst, $src2, $src3}"),
29f4a2713aSLionel Sambuc                   [(set VR128:$dst, (OpVT128 (Op VR128:$src2,
30f4a2713aSLionel Sambuc                                               VR128:$src1, VR128:$src3)))]>;
31f4a2713aSLionel Sambuc
32*0a6a1f1dSLionel Sambuc  let mayLoad = 1, isCommutable = IsMVariantCommutable in
33f4a2713aSLionel Sambuc  def m     : FMA3<opc, MRMSrcMem, (outs VR128:$dst),
34f4a2713aSLionel Sambuc                   (ins VR128:$src1, VR128:$src2, f128mem:$src3),
35f4a2713aSLionel Sambuc                   !strconcat(OpcodeStr,
36f4a2713aSLionel Sambuc                              "\t{$src3, $src2, $dst|$dst, $src2, $src3}"),
37f4a2713aSLionel Sambuc                   [(set VR128:$dst, (OpVT128 (Op VR128:$src2, VR128:$src1,
38f4a2713aSLionel Sambuc                                               (MemFrag128 addr:$src3))))]>;
39f4a2713aSLionel Sambuc
40*0a6a1f1dSLionel Sambuc  let usesCustomInserter = 1, isCommutable = IsRVariantCommutable in
41f4a2713aSLionel Sambuc  def rY    : FMA3<opc, MRMSrcReg, (outs VR256:$dst),
42f4a2713aSLionel Sambuc                   (ins VR256:$src1, VR256:$src2, VR256:$src3),
43f4a2713aSLionel Sambuc                   !strconcat(OpcodeStr,
44f4a2713aSLionel Sambuc                              "\t{$src3, $src2, $dst|$dst, $src2, $src3}"),
45f4a2713aSLionel Sambuc                   [(set VR256:$dst, (OpVT256 (Op VR256:$src2, VR256:$src1,
46f4a2713aSLionel Sambuc                                               VR256:$src3)))]>, VEX_L;
47f4a2713aSLionel Sambuc
48*0a6a1f1dSLionel Sambuc  let mayLoad = 1, isCommutable = IsMVariantCommutable in
49f4a2713aSLionel Sambuc  def mY    : FMA3<opc, MRMSrcMem, (outs VR256:$dst),
50f4a2713aSLionel Sambuc                   (ins VR256:$src1, VR256:$src2, f256mem:$src3),
51f4a2713aSLionel Sambuc                   !strconcat(OpcodeStr,
52f4a2713aSLionel Sambuc                              "\t{$src3, $src2, $dst|$dst, $src2, $src3}"),
53f4a2713aSLionel Sambuc                   [(set VR256:$dst,
54f4a2713aSLionel Sambuc                     (OpVT256 (Op VR256:$src2, VR256:$src1,
55f4a2713aSLionel Sambuc                               (MemFrag256 addr:$src3))))]>, VEX_L;
56f4a2713aSLionel Sambuc}
57f4a2713aSLionel Sambuc} // Constraints = "$src1 = $dst"
58f4a2713aSLionel Sambuc
59f4a2713aSLionel Sambucmulticlass fma3p_forms<bits<8> opc132, bits<8> opc213, bits<8> opc231,
60f4a2713aSLionel Sambuc                       string OpcodeStr, string PackTy,
61f4a2713aSLionel Sambuc                       PatFrag MemFrag128, PatFrag MemFrag256,
62f4a2713aSLionel Sambuc                       SDNode Op, ValueType OpTy128, ValueType OpTy256> {
63*0a6a1f1dSLionel Sambuc  // For 213, both the register and memory variant are commutable.
64*0a6a1f1dSLionel Sambuc  // Indeed, the commutable operands are 1 and 2 and both live in registers
65*0a6a1f1dSLionel Sambuc  // for both variants.
66f4a2713aSLionel Sambuc  defm r213 : fma3p_rm<opc213,
67f4a2713aSLionel Sambuc                       !strconcat(OpcodeStr, "213", PackTy),
68*0a6a1f1dSLionel Sambuc                       MemFrag128, MemFrag256, OpTy128, OpTy256,
69*0a6a1f1dSLionel Sambuc                       /* IsRVariantCommutable */ 1,
70*0a6a1f1dSLionel Sambuc                       /* IsMVariantCommutable */ 1,
71*0a6a1f1dSLionel Sambuc                       Op>;
72*0a6a1f1dSLionel Sambuclet hasSideEffects = 0 in {
73f4a2713aSLionel Sambuc  defm r132 : fma3p_rm<opc132,
74f4a2713aSLionel Sambuc                       !strconcat(OpcodeStr, "132", PackTy),
75f4a2713aSLionel Sambuc                       MemFrag128, MemFrag256, OpTy128, OpTy256>;
76*0a6a1f1dSLionel Sambuc  // For 231, only the register variant is commutable.
77*0a6a1f1dSLionel Sambuc  // For the memory variant the folded operand must be in 3. Thus,
78*0a6a1f1dSLionel Sambuc  // in that case, it cannot be swapped with 2.
79f4a2713aSLionel Sambuc  defm r231 : fma3p_rm<opc231,
80f4a2713aSLionel Sambuc                       !strconcat(OpcodeStr, "231", PackTy),
81*0a6a1f1dSLionel Sambuc                       MemFrag128, MemFrag256, OpTy128, OpTy256,
82*0a6a1f1dSLionel Sambuc                       /* IsRVariantCommutable */ 1,
83*0a6a1f1dSLionel Sambuc                       /* IsMVariantCommutable */ 0>;
84*0a6a1f1dSLionel Sambuc} // hasSideEffects = 0
85f4a2713aSLionel Sambuc}
86f4a2713aSLionel Sambuc
87f4a2713aSLionel Sambuc// Fused Multiply-Add
88f4a2713aSLionel Sambuclet ExeDomain = SSEPackedSingle in {
89f4a2713aSLionel Sambuc  defm VFMADDPS    : fma3p_forms<0x98, 0xA8, 0xB8, "vfmadd", "ps", loadv4f32,
90f4a2713aSLionel Sambuc                                 loadv8f32, X86Fmadd, v4f32, v8f32>;
91f4a2713aSLionel Sambuc  defm VFMSUBPS    : fma3p_forms<0x9A, 0xAA, 0xBA, "vfmsub", "ps", loadv4f32,
92f4a2713aSLionel Sambuc                                 loadv8f32, X86Fmsub, v4f32, v8f32>;
93f4a2713aSLionel Sambuc  defm VFMADDSUBPS : fma3p_forms<0x96, 0xA6, 0xB6, "vfmaddsub", "ps",
94f4a2713aSLionel Sambuc                                 loadv4f32, loadv8f32, X86Fmaddsub,
95f4a2713aSLionel Sambuc                                 v4f32, v8f32>;
96f4a2713aSLionel Sambuc  defm VFMSUBADDPS : fma3p_forms<0x97, 0xA7, 0xB7, "vfmsubadd", "ps",
97f4a2713aSLionel Sambuc                                 loadv4f32, loadv8f32, X86Fmsubadd,
98f4a2713aSLionel Sambuc                                 v4f32, v8f32>;
99f4a2713aSLionel Sambuc}
100f4a2713aSLionel Sambuc
101f4a2713aSLionel Sambuclet ExeDomain = SSEPackedDouble in {
102f4a2713aSLionel Sambuc  defm VFMADDPD    : fma3p_forms<0x98, 0xA8, 0xB8, "vfmadd", "pd", loadv2f64,
103f4a2713aSLionel Sambuc                                 loadv4f64, X86Fmadd, v2f64, v4f64>, VEX_W;
104f4a2713aSLionel Sambuc  defm VFMSUBPD    : fma3p_forms<0x9A, 0xAA, 0xBA, "vfmsub", "pd", loadv2f64,
105f4a2713aSLionel Sambuc                                 loadv4f64, X86Fmsub, v2f64, v4f64>, VEX_W;
106f4a2713aSLionel Sambuc  defm VFMADDSUBPD : fma3p_forms<0x96, 0xA6, 0xB6, "vfmaddsub", "pd",
107f4a2713aSLionel Sambuc                                 loadv2f64, loadv4f64, X86Fmaddsub,
108f4a2713aSLionel Sambuc                                 v2f64, v4f64>, VEX_W;
109f4a2713aSLionel Sambuc  defm VFMSUBADDPD : fma3p_forms<0x97, 0xA7, 0xB7, "vfmsubadd", "pd",
110f4a2713aSLionel Sambuc                                 loadv2f64, loadv4f64, X86Fmsubadd,
111f4a2713aSLionel Sambuc                                 v2f64, v4f64>, VEX_W;
112f4a2713aSLionel Sambuc}
113f4a2713aSLionel Sambuc
114f4a2713aSLionel Sambuc// Fused Negative Multiply-Add
115f4a2713aSLionel Sambuclet ExeDomain = SSEPackedSingle in {
116f4a2713aSLionel Sambuc  defm VFNMADDPS : fma3p_forms<0x9C, 0xAC, 0xBC, "vfnmadd", "ps",  loadv4f32,
117f4a2713aSLionel Sambuc                               loadv8f32, X86Fnmadd, v4f32, v8f32>;
118f4a2713aSLionel Sambuc  defm VFNMSUBPS : fma3p_forms<0x9E, 0xAE, 0xBE, "vfnmsub", "ps",  loadv4f32,
119f4a2713aSLionel Sambuc                               loadv8f32, X86Fnmsub, v4f32, v8f32>;
120f4a2713aSLionel Sambuc}
121f4a2713aSLionel Sambuclet ExeDomain = SSEPackedDouble in {
122f4a2713aSLionel Sambuc  defm VFNMADDPD : fma3p_forms<0x9C, 0xAC, 0xBC, "vfnmadd", "pd", loadv2f64,
123f4a2713aSLionel Sambuc                               loadv4f64, X86Fnmadd, v2f64, v4f64>, VEX_W;
124f4a2713aSLionel Sambuc  defm VFNMSUBPD : fma3p_forms<0x9E, 0xAE, 0xBE, "vfnmsub", "pd",
125f4a2713aSLionel Sambuc                               loadv2f64, loadv4f64, X86Fnmsub, v2f64,
126f4a2713aSLionel Sambuc                               v4f64>, VEX_W;
127f4a2713aSLionel Sambuc}
128f4a2713aSLionel Sambuc
129f4a2713aSLionel Sambuclet Constraints = "$src1 = $dst" in {
130f4a2713aSLionel Sambucmulticlass fma3s_rm<bits<8> opc, string OpcodeStr, X86MemOperand x86memop,
131f4a2713aSLionel Sambuc                    RegisterClass RC, ValueType OpVT, PatFrag mem_frag,
132*0a6a1f1dSLionel Sambuc                    bit IsRVariantCommutable = 0, bit IsMVariantCommutable = 0,
133f4a2713aSLionel Sambuc                    SDPatternOperator OpNode = null_frag> {
134*0a6a1f1dSLionel Sambuc  let usesCustomInserter = 1, isCommutable = IsRVariantCommutable in
135f4a2713aSLionel Sambuc  def r     : FMA3<opc, MRMSrcReg, (outs RC:$dst),
136f4a2713aSLionel Sambuc                   (ins RC:$src1, RC:$src2, RC:$src3),
137f4a2713aSLionel Sambuc                   !strconcat(OpcodeStr,
138f4a2713aSLionel Sambuc                              "\t{$src3, $src2, $dst|$dst, $src2, $src3}"),
139f4a2713aSLionel Sambuc                   [(set RC:$dst,
140f4a2713aSLionel Sambuc                     (OpVT (OpNode RC:$src2, RC:$src1, RC:$src3)))]>;
141*0a6a1f1dSLionel Sambuc
142*0a6a1f1dSLionel Sambuc  let mayLoad = 1, isCommutable = IsMVariantCommutable in
143f4a2713aSLionel Sambuc  def m     : FMA3<opc, MRMSrcMem, (outs RC:$dst),
144f4a2713aSLionel Sambuc                   (ins RC:$src1, RC:$src2, x86memop:$src3),
145f4a2713aSLionel Sambuc                   !strconcat(OpcodeStr,
146f4a2713aSLionel Sambuc                              "\t{$src3, $src2, $dst|$dst, $src2, $src3}"),
147f4a2713aSLionel Sambuc                   [(set RC:$dst,
148f4a2713aSLionel Sambuc                     (OpVT (OpNode RC:$src2, RC:$src1,
149f4a2713aSLionel Sambuc                            (mem_frag addr:$src3))))]>;
150f4a2713aSLionel Sambuc}
151f4a2713aSLionel Sambuc} // Constraints = "$src1 = $dst"
152f4a2713aSLionel Sambuc
153f4a2713aSLionel Sambucmulticlass fma3s_forms<bits<8> opc132, bits<8> opc213, bits<8> opc231,
154*0a6a1f1dSLionel Sambuc                       string OpStr, string PackTy, string PT2, Intrinsic Int,
155f4a2713aSLionel Sambuc                       SDNode OpNode, RegisterClass RC, ValueType OpVT,
156f4a2713aSLionel Sambuc                       X86MemOperand x86memop, Operand memop, PatFrag mem_frag,
157f4a2713aSLionel Sambuc                       ComplexPattern mem_cpat> {
158*0a6a1f1dSLionel Sambuclet hasSideEffects = 0 in {
159f4a2713aSLionel Sambuc  defm r132 : fma3s_rm<opc132, !strconcat(OpStr, "132", PackTy),
160f4a2713aSLionel Sambuc                       x86memop, RC, OpVT, mem_frag>;
161*0a6a1f1dSLionel Sambuc  // See the other defm of r231 for the explanation regarding the
162*0a6a1f1dSLionel Sambuc  // commutable flags.
163f4a2713aSLionel Sambuc  defm r231 : fma3s_rm<opc231, !strconcat(OpStr, "231", PackTy),
164*0a6a1f1dSLionel Sambuc                       x86memop, RC, OpVT, mem_frag,
165*0a6a1f1dSLionel Sambuc                       /* IsRVariantCommutable */ 1,
166*0a6a1f1dSLionel Sambuc                       /* IsMVariantCommutable */ 0>;
167f4a2713aSLionel Sambuc}
168f4a2713aSLionel Sambuc
169*0a6a1f1dSLionel Sambuc// See the other defm of r213 for the explanation regarding the
170*0a6a1f1dSLionel Sambuc// commutable flags.
171f4a2713aSLionel Sambucdefm r213 : fma3s_rm<opc213, !strconcat(OpStr, "213", PackTy),
172*0a6a1f1dSLionel Sambuc                     x86memop, RC, OpVT, mem_frag,
173*0a6a1f1dSLionel Sambuc                     /* IsRVariantCommutable */ 1,
174*0a6a1f1dSLionel Sambuc                     /* IsMVariantCommutable */ 1,
175*0a6a1f1dSLionel Sambuc                     OpNode>;
176f4a2713aSLionel Sambuc}
177f4a2713aSLionel Sambuc
178f4a2713aSLionel Sambucmulticlass fma3s<bits<8> opc132, bits<8> opc213, bits<8> opc231,
179f4a2713aSLionel Sambuc                 string OpStr, Intrinsic IntF32, Intrinsic IntF64,
180f4a2713aSLionel Sambuc                 SDNode OpNode> {
181*0a6a1f1dSLionel Sambuc  defm SS : fma3s_forms<opc132, opc213, opc231, OpStr, "ss", "SS", IntF32, OpNode,
182f4a2713aSLionel Sambuc                        FR32, f32, f32mem, ssmem, loadf32, sse_load_f32>;
183*0a6a1f1dSLionel Sambuc  defm SD : fma3s_forms<opc132, opc213, opc231, OpStr, "sd", "PD", IntF64, OpNode,
184f4a2713aSLionel Sambuc                        FR64, f64, f64mem, sdmem, loadf64, sse_load_f64>, VEX_W;
185*0a6a1f1dSLionel Sambuc
186*0a6a1f1dSLionel Sambuc  def : Pat<(IntF32 VR128:$src1, VR128:$src2, VR128:$src3),
187*0a6a1f1dSLionel Sambuc            (COPY_TO_REGCLASS
188*0a6a1f1dSLionel Sambuc              (!cast<Instruction>(NAME#"SSr213r")
189*0a6a1f1dSLionel Sambuc                (COPY_TO_REGCLASS $src2, FR32),
190*0a6a1f1dSLionel Sambuc                (COPY_TO_REGCLASS $src1, FR32),
191*0a6a1f1dSLionel Sambuc                (COPY_TO_REGCLASS $src3, FR32)),
192*0a6a1f1dSLionel Sambuc              VR128)>;
193*0a6a1f1dSLionel Sambuc
194*0a6a1f1dSLionel Sambuc  def : Pat<(IntF64 VR128:$src1, VR128:$src2, VR128:$src3),
195*0a6a1f1dSLionel Sambuc            (COPY_TO_REGCLASS
196*0a6a1f1dSLionel Sambuc              (!cast<Instruction>(NAME#"SDr213r")
197*0a6a1f1dSLionel Sambuc                (COPY_TO_REGCLASS $src2, FR64),
198*0a6a1f1dSLionel Sambuc                (COPY_TO_REGCLASS $src1, FR64),
199*0a6a1f1dSLionel Sambuc                (COPY_TO_REGCLASS $src3, FR64)),
200*0a6a1f1dSLionel Sambuc              VR128)>;
201f4a2713aSLionel Sambuc}
202f4a2713aSLionel Sambuc
203f4a2713aSLionel Sambucdefm VFMADD : fma3s<0x99, 0xA9, 0xB9, "vfmadd", int_x86_fma_vfmadd_ss,
204f4a2713aSLionel Sambuc                    int_x86_fma_vfmadd_sd, X86Fmadd>, VEX_LIG;
205f4a2713aSLionel Sambucdefm VFMSUB : fma3s<0x9B, 0xAB, 0xBB, "vfmsub", int_x86_fma_vfmsub_ss,
206f4a2713aSLionel Sambuc                    int_x86_fma_vfmsub_sd, X86Fmsub>, VEX_LIG;
207f4a2713aSLionel Sambuc
208f4a2713aSLionel Sambucdefm VFNMADD : fma3s<0x9D, 0xAD, 0xBD, "vfnmadd", int_x86_fma_vfnmadd_ss,
209f4a2713aSLionel Sambuc                     int_x86_fma_vfnmadd_sd, X86Fnmadd>, VEX_LIG;
210f4a2713aSLionel Sambucdefm VFNMSUB : fma3s<0x9F, 0xAF, 0xBF, "vfnmsub", int_x86_fma_vfnmsub_ss,
211f4a2713aSLionel Sambuc                     int_x86_fma_vfnmsub_sd, X86Fnmsub>, VEX_LIG;
212f4a2713aSLionel Sambuc
213f4a2713aSLionel Sambuc
214f4a2713aSLionel Sambuc//===----------------------------------------------------------------------===//
215f4a2713aSLionel Sambuc// FMA4 - AMD 4 operand Fused Multiply-Add instructions
216f4a2713aSLionel Sambuc//===----------------------------------------------------------------------===//
217f4a2713aSLionel Sambuc
218f4a2713aSLionel Sambuc
219f4a2713aSLionel Sambucmulticlass fma4s<bits<8> opc, string OpcodeStr, RegisterClass RC,
220f4a2713aSLionel Sambuc                 X86MemOperand x86memop, ValueType OpVT, SDNode OpNode,
221f4a2713aSLionel Sambuc                 PatFrag mem_frag> {
222f4a2713aSLionel Sambuc  let isCommutable = 1 in
223f4a2713aSLionel Sambuc  def rr : FMA4<opc, MRMSrcReg, (outs RC:$dst),
224f4a2713aSLionel Sambuc           (ins RC:$src1, RC:$src2, RC:$src3),
225f4a2713aSLionel Sambuc           !strconcat(OpcodeStr,
226f4a2713aSLionel Sambuc           "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
227f4a2713aSLionel Sambuc           [(set RC:$dst,
228f4a2713aSLionel Sambuc             (OpVT (OpNode RC:$src1, RC:$src2, RC:$src3)))]>, VEX_W, VEX_LIG, MemOp4;
229f4a2713aSLionel Sambuc  def rm : FMA4<opc, MRMSrcMem, (outs RC:$dst),
230f4a2713aSLionel Sambuc           (ins RC:$src1, RC:$src2, x86memop:$src3),
231f4a2713aSLionel Sambuc           !strconcat(OpcodeStr,
232f4a2713aSLionel Sambuc           "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
233f4a2713aSLionel Sambuc           [(set RC:$dst, (OpNode RC:$src1, RC:$src2,
234f4a2713aSLionel Sambuc                           (mem_frag addr:$src3)))]>, VEX_W, VEX_LIG, MemOp4;
235f4a2713aSLionel Sambuc  def mr : FMA4<opc, MRMSrcMem, (outs RC:$dst),
236f4a2713aSLionel Sambuc           (ins RC:$src1, x86memop:$src2, RC:$src3),
237f4a2713aSLionel Sambuc           !strconcat(OpcodeStr,
238f4a2713aSLionel Sambuc           "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
239f4a2713aSLionel Sambuc           [(set RC:$dst,
240f4a2713aSLionel Sambuc             (OpNode RC:$src1, (mem_frag addr:$src2), RC:$src3))]>, VEX_LIG;
241f4a2713aSLionel Sambuc// For disassembler
242*0a6a1f1dSLionel Sambuclet isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in
243f4a2713aSLionel Sambuc  def rr_REV : FMA4<opc, MRMSrcReg, (outs RC:$dst),
244f4a2713aSLionel Sambuc               (ins RC:$src1, RC:$src2, RC:$src3),
245f4a2713aSLionel Sambuc               !strconcat(OpcodeStr,
246f4a2713aSLionel Sambuc               "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"), []>,
247f4a2713aSLionel Sambuc               VEX_LIG;
248f4a2713aSLionel Sambuc}
249f4a2713aSLionel Sambuc
250f4a2713aSLionel Sambucmulticlass fma4s_int<bits<8> opc, string OpcodeStr, Operand memop,
251f4a2713aSLionel Sambuc                     ComplexPattern mem_cpat, Intrinsic Int> {
252*0a6a1f1dSLionel Sambuclet isCodeGenOnly = 1 in {
253f4a2713aSLionel Sambuc  let isCommutable = 1 in
254f4a2713aSLionel Sambuc  def rr_Int : FMA4<opc, MRMSrcReg, (outs VR128:$dst),
255f4a2713aSLionel Sambuc               (ins VR128:$src1, VR128:$src2, VR128:$src3),
256f4a2713aSLionel Sambuc               !strconcat(OpcodeStr,
257f4a2713aSLionel Sambuc               "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
258f4a2713aSLionel Sambuc               [(set VR128:$dst,
259f4a2713aSLionel Sambuc                 (Int VR128:$src1, VR128:$src2, VR128:$src3))]>, VEX_W, VEX_LIG, MemOp4;
260f4a2713aSLionel Sambuc  def rm_Int : FMA4<opc, MRMSrcMem, (outs VR128:$dst),
261f4a2713aSLionel Sambuc               (ins VR128:$src1, VR128:$src2, memop:$src3),
262f4a2713aSLionel Sambuc               !strconcat(OpcodeStr,
263f4a2713aSLionel Sambuc               "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
264f4a2713aSLionel Sambuc               [(set VR128:$dst, (Int VR128:$src1, VR128:$src2,
265f4a2713aSLionel Sambuc                                  mem_cpat:$src3))]>, VEX_W, VEX_LIG, MemOp4;
266f4a2713aSLionel Sambuc  def mr_Int : FMA4<opc, MRMSrcMem, (outs VR128:$dst),
267f4a2713aSLionel Sambuc               (ins VR128:$src1, memop:$src2, VR128:$src3),
268f4a2713aSLionel Sambuc               !strconcat(OpcodeStr,
269f4a2713aSLionel Sambuc               "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
270f4a2713aSLionel Sambuc               [(set VR128:$dst,
271f4a2713aSLionel Sambuc                 (Int VR128:$src1, mem_cpat:$src2, VR128:$src3))]>, VEX_LIG;
272*0a6a1f1dSLionel Sambuc} // isCodeGenOnly = 1
273f4a2713aSLionel Sambuc}
274f4a2713aSLionel Sambuc
275f4a2713aSLionel Sambucmulticlass fma4p<bits<8> opc, string OpcodeStr, SDNode OpNode,
276f4a2713aSLionel Sambuc                 ValueType OpVT128, ValueType OpVT256,
277f4a2713aSLionel Sambuc                 PatFrag ld_frag128, PatFrag ld_frag256> {
278f4a2713aSLionel Sambuc  let isCommutable = 1 in
279f4a2713aSLionel Sambuc  def rr : FMA4<opc, MRMSrcReg, (outs VR128:$dst),
280f4a2713aSLionel Sambuc           (ins VR128:$src1, VR128:$src2, VR128:$src3),
281f4a2713aSLionel Sambuc           !strconcat(OpcodeStr,
282f4a2713aSLionel Sambuc           "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
283f4a2713aSLionel Sambuc           [(set VR128:$dst,
284f4a2713aSLionel Sambuc             (OpVT128 (OpNode VR128:$src1, VR128:$src2, VR128:$src3)))]>,
285f4a2713aSLionel Sambuc           VEX_W, MemOp4;
286f4a2713aSLionel Sambuc  def rm : FMA4<opc, MRMSrcMem, (outs VR128:$dst),
287f4a2713aSLionel Sambuc           (ins VR128:$src1, VR128:$src2, f128mem:$src3),
288f4a2713aSLionel Sambuc           !strconcat(OpcodeStr,
289f4a2713aSLionel Sambuc           "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
290f4a2713aSLionel Sambuc           [(set VR128:$dst, (OpNode VR128:$src1, VR128:$src2,
291f4a2713aSLionel Sambuc                              (ld_frag128 addr:$src3)))]>, VEX_W, MemOp4;
292f4a2713aSLionel Sambuc  def mr : FMA4<opc, MRMSrcMem, (outs VR128:$dst),
293f4a2713aSLionel Sambuc           (ins VR128:$src1, f128mem:$src2, VR128:$src3),
294f4a2713aSLionel Sambuc           !strconcat(OpcodeStr,
295f4a2713aSLionel Sambuc           "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
296f4a2713aSLionel Sambuc           [(set VR128:$dst,
297f4a2713aSLionel Sambuc             (OpNode VR128:$src1, (ld_frag128 addr:$src2), VR128:$src3))]>;
298f4a2713aSLionel Sambuc  let isCommutable = 1 in
299f4a2713aSLionel Sambuc  def rrY : FMA4<opc, MRMSrcReg, (outs VR256:$dst),
300f4a2713aSLionel Sambuc           (ins VR256:$src1, VR256:$src2, VR256:$src3),
301f4a2713aSLionel Sambuc           !strconcat(OpcodeStr,
302f4a2713aSLionel Sambuc           "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
303f4a2713aSLionel Sambuc           [(set VR256:$dst,
304f4a2713aSLionel Sambuc             (OpVT256 (OpNode VR256:$src1, VR256:$src2, VR256:$src3)))]>,
305f4a2713aSLionel Sambuc           VEX_W, MemOp4, VEX_L;
306f4a2713aSLionel Sambuc  def rmY : FMA4<opc, MRMSrcMem, (outs VR256:$dst),
307f4a2713aSLionel Sambuc           (ins VR256:$src1, VR256:$src2, f256mem:$src3),
308f4a2713aSLionel Sambuc           !strconcat(OpcodeStr,
309f4a2713aSLionel Sambuc           "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
310f4a2713aSLionel Sambuc           [(set VR256:$dst, (OpNode VR256:$src1, VR256:$src2,
311f4a2713aSLionel Sambuc                              (ld_frag256 addr:$src3)))]>, VEX_W, MemOp4, VEX_L;
312f4a2713aSLionel Sambuc  def mrY : FMA4<opc, MRMSrcMem, (outs VR256:$dst),
313f4a2713aSLionel Sambuc           (ins VR256:$src1, f256mem:$src2, VR256:$src3),
314f4a2713aSLionel Sambuc           !strconcat(OpcodeStr,
315f4a2713aSLionel Sambuc           "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
316f4a2713aSLionel Sambuc           [(set VR256:$dst, (OpNode VR256:$src1,
317f4a2713aSLionel Sambuc                              (ld_frag256 addr:$src2), VR256:$src3))]>, VEX_L;
318f4a2713aSLionel Sambuc// For disassembler
319*0a6a1f1dSLionel Sambuclet isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in {
320f4a2713aSLionel Sambuc  def rr_REV : FMA4<opc, MRMSrcReg, (outs VR128:$dst),
321f4a2713aSLionel Sambuc               (ins VR128:$src1, VR128:$src2, VR128:$src3),
322f4a2713aSLionel Sambuc               !strconcat(OpcodeStr,
323f4a2713aSLionel Sambuc               "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"), []>;
324f4a2713aSLionel Sambuc  def rrY_REV : FMA4<opc, MRMSrcReg, (outs VR256:$dst),
325f4a2713aSLionel Sambuc                (ins VR256:$src1, VR256:$src2, VR256:$src3),
326f4a2713aSLionel Sambuc                !strconcat(OpcodeStr,
327f4a2713aSLionel Sambuc                "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"), []>,
328f4a2713aSLionel Sambuc                VEX_L;
329f4a2713aSLionel Sambuc} // isCodeGenOnly = 1
330f4a2713aSLionel Sambuc}
331f4a2713aSLionel Sambuc
332f4a2713aSLionel Sambucdefm VFMADDSS4  : fma4s<0x6A, "vfmaddss", FR32, f32mem, f32, X86Fmadd, loadf32>,
333f4a2713aSLionel Sambuc                  fma4s_int<0x6A, "vfmaddss", ssmem, sse_load_f32,
334f4a2713aSLionel Sambuc                            int_x86_fma_vfmadd_ss>;
335f4a2713aSLionel Sambucdefm VFMADDSD4  : fma4s<0x6B, "vfmaddsd", FR64, f64mem, f64, X86Fmadd, loadf64>,
336f4a2713aSLionel Sambuc                  fma4s_int<0x6B, "vfmaddsd", sdmem, sse_load_f64,
337f4a2713aSLionel Sambuc                            int_x86_fma_vfmadd_sd>;
338f4a2713aSLionel Sambucdefm VFMSUBSS4  : fma4s<0x6E, "vfmsubss", FR32, f32mem, f32, X86Fmsub, loadf32>,
339f4a2713aSLionel Sambuc                  fma4s_int<0x6E, "vfmsubss", ssmem, sse_load_f32,
340f4a2713aSLionel Sambuc                            int_x86_fma_vfmsub_ss>;
341f4a2713aSLionel Sambucdefm VFMSUBSD4  : fma4s<0x6F, "vfmsubsd", FR64, f64mem, f64, X86Fmsub, loadf64>,
342f4a2713aSLionel Sambuc                  fma4s_int<0x6F, "vfmsubsd", sdmem, sse_load_f64,
343f4a2713aSLionel Sambuc                            int_x86_fma_vfmsub_sd>;
344f4a2713aSLionel Sambucdefm VFNMADDSS4 : fma4s<0x7A, "vfnmaddss", FR32, f32mem, f32,
345f4a2713aSLionel Sambuc                        X86Fnmadd, loadf32>,
346f4a2713aSLionel Sambuc                  fma4s_int<0x7A, "vfnmaddss", ssmem, sse_load_f32,
347f4a2713aSLionel Sambuc                            int_x86_fma_vfnmadd_ss>;
348f4a2713aSLionel Sambucdefm VFNMADDSD4 : fma4s<0x7B, "vfnmaddsd", FR64, f64mem, f64,
349f4a2713aSLionel Sambuc                        X86Fnmadd, loadf64>,
350f4a2713aSLionel Sambuc                  fma4s_int<0x7B, "vfnmaddsd", sdmem, sse_load_f64,
351f4a2713aSLionel Sambuc                            int_x86_fma_vfnmadd_sd>;
352f4a2713aSLionel Sambucdefm VFNMSUBSS4 : fma4s<0x7E, "vfnmsubss", FR32, f32mem, f32,
353f4a2713aSLionel Sambuc                        X86Fnmsub, loadf32>,
354f4a2713aSLionel Sambuc                  fma4s_int<0x7E, "vfnmsubss", ssmem, sse_load_f32,
355f4a2713aSLionel Sambuc                            int_x86_fma_vfnmsub_ss>;
356f4a2713aSLionel Sambucdefm VFNMSUBSD4 : fma4s<0x7F, "vfnmsubsd", FR64, f64mem, f64,
357f4a2713aSLionel Sambuc                        X86Fnmsub, loadf64>,
358f4a2713aSLionel Sambuc                  fma4s_int<0x7F, "vfnmsubsd", sdmem, sse_load_f64,
359f4a2713aSLionel Sambuc                            int_x86_fma_vfnmsub_sd>;
360f4a2713aSLionel Sambuc
361f4a2713aSLionel Sambuclet ExeDomain = SSEPackedSingle in {
362f4a2713aSLionel Sambuc  defm VFMADDPS4    : fma4p<0x68, "vfmaddps", X86Fmadd, v4f32, v8f32,
363f4a2713aSLionel Sambuc                            loadv4f32, loadv8f32>;
364f4a2713aSLionel Sambuc  defm VFMSUBPS4    : fma4p<0x6C, "vfmsubps", X86Fmsub, v4f32, v8f32,
365f4a2713aSLionel Sambuc                            loadv4f32, loadv8f32>;
366f4a2713aSLionel Sambuc  defm VFNMADDPS4   : fma4p<0x78, "vfnmaddps", X86Fnmadd, v4f32, v8f32,
367f4a2713aSLionel Sambuc                            loadv4f32, loadv8f32>;
368f4a2713aSLionel Sambuc  defm VFNMSUBPS4   : fma4p<0x7C, "vfnmsubps", X86Fnmsub, v4f32, v8f32,
369f4a2713aSLionel Sambuc                            loadv4f32, loadv8f32>;
370f4a2713aSLionel Sambuc  defm VFMADDSUBPS4 : fma4p<0x5C, "vfmaddsubps", X86Fmaddsub, v4f32, v8f32,
371f4a2713aSLionel Sambuc                            loadv4f32, loadv8f32>;
372f4a2713aSLionel Sambuc  defm VFMSUBADDPS4 : fma4p<0x5E, "vfmsubaddps", X86Fmsubadd, v4f32, v8f32,
373f4a2713aSLionel Sambuc                            loadv4f32, loadv8f32>;
374f4a2713aSLionel Sambuc}
375f4a2713aSLionel Sambuc
376f4a2713aSLionel Sambuclet ExeDomain = SSEPackedDouble in {
377f4a2713aSLionel Sambuc  defm VFMADDPD4    : fma4p<0x69, "vfmaddpd", X86Fmadd, v2f64, v4f64,
378f4a2713aSLionel Sambuc                            loadv2f64, loadv4f64>;
379f4a2713aSLionel Sambuc  defm VFMSUBPD4    : fma4p<0x6D, "vfmsubpd", X86Fmsub, v2f64, v4f64,
380f4a2713aSLionel Sambuc                            loadv2f64, loadv4f64>;
381f4a2713aSLionel Sambuc  defm VFNMADDPD4   : fma4p<0x79, "vfnmaddpd", X86Fnmadd, v2f64, v4f64,
382f4a2713aSLionel Sambuc                            loadv2f64, loadv4f64>;
383f4a2713aSLionel Sambuc  defm VFNMSUBPD4   : fma4p<0x7D, "vfnmsubpd", X86Fnmsub, v2f64, v4f64,
384f4a2713aSLionel Sambuc                            loadv2f64, loadv4f64>;
385f4a2713aSLionel Sambuc  defm VFMADDSUBPD4 : fma4p<0x5D, "vfmaddsubpd", X86Fmaddsub, v2f64, v4f64,
386f4a2713aSLionel Sambuc                            loadv2f64, loadv4f64>;
387f4a2713aSLionel Sambuc  defm VFMSUBADDPD4 : fma4p<0x5F, "vfmsubaddpd", X86Fmsubadd, v2f64, v4f64,
388f4a2713aSLionel Sambuc                            loadv2f64, loadv4f64>;
389f4a2713aSLionel Sambuc}
390f4a2713aSLionel Sambuc
391