dfp.md revision 1.10 1 ;; Decimal Floating Point (DFP) patterns.
2 ;; Copyright (C) 2007-2018 Free Software Foundation, Inc.
3 ;; Contributed by Ben Elliston (bje (a] au.ibm.com) and Peter Bergner
4 ;; (bergner (a] vnet.ibm.com).
5
6 ;; This file is part of GCC.
7
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.
12
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.
17
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/>.
21
22 ;;
23 ;; UNSPEC usage
24 ;;
25
26 (define_c_enum "unspec"
27 [UNSPEC_MOVSD_LOAD
28 UNSPEC_MOVSD_STORE
29 ])
30
31
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"
39 "stfd%U0%X0 %1,%0"
40 [(set_attr "type" "fpstore")
41 (set_attr "length" "4")])
42
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"
50 "lfd%U1%X1 %0,%1"
51 [(set_attr "type" "fpload")
52 (set_attr "length" "4")])
53
54 ;; Hardware support for decimal floating point operations.
55
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" "dfp")])
62
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"
67 {
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;
72 })
73
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" "dfp")])
80
81 (define_insn "negdd2"
82 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
83 (neg:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
84 "TARGET_HARD_FLOAT"
85 "fneg %0,%1"
86 [(set_attr "type" "fpsimple")])
87
88 (define_insn "absdd2"
89 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
90 (abs:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
91 "TARGET_HARD_FLOAT"
92 "fabs %0,%1"
93 [(set_attr "type" "fpsimple")])
94
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"))))]
98 "TARGET_HARD_FLOAT"
99 "fnabs %0,%1"
100 [(set_attr "type" "fpsimple")])
101
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")))]
105 "TARGET_HARD_FLOAT"
106 "@
107 fneg %0,%1
108 fneg %0,%1\;fmr %L0,%L1"
109 [(set_attr "type" "fpsimple")
110 (set_attr "length" "4,8")])
111
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")))]
115 "TARGET_HARD_FLOAT"
116 "@
117 fabs %0,%1
118 fabs %0,%1\;fmr %L0,%L1"
119 [(set_attr "type" "fpsimple")
120 (set_attr "length" "4,8")])
121
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"))))]
125 "TARGET_HARD_FLOAT"
126 "@
127 fnabs %0,%1
128 fnabs %0,%1\;fmr %L0,%L1"
129 [(set_attr "type" "fpsimple")
130 (set_attr "length" "4,8")])
131
132 ;; Hardware support for decimal floating point operations.
133
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")))]
137 "TARGET_DFP"
138 "dctqpq %0,%1"
139 [(set_attr "type" "dfp")])
140
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.
145
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"))]
150 "TARGET_DFP"
151 "drdpq %2,%1\;fmr %0,%2"
152 [(set_attr "type" "dfp")
153 (set_attr "length" "8")])
154
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")))]
159 "TARGET_DFP"
160 "dadd %0,%1,%2"
161 [(set_attr "type" "dfp")])
162
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")))]
167 "TARGET_DFP"
168 "daddq %0,%1,%2"
169 [(set_attr "type" "dfp")])
170
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")))]
175 "TARGET_DFP"
176 "dsub %0,%1,%2"
177 [(set_attr "type" "dfp")])
178
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")))]
183 "TARGET_DFP"
184 "dsubq %0,%1,%2"
185 [(set_attr "type" "dfp")])
186
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")))]
191 "TARGET_DFP"
192 "dmul %0,%1,%2"
193 [(set_attr "type" "dfp")])
194
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")))]
199 "TARGET_DFP"
200 "dmulq %0,%1,%2"
201 [(set_attr "type" "dfp")])
202
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")))]
207 "TARGET_DFP"
208 "ddiv %0,%1,%2"
209 [(set_attr "type" "dfp")])
210
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")))]
215 "TARGET_DFP"
216 "ddivq %0,%1,%2"
217 [(set_attr "type" "dfp")])
218
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")))]
223 "TARGET_DFP"
224 "dcmpu %0,%1,%2"
225 [(set_attr "type" "dfp")])
226
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")))]
231 "TARGET_DFP"
232 "dcmpuq %0,%1,%2"
233 [(set_attr "type" "dfp")])
234
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"
239 "dcffix %0,%1"
240 [(set_attr "type" "dfp")])
241
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")))]
245 "TARGET_DFP"
246 "dcffixq %0,%1"
247 [(set_attr "type" "dfp")])
248
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.
251
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")))]
255 "TARGET_DFP"
256 "drintn. 0,%0,%1,1"
257 [(set_attr "type" "dfp")])
258
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.
261
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")))]
265 "TARGET_DFP"
266 "dctfix %0,%1"
267 [(set_attr "type" "dfp")])
268
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.
271
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")))]
275 "TARGET_DFP"
276 "drintnq. 0,%0,%1,1"
277 [(set_attr "type" "dfp")])
278
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.
281
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")))]
285 "TARGET_DFP"
286 "dctfixq %0,%1"
287 [(set_attr "type" "dfp")])
288
289
291 ;; Decimal builtin support
292
293 (define_c_enum "unspec"
294 [UNSPEC_DDEDPD
295 UNSPEC_DENBCD
296 UNSPEC_DXEX
297 UNSPEC_DIEX
298 UNSPEC_DSCLI
299 UNSPEC_DTSTSFI
300 UNSPEC_DSCRI])
301
302 (define_code_iterator DFP_TEST [eq lt gt unordered])
303
304 (define_mode_iterator D64_D128 [DD TD])
305
306 (define_mode_attr dfp_suffix [(DD "")
307 (TD "q")])
308
309 (define_insn "dfp_ddedpd_<mode>"
310 [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
311 (unspec:D64_D128 [(match_operand:QI 1 "const_0_to_3_operand" "i")
312 (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
313 UNSPEC_DDEDPD))]
314 "TARGET_DFP"
315 "ddedpd<dfp_suffix> %1,%0,%2"
316 [(set_attr "type" "dfp")])
317
318 (define_insn "dfp_denbcd_<mode>"
319 [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
320 (unspec:D64_D128 [(match_operand:QI 1 "const_0_to_1_operand" "i")
321 (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
322 UNSPEC_DENBCD))]
323 "TARGET_DFP"
324 "denbcd<dfp_suffix> %1,%0,%2"
325 [(set_attr "type" "dfp")])
326
327 (define_insn "dfp_dxex_<mode>"
328 [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
329 (unspec:DI [(match_operand:D64_D128 1 "gpc_reg_operand" "d")]
330 UNSPEC_DXEX))]
331 "TARGET_DFP"
332 "dxex<dfp_suffix> %0,%1"
333 [(set_attr "type" "dfp")])
334
335 (define_insn "dfp_diex_<mode>"
336 [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
337 (unspec:D64_D128 [(match_operand:DI 1 "gpc_reg_operand" "d")
338 (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
339 UNSPEC_DXEX))]
340 "TARGET_DFP"
341 "diex<dfp_suffix> %0,%1,%2"
342 [(set_attr "type" "dfp")])
343
344 (define_expand "dfptstsfi_<code>_<mode>"
345 [(set (match_dup 3)
346 (compare:CCFP
347 (unspec:D64_D128
348 [(match_operand:SI 1 "const_int_operand")
349 (match_operand:D64_D128 2 "gpc_reg_operand")]
350 UNSPEC_DTSTSFI)
351 (match_dup 4)))
352 (set (match_operand:SI 0 "register_operand")
353 (DFP_TEST:SI (match_dup 3)
354 (const_int 0)))
355 ]
356 "TARGET_P9_MISC"
357 {
358 operands[3] = gen_reg_rtx (CCFPmode);
359 operands[4] = const0_rtx;
360 })
361
362 (define_insn "*dfp_sgnfcnc_<mode>"
363 [(set (match_operand:CCFP 0 "" "=y")
364 (compare:CCFP
365 (unspec:D64_D128 [(match_operand:SI 1 "const_int_operand" "n")
366 (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
367 UNSPEC_DTSTSFI)
368 (match_operand:SI 3 "zero_constant" "j")))]
369 "TARGET_P9_MISC"
370 {
371 /* If immediate operand is greater than 63, it will behave as if
372 the value had been 63. The code generator does not support
373 immediate operand values greater than 63. */
374 if (!(IN_RANGE (INTVAL (operands[1]), 0, 63)))
375 operands[1] = GEN_INT (63);
376 return "dtstsfi<dfp_suffix> %0,%1,%2";
377 }
378 [(set_attr "type" "fp")])
379
380 (define_insn "dfp_dscli_<mode>"
381 [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
382 (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
383 (match_operand:QI 2 "immediate_operand" "i")]
384 UNSPEC_DSCLI))]
385 "TARGET_DFP"
386 "dscli<dfp_suffix> %0,%1,%2"
387 [(set_attr "type" "dfp")])
388
389 (define_insn "dfp_dscri_<mode>"
390 [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
391 (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
392 (match_operand:QI 2 "immediate_operand" "i")]
393 UNSPEC_DSCRI))]
394 "TARGET_DFP"
395 "dscri<dfp_suffix> %0,%1,%2"
396 [(set_attr "type" "dfp")])
397