Merge branches/gcc-4_8-branch rev 210799.
[official-gcc.git] / gcc-4_8-branch / gcc / config / rs6000 / dfp.md
bloba3c09390ae100c24b3e5e48a7b747cebeee016bb
1 ;; Decimal Floating Point (DFP) patterns.
2 ;; Copyright (C) 2007-2013 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")
41       (if_then_else
42         (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
43         (const_string "fpstore_ux")
44         (if_then_else
45           (match_test "update_address_mem (operands[0], VOIDmode)")
46           (const_string "fpstore_u")
47           (const_string "fpstore"))))
48    (set_attr "length" "4")])
50 (define_insn "movsd_load"
51   [(set (match_operand:SD 0 "nonimmediate_operand" "=f")
52         (unspec:SD [(match_operand:DD 1 "input_operand" "m")]
53                    UNSPEC_MOVSD_LOAD))]
54   "(gpc_reg_operand (operands[0], SDmode)
55    || gpc_reg_operand (operands[1], DDmode))
56    && TARGET_HARD_FLOAT && TARGET_FPRS"
57   "lfd%U1%X1 %0,%1"
58   [(set (attr "type")
59       (if_then_else
60         (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
61         (const_string "fpload_ux")
62         (if_then_else
63           (match_test "update_address_mem (operands[1], VOIDmode)")
64           (const_string "fpload_u")
65           (const_string "fpload"))))
66    (set_attr "length" "4")])
68 ;; Hardware support for decimal floating point operations.
70 (define_insn "extendsddd2"
71   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
72         (float_extend:DD (match_operand:SD 1 "gpc_reg_operand" "f")))]
73   "TARGET_DFP"
74   "dctdp %0,%1"
75   [(set_attr "type" "fp")])
77 (define_expand "extendsdtd2"
78   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
79         (float_extend:TD (match_operand:SD 1 "gpc_reg_operand" "d")))]
80   "TARGET_DFP"
82   rtx tmp = gen_reg_rtx (DDmode);
83   emit_insn (gen_extendsddd2 (tmp, operands[1]));
84   emit_insn (gen_extendddtd2 (operands[0], tmp));
85   DONE;
88 (define_insn "truncddsd2"
89   [(set (match_operand:SD 0 "gpc_reg_operand" "=f")
90         (float_truncate:SD (match_operand:DD 1 "gpc_reg_operand" "d")))]
91   "TARGET_DFP"
92   "drsp %0,%1"
93   [(set_attr "type" "fp")])
95 (define_expand "negdd2"
96   [(set (match_operand:DD 0 "gpc_reg_operand" "")
97         (neg:DD (match_operand:DD 1 "gpc_reg_operand" "")))]
98   "TARGET_HARD_FLOAT && TARGET_FPRS"
99   "")
101 (define_insn "*negdd2_fpr"
102   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
103         (neg:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
104   "TARGET_HARD_FLOAT && TARGET_FPRS"
105   "fneg %0,%1"
106   [(set_attr "type" "fp")])
108 (define_expand "absdd2"
109   [(set (match_operand:DD 0 "gpc_reg_operand" "")
110         (abs:DD (match_operand:DD 1 "gpc_reg_operand" "")))]
111   "TARGET_HARD_FLOAT && TARGET_FPRS"
112   "")
114 (define_insn "*absdd2_fpr"
115   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
116         (abs:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
117   "TARGET_HARD_FLOAT && TARGET_FPRS"
118   "fabs %0,%1"
119   [(set_attr "type" "fp")])
121 (define_insn "*nabsdd2_fpr"
122   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
123         (neg:DD (abs:DD (match_operand:DD 1 "gpc_reg_operand" "d"))))]
124   "TARGET_HARD_FLOAT && TARGET_FPRS"
125   "fnabs %0,%1"
126   [(set_attr "type" "fp")])
128 (define_expand "negtd2"
129   [(set (match_operand:TD 0 "gpc_reg_operand" "")
130         (neg:TD (match_operand:TD 1 "gpc_reg_operand" "")))]
131   "TARGET_HARD_FLOAT && TARGET_FPRS"
132   "")
134 (define_insn "*negtd2_fpr"
135   [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d")
136         (neg:TD (match_operand:TD 1 "gpc_reg_operand" "0,d")))]
137   "TARGET_HARD_FLOAT && TARGET_FPRS"
138   "@
139    fneg %0,%1
140    fneg %0,%1\;fmr %L0,%L1"
141   [(set_attr "type" "fp")
142    (set_attr "length" "4,8")])
144 (define_expand "abstd2"
145   [(set (match_operand:TD 0 "gpc_reg_operand" "")
146         (abs:TD (match_operand:TD 1 "gpc_reg_operand" "")))]
147   "TARGET_HARD_FLOAT && TARGET_FPRS"
148   "")
150 (define_insn "*abstd2_fpr"
151   [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d")
152         (abs:TD (match_operand:TD 1 "gpc_reg_operand" "0,d")))]
153   "TARGET_HARD_FLOAT && TARGET_FPRS"
154   "@
155    fabs %0,%1
156    fabs %0,%1\;fmr %L0,%L1"
157   [(set_attr "type" "fp")
158    (set_attr "length" "4,8")])
160 (define_insn "*nabstd2_fpr"
161   [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d")
162         (neg:TD (abs:TD (match_operand:TD 1 "gpc_reg_operand" "0,d"))))]
163   "TARGET_HARD_FLOAT && TARGET_FPRS"
164   "@
165    fnabs %0,%1
166    fnabs %0,%1\;fmr %L0,%L1"
167   [(set_attr "type" "fp")
168    (set_attr "length" "4,8")])
170 ;; Hardware support for decimal floating point operations.
172 (define_insn "extendddtd2"
173   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
174         (float_extend:TD (match_operand:DD 1 "gpc_reg_operand" "d")))]
175   "TARGET_DFP"
176   "dctqpq %0,%1"
177   [(set_attr "type" "fp")])
179 ;; The result of drdpq is an even/odd register pair with the converted
180 ;; value in the even register and zero in the odd register.
181 ;; FIXME: Avoid the register move by using a reload constraint to ensure
182 ;; that the result is the first of the pair receiving the result of drdpq.
184 (define_insn "trunctddd2"
185   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
186         (float_truncate:DD (match_operand:TD 1 "gpc_reg_operand" "d")))
187    (clobber (match_scratch:TD 2 "=d"))]
188   "TARGET_DFP"
189   "drdpq %2,%1\;fmr %0,%2"
190   [(set_attr "type" "fp")])
192 (define_insn "adddd3"
193   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
194         (plus:DD (match_operand:DD 1 "gpc_reg_operand" "%d")
195                  (match_operand:DD 2 "gpc_reg_operand" "d")))]
196   "TARGET_DFP"
197   "dadd %0,%1,%2"
198   [(set_attr "type" "fp")])
200 (define_insn "addtd3"
201   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
202         (plus:TD (match_operand:TD 1 "gpc_reg_operand" "%d")
203                  (match_operand:TD 2 "gpc_reg_operand" "d")))]
204   "TARGET_DFP"
205   "daddq %0,%1,%2"
206   [(set_attr "type" "fp")])
208 (define_insn "subdd3"
209   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
210         (minus:DD (match_operand:DD 1 "gpc_reg_operand" "d")
211                   (match_operand:DD 2 "gpc_reg_operand" "d")))]
212   "TARGET_DFP"
213   "dsub %0,%1,%2"
214   [(set_attr "type" "fp")])
216 (define_insn "subtd3"
217   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
218         (minus:TD (match_operand:TD 1 "gpc_reg_operand" "d")
219                   (match_operand:TD 2 "gpc_reg_operand" "d")))]
220   "TARGET_DFP"
221   "dsubq %0,%1,%2"
222   [(set_attr "type" "fp")])
224 (define_insn "muldd3"
225   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
226         (mult:DD (match_operand:DD 1 "gpc_reg_operand" "%d")
227                  (match_operand:DD 2 "gpc_reg_operand" "d")))]
228   "TARGET_DFP"
229   "dmul %0,%1,%2"
230   [(set_attr "type" "fp")])
232 (define_insn "multd3"
233   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
234         (mult:TD (match_operand:TD 1 "gpc_reg_operand" "%d")
235                  (match_operand:TD 2 "gpc_reg_operand" "d")))]
236   "TARGET_DFP"
237   "dmulq %0,%1,%2"
238   [(set_attr "type" "fp")])
240 (define_insn "divdd3"
241   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
242         (div:DD (match_operand:DD 1 "gpc_reg_operand" "d")
243                 (match_operand:DD 2 "gpc_reg_operand" "d")))]
244   "TARGET_DFP"
245   "ddiv %0,%1,%2"
246   [(set_attr "type" "fp")])
248 (define_insn "divtd3"
249   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
250         (div:TD (match_operand:TD 1 "gpc_reg_operand" "d")
251                 (match_operand:TD 2 "gpc_reg_operand" "d")))]
252   "TARGET_DFP"
253   "ddivq %0,%1,%2"
254   [(set_attr "type" "fp")])
256 (define_insn "*cmpdd_internal1"
257   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
258         (compare:CCFP (match_operand:DD 1 "gpc_reg_operand" "d")
259                       (match_operand:DD 2 "gpc_reg_operand" "d")))]
260   "TARGET_DFP"
261   "dcmpu %0,%1,%2"
262   [(set_attr "type" "fpcompare")])
264 (define_insn "*cmptd_internal1"
265   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
266         (compare:CCFP (match_operand:TD 1 "gpc_reg_operand" "d")
267                       (match_operand:TD 2 "gpc_reg_operand" "d")))]
268   "TARGET_DFP"
269   "dcmpuq %0,%1,%2"
270   [(set_attr "type" "fpcompare")])
272 (define_insn "floatdidd2"
273   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
274         (float:DD (match_operand:DI 1 "gpc_reg_operand" "d")))]
275   "TARGET_DFP && TARGET_POPCNTD"
276   "dcffix %0,%1"
277   [(set_attr "type" "fp")])
279 (define_insn "floatditd2"
280   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
281         (float:TD (match_operand:DI 1 "gpc_reg_operand" "d")))]
282   "TARGET_DFP"
283   "dcffixq %0,%1"
284   [(set_attr "type" "fp")])
286 ;; Convert a decimal64 to a decimal64 whose value is an integer.
287 ;; This is the first stage of converting it to an integer type.
289 (define_insn "ftruncdd2"
290   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
291         (fix:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
292   "TARGET_DFP"
293   "drintn. 0,%0,%1,1"
294   [(set_attr "type" "fp")])
296 ;; Convert a decimal64 whose value is an integer to an actual integer.
297 ;; This is the second stage of converting decimal float to integer type.
299 (define_insn "fixdddi2"
300   [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
301         (fix:DI (match_operand:DD 1 "gpc_reg_operand" "d")))]
302   "TARGET_DFP"
303   "dctfix %0,%1"
304   [(set_attr "type" "fp")])
306 ;; Convert a decimal128 to a decimal128 whose value is an integer.
307 ;; This is the first stage of converting it to an integer type.
309 (define_insn "ftrunctd2"
310   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
311         (fix:TD (match_operand:TD 1 "gpc_reg_operand" "d")))]
312   "TARGET_DFP"
313   "drintnq. 0,%0,%1,1"
314   [(set_attr "type" "fp")])
316 ;; Convert a decimal128 whose value is an integer to an actual integer.
317 ;; This is the second stage of converting decimal float to integer type.
319 (define_insn "fixtddi2"
320   [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
321         (fix:DI (match_operand:TD 1 "gpc_reg_operand" "d")))]
322   "TARGET_DFP"
323   "dctfixq %0,%1"
324   [(set_attr "type" "fp")])
327 ;; Decimal builtin support
329 (define_c_enum "unspec"
330   [UNSPEC_DDEDPD
331    UNSPEC_DENBCD
332    UNSPEC_DXEX
333    UNSPEC_DIEX
334    UNSPEC_DSCLI
335    UNSPEC_DSCRI])
337 (define_mode_iterator D64_D128 [DD TD])
339 (define_mode_attr dfp_suffix [(DD "")
340                               (TD "q")])
342 (define_insn "dfp_ddedpd_<mode>"
343   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
344         (unspec:D64_D128 [(match_operand:QI 1 "const_0_to_3_operand" "i")
345                           (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
346                          UNSPEC_DDEDPD))]
347   "TARGET_DFP"
348   "ddedpd<dfp_suffix> %1,%0,%2"
349   [(set_attr "type" "fp")])
351 (define_insn "dfp_denbcd_<mode>"
352   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
353         (unspec:D64_D128 [(match_operand:QI 1 "const_0_to_1_operand" "i")
354                           (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
355                          UNSPEC_DENBCD))]
356   "TARGET_DFP"
357   "denbcd<dfp_suffix> %1,%0,%2"
358   [(set_attr "type" "fp")])
360 (define_insn "dfp_dxex_<mode>"
361   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
362         (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")]
363                          UNSPEC_DXEX))]
364   "TARGET_DFP"
365   "dxex<dfp_suffix> %0,%1"
366   [(set_attr "type" "fp")])
368 (define_insn "dfp_diex_<mode>"
369   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
370         (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
371                           (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
372                          UNSPEC_DXEX))]
373   "TARGET_DFP"
374   "diex<dfp_suffix> %0,%1,%2"
375   [(set_attr "type" "fp")])
377 (define_insn "dfp_dscli_<mode>"
378   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
379         (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
380                           (match_operand:QI 2 "immediate_operand" "i")]
381                          UNSPEC_DSCLI))]
382   "TARGET_DFP"
383   "dscli<dfp_suffix> %0,%1,%2"
384   [(set_attr "type" "fp")])
386 (define_insn "dfp_dscri_<mode>"
387   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
388         (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
389                           (match_operand:QI 2 "immediate_operand" "i")]
390                          UNSPEC_DSCRI))]
391   "TARGET_DFP"
392   "dscri<dfp_suffix> %0,%1,%2"
393   [(set_attr "type" "fp")])