dfp.md revision 1.5 1 ;; Decimal Floating Point (DFP) patterns.
2 ;; Copyright (C) 2007-2015 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 && TARGET_FPRS"
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 && TARGET_FPRS"
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" "fp")])
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" "fp")])
80
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"
85 "")
86
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"
91 "fneg %0,%1"
92 [(set_attr "type" "fp")])
93
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"
98 "")
99
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"
104 "fabs %0,%1"
105 [(set_attr "type" "fp")])
106
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"
111 "fnabs %0,%1"
112 [(set_attr "type" "fp")])
113
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"
118 "")
119
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"
124 "@
125 fneg %0,%1
126 fneg %0,%1\;fmr %L0,%L1"
127 [(set_attr "type" "fp")
128 (set_attr "length" "4,8")])
129
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"
134 "")
135
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"
140 "@
141 fabs %0,%1
142 fabs %0,%1\;fmr %L0,%L1"
143 [(set_attr "type" "fp")
144 (set_attr "length" "4,8")])
145
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"
150 "@
151 fnabs %0,%1
152 fnabs %0,%1\;fmr %L0,%L1"
153 [(set_attr "type" "fp")
154 (set_attr "length" "4,8")])
155
156 ;; Hardware support for decimal floating point operations.
157
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")))]
161 "TARGET_DFP"
162 "dctqpq %0,%1"
163 [(set_attr "type" "fp")])
164
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.
169
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"))]
174 "TARGET_DFP"
175 "drdpq %2,%1\;fmr %0,%2"
176 [(set_attr "type" "fp")])
177
178 (define_insn "adddd3"
179 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
180 (plus:DD (match_operand:DD 1 "gpc_reg_operand" "%d")
181 (match_operand:DD 2 "gpc_reg_operand" "d")))]
182 "TARGET_DFP"
183 "dadd %0,%1,%2"
184 [(set_attr "type" "fp")])
185
186 (define_insn "addtd3"
187 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
188 (plus:TD (match_operand:TD 1 "gpc_reg_operand" "%d")
189 (match_operand:TD 2 "gpc_reg_operand" "d")))]
190 "TARGET_DFP"
191 "daddq %0,%1,%2"
192 [(set_attr "type" "fp")])
193
194 (define_insn "subdd3"
195 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
196 (minus:DD (match_operand:DD 1 "gpc_reg_operand" "d")
197 (match_operand:DD 2 "gpc_reg_operand" "d")))]
198 "TARGET_DFP"
199 "dsub %0,%1,%2"
200 [(set_attr "type" "fp")])
201
202 (define_insn "subtd3"
203 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
204 (minus:TD (match_operand:TD 1 "gpc_reg_operand" "d")
205 (match_operand:TD 2 "gpc_reg_operand" "d")))]
206 "TARGET_DFP"
207 "dsubq %0,%1,%2"
208 [(set_attr "type" "fp")])
209
210 (define_insn "muldd3"
211 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
212 (mult:DD (match_operand:DD 1 "gpc_reg_operand" "%d")
213 (match_operand:DD 2 "gpc_reg_operand" "d")))]
214 "TARGET_DFP"
215 "dmul %0,%1,%2"
216 [(set_attr "type" "fp")])
217
218 (define_insn "multd3"
219 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
220 (mult:TD (match_operand:TD 1 "gpc_reg_operand" "%d")
221 (match_operand:TD 2 "gpc_reg_operand" "d")))]
222 "TARGET_DFP"
223 "dmulq %0,%1,%2"
224 [(set_attr "type" "fp")])
225
226 (define_insn "divdd3"
227 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
228 (div:DD (match_operand:DD 1 "gpc_reg_operand" "d")
229 (match_operand:DD 2 "gpc_reg_operand" "d")))]
230 "TARGET_DFP"
231 "ddiv %0,%1,%2"
232 [(set_attr "type" "fp")])
233
234 (define_insn "divtd3"
235 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
236 (div:TD (match_operand:TD 1 "gpc_reg_operand" "d")
237 (match_operand:TD 2 "gpc_reg_operand" "d")))]
238 "TARGET_DFP"
239 "ddivq %0,%1,%2"
240 [(set_attr "type" "fp")])
241
242 (define_insn "*cmpdd_internal1"
243 [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
244 (compare:CCFP (match_operand:DD 1 "gpc_reg_operand" "d")
245 (match_operand:DD 2 "gpc_reg_operand" "d")))]
246 "TARGET_DFP"
247 "dcmpu %0,%1,%2"
248 [(set_attr "type" "fpcompare")])
249
250 (define_insn "*cmptd_internal1"
251 [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
252 (compare:CCFP (match_operand:TD 1 "gpc_reg_operand" "d")
253 (match_operand:TD 2 "gpc_reg_operand" "d")))]
254 "TARGET_DFP"
255 "dcmpuq %0,%1,%2"
256 [(set_attr "type" "fpcompare")])
257
258 (define_insn "floatdidd2"
259 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
260 (float:DD (match_operand:DI 1 "gpc_reg_operand" "d")))]
261 "TARGET_DFP && TARGET_POPCNTD"
262 "dcffix %0,%1"
263 [(set_attr "type" "fp")])
264
265 (define_insn "floatditd2"
266 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
267 (float:TD (match_operand:DI 1 "gpc_reg_operand" "d")))]
268 "TARGET_DFP"
269 "dcffixq %0,%1"
270 [(set_attr "type" "fp")])
271
272 ;; Convert a decimal64 to a decimal64 whose value is an integer.
273 ;; This is the first stage of converting it to an integer type.
274
275 (define_insn "ftruncdd2"
276 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
277 (fix:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
278 "TARGET_DFP"
279 "drintn. 0,%0,%1,1"
280 [(set_attr "type" "fp")])
281
282 ;; Convert a decimal64 whose value is an integer to an actual integer.
283 ;; This is the second stage of converting decimal float to integer type.
284
285 (define_insn "fixdddi2"
286 [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
287 (fix:DI (match_operand:DD 1 "gpc_reg_operand" "d")))]
288 "TARGET_DFP"
289 "dctfix %0,%1"
290 [(set_attr "type" "fp")])
291
292 ;; Convert a decimal128 to a decimal128 whose value is an integer.
293 ;; This is the first stage of converting it to an integer type.
294
295 (define_insn "ftrunctd2"
296 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
297 (fix:TD (match_operand:TD 1 "gpc_reg_operand" "d")))]
298 "TARGET_DFP"
299 "drintnq. 0,%0,%1,1"
300 [(set_attr "type" "fp")])
301
302 ;; Convert a decimal128 whose value is an integer to an actual integer.
303 ;; This is the second stage of converting decimal float to integer type.
304
305 (define_insn "fixtddi2"
306 [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
307 (fix:DI (match_operand:TD 1 "gpc_reg_operand" "d")))]
308 "TARGET_DFP"
309 "dctfixq %0,%1"
310 [(set_attr "type" "fp")])
311
312
314 ;; Decimal builtin support
315
316 (define_c_enum "unspec"
317 [UNSPEC_DDEDPD
318 UNSPEC_DENBCD
319 UNSPEC_DXEX
320 UNSPEC_DIEX
321 UNSPEC_DSCLI
322 UNSPEC_DSCRI])
323
324 (define_mode_iterator D64_D128 [DD TD])
325
326 (define_mode_attr dfp_suffix [(DD "")
327 (TD "q")])
328
329 (define_insn "dfp_ddedpd_<mode>"
330 [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
331 (unspec:D64_D128 [(match_operand:QI 1 "const_0_to_3_operand" "i")
332 (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
333 UNSPEC_DDEDPD))]
334 "TARGET_DFP"
335 "ddedpd<dfp_suffix> %1,%0,%2"
336 [(set_attr "type" "fp")])
337
338 (define_insn "dfp_denbcd_<mode>"
339 [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
340 (unspec:D64_D128 [(match_operand:QI 1 "const_0_to_1_operand" "i")
341 (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
342 UNSPEC_DENBCD))]
343 "TARGET_DFP"
344 "denbcd<dfp_suffix> %1,%0,%2"
345 [(set_attr "type" "fp")])
346
347 (define_insn "dfp_dxex_<mode>"
348 [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
349 (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")]
350 UNSPEC_DXEX))]
351 "TARGET_DFP"
352 "dxex<dfp_suffix> %0,%1"
353 [(set_attr "type" "fp")])
354
355 (define_insn "dfp_diex_<mode>"
356 [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
357 (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
358 (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
359 UNSPEC_DXEX))]
360 "TARGET_DFP"
361 "diex<dfp_suffix> %0,%1,%2"
362 [(set_attr "type" "fp")])
363
364 (define_insn "dfp_dscli_<mode>"
365 [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
366 (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
367 (match_operand:QI 2 "immediate_operand" "i")]
368 UNSPEC_DSCLI))]
369 "TARGET_DFP"
370 "dscli<dfp_suffix> %0,%1,%2"
371 [(set_attr "type" "fp")])
372
373 (define_insn "dfp_dscri_<mode>"
374 [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
375 (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
376 (match_operand:QI 2 "immediate_operand" "i")]
377 UNSPEC_DSCRI))]
378 "TARGET_DFP"
379 "dscri<dfp_suffix> %0,%1,%2"
380 [(set_attr "type" "fp")])
381