dfp.md revision 1.1.1.2 1 ;; Decimal Floating Point (DFP) patterns.
2 ;; Copyright (C) 2007-2013 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")
41 (if_then_else
42 (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
43 (const_string "fpstore_ux")
44 (if_then_else
45 (match_test "update_address_mem (operands[0], VOIDmode)")
46 (const_string "fpstore_u")
47 (const_string "fpstore"))))
48 (set_attr "length" "4")])
49
50 (define_insn "movsd_load"
51 [(set (match_operand:SD 0 "nonimmediate_operand" "=f")
52 (unspec:SD [(match_operand:DD 1 "input_operand" "m")]
53 UNSPEC_MOVSD_LOAD))]
54 "(gpc_reg_operand (operands[0], SDmode)
55 || gpc_reg_operand (operands[1], DDmode))
56 && TARGET_HARD_FLOAT && TARGET_FPRS"
57 "lfd%U1%X1 %0,%1"
58 [(set (attr "type")
59 (if_then_else
60 (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
61 (const_string "fpload_ux")
62 (if_then_else
63 (match_test "update_address_mem (operands[1], VOIDmode)")
64 (const_string "fpload_u")
65 (const_string "fpload"))))
66 (set_attr "length" "4")])
67
68 ;; Hardware support for decimal floating point operations.
69
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")))]
73 "TARGET_DFP"
74 "dctdp %0,%1"
75 [(set_attr "type" "fp")])
76
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")))]
80 "TARGET_DFP"
81 {
82 rtx tmp = gen_reg_rtx (DDmode);
83 emit_insn (gen_extendsddd2 (tmp, operands[1]));
84 emit_insn (gen_extendddtd2 (operands[0], tmp));
85 DONE;
86 })
87
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")))]
91 "TARGET_DFP"
92 "drsp %0,%1"
93 [(set_attr "type" "fp")])
94
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"
99 "")
100
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"
105 "fneg %0,%1"
106 [(set_attr "type" "fp")])
107
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"
112 "")
113
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"
118 "fabs %0,%1"
119 [(set_attr "type" "fp")])
120
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"
125 "fnabs %0,%1"
126 [(set_attr "type" "fp")])
127
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"
132 "")
133
134 (define_insn "*negtd2_fpr"
135 [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d")
136 (neg:TD (match_operand:TD 1 "gpc_reg_operand" "0,d")))]
137 "TARGET_HARD_FLOAT && TARGET_FPRS"
138 "@
139 fneg %0,%1
140 fneg %0,%1\;fmr %L0,%L1"
141 [(set_attr "type" "fp")
142 (set_attr "length" "4,8")])
143
144 (define_expand "abstd2"
145 [(set (match_operand:TD 0 "gpc_reg_operand" "")
146 (abs:TD (match_operand:TD 1 "gpc_reg_operand" "")))]
147 "TARGET_HARD_FLOAT && TARGET_FPRS"
148 "")
149
150 (define_insn "*abstd2_fpr"
151 [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d")
152 (abs:TD (match_operand:TD 1 "gpc_reg_operand" "0,d")))]
153 "TARGET_HARD_FLOAT && TARGET_FPRS"
154 "@
155 fabs %0,%1
156 fabs %0,%1\;fmr %L0,%L1"
157 [(set_attr "type" "fp")
158 (set_attr "length" "4,8")])
159
160 (define_insn "*nabstd2_fpr"
161 [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d")
162 (neg:TD (abs:TD (match_operand:TD 1 "gpc_reg_operand" "0,d"))))]
163 "TARGET_HARD_FLOAT && TARGET_FPRS"
164 "@
165 fnabs %0,%1
166 fnabs %0,%1\;fmr %L0,%L1"
167 [(set_attr "type" "fp")
168 (set_attr "length" "4,8")])
169
170 ;; Hardware support for decimal floating point operations.
171
172 (define_insn "extendddtd2"
173 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
174 (float_extend:TD (match_operand:DD 1 "gpc_reg_operand" "d")))]
175 "TARGET_DFP"
176 "dctqpq %0,%1"
177 [(set_attr "type" "fp")])
178
179 ;; The result of drdpq is an even/odd register pair with the converted
180 ;; value in the even register and zero in the odd register.
181 ;; FIXME: Avoid the register move by using a reload constraint to ensure
182 ;; that the result is the first of the pair receiving the result of drdpq.
183
184 (define_insn "trunctddd2"
185 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
186 (float_truncate:DD (match_operand:TD 1 "gpc_reg_operand" "d")))
187 (clobber (match_scratch:TD 2 "=d"))]
188 "TARGET_DFP"
189 "drdpq %2,%1\;fmr %0,%2"
190 [(set_attr "type" "fp")])
191
192 (define_insn "adddd3"
193 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
194 (plus:DD (match_operand:DD 1 "gpc_reg_operand" "%d")
195 (match_operand:DD 2 "gpc_reg_operand" "d")))]
196 "TARGET_DFP"
197 "dadd %0,%1,%2"
198 [(set_attr "type" "fp")])
199
200 (define_insn "addtd3"
201 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
202 (plus:TD (match_operand:TD 1 "gpc_reg_operand" "%d")
203 (match_operand:TD 2 "gpc_reg_operand" "d")))]
204 "TARGET_DFP"
205 "daddq %0,%1,%2"
206 [(set_attr "type" "fp")])
207
208 (define_insn "subdd3"
209 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
210 (minus:DD (match_operand:DD 1 "gpc_reg_operand" "d")
211 (match_operand:DD 2 "gpc_reg_operand" "d")))]
212 "TARGET_DFP"
213 "dsub %0,%1,%2"
214 [(set_attr "type" "fp")])
215
216 (define_insn "subtd3"
217 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
218 (minus:TD (match_operand:TD 1 "gpc_reg_operand" "d")
219 (match_operand:TD 2 "gpc_reg_operand" "d")))]
220 "TARGET_DFP"
221 "dsubq %0,%1,%2"
222 [(set_attr "type" "fp")])
223
224 (define_insn "muldd3"
225 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
226 (mult:DD (match_operand:DD 1 "gpc_reg_operand" "%d")
227 (match_operand:DD 2 "gpc_reg_operand" "d")))]
228 "TARGET_DFP"
229 "dmul %0,%1,%2"
230 [(set_attr "type" "fp")])
231
232 (define_insn "multd3"
233 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
234 (mult:TD (match_operand:TD 1 "gpc_reg_operand" "%d")
235 (match_operand:TD 2 "gpc_reg_operand" "d")))]
236 "TARGET_DFP"
237 "dmulq %0,%1,%2"
238 [(set_attr "type" "fp")])
239
240 (define_insn "divdd3"
241 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
242 (div:DD (match_operand:DD 1 "gpc_reg_operand" "d")
243 (match_operand:DD 2 "gpc_reg_operand" "d")))]
244 "TARGET_DFP"
245 "ddiv %0,%1,%2"
246 [(set_attr "type" "fp")])
247
248 (define_insn "divtd3"
249 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
250 (div:TD (match_operand:TD 1 "gpc_reg_operand" "d")
251 (match_operand:TD 2 "gpc_reg_operand" "d")))]
252 "TARGET_DFP"
253 "ddivq %0,%1,%2"
254 [(set_attr "type" "fp")])
255
256 (define_insn "*cmpdd_internal1"
257 [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
258 (compare:CCFP (match_operand:DD 1 "gpc_reg_operand" "d")
259 (match_operand:DD 2 "gpc_reg_operand" "d")))]
260 "TARGET_DFP"
261 "dcmpu %0,%1,%2"
262 [(set_attr "type" "fpcompare")])
263
264 (define_insn "*cmptd_internal1"
265 [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
266 (compare:CCFP (match_operand:TD 1 "gpc_reg_operand" "d")
267 (match_operand:TD 2 "gpc_reg_operand" "d")))]
268 "TARGET_DFP"
269 "dcmpuq %0,%1,%2"
270 [(set_attr "type" "fpcompare")])
271
272 (define_insn "floatdidd2"
273 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
274 (float:DD (match_operand:DI 1 "gpc_reg_operand" "d")))]
275 "TARGET_DFP && TARGET_POPCNTD"
276 "dcffix %0,%1"
277 [(set_attr "type" "fp")])
278
279 (define_insn "floatditd2"
280 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
281 (float:TD (match_operand:DI 1 "gpc_reg_operand" "d")))]
282 "TARGET_DFP"
283 "dcffixq %0,%1"
284 [(set_attr "type" "fp")])
285
286 ;; Convert a decimal64 to a decimal64 whose value is an integer.
287 ;; This is the first stage of converting it to an integer type.
288
289 (define_insn "ftruncdd2"
290 [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
291 (fix:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
292 "TARGET_DFP"
293 "drintn. 0,%0,%1,1"
294 [(set_attr "type" "fp")])
295
296 ;; Convert a decimal64 whose value is an integer to an actual integer.
297 ;; This is the second stage of converting decimal float to integer type.
298
299 (define_insn "fixdddi2"
300 [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
301 (fix:DI (match_operand:DD 1 "gpc_reg_operand" "d")))]
302 "TARGET_DFP"
303 "dctfix %0,%1"
304 [(set_attr "type" "fp")])
305
306 ;; Convert a decimal128 to a decimal128 whose value is an integer.
307 ;; This is the first stage of converting it to an integer type.
308
309 (define_insn "ftrunctd2"
310 [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
311 (fix:TD (match_operand:TD 1 "gpc_reg_operand" "d")))]
312 "TARGET_DFP"
313 "drintnq. 0,%0,%1,1"
314 [(set_attr "type" "fp")])
315
316 ;; Convert a decimal128 whose value is an integer to an actual integer.
317 ;; This is the second stage of converting decimal float to integer type.
318
319 (define_insn "fixtddi2"
320 [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
321 (fix:DI (match_operand:TD 1 "gpc_reg_operand" "d")))]
322 "TARGET_DFP"
323 "dctfixq %0,%1"
324 [(set_attr "type" "fp")])
325
326
328 ;; Decimal builtin support
329
330 (define_c_enum "unspec"
331 [UNSPEC_DDEDPD
332 UNSPEC_DENBCD
333 UNSPEC_DXEX
334 UNSPEC_DIEX
335 UNSPEC_DSCLI
336 UNSPEC_DSCRI])
337
338 (define_mode_iterator D64_D128 [DD TD])
339
340 (define_mode_attr dfp_suffix [(DD "")
341 (TD "q")])
342
343 (define_insn "dfp_ddedpd_<mode>"
344 [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
345 (unspec:D64_D128 [(match_operand:QI 1 "const_0_to_3_operand" "i")
346 (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
347 UNSPEC_DDEDPD))]
348 "TARGET_DFP"
349 "ddedpd<dfp_suffix> %1,%0,%2"
350 [(set_attr "type" "fp")])
351
352 (define_insn "dfp_denbcd_<mode>"
353 [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
354 (unspec:D64_D128 [(match_operand:QI 1 "const_0_to_1_operand" "i")
355 (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
356 UNSPEC_DENBCD))]
357 "TARGET_DFP"
358 "denbcd<dfp_suffix> %1,%0,%2"
359 [(set_attr "type" "fp")])
360
361 (define_insn "dfp_dxex_<mode>"
362 [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
363 (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")]
364 UNSPEC_DXEX))]
365 "TARGET_DFP"
366 "dxex<dfp_suffix> %0,%1"
367 [(set_attr "type" "fp")])
368
369 (define_insn "dfp_diex_<mode>"
370 [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
371 (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
372 (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
373 UNSPEC_DXEX))]
374 "TARGET_DFP"
375 "diex<dfp_suffix> %0,%1,%2"
376 [(set_attr "type" "fp")])
377
378 (define_insn "dfp_dscli_<mode>"
379 [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
380 (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
381 (match_operand:QI 2 "immediate_operand" "i")]
382 UNSPEC_DSCLI))]
383 "TARGET_DFP"
384 "dscli<dfp_suffix> %0,%1,%2"
385 [(set_attr "type" "fp")])
386
387 (define_insn "dfp_dscri_<mode>"
388 [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
389 (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
390 (match_operand:QI 2 "immediate_operand" "i")]
391 UNSPEC_DSCRI))]
392 "TARGET_DFP"
393 "dscri<dfp_suffix> %0,%1,%2"
394 [(set_attr "type" "fp")])
395