1//===- SystemZInstrFP.td - SystemZ FP Instruction defs --------*- tblgen-*-===//
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//===----------------------------------------------------------------------===//
9//
10// This file describes the SystemZ (binary) floating point instructions in
11// TableGen format.
12//
13//===----------------------------------------------------------------------===//
14
15// FIXME: multiclassify!
16
17//===----------------------------------------------------------------------===//
18// FP Pattern fragments
19
20def fpimm0 : PatLeaf<(fpimm), [{
21  return N->isExactlyValue(+0.0);
22}]>;
23
24def fpimmneg0 : PatLeaf<(fpimm), [{
25  return N->isExactlyValue(-0.0);
26}]>;
27
28let usesCustomDAGSchedInserter = 1 in {
29  def SelectF32 : Pseudo<(outs FP32:$dst), (ins FP32:$src1, FP32:$src2, i8imm:$cc),
30                        "# SelectF32 PSEUDO",
31                        [(set FP32:$dst,
32                              (SystemZselect FP32:$src1, FP32:$src2, imm:$cc))]>;
33  def SelectF64 : Pseudo<(outs FP64:$dst), (ins FP64:$src1, FP64:$src2, i8imm:$cc),
34                        "# SelectF64 PSEUDO",
35                        [(set FP64:$dst,
36                              (SystemZselect FP64:$src1, FP64:$src2, imm:$cc))]>;
37}
38
39//===----------------------------------------------------------------------===//
40// Move Instructions
41
42// Floating point constant loads.
43let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
44def LD_Fp032 : Pseudo<(outs FP32:$dst), (ins),
45                      "lzer\t{$dst}",
46                      [(set FP32:$dst, fpimm0)]>;
47def LD_Fp064 : Pseudo<(outs FP64:$dst), (ins),
48                      "lzdr\t{$dst}",
49                      [(set FP64:$dst, fpimm0)]>;
50}
51
52let neverHasSideEffects = 1 in {
53def FMOV32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src),
54                      "ler\t{$dst, $src}",
55                      []>;
56def FMOV64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src),
57                      "ldr\t{$dst, $src}",
58                      []>;
59}
60
61let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in {
62def FMOV32rm  : Pseudo<(outs FP32:$dst), (ins rriaddr12:$src),
63                      "le\t{$dst, $src}",
64                      [(set FP32:$dst, (load rriaddr12:$src))]>;
65def FMOV32rmy : Pseudo<(outs FP32:$dst), (ins rriaddr:$src),
66                      "ley\t{$dst, $src}",
67                      [(set FP32:$dst, (load rriaddr:$src))]>;
68def FMOV64rm  : Pseudo<(outs FP64:$dst), (ins rriaddr12:$src),
69                      "ld\t{$dst, $src}",
70                      [(set FP64:$dst, (load rriaddr12:$src))]>;
71def FMOV64rmy : Pseudo<(outs FP64:$dst), (ins rriaddr:$src),
72                      "ldy\t{$dst, $src}",
73                      [(set FP64:$dst, (load rriaddr:$src))]>;
74}
75
76def FMOV32mr  : Pseudo<(outs), (ins rriaddr12:$dst, FP32:$src),
77                       "ste\t{$src, $dst}",
78                       [(store FP32:$src, rriaddr12:$dst)]>;
79def FMOV32mry : Pseudo<(outs), (ins rriaddr:$dst, FP32:$src),
80                       "stey\t{$src, $dst}",
81                       [(store FP32:$src, rriaddr:$dst)]>;
82def FMOV64mr  : Pseudo<(outs), (ins rriaddr12:$dst, FP64:$src),
83                       "std\t{$src, $dst}",
84                       [(store FP64:$src, rriaddr12:$dst)]>;
85def FMOV64mry : Pseudo<(outs), (ins rriaddr:$dst, FP64:$src),
86                       "stdy\t{$src, $dst}",
87                       [(store FP64:$src, rriaddr:$dst)]>;
88
89//===----------------------------------------------------------------------===//
90// Arithmetic Instructions
91
92
93let Defs = [PSW] in {
94def FNEG32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src),
95                       "lcebr\t{$dst, $src}",
96                       [(set FP32:$dst, (fneg FP32:$src)),
97                        (implicit PSW)]>;
98def FNEG64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src),
99                       "lcdbr\t{$dst, $src}",
100                       [(set FP64:$dst, (fneg FP64:$src)),
101                        (implicit PSW)]>;
102
103def FABS32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src),
104                       "lpebr\t{$dst, $src}",
105                       [(set FP32:$dst, (fabs FP32:$src)),
106                        (implicit PSW)]>;
107def FABS64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src),
108                       "lpdbr\t{$dst, $src}",
109                       [(set FP64:$dst, (fabs FP64:$src)),
110                        (implicit PSW)]>;
111
112def FNABS32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src),
113                       "lnebr\t{$dst, $src}",
114                       [(set FP32:$dst, (fneg(fabs FP32:$src))),
115                        (implicit PSW)]>;
116def FNABS64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src),
117                       "lndbr\t{$dst, $src}",
118                       [(set FP64:$dst, (fneg(fabs FP64:$src))),
119                        (implicit PSW)]>;
120}
121
122let isTwoAddress = 1 in {
123let Defs = [PSW] in {
124let isCommutable = 1 in { // X = ADD Y, Z  == X = ADD Z, Y
125def FADD32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src1, FP32:$src2),
126                       "aebr\t{$dst, $src2}",
127                       [(set FP32:$dst, (fadd FP32:$src1, FP32:$src2)),
128                        (implicit PSW)]>;
129def FADD64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src1, FP64:$src2),
130                       "adbr\t{$dst, $src2}",
131                       [(set FP64:$dst, (fadd FP64:$src1, FP64:$src2)),
132                        (implicit PSW)]>;
133}
134
135def FADD32rm : Pseudo<(outs FP32:$dst), (ins FP32:$src1, rriaddr12:$src2),
136                       "aeb\t{$dst, $src2}",
137                       [(set FP32:$dst, (fadd FP32:$src1, (load rriaddr12:$src2))),
138                        (implicit PSW)]>;
139def FADD64rm : Pseudo<(outs FP64:$dst), (ins FP64:$src1, rriaddr12:$src2),
140                       "adb\t{$dst, $src2}",
141                       [(set FP64:$dst, (fadd FP64:$src1, (load rriaddr12:$src2))),
142                        (implicit PSW)]>;
143
144def FSUB32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src1, FP32:$src2),
145                       "sebr\t{$dst, $src2}",
146                       [(set FP32:$dst, (fsub FP32:$src1, FP32:$src2)),
147                        (implicit PSW)]>;
148def FSUB64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src1, FP64:$src2),
149                       "sdbr\t{$dst, $src2}",
150                       [(set FP64:$dst, (fsub FP64:$src1, FP64:$src2)),
151                        (implicit PSW)]>;
152
153def FSUB32rm : Pseudo<(outs FP32:$dst), (ins FP32:$src1, rriaddr12:$src2),
154                       "seb\t{$dst, $src2}",
155                       [(set FP32:$dst, (fsub FP32:$src1, (load rriaddr12:$src2))),
156                        (implicit PSW)]>;
157def FSUB64rm : Pseudo<(outs FP64:$dst), (ins FP64:$src1, rriaddr12:$src2),
158                       "sdb\t{$dst, $src2}",
159                       [(set FP64:$dst, (fsub FP64:$src1, (load rriaddr12:$src2))),
160                        (implicit PSW)]>;
161} // Defs = [PSW]
162
163let isCommutable = 1 in { // X = MUL Y, Z  == X = MUL Z, Y
164def FMUL32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src1, FP32:$src2),
165                       "meebr\t{$dst, $src2}",
166                       [(set FP32:$dst, (fmul FP32:$src1, FP32:$src2))]>;
167def FMUL64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src1, FP64:$src2),
168                       "mdbr\t{$dst, $src2}",
169                       [(set FP64:$dst, (fmul FP64:$src1, FP64:$src2))]>;
170}
171
172def FMUL32rm : Pseudo<(outs FP32:$dst), (ins FP32:$src1, rriaddr12:$src2),
173                       "meeb\t{$dst, $src2}",
174                       [(set FP32:$dst, (fmul FP32:$src1, (load rriaddr12:$src2)))]>;
175def FMUL64rm : Pseudo<(outs FP64:$dst), (ins FP64:$src1, rriaddr12:$src2),
176                       "mdb\t{$dst, $src2}",
177                       [(set FP64:$dst, (fmul FP64:$src1, (load rriaddr12:$src2)))]>;
178
179def FMADD32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src1, FP32:$src2, FP32:$src3),
180                       "maebr\t{$dst, $src3, $src2}",
181                       [(set FP32:$dst, (fadd (fmul FP32:$src2, FP32:$src3),
182                                              FP32:$src1))]>;
183def FMADD32rm : Pseudo<(outs FP32:$dst), (ins FP32:$src1, rriaddr12:$src2, FP32:$src3),
184                       "maeb\t{$dst, $src3, $src2}",
185                       [(set FP32:$dst, (fadd (fmul (load rriaddr12:$src2),
186                                                     FP32:$src3),
187                                              FP32:$src1))]>;
188
189def FMADD64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src1, FP64:$src2, FP64:$src3),
190                       "madbr\t{$dst, $src3, $src2}",
191                       [(set FP64:$dst, (fadd (fmul FP64:$src2, FP64:$src3),
192                                              FP64:$src1))]>;
193def FMADD64rm : Pseudo<(outs FP64:$dst), (ins FP64:$src1, rriaddr12:$src2, FP64:$src3),
194                       "madb\t{$dst, $src3, $src2}",
195                       [(set FP64:$dst, (fadd (fmul (load rriaddr12:$src2),
196                                                     FP64:$src3),
197                                              FP64:$src1))]>;
198
199def FMSUB32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src1, FP32:$src2, FP32:$src3),
200                       "msebr\t{$dst, $src3, $src2}",
201                       [(set FP32:$dst, (fsub (fmul FP32:$src2, FP32:$src3),
202                                              FP32:$src1))]>;
203def FMSUB32rm : Pseudo<(outs FP32:$dst), (ins FP32:$src1, rriaddr12:$src2, FP32:$src3),
204                       "mseb\t{$dst, $src3, $src2}",
205                       [(set FP32:$dst, (fsub (fmul (load rriaddr12:$src2),
206                                                     FP32:$src3),
207                                              FP32:$src1))]>;
208
209def FMSUB64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src1, FP64:$src2, FP64:$src3),
210                       "msdbr\t{$dst, $src3, $src2}",
211                       [(set FP64:$dst, (fsub (fmul FP64:$src2, FP64:$src3),
212                                              FP64:$src1))]>;
213def FMSUB64rm : Pseudo<(outs FP64:$dst), (ins FP64:$src1, rriaddr12:$src2, FP64:$src3),
214                       "msdb\t{$dst, $src3, $src2}",
215                       [(set FP64:$dst, (fsub (fmul (load rriaddr12:$src2),
216                                                     FP64:$src3),
217                                              FP64:$src1))]>;
218
219def FDIV32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src1, FP32:$src2),
220                       "debr\t{$dst, $src2}",
221                       [(set FP32:$dst, (fdiv FP32:$src1, FP32:$src2))]>;
222def FDIV64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src1, FP64:$src2),
223                       "ddbr\t{$dst, $src2}",
224                       [(set FP64:$dst, (fdiv FP64:$src1, FP64:$src2))]>;
225
226def FDIV32rm : Pseudo<(outs FP32:$dst), (ins FP32:$src1, rriaddr12:$src2),
227                       "deb\t{$dst, $src2}",
228                       [(set FP32:$dst, (fdiv FP32:$src1, (load rriaddr12:$src2)))]>;
229def FDIV64rm : Pseudo<(outs FP64:$dst), (ins FP64:$src1, rriaddr12:$src2),
230                       "ddb\t{$dst, $src2}",
231                       [(set FP64:$dst, (fdiv FP64:$src1, (load rriaddr12:$src2)))]>;
232
233} // isTwoAddress = 1
234
235def FSQRT32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src),
236                       "sqebr\t{$dst, $src}",
237                       [(set FP32:$dst, (fsqrt FP32:$src))]>;
238def FSQRT64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src),
239                       "sqdbr\t{$dst, $src}",
240                       [(set FP64:$dst, (fsqrt FP64:$src))]>;
241
242def FSQRT32rm : Pseudo<(outs FP32:$dst), (ins rriaddr12:$src),
243                       "sqeb\t{$dst, $src}",
244                       [(set FP32:$dst, (fsqrt (load rriaddr12:$src)))]>;
245def FSQRT64rm : Pseudo<(outs FP64:$dst), (ins rriaddr12:$src),
246                       "sqdb\t{$dst, $src}",
247                       [(set FP64:$dst, (fsqrt (load rriaddr12:$src)))]>;
248
249def FROUND64r32 : Pseudo<(outs FP32:$dst), (ins FP64:$src),
250                         "ledbr\t{$dst, $src}",
251                         [(set FP32:$dst, (fround FP64:$src))]>;
252
253def FEXT32r64   : Pseudo<(outs FP64:$dst), (ins FP32:$src),
254                         "ldebr\t{$dst, $src}",
255                         [(set FP64:$dst, (fextend FP32:$src))]>;
256def FEXT32m64   : Pseudo<(outs FP64:$dst), (ins rriaddr12:$src),
257                         "ldeb\t{$dst, $src}",
258                         [(set FP64:$dst, (fextend (load rriaddr12:$src)))]>;
259
260let Defs = [PSW] in {
261def FCONVFP32   : Pseudo<(outs FP32:$dst), (ins GR32:$src),
262                         "cefbr\t{$dst, $src}",
263                         [(set FP32:$dst, (sint_to_fp GR32:$src)),
264                          (implicit PSW)]>;
265def FCONVFP32r64: Pseudo<(outs FP32:$dst), (ins GR64:$src),
266                         "cegbr\t{$dst, $src}",
267                         [(set FP32:$dst, (sint_to_fp GR64:$src)),
268                          (implicit PSW)]>;
269
270def FCONVFP64r32: Pseudo<(outs FP64:$dst), (ins GR32:$src),
271                         "cdfbr\t{$dst, $src}",
272                         [(set FP64:$dst, (sint_to_fp GR32:$src)),
273                          (implicit PSW)]>;
274def FCONVFP64   : Pseudo<(outs FP64:$dst), (ins GR64:$src),
275                         "cdgbr\t{$dst, $src}",
276                         [(set FP64:$dst, (sint_to_fp GR64:$src)),
277                          (implicit PSW)]>;
278
279def FCONVGR32   : Pseudo<(outs GR32:$dst), (ins FP32:$src),
280                         "cfebr\t{$dst, 5, $src}",
281                         [(set GR32:$dst, (fp_to_sint FP32:$src)),
282                          (implicit PSW)]>;
283def FCONVGR32r64: Pseudo<(outs GR32:$dst), (ins FP64:$src),
284                         "cfdbr\t{$dst, 5, $src}",
285                         [(set GR32:$dst, (fp_to_sint FP64:$src)),
286                          (implicit PSW)]>;
287
288def FCONVGR64r32: Pseudo<(outs GR64:$dst), (ins FP32:$src),
289                         "cgebr\t{$dst, 5, $src}",
290                         [(set GR64:$dst, (fp_to_sint FP32:$src)),
291                          (implicit PSW)]>;
292def FCONVGR64   : Pseudo<(outs GR64:$dst), (ins FP64:$src),
293                         "cgdbr\t{$dst, 5, $src}",
294                         [(set GR64:$dst, (fp_to_sint FP64:$src)),
295                          (implicit PSW)]>;
296} // Defs = [PSW]
297
298def FBCONVG64   : Pseudo<(outs GR64:$dst), (ins FP64:$src),
299                         "lgdr\t{$dst, $src}",
300                         [(set GR64:$dst, (bitconvert FP64:$src))]>;
301def FBCONVF64   : Pseudo<(outs FP64:$dst), (ins GR64:$src),
302                         "ldgr\t{$dst, $src}",
303                         [(set FP64:$dst, (bitconvert GR64:$src))]>;
304
305//===----------------------------------------------------------------------===//
306// Test instructions (like AND but do not produce any result)
307
308// Integer comparisons
309let Defs = [PSW] in {
310def FCMP32rr : Pseudo<(outs), (ins FP32:$src1, FP32:$src2),
311                      "cebr\t$src1, $src2",
312                      [(SystemZcmp FP32:$src1, FP32:$src2), (implicit PSW)]>;
313def FCMP64rr : Pseudo<(outs), (ins FP64:$src1, FP64:$src2),
314                      "cdbr\t$src1, $src2",
315                      [(SystemZcmp FP64:$src1, FP64:$src2), (implicit PSW)]>;
316
317def FCMP32rm : Pseudo<(outs), (ins FP32:$src1, rriaddr12:$src2),
318                      "ceb\t$src1, $src2",
319                      [(SystemZcmp FP32:$src1, (load rriaddr12:$src2)),
320                       (implicit PSW)]>;
321def FCMP64rm : Pseudo<(outs), (ins FP64:$src1, rriaddr12:$src2),
322                      "cdb\t$src1, $src2",
323                      [(SystemZcmp FP64:$src1, (load rriaddr12:$src2)),
324                       (implicit PSW)]>;
325} // Defs = [PSW]
326
327//===----------------------------------------------------------------------===//
328// Non-Instruction Patterns
329//===----------------------------------------------------------------------===//
330
331// Floating point constant -0.0
332def : Pat<(f32 fpimmneg0), (FNEG32rr (LD_Fp032))>;
333def : Pat<(f64 fpimmneg0), (FNEG64rr (LD_Fp064))>;
334