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/>.
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"
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")]
47 "(gpc_reg_operand (operands[0], SDmode)
48 || gpc_reg_operand (operands[1], DDmode))
49 && TARGET_HARD_FLOAT && TARGET_FPRS"
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")))]
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")))]
68 rtx tmp = gen_reg_rtx (DDmode);
69 emit_insn (gen_extendsddd2 (tmp, operands[1]));
70 emit_insn (gen_extendddtd2 (operands[0], tmp));
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")))]
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"
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"
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"
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"
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"
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"
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"
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"
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"
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"
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")))]
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"))]
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")))]
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")))]
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")))]
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")))]
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")))]
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")))]
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")))]
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")))]
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")))]
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")))]
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"
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")))]
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")))]
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")))]
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")))]
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")))]
311 [(set_attr "type" "dfp")])
314 ;; Decimal builtin support
316 (define_c_enum "unspec"
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 "")
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")]
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")]
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")]
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")]
364 "diex<dfp_suffix> %0,%1,%2"
365 [(set_attr "type" "dfp")])
367 (define_expand "dfptstsfi_<code>_<mode>"
371 [(match_operand:SI 1 "const_int_operand" "n")
372 (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
375 (set (match_operand:SI 0 "register_operand" "")
376 (DFP_TEST:SI (match_dup 3)
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")
388 (unspec:D64_D128 [(match_operand:SI 1 "const_int_operand" "n")
389 (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
391 (match_operand:SI 3 "zero_constant" "j")))]
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")]
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")]
418 "dscri<dfp_suffix> %0,%1,%2"
419 [(set_attr "type" "dfp")])