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))
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))
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")])
82 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
83 (neg:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
86 [(set_attr "type" "fpsimple")])
89 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
90 (abs:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
93 [(set_attr "type" "fpsimple")])
95 (define_insn "*nabsdd2_fpr"
96 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
97 (neg:DD (abs:DD (match_operand:DD 1 "gpc_reg_operand" "d"))))]
100 [(set_attr "type" "fpsimple")])
102 (define_insn "negtd2"
103 [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d")
104 (neg:TD (match_operand:TD 1 "gpc_reg_operand" "0,d")))]
108 fneg %0,%1\;fmr %L0,%L1"
109 [(set_attr "type" "fpsimple")
110 (set_attr "length" "4,8")])
112 (define_insn "abstd2"
113 [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d")
114 (abs:TD (match_operand:TD 1 "gpc_reg_operand" "0,d")))]
118 fabs %0,%1\;fmr %L0,%L1"
119 [(set_attr "type" "fpsimple")
120 (set_attr "length" "4,8")])
122 (define_insn "*nabstd2_fpr"
123 [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d")
124 (neg:TD (abs:TD (match_operand:TD 1 "gpc_reg_operand" "0,d"))))]
128 fnabs %0,%1\;fmr %L0,%L1"
129 [(set_attr "type" "fpsimple")
130 (set_attr "length" "4,8")])
132 ;; Hardware support for decimal floating point operations.
134 (define_insn "extendddtd2"
135 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
136 (float_extend:TD (match_operand:DD 1 "gpc_reg_operand" "d")))]
139 [(set_attr "type" "dfp")])
141 ;; The result of drdpq is an even/odd register pair with the converted
142 ;; value in the even register and zero in the odd register.
143 ;; FIXME: Avoid the register move by using a reload constraint to ensure
144 ;; that the result is the first of the pair receiving the result of drdpq.
146 (define_insn "trunctddd2"
147 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
148 (float_truncate:DD (match_operand:TD 1 "gpc_reg_operand" "d")))
149 (clobber (match_scratch:TD 2 "=d"))]
151 "drdpq %2,%1\;fmr %0,%2"
152 [(set_attr "type" "dfp")
153 (set_attr "length" "8")])
155 (define_insn "adddd3"
156 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
157 (plus:DD (match_operand:DD 1 "gpc_reg_operand" "%d")
158 (match_operand:DD 2 "gpc_reg_operand" "d")))]
161 [(set_attr "type" "dfp")])
163 (define_insn "addtd3"
164 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
165 (plus:TD (match_operand:TD 1 "gpc_reg_operand" "%d")
166 (match_operand:TD 2 "gpc_reg_operand" "d")))]
169 [(set_attr "type" "dfp")])
171 (define_insn "subdd3"
172 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
173 (minus:DD (match_operand:DD 1 "gpc_reg_operand" "d")
174 (match_operand:DD 2 "gpc_reg_operand" "d")))]
177 [(set_attr "type" "dfp")])
179 (define_insn "subtd3"
180 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
181 (minus:TD (match_operand:TD 1 "gpc_reg_operand" "d")
182 (match_operand:TD 2 "gpc_reg_operand" "d")))]
185 [(set_attr "type" "dfp")])
187 (define_insn "muldd3"
188 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
189 (mult:DD (match_operand:DD 1 "gpc_reg_operand" "%d")
190 (match_operand:DD 2 "gpc_reg_operand" "d")))]
193 [(set_attr "type" "dfp")])
195 (define_insn "multd3"
196 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
197 (mult:TD (match_operand:TD 1 "gpc_reg_operand" "%d")
198 (match_operand:TD 2 "gpc_reg_operand" "d")))]
201 [(set_attr "type" "dfp")])
203 (define_insn "divdd3"
204 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
205 (div:DD (match_operand:DD 1 "gpc_reg_operand" "d")
206 (match_operand:DD 2 "gpc_reg_operand" "d")))]
209 [(set_attr "type" "dfp")])
211 (define_insn "divtd3"
212 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
213 (div:TD (match_operand:TD 1 "gpc_reg_operand" "d")
214 (match_operand:TD 2 "gpc_reg_operand" "d")))]
217 [(set_attr "type" "dfp")])
219 (define_insn "*cmpdd_internal1"
220 [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
221 (compare:CCFP (match_operand:DD 1 "gpc_reg_operand" "d")
222 (match_operand:DD 2 "gpc_reg_operand" "d")))]
225 [(set_attr "type" "dfp")])
227 (define_insn "*cmptd_internal1"
228 [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
229 (compare:CCFP (match_operand:TD 1 "gpc_reg_operand" "d")
230 (match_operand:TD 2 "gpc_reg_operand" "d")))]
233 [(set_attr "type" "dfp")])
235 (define_insn "floatdidd2"
236 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
237 (float:DD (match_operand:DI 1 "gpc_reg_operand" "d")))]
238 "TARGET_DFP && TARGET_POPCNTD"
240 [(set_attr "type" "dfp")])
242 (define_insn "floatditd2"
243 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
244 (float:TD (match_operand:DI 1 "gpc_reg_operand" "d")))]
247 [(set_attr "type" "dfp")])
249 ;; Convert a decimal64 to a decimal64 whose value is an integer.
250 ;; This is the first stage of converting it to an integer type.
252 (define_insn "ftruncdd2"
253 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
254 (fix:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
257 [(set_attr "type" "dfp")])
259 ;; Convert a decimal64 whose value is an integer to an actual integer.
260 ;; This is the second stage of converting decimal float to integer type.
262 (define_insn "fixdddi2"
263 [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
264 (fix:DI (match_operand:DD 1 "gpc_reg_operand" "d")))]
267 [(set_attr "type" "dfp")])
269 ;; Convert a decimal128 to a decimal128 whose value is an integer.
270 ;; This is the first stage of converting it to an integer type.
272 (define_insn "ftrunctd2"
273 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
274 (fix:TD (match_operand:TD 1 "gpc_reg_operand" "d")))]
277 [(set_attr "type" "dfp")])
279 ;; Convert a decimal128 whose value is an integer to an actual integer.
280 ;; This is the second stage of converting decimal float to integer type.
282 (define_insn "fixtddi2"
283 [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
284 (fix:DI (match_operand:TD 1 "gpc_reg_operand" "d")))]
287 [(set_attr "type" "dfp")])
290 ;; Decimal builtin support
292 (define_c_enum "unspec"
301 (define_code_iterator DFP_TEST [eq lt gt unordered])
303 (define_mode_iterator D64_D128 [DD TD])
305 (define_mode_attr dfp_suffix [(DD "")
308 (define_insn "dfp_ddedpd_<mode>"
309 [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
310 (unspec:D64_D128 [(match_operand:QI 1 "const_0_to_3_operand" "i")
311 (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
314 "ddedpd<dfp_suffix> %1,%0,%2"
315 [(set_attr "type" "dfp")])
317 (define_insn "dfp_denbcd_<mode>"
318 [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
319 (unspec:D64_D128 [(match_operand:QI 1 "const_0_to_1_operand" "i")
320 (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
323 "denbcd<dfp_suffix> %1,%0,%2"
324 [(set_attr "type" "dfp")])
326 (define_insn "dfp_dxex_<mode>"
327 [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
328 (unspec:DI [(match_operand:D64_D128 1 "gpc_reg_operand" "d")]
331 "dxex<dfp_suffix> %0,%1"
332 [(set_attr "type" "dfp")])
334 (define_insn "dfp_diex_<mode>"
335 [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
336 (unspec:D64_D128 [(match_operand:DI 1 "gpc_reg_operand" "d")
337 (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
340 "diex<dfp_suffix> %0,%1,%2"
341 [(set_attr "type" "dfp")])
343 (define_expand "dfptstsfi_<code>_<mode>"
347 [(match_operand:SI 1 "const_int_operand" "n")
348 (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
351 (set (match_operand:SI 0 "register_operand" "")
352 (DFP_TEST:SI (match_dup 3)
357 operands[3] = gen_reg_rtx (CCFPmode);
358 operands[4] = const0_rtx;
361 (define_insn "*dfp_sgnfcnc_<mode>"
362 [(set (match_operand:CCFP 0 "" "=y")
364 (unspec:D64_D128 [(match_operand:SI 1 "const_int_operand" "n")
365 (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
367 (match_operand:SI 3 "zero_constant" "j")))]
370 /* If immediate operand is greater than 63, it will behave as if
371 the value had been 63. The code generator does not support
372 immediate operand values greater than 63. */
373 if (!(IN_RANGE (INTVAL (operands[1]), 0, 63)))
374 operands[1] = GEN_INT (63);
375 return "dtstsfi<dfp_suffix> %0,%1,%2";
377 [(set_attr "type" "fp")])
379 (define_insn "dfp_dscli_<mode>"
380 [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
381 (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
382 (match_operand:QI 2 "immediate_operand" "i")]
385 "dscli<dfp_suffix> %0,%1,%2"
386 [(set_attr "type" "dfp")])
388 (define_insn "dfp_dscri_<mode>"
389 [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
390 (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
391 (match_operand:QI 2 "immediate_operand" "i")]
394 "dscri<dfp_suffix> %0,%1,%2"
395 [(set_attr "type" "dfp")])