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