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/>.
26 (define_c_enum "unspec"
32 (define_insn "movsd_store"
33 [(set (match_operand:DD 0 "nonimmediate_operand" "=m")
34 (unspec:DD [(match_operand:SD 1 "input_operand" "d")]
36 "(gpc_reg_operand (operands[0], DDmode)
37 || gpc_reg_operand (operands[1], SDmode))
38 && TARGET_HARD_FLOAT && TARGET_FPRS"
42 (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
43 (const_string "fpstore_ux")
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")]
54 "(gpc_reg_operand (operands[0], SDmode)
55 || gpc_reg_operand (operands[1], DDmode))
56 && TARGET_HARD_FLOAT && TARGET_FPRS"
60 (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
61 (const_string "fpload_ux")
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")))]
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")))]
82 rtx tmp = gen_reg_rtx (DDmode);
83 emit_insn (gen_extendsddd2 (tmp, operands[1]));
84 emit_insn (gen_extendddtd2 (operands[0], tmp));
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")))]
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"
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"
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"
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"
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"
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"
134 (define_insn "*negtd2_fpr"
135 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
136 (neg:TD (match_operand:TD 1 "gpc_reg_operand" "d")))]
137 "TARGET_HARD_FLOAT && TARGET_FPRS"
139 [(set_attr "type" "fp")])
141 (define_expand "abstd2"
142 [(set (match_operand:TD 0 "gpc_reg_operand" "")
143 (abs:TD (match_operand:TD 1 "gpc_reg_operand" "")))]
144 "TARGET_HARD_FLOAT && TARGET_FPRS"
147 (define_insn "*abstd2_fpr"
148 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
149 (abs:TD (match_operand:TD 1 "gpc_reg_operand" "d")))]
150 "TARGET_HARD_FLOAT && TARGET_FPRS"
152 [(set_attr "type" "fp")])
154 (define_insn "*nabstd2_fpr"
155 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
156 (neg:TD (abs:TD (match_operand:TD 1 "gpc_reg_operand" "d"))))]
157 "TARGET_HARD_FLOAT && TARGET_FPRS"
159 [(set_attr "type" "fp")])
161 ;; Hardware support for decimal floating point operations.
163 (define_insn "extendddtd2"
164 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
165 (float_extend:TD (match_operand:DD 1 "gpc_reg_operand" "d")))]
168 [(set_attr "type" "fp")])
170 ;; The result of drdpq is an even/odd register pair with the converted
171 ;; value in the even register and zero in the odd register.
172 ;; FIXME: Avoid the register move by using a reload constraint to ensure
173 ;; that the result is the first of the pair receiving the result of drdpq.
175 (define_insn "trunctddd2"
176 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
177 (float_truncate:DD (match_operand:TD 1 "gpc_reg_operand" "d")))
178 (clobber (match_scratch:TD 2 "=d"))]
180 "drdpq %2,%1\;fmr %0,%2"
181 [(set_attr "type" "fp")])
183 (define_insn "adddd3"
184 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
185 (plus:DD (match_operand:DD 1 "gpc_reg_operand" "%d")
186 (match_operand:DD 2 "gpc_reg_operand" "d")))]
189 [(set_attr "type" "fp")])
191 (define_insn "addtd3"
192 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
193 (plus:TD (match_operand:TD 1 "gpc_reg_operand" "%d")
194 (match_operand:TD 2 "gpc_reg_operand" "d")))]
197 [(set_attr "type" "fp")])
199 (define_insn "subdd3"
200 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
201 (minus:DD (match_operand:DD 1 "gpc_reg_operand" "d")
202 (match_operand:DD 2 "gpc_reg_operand" "d")))]
205 [(set_attr "type" "fp")])
207 (define_insn "subtd3"
208 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
209 (minus:TD (match_operand:TD 1 "gpc_reg_operand" "d")
210 (match_operand:TD 2 "gpc_reg_operand" "d")))]
213 [(set_attr "type" "fp")])
215 (define_insn "muldd3"
216 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
217 (mult:DD (match_operand:DD 1 "gpc_reg_operand" "%d")
218 (match_operand:DD 2 "gpc_reg_operand" "d")))]
221 [(set_attr "type" "fp")])
223 (define_insn "multd3"
224 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
225 (mult:TD (match_operand:TD 1 "gpc_reg_operand" "%d")
226 (match_operand:TD 2 "gpc_reg_operand" "d")))]
229 [(set_attr "type" "fp")])
231 (define_insn "divdd3"
232 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
233 (div:DD (match_operand:DD 1 "gpc_reg_operand" "d")
234 (match_operand:DD 2 "gpc_reg_operand" "d")))]
237 [(set_attr "type" "fp")])
239 (define_insn "divtd3"
240 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
241 (div:TD (match_operand:TD 1 "gpc_reg_operand" "d")
242 (match_operand:TD 2 "gpc_reg_operand" "d")))]
245 [(set_attr "type" "fp")])
247 (define_insn "*cmpdd_internal1"
248 [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
249 (compare:CCFP (match_operand:DD 1 "gpc_reg_operand" "d")
250 (match_operand:DD 2 "gpc_reg_operand" "d")))]
253 [(set_attr "type" "fpcompare")])
255 (define_insn "*cmptd_internal1"
256 [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
257 (compare:CCFP (match_operand:TD 1 "gpc_reg_operand" "d")
258 (match_operand:TD 2 "gpc_reg_operand" "d")))]
261 [(set_attr "type" "fpcompare")])
263 (define_insn "floatdidd2"
264 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
265 (float:DD (match_operand:DI 1 "gpc_reg_operand" "d")))]
266 "TARGET_DFP && TARGET_POPCNTD"
268 [(set_attr "type" "fp")])
270 (define_insn "floatditd2"
271 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
272 (float:TD (match_operand:DI 1 "gpc_reg_operand" "d")))]
275 [(set_attr "type" "fp")])
277 ;; Convert a decimal64 to a decimal64 whose value is an integer.
278 ;; This is the first stage of converting it to an integer type.
280 (define_insn "ftruncdd2"
281 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
282 (fix:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
285 [(set_attr "type" "fp")])
287 ;; Convert a decimal64 whose value is an integer to an actual integer.
288 ;; This is the second stage of converting decimal float to integer type.
290 (define_insn "fixdddi2"
291 [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
292 (fix:DI (match_operand:DD 1 "gpc_reg_operand" "d")))]
295 [(set_attr "type" "fp")])
297 ;; Convert a decimal128 to a decimal128 whose value is an integer.
298 ;; This is the first stage of converting it to an integer type.
300 (define_insn "ftrunctd2"
301 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
302 (fix:TD (match_operand:TD 1 "gpc_reg_operand" "d")))]
305 [(set_attr "type" "fp")])
307 ;; Convert a decimal128 whose value is an integer to an actual integer.
308 ;; This is the second stage of converting decimal float to integer type.
310 (define_insn "fixtddi2"
311 [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
312 (fix:DI (match_operand:TD 1 "gpc_reg_operand" "d")))]
315 [(set_attr "type" "fp")])