2018-02-09 Sebastian Perta <sebastian.perta@renesas.com>
[official-gcc.git] / gcc / config / powerpcspe / dfp.md
blob03e5bc1537b9c1b473495a96c6cec15d0f874cdd
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 && TARGET_FPRS"
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 && TARGET_FPRS"
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_expand "negdd2"
82   [(set (match_operand:DD 0 "gpc_reg_operand" "")
83         (neg:DD (match_operand:DD 1 "gpc_reg_operand" "")))]
84   "TARGET_HARD_FLOAT && TARGET_FPRS"
85   "")
87 (define_insn "*negdd2_fpr"
88   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
89         (neg:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
90   "TARGET_HARD_FLOAT && TARGET_FPRS"
91   "fneg %0,%1"
92   [(set_attr "type" "fpsimple")])
94 (define_expand "absdd2"
95   [(set (match_operand:DD 0 "gpc_reg_operand" "")
96         (abs:DD (match_operand:DD 1 "gpc_reg_operand" "")))]
97   "TARGET_HARD_FLOAT && TARGET_FPRS"
98   "")
100 (define_insn "*absdd2_fpr"
101   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
102         (abs:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
103   "TARGET_HARD_FLOAT && TARGET_FPRS"
104   "fabs %0,%1"
105   [(set_attr "type" "fpsimple")])
107 (define_insn "*nabsdd2_fpr"
108   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
109         (neg:DD (abs:DD (match_operand:DD 1 "gpc_reg_operand" "d"))))]
110   "TARGET_HARD_FLOAT && TARGET_FPRS"
111   "fnabs %0,%1"
112   [(set_attr "type" "fpsimple")])
114 (define_expand "negtd2"
115   [(set (match_operand:TD 0 "gpc_reg_operand" "")
116         (neg:TD (match_operand:TD 1 "gpc_reg_operand" "")))]
117   "TARGET_HARD_FLOAT && TARGET_FPRS"
118   "")
120 (define_insn "*negtd2_fpr"
121   [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d")
122         (neg:TD (match_operand:TD 1 "gpc_reg_operand" "0,d")))]
123   "TARGET_HARD_FLOAT && TARGET_FPRS"
124   "@
125    fneg %0,%1
126    fneg %0,%1\;fmr %L0,%L1"
127   [(set_attr "type" "fpsimple")
128    (set_attr "length" "4,8")])
130 (define_expand "abstd2"
131   [(set (match_operand:TD 0 "gpc_reg_operand" "")
132         (abs:TD (match_operand:TD 1 "gpc_reg_operand" "")))]
133   "TARGET_HARD_FLOAT && TARGET_FPRS"
134   "")
136 (define_insn "*abstd2_fpr"
137   [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d")
138         (abs:TD (match_operand:TD 1 "gpc_reg_operand" "0,d")))]
139   "TARGET_HARD_FLOAT && TARGET_FPRS"
140   "@
141    fabs %0,%1
142    fabs %0,%1\;fmr %L0,%L1"
143   [(set_attr "type" "fpsimple")
144    (set_attr "length" "4,8")])
146 (define_insn "*nabstd2_fpr"
147   [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d")
148         (neg:TD (abs:TD (match_operand:TD 1 "gpc_reg_operand" "0,d"))))]
149   "TARGET_HARD_FLOAT && TARGET_FPRS"
150   "@
151    fnabs %0,%1
152    fnabs %0,%1\;fmr %L0,%L1"
153   [(set_attr "type" "fpsimple")
154    (set_attr "length" "4,8")])
156 ;; Hardware support for decimal floating point operations.
158 (define_insn "extendddtd2"
159   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
160         (float_extend:TD (match_operand:DD 1 "gpc_reg_operand" "d")))]
161   "TARGET_DFP"
162   "dctqpq %0,%1"
163   [(set_attr "type" "dfp")])
165 ;; The result of drdpq is an even/odd register pair with the converted
166 ;; value in the even register and zero in the odd register.
167 ;; FIXME: Avoid the register move by using a reload constraint to ensure
168 ;; that the result is the first of the pair receiving the result of drdpq.
170 (define_insn "trunctddd2"
171   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
172         (float_truncate:DD (match_operand:TD 1 "gpc_reg_operand" "d")))
173    (clobber (match_scratch:TD 2 "=d"))]
174   "TARGET_DFP"
175   "drdpq %2,%1\;fmr %0,%2"
176   [(set_attr "type" "dfp")
177    (set_attr "length" "8")])
179 (define_insn "adddd3"
180   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
181         (plus:DD (match_operand:DD 1 "gpc_reg_operand" "%d")
182                  (match_operand:DD 2 "gpc_reg_operand" "d")))]
183   "TARGET_DFP"
184   "dadd %0,%1,%2"
185   [(set_attr "type" "dfp")])
187 (define_insn "addtd3"
188   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
189         (plus:TD (match_operand:TD 1 "gpc_reg_operand" "%d")
190                  (match_operand:TD 2 "gpc_reg_operand" "d")))]
191   "TARGET_DFP"
192   "daddq %0,%1,%2"
193   [(set_attr "type" "dfp")])
195 (define_insn "subdd3"
196   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
197         (minus:DD (match_operand:DD 1 "gpc_reg_operand" "d")
198                   (match_operand:DD 2 "gpc_reg_operand" "d")))]
199   "TARGET_DFP"
200   "dsub %0,%1,%2"
201   [(set_attr "type" "dfp")])
203 (define_insn "subtd3"
204   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
205         (minus:TD (match_operand:TD 1 "gpc_reg_operand" "d")
206                   (match_operand:TD 2 "gpc_reg_operand" "d")))]
207   "TARGET_DFP"
208   "dsubq %0,%1,%2"
209   [(set_attr "type" "dfp")])
211 (define_insn "muldd3"
212   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
213         (mult:DD (match_operand:DD 1 "gpc_reg_operand" "%d")
214                  (match_operand:DD 2 "gpc_reg_operand" "d")))]
215   "TARGET_DFP"
216   "dmul %0,%1,%2"
217   [(set_attr "type" "dfp")])
219 (define_insn "multd3"
220   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
221         (mult:TD (match_operand:TD 1 "gpc_reg_operand" "%d")
222                  (match_operand:TD 2 "gpc_reg_operand" "d")))]
223   "TARGET_DFP"
224   "dmulq %0,%1,%2"
225   [(set_attr "type" "dfp")])
227 (define_insn "divdd3"
228   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
229         (div:DD (match_operand:DD 1 "gpc_reg_operand" "d")
230                 (match_operand:DD 2 "gpc_reg_operand" "d")))]
231   "TARGET_DFP"
232   "ddiv %0,%1,%2"
233   [(set_attr "type" "dfp")])
235 (define_insn "divtd3"
236   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
237         (div:TD (match_operand:TD 1 "gpc_reg_operand" "d")
238                 (match_operand:TD 2 "gpc_reg_operand" "d")))]
239   "TARGET_DFP"
240   "ddivq %0,%1,%2"
241   [(set_attr "type" "dfp")])
243 (define_insn "*cmpdd_internal1"
244   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
245         (compare:CCFP (match_operand:DD 1 "gpc_reg_operand" "d")
246                       (match_operand:DD 2 "gpc_reg_operand" "d")))]
247   "TARGET_DFP"
248   "dcmpu %0,%1,%2"
249   [(set_attr "type" "dfp")])
251 (define_insn "*cmptd_internal1"
252   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
253         (compare:CCFP (match_operand:TD 1 "gpc_reg_operand" "d")
254                       (match_operand:TD 2 "gpc_reg_operand" "d")))]
255   "TARGET_DFP"
256   "dcmpuq %0,%1,%2"
257   [(set_attr "type" "dfp")])
259 (define_insn "floatdidd2"
260   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
261         (float:DD (match_operand:DI 1 "gpc_reg_operand" "d")))]
262   "TARGET_DFP && TARGET_POPCNTD"
263   "dcffix %0,%1"
264   [(set_attr "type" "dfp")])
266 (define_insn "floatditd2"
267   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
268         (float:TD (match_operand:DI 1 "gpc_reg_operand" "d")))]
269   "TARGET_DFP"
270   "dcffixq %0,%1"
271   [(set_attr "type" "dfp")])
273 ;; Convert a decimal64 to a decimal64 whose value is an integer.
274 ;; This is the first stage of converting it to an integer type.
276 (define_insn "ftruncdd2"
277   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
278         (fix:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
279   "TARGET_DFP"
280   "drintn. 0,%0,%1,1"
281   [(set_attr "type" "dfp")])
283 ;; Convert a decimal64 whose value is an integer to an actual integer.
284 ;; This is the second stage of converting decimal float to integer type.
286 (define_insn "fixdddi2"
287   [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
288         (fix:DI (match_operand:DD 1 "gpc_reg_operand" "d")))]
289   "TARGET_DFP"
290   "dctfix %0,%1"
291   [(set_attr "type" "dfp")])
293 ;; Convert a decimal128 to a decimal128 whose value is an integer.
294 ;; This is the first stage of converting it to an integer type.
296 (define_insn "ftrunctd2"
297   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
298         (fix:TD (match_operand:TD 1 "gpc_reg_operand" "d")))]
299   "TARGET_DFP"
300   "drintnq. 0,%0,%1,1"
301   [(set_attr "type" "dfp")])
303 ;; Convert a decimal128 whose value is an integer to an actual integer.
304 ;; This is the second stage of converting decimal float to integer type.
306 (define_insn "fixtddi2"
307   [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
308         (fix:DI (match_operand:TD 1 "gpc_reg_operand" "d")))]
309   "TARGET_DFP"
310   "dctfixq %0,%1"
311   [(set_attr "type" "dfp")])
314 ;; Decimal builtin support
316 (define_c_enum "unspec"
317   [UNSPEC_DDEDPD
318    UNSPEC_DENBCD
319    UNSPEC_DXEX
320    UNSPEC_DIEX
321    UNSPEC_DSCLI
322    UNSPEC_DTSTSFI
323    UNSPEC_DSCRI])
325 (define_code_iterator DFP_TEST [eq lt gt unordered])
327 (define_mode_iterator D64_D128 [DD TD])
329 (define_mode_attr dfp_suffix [(DD "")
330                               (TD "q")])
332 (define_insn "dfp_ddedpd_<mode>"
333   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
334         (unspec:D64_D128 [(match_operand:QI 1 "const_0_to_3_operand" "i")
335                           (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
336                          UNSPEC_DDEDPD))]
337   "TARGET_DFP"
338   "ddedpd<dfp_suffix> %1,%0,%2"
339   [(set_attr "type" "dfp")])
341 (define_insn "dfp_denbcd_<mode>"
342   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
343         (unspec:D64_D128 [(match_operand:QI 1 "const_0_to_1_operand" "i")
344                           (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
345                          UNSPEC_DENBCD))]
346   "TARGET_DFP"
347   "denbcd<dfp_suffix> %1,%0,%2"
348   [(set_attr "type" "dfp")])
350 (define_insn "dfp_dxex_<mode>"
351   [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
352         (unspec:DI [(match_operand:D64_D128 1 "gpc_reg_operand" "d")]
353                    UNSPEC_DXEX))]
354   "TARGET_DFP"
355   "dxex<dfp_suffix> %0,%1"
356   [(set_attr "type" "dfp")])
358 (define_insn "dfp_diex_<mode>"
359   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
360         (unspec:D64_D128 [(match_operand:DI 1 "gpc_reg_operand" "d")
361                           (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
362                          UNSPEC_DXEX))]
363   "TARGET_DFP"
364   "diex<dfp_suffix> %0,%1,%2"
365   [(set_attr "type" "dfp")])
367 (define_expand "dfptstsfi_<code>_<mode>"
368   [(set (match_dup 3)
369         (compare:CCFP
370          (unspec:D64_D128
371           [(match_operand:SI 1 "const_int_operand" "n")
372            (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
373           UNSPEC_DTSTSFI)
374          (match_dup 4)))
375    (set (match_operand:SI 0 "register_operand" "")
376         (DFP_TEST:SI (match_dup 3)
377                      (const_int 0)))
378   ]
379   "TARGET_P9_MISC"
381   operands[3] = gen_reg_rtx (CCFPmode);
382   operands[4] = const0_rtx;
385 (define_insn "*dfp_sgnfcnc_<mode>"
386   [(set (match_operand:CCFP 0 "" "=y")
387         (compare:CCFP
388          (unspec:D64_D128 [(match_operand:SI 1 "const_int_operand" "n")
389                            (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
390           UNSPEC_DTSTSFI)
391          (match_operand:SI 3 "zero_constant" "j")))]
392   "TARGET_P9_MISC"
394   /* If immediate operand is greater than 63, it will behave as if
395      the value had been 63.  The code generator does not support
396      immediate operand values greater than 63.  */
397   if (!(IN_RANGE (INTVAL (operands[1]), 0, 63)))
398     operands[1] = GEN_INT (63);
399   return "dtstsfi<dfp_suffix> %0,%1,%2";
401   [(set_attr "type" "fp")])
403 (define_insn "dfp_dscli_<mode>"
404   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
405         (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
406                           (match_operand:QI 2 "immediate_operand" "i")]
407                          UNSPEC_DSCLI))]
408   "TARGET_DFP"
409   "dscli<dfp_suffix> %0,%1,%2"
410   [(set_attr "type" "dfp")])
412 (define_insn "dfp_dscri_<mode>"
413   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
414         (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
415                           (match_operand:QI 2 "immediate_operand" "i")]
416                          UNSPEC_DSCRI))]
417   "TARGET_DFP"
418   "dscri<dfp_suffix> %0,%1,%2"
419   [(set_attr "type" "dfp")])