[testsuite]
[official-gcc.git] / gcc / config / rs6000 / dfp.md
blob216251f69f0b7530730d338e4cff87f16ac3c125
1 ;; Decimal Floating Point (DFP) patterns.
2 ;; Copyright (C) 2007-2018 Free Software Foundation, Inc.
3 ;; Contributed by Ben Elliston (bje@au.ibm.com) and Peter Bergner
4 ;; (bergner@vnet.ibm.com).
6 ;; This file is part of GCC.
8 ;; GCC is free software; you can redistribute it and/or modify it
9 ;; under the terms of the GNU General Public License as published
10 ;; by the Free Software Foundation; either version 3, or (at your
11 ;; option) any later version.
13 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
14 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16 ;; License for more details.
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with GCC; see the file COPYING3.  If not see
20 ;; <http://www.gnu.org/licenses/>.
23 ;; UNSPEC usage
26 (define_c_enum "unspec"
27   [UNSPEC_MOVSD_LOAD
28    UNSPEC_MOVSD_STORE
29   ])
32 (define_insn "movsd_store"
33   [(set (match_operand:DD 0 "nonimmediate_operand" "=m")
34         (unspec:DD [(match_operand:SD 1 "input_operand" "d")]
35                    UNSPEC_MOVSD_STORE))]
36   "(gpc_reg_operand (operands[0], DDmode)
37    || gpc_reg_operand (operands[1], SDmode))
38    && TARGET_HARD_FLOAT"
39   "stfd%U0%X0 %1,%0"
40   [(set_attr "type" "fpstore")
41    (set_attr "length" "4")])
43 (define_insn "movsd_load"
44   [(set (match_operand:SD 0 "nonimmediate_operand" "=f")
45         (unspec:SD [(match_operand:DD 1 "input_operand" "m")]
46                    UNSPEC_MOVSD_LOAD))]
47   "(gpc_reg_operand (operands[0], SDmode)
48    || gpc_reg_operand (operands[1], DDmode))
49    && TARGET_HARD_FLOAT"
50   "lfd%U1%X1 %0,%1"
51   [(set_attr "type" "fpload")
52    (set_attr "length" "4")])
54 ;; Hardware support for decimal floating point operations.
56 (define_insn "extendsddd2"
57   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
58         (float_extend:DD (match_operand:SD 1 "gpc_reg_operand" "f")))]
59   "TARGET_DFP"
60   "dctdp %0,%1"
61   [(set_attr "type" "dfp")])
63 (define_expand "extendsdtd2"
64   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
65         (float_extend:TD (match_operand:SD 1 "gpc_reg_operand" "d")))]
66   "TARGET_DFP"
68   rtx tmp = gen_reg_rtx (DDmode);
69   emit_insn (gen_extendsddd2 (tmp, operands[1]));
70   emit_insn (gen_extendddtd2 (operands[0], tmp));
71   DONE;
74 (define_insn "truncddsd2"
75   [(set (match_operand:SD 0 "gpc_reg_operand" "=f")
76         (float_truncate:SD (match_operand:DD 1 "gpc_reg_operand" "d")))]
77   "TARGET_DFP"
78   "drsp %0,%1"
79   [(set_attr "type" "dfp")])
81 (define_insn "negdd2"
82   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
83         (neg:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
84   "TARGET_HARD_FLOAT"
85   "fneg %0,%1"
86   [(set_attr "type" "fpsimple")])
88 (define_insn "absdd2"
89   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
90         (abs:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
91   "TARGET_HARD_FLOAT"
92   "fabs %0,%1"
93   [(set_attr "type" "fpsimple")])
95 (define_insn "*nabsdd2_fpr"
96   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
97         (neg:DD (abs:DD (match_operand:DD 1 "gpc_reg_operand" "d"))))]
98   "TARGET_HARD_FLOAT"
99   "fnabs %0,%1"
100   [(set_attr "type" "fpsimple")])
102 (define_insn "negtd2"
103   [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d")
104         (neg:TD (match_operand:TD 1 "gpc_reg_operand" "0,d")))]
105   "TARGET_HARD_FLOAT"
106   "@
107    fneg %0,%1
108    fneg %0,%1\;fmr %L0,%L1"
109   [(set_attr "type" "fpsimple")
110    (set_attr "length" "4,8")])
112 (define_insn "abstd2"
113   [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d")
114         (abs:TD (match_operand:TD 1 "gpc_reg_operand" "0,d")))]
115   "TARGET_HARD_FLOAT"
116   "@
117    fabs %0,%1
118    fabs %0,%1\;fmr %L0,%L1"
119   [(set_attr "type" "fpsimple")
120    (set_attr "length" "4,8")])
122 (define_insn "*nabstd2_fpr"
123   [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d")
124         (neg:TD (abs:TD (match_operand:TD 1 "gpc_reg_operand" "0,d"))))]
125   "TARGET_HARD_FLOAT"
126   "@
127    fnabs %0,%1
128    fnabs %0,%1\;fmr %L0,%L1"
129   [(set_attr "type" "fpsimple")
130    (set_attr "length" "4,8")])
132 ;; Hardware support for decimal floating point operations.
134 (define_insn "extendddtd2"
135   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
136         (float_extend:TD (match_operand:DD 1 "gpc_reg_operand" "d")))]
137   "TARGET_DFP"
138   "dctqpq %0,%1"
139   [(set_attr "type" "dfp")])
141 ;; The result of drdpq is an even/odd register pair with the converted
142 ;; value in the even register and zero in the odd register.
143 ;; FIXME: Avoid the register move by using a reload constraint to ensure
144 ;; that the result is the first of the pair receiving the result of drdpq.
146 (define_insn "trunctddd2"
147   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
148         (float_truncate:DD (match_operand:TD 1 "gpc_reg_operand" "d")))
149    (clobber (match_scratch:TD 2 "=d"))]
150   "TARGET_DFP"
151   "drdpq %2,%1\;fmr %0,%2"
152   [(set_attr "type" "dfp")
153    (set_attr "length" "8")])
155 (define_insn "adddd3"
156   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
157         (plus:DD (match_operand:DD 1 "gpc_reg_operand" "%d")
158                  (match_operand:DD 2 "gpc_reg_operand" "d")))]
159   "TARGET_DFP"
160   "dadd %0,%1,%2"
161   [(set_attr "type" "dfp")])
163 (define_insn "addtd3"
164   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
165         (plus:TD (match_operand:TD 1 "gpc_reg_operand" "%d")
166                  (match_operand:TD 2 "gpc_reg_operand" "d")))]
167   "TARGET_DFP"
168   "daddq %0,%1,%2"
169   [(set_attr "type" "dfp")])
171 (define_insn "subdd3"
172   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
173         (minus:DD (match_operand:DD 1 "gpc_reg_operand" "d")
174                   (match_operand:DD 2 "gpc_reg_operand" "d")))]
175   "TARGET_DFP"
176   "dsub %0,%1,%2"
177   [(set_attr "type" "dfp")])
179 (define_insn "subtd3"
180   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
181         (minus:TD (match_operand:TD 1 "gpc_reg_operand" "d")
182                   (match_operand:TD 2 "gpc_reg_operand" "d")))]
183   "TARGET_DFP"
184   "dsubq %0,%1,%2"
185   [(set_attr "type" "dfp")])
187 (define_insn "muldd3"
188   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
189         (mult:DD (match_operand:DD 1 "gpc_reg_operand" "%d")
190                  (match_operand:DD 2 "gpc_reg_operand" "d")))]
191   "TARGET_DFP"
192   "dmul %0,%1,%2"
193   [(set_attr "type" "dfp")])
195 (define_insn "multd3"
196   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
197         (mult:TD (match_operand:TD 1 "gpc_reg_operand" "%d")
198                  (match_operand:TD 2 "gpc_reg_operand" "d")))]
199   "TARGET_DFP"
200   "dmulq %0,%1,%2"
201   [(set_attr "type" "dfp")])
203 (define_insn "divdd3"
204   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
205         (div:DD (match_operand:DD 1 "gpc_reg_operand" "d")
206                 (match_operand:DD 2 "gpc_reg_operand" "d")))]
207   "TARGET_DFP"
208   "ddiv %0,%1,%2"
209   [(set_attr "type" "dfp")])
211 (define_insn "divtd3"
212   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
213         (div:TD (match_operand:TD 1 "gpc_reg_operand" "d")
214                 (match_operand:TD 2 "gpc_reg_operand" "d")))]
215   "TARGET_DFP"
216   "ddivq %0,%1,%2"
217   [(set_attr "type" "dfp")])
219 (define_insn "*cmpdd_internal1"
220   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
221         (compare:CCFP (match_operand:DD 1 "gpc_reg_operand" "d")
222                       (match_operand:DD 2 "gpc_reg_operand" "d")))]
223   "TARGET_DFP"
224   "dcmpu %0,%1,%2"
225   [(set_attr "type" "dfp")])
227 (define_insn "*cmptd_internal1"
228   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
229         (compare:CCFP (match_operand:TD 1 "gpc_reg_operand" "d")
230                       (match_operand:TD 2 "gpc_reg_operand" "d")))]
231   "TARGET_DFP"
232   "dcmpuq %0,%1,%2"
233   [(set_attr "type" "dfp")])
235 (define_insn "floatdidd2"
236   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
237         (float:DD (match_operand:DI 1 "gpc_reg_operand" "d")))]
238   "TARGET_DFP && TARGET_POPCNTD"
239   "dcffix %0,%1"
240   [(set_attr "type" "dfp")])
242 (define_insn "floatditd2"
243   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
244         (float:TD (match_operand:DI 1 "gpc_reg_operand" "d")))]
245   "TARGET_DFP"
246   "dcffixq %0,%1"
247   [(set_attr "type" "dfp")])
249 ;; Convert a decimal64 to a decimal64 whose value is an integer.
250 ;; This is the first stage of converting it to an integer type.
252 (define_insn "ftruncdd2"
253   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
254         (fix:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
255   "TARGET_DFP"
256   "drintn. 0,%0,%1,1"
257   [(set_attr "type" "dfp")])
259 ;; Convert a decimal64 whose value is an integer to an actual integer.
260 ;; This is the second stage of converting decimal float to integer type.
262 (define_insn "fixdddi2"
263   [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
264         (fix:DI (match_operand:DD 1 "gpc_reg_operand" "d")))]
265   "TARGET_DFP"
266   "dctfix %0,%1"
267   [(set_attr "type" "dfp")])
269 ;; Convert a decimal128 to a decimal128 whose value is an integer.
270 ;; This is the first stage of converting it to an integer type.
272 (define_insn "ftrunctd2"
273   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
274         (fix:TD (match_operand:TD 1 "gpc_reg_operand" "d")))]
275   "TARGET_DFP"
276   "drintnq. 0,%0,%1,1"
277   [(set_attr "type" "dfp")])
279 ;; Convert a decimal128 whose value is an integer to an actual integer.
280 ;; This is the second stage of converting decimal float to integer type.
282 (define_insn "fixtddi2"
283   [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
284         (fix:DI (match_operand:TD 1 "gpc_reg_operand" "d")))]
285   "TARGET_DFP"
286   "dctfixq %0,%1"
287   [(set_attr "type" "dfp")])
290 ;; Decimal builtin support
292 (define_c_enum "unspec"
293   [UNSPEC_DDEDPD
294    UNSPEC_DENBCD
295    UNSPEC_DXEX
296    UNSPEC_DIEX
297    UNSPEC_DSCLI
298    UNSPEC_DTSTSFI
299    UNSPEC_DSCRI])
301 (define_code_iterator DFP_TEST [eq lt gt unordered])
303 (define_mode_iterator D64_D128 [DD TD])
305 (define_mode_attr dfp_suffix [(DD "")
306                               (TD "q")])
308 (define_insn "dfp_ddedpd_<mode>"
309   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
310         (unspec:D64_D128 [(match_operand:QI 1 "const_0_to_3_operand" "i")
311                           (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
312                          UNSPEC_DDEDPD))]
313   "TARGET_DFP"
314   "ddedpd<dfp_suffix> %1,%0,%2"
315   [(set_attr "type" "dfp")])
317 (define_insn "dfp_denbcd_<mode>"
318   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
319         (unspec:D64_D128 [(match_operand:QI 1 "const_0_to_1_operand" "i")
320                           (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
321                          UNSPEC_DENBCD))]
322   "TARGET_DFP"
323   "denbcd<dfp_suffix> %1,%0,%2"
324   [(set_attr "type" "dfp")])
326 (define_insn "dfp_dxex_<mode>"
327   [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
328         (unspec:DI [(match_operand:D64_D128 1 "gpc_reg_operand" "d")]
329                    UNSPEC_DXEX))]
330   "TARGET_DFP"
331   "dxex<dfp_suffix> %0,%1"
332   [(set_attr "type" "dfp")])
334 (define_insn "dfp_diex_<mode>"
335   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
336         (unspec:D64_D128 [(match_operand:DI 1 "gpc_reg_operand" "d")
337                           (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
338                          UNSPEC_DXEX))]
339   "TARGET_DFP"
340   "diex<dfp_suffix> %0,%1,%2"
341   [(set_attr "type" "dfp")])
343 (define_expand "dfptstsfi_<code>_<mode>"
344   [(set (match_dup 3)
345         (compare:CCFP
346          (unspec:D64_D128
347           [(match_operand:SI 1 "const_int_operand" "n")
348            (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
349           UNSPEC_DTSTSFI)
350          (match_dup 4)))
351    (set (match_operand:SI 0 "register_operand" "")
352         (DFP_TEST:SI (match_dup 3)
353                      (const_int 0)))
354   ]
355   "TARGET_P9_MISC"
357   operands[3] = gen_reg_rtx (CCFPmode);
358   operands[4] = const0_rtx;
361 (define_insn "*dfp_sgnfcnc_<mode>"
362   [(set (match_operand:CCFP 0 "" "=y")
363         (compare:CCFP
364          (unspec:D64_D128 [(match_operand:SI 1 "const_int_operand" "n")
365                            (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
366           UNSPEC_DTSTSFI)
367          (match_operand:SI 3 "zero_constant" "j")))]
368   "TARGET_P9_MISC"
370   /* If immediate operand is greater than 63, it will behave as if
371      the value had been 63.  The code generator does not support
372      immediate operand values greater than 63.  */
373   if (!(IN_RANGE (INTVAL (operands[1]), 0, 63)))
374     operands[1] = GEN_INT (63);
375   return "dtstsfi<dfp_suffix> %0,%1,%2";
377   [(set_attr "type" "fp")])
379 (define_insn "dfp_dscli_<mode>"
380   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
381         (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
382                           (match_operand:QI 2 "immediate_operand" "i")]
383                          UNSPEC_DSCLI))]
384   "TARGET_DFP"
385   "dscli<dfp_suffix> %0,%1,%2"
386   [(set_attr "type" "dfp")])
388 (define_insn "dfp_dscri_<mode>"
389   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
390         (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
391                           (match_operand:QI 2 "immediate_operand" "i")]
392                          UNSPEC_DSCRI))]
393   "TARGET_DFP"
394   "dscri<dfp_suffix> %0,%1,%2"
395   [(set_attr "type" "dfp")])