2014-10-24 Richard Biener <rguenther@suse.de>
[official-gcc.git] / gcc / config / rs6000 / dfp.md
blob63ae541225e709b7b1bc1023fa3b87096cdb2650
1 ;; Decimal Floating Point (DFP) patterns.
2 ;; Copyright (C) 2007-2014 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" "fp")])
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" "fp")])
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" "fp")])
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" "fp")])
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" "fp")])
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" "fp")
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" "fp")
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" "fp")
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" "fp")])
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" "fp")])
178 (define_insn "adddd3"
179   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
180         (plus:DD (match_operand:DD 1 "gpc_reg_operand" "%d")
181                  (match_operand:DD 2 "gpc_reg_operand" "d")))]
182   "TARGET_DFP"
183   "dadd %0,%1,%2"
184   [(set_attr "type" "fp")])
186 (define_insn "addtd3"
187   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
188         (plus:TD (match_operand:TD 1 "gpc_reg_operand" "%d")
189                  (match_operand:TD 2 "gpc_reg_operand" "d")))]
190   "TARGET_DFP"
191   "daddq %0,%1,%2"
192   [(set_attr "type" "fp")])
194 (define_insn "subdd3"
195   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
196         (minus:DD (match_operand:DD 1 "gpc_reg_operand" "d")
197                   (match_operand:DD 2 "gpc_reg_operand" "d")))]
198   "TARGET_DFP"
199   "dsub %0,%1,%2"
200   [(set_attr "type" "fp")])
202 (define_insn "subtd3"
203   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
204         (minus:TD (match_operand:TD 1 "gpc_reg_operand" "d")
205                   (match_operand:TD 2 "gpc_reg_operand" "d")))]
206   "TARGET_DFP"
207   "dsubq %0,%1,%2"
208   [(set_attr "type" "fp")])
210 (define_insn "muldd3"
211   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
212         (mult:DD (match_operand:DD 1 "gpc_reg_operand" "%d")
213                  (match_operand:DD 2 "gpc_reg_operand" "d")))]
214   "TARGET_DFP"
215   "dmul %0,%1,%2"
216   [(set_attr "type" "fp")])
218 (define_insn "multd3"
219   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
220         (mult:TD (match_operand:TD 1 "gpc_reg_operand" "%d")
221                  (match_operand:TD 2 "gpc_reg_operand" "d")))]
222   "TARGET_DFP"
223   "dmulq %0,%1,%2"
224   [(set_attr "type" "fp")])
226 (define_insn "divdd3"
227   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
228         (div:DD (match_operand:DD 1 "gpc_reg_operand" "d")
229                 (match_operand:DD 2 "gpc_reg_operand" "d")))]
230   "TARGET_DFP"
231   "ddiv %0,%1,%2"
232   [(set_attr "type" "fp")])
234 (define_insn "divtd3"
235   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
236         (div:TD (match_operand:TD 1 "gpc_reg_operand" "d")
237                 (match_operand:TD 2 "gpc_reg_operand" "d")))]
238   "TARGET_DFP"
239   "ddivq %0,%1,%2"
240   [(set_attr "type" "fp")])
242 (define_insn "*cmpdd_internal1"
243   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
244         (compare:CCFP (match_operand:DD 1 "gpc_reg_operand" "d")
245                       (match_operand:DD 2 "gpc_reg_operand" "d")))]
246   "TARGET_DFP"
247   "dcmpu %0,%1,%2"
248   [(set_attr "type" "fpcompare")])
250 (define_insn "*cmptd_internal1"
251   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
252         (compare:CCFP (match_operand:TD 1 "gpc_reg_operand" "d")
253                       (match_operand:TD 2 "gpc_reg_operand" "d")))]
254   "TARGET_DFP"
255   "dcmpuq %0,%1,%2"
256   [(set_attr "type" "fpcompare")])
258 (define_insn "floatdidd2"
259   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
260         (float:DD (match_operand:DI 1 "gpc_reg_operand" "d")))]
261   "TARGET_DFP && TARGET_POPCNTD"
262   "dcffix %0,%1"
263   [(set_attr "type" "fp")])
265 (define_insn "floatditd2"
266   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
267         (float:TD (match_operand:DI 1 "gpc_reg_operand" "d")))]
268   "TARGET_DFP"
269   "dcffixq %0,%1"
270   [(set_attr "type" "fp")])
272 ;; Convert a decimal64 to a decimal64 whose value is an integer.
273 ;; This is the first stage of converting it to an integer type.
275 (define_insn "ftruncdd2"
276   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
277         (fix:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
278   "TARGET_DFP"
279   "drintn. 0,%0,%1,1"
280   [(set_attr "type" "fp")])
282 ;; Convert a decimal64 whose value is an integer to an actual integer.
283 ;; This is the second stage of converting decimal float to integer type.
285 (define_insn "fixdddi2"
286   [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
287         (fix:DI (match_operand:DD 1 "gpc_reg_operand" "d")))]
288   "TARGET_DFP"
289   "dctfix %0,%1"
290   [(set_attr "type" "fp")])
292 ;; Convert a decimal128 to a decimal128 whose value is an integer.
293 ;; This is the first stage of converting it to an integer type.
295 (define_insn "ftrunctd2"
296   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
297         (fix:TD (match_operand:TD 1 "gpc_reg_operand" "d")))]
298   "TARGET_DFP"
299   "drintnq. 0,%0,%1,1"
300   [(set_attr "type" "fp")])
302 ;; Convert a decimal128 whose value is an integer to an actual integer.
303 ;; This is the second stage of converting decimal float to integer type.
305 (define_insn "fixtddi2"
306   [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
307         (fix:DI (match_operand:TD 1 "gpc_reg_operand" "d")))]
308   "TARGET_DFP"
309   "dctfixq %0,%1"
310   [(set_attr "type" "fp")])
313 ;; Decimal builtin support
315 (define_c_enum "unspec"
316   [UNSPEC_DDEDPD
317    UNSPEC_DENBCD
318    UNSPEC_DXEX
319    UNSPEC_DIEX
320    UNSPEC_DSCLI
321    UNSPEC_DSCRI])
323 (define_mode_iterator D64_D128 [DD TD])
325 (define_mode_attr dfp_suffix [(DD "")
326                               (TD "q")])
328 (define_insn "dfp_ddedpd_<mode>"
329   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
330         (unspec:D64_D128 [(match_operand:QI 1 "const_0_to_3_operand" "i")
331                           (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
332                          UNSPEC_DDEDPD))]
333   "TARGET_DFP"
334   "ddedpd<dfp_suffix> %1,%0,%2"
335   [(set_attr "type" "fp")])
337 (define_insn "dfp_denbcd_<mode>"
338   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
339         (unspec:D64_D128 [(match_operand:QI 1 "const_0_to_1_operand" "i")
340                           (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
341                          UNSPEC_DENBCD))]
342   "TARGET_DFP"
343   "denbcd<dfp_suffix> %1,%0,%2"
344   [(set_attr "type" "fp")])
346 (define_insn "dfp_dxex_<mode>"
347   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
348         (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")]
349                          UNSPEC_DXEX))]
350   "TARGET_DFP"
351   "dxex<dfp_suffix> %0,%1"
352   [(set_attr "type" "fp")])
354 (define_insn "dfp_diex_<mode>"
355   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
356         (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
357                           (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
358                          UNSPEC_DXEX))]
359   "TARGET_DFP"
360   "diex<dfp_suffix> %0,%1,%2"
361   [(set_attr "type" "fp")])
363 (define_insn "dfp_dscli_<mode>"
364   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
365         (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
366                           (match_operand:QI 2 "immediate_operand" "i")]
367                          UNSPEC_DSCLI))]
368   "TARGET_DFP"
369   "dscli<dfp_suffix> %0,%1,%2"
370   [(set_attr "type" "fp")])
372 (define_insn "dfp_dscri_<mode>"
373   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
374         (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
375                           (match_operand:QI 2 "immediate_operand" "i")]
376                          UNSPEC_DSCRI))]
377   "TARGET_DFP"
378   "dscri<dfp_suffix> %0,%1,%2"
379   [(set_attr "type" "fp")])