1;; Decimal Floating Point (DFP) patterns.
2;; Copyright (C) 2007-2013 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_expand "movsd"
33  [(set (match_operand:SD 0 "nonimmediate_operand" "")
34	(match_operand:SD 1 "any_operand" ""))]
35  "TARGET_HARD_FLOAT && TARGET_FPRS"
36  "{ rs6000_emit_move (operands[0], operands[1], SDmode); DONE; }")
37
38(define_split
39  [(set (match_operand:SD 0 "gpc_reg_operand" "")
40	(match_operand:SD 1 "const_double_operand" ""))]
41  "reload_completed
42   && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
43       || (GET_CODE (operands[0]) == SUBREG
44	   && GET_CODE (SUBREG_REG (operands[0])) == REG
45	   && REGNO (SUBREG_REG (operands[0])) <= 31))"
46  [(set (match_dup 2) (match_dup 3))]
47  "
48{
49  long l;
50  REAL_VALUE_TYPE rv;
51
52  REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
53  REAL_VALUE_TO_TARGET_DECIMAL32 (rv, l);
54
55  if (! TARGET_POWERPC64)
56    operands[2] = operand_subword (operands[0], 0, 0, SDmode);
57  else
58    operands[2] = gen_lowpart (SImode, operands[0]);
59
60  operands[3] = gen_int_mode (l, SImode);
61}")
62
63(define_insn "movsd_hardfloat"
64  [(set (match_operand:SD 0 "nonimmediate_operand" "=r,r,m,f,*c*l,!r,*h,!r,!r")
65	(match_operand:SD 1 "input_operand"        "r,m,r,f,r,h,0,G,Fn"))]
66  "(gpc_reg_operand (operands[0], SDmode)
67   || gpc_reg_operand (operands[1], SDmode))
68   && (TARGET_HARD_FLOAT && TARGET_FPRS)"
69  "@
70   mr %0,%1
71   lwz%U1%X1 %0,%1
72   stw%U0%X0 %1,%0
73   fmr %0,%1
74   mt%0 %1
75   mf%1 %0
76   nop
77   #
78   #"
79  [(set_attr "type" "*,load,store,fp,mtjmpr,mfjmpr,*,*,*")
80   (set_attr "length" "4,4,4,4,4,4,4,4,8")])
81
82(define_insn "movsd_softfloat"
83  [(set (match_operand:SD 0 "nonimmediate_operand" "=r,cl,r,r,m,r,r,r,r,r,*h")
84	(match_operand:SD 1 "input_operand" "r,r,h,m,r,I,L,R,G,Fn,0"))]
85  "(gpc_reg_operand (operands[0], SDmode)
86   || gpc_reg_operand (operands[1], SDmode))
87   && (TARGET_SOFT_FLOAT || !TARGET_FPRS)"
88  "@
89   mr %0,%1
90   mt%0 %1
91   mf%1 %0
92   lwz%U1%X1 %0,%1
93   stw%U0%X0 %1,%0
94   li %0,%1
95   lis %0,%v1
96   la %0,%a1
97   #
98   #
99   nop"
100  [(set_attr "type" "*,mtjmpr,mfjmpr,load,store,*,*,*,*,*,*")
101   (set_attr "length" "4,4,4,4,4,4,4,4,4,8,4")])
102
103(define_insn "movsd_store"
104  [(set (match_operand:DD 0 "nonimmediate_operand" "=m")
105	(unspec:DD [(match_operand:SD 1 "input_operand" "d")]
106		   UNSPEC_MOVSD_STORE))]
107  "(gpc_reg_operand (operands[0], DDmode)
108   || gpc_reg_operand (operands[1], SDmode))
109   && TARGET_HARD_FLOAT && TARGET_FPRS"
110  "stfd%U0%X0 %1,%0"
111  [(set_attr "type" "fpstore")
112   (set_attr "length" "4")])
113
114(define_insn "movsd_load"
115  [(set (match_operand:SD 0 "nonimmediate_operand" "=f")
116	(unspec:SD [(match_operand:DD 1 "input_operand" "m")]
117		   UNSPEC_MOVSD_LOAD))]
118  "(gpc_reg_operand (operands[0], SDmode)
119   || gpc_reg_operand (operands[1], DDmode))
120   && TARGET_HARD_FLOAT && TARGET_FPRS"
121  "lfd%U1%X1 %0,%1"
122  [(set_attr "type" "fpload")
123   (set_attr "length" "4")])
124
125;; Hardware support for decimal floating point operations.
126
127(define_insn "extendsddd2"
128  [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
129	(float_extend:DD (match_operand:SD 1 "gpc_reg_operand" "f")))]
130  "TARGET_DFP"
131  "dctdp %0,%1"
132  [(set_attr "type" "fp")])
133
134(define_expand "extendsdtd2"
135  [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
136	(float_extend:TD (match_operand:SD 1 "gpc_reg_operand" "d")))]
137  "TARGET_DFP"
138{
139  rtx tmp = gen_reg_rtx (DDmode);
140  emit_insn (gen_extendsddd2 (tmp, operands[1]));
141  emit_insn (gen_extendddtd2 (operands[0], tmp));
142  DONE;
143})
144
145(define_insn "truncddsd2"
146  [(set (match_operand:SD 0 "gpc_reg_operand" "=f")
147	(float_truncate:SD (match_operand:DD 1 "gpc_reg_operand" "d")))]
148  "TARGET_DFP"
149  "drsp %0,%1"
150  [(set_attr "type" "fp")])
151
152(define_expand "negdd2"
153  [(set (match_operand:DD 0 "gpc_reg_operand" "")
154	(neg:DD (match_operand:DD 1 "gpc_reg_operand" "")))]
155  "TARGET_HARD_FLOAT && TARGET_FPRS"
156  "")
157
158(define_insn "*negdd2_fpr"
159  [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
160	(neg:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
161  "TARGET_HARD_FLOAT && TARGET_FPRS"
162  "fneg %0,%1"
163  [(set_attr "type" "fp")])
164
165(define_expand "absdd2"
166  [(set (match_operand:DD 0 "gpc_reg_operand" "")
167	(abs:DD (match_operand:DD 1 "gpc_reg_operand" "")))]
168  "TARGET_HARD_FLOAT && TARGET_FPRS"
169  "")
170
171(define_insn "*absdd2_fpr"
172  [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
173	(abs:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
174  "TARGET_HARD_FLOAT && TARGET_FPRS"
175  "fabs %0,%1"
176  [(set_attr "type" "fp")])
177
178(define_insn "*nabsdd2_fpr"
179  [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
180	(neg:DD (abs:DD (match_operand:DD 1 "gpc_reg_operand" "d"))))]
181  "TARGET_HARD_FLOAT && TARGET_FPRS"
182  "fnabs %0,%1"
183  [(set_attr "type" "fp")])
184
185(define_expand "movdd"
186  [(set (match_operand:DD 0 "nonimmediate_operand" "")
187	(match_operand:DD 1 "any_operand" ""))]
188  ""
189  "{ rs6000_emit_move (operands[0], operands[1], DDmode); DONE; }")
190
191(define_split
192  [(set (match_operand:DD 0 "gpc_reg_operand" "")
193	(match_operand:DD 1 "const_int_operand" ""))]
194  "! TARGET_POWERPC64 && reload_completed
195   && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
196       || (GET_CODE (operands[0]) == SUBREG
197	   && GET_CODE (SUBREG_REG (operands[0])) == REG
198	   && REGNO (SUBREG_REG (operands[0])) <= 31))"
199  [(set (match_dup 2) (match_dup 4))
200   (set (match_dup 3) (match_dup 1))]
201  "
202{
203  int endian = (WORDS_BIG_ENDIAN == 0);
204  HOST_WIDE_INT value = INTVAL (operands[1]);
205
206  operands[2] = operand_subword (operands[0], endian, 0, DDmode);
207  operands[3] = operand_subword (operands[0], 1 - endian, 0, DDmode);
208#if HOST_BITS_PER_WIDE_INT == 32
209  operands[4] = (value & 0x80000000) ? constm1_rtx : const0_rtx;
210#else
211  operands[4] = GEN_INT (value >> 32);
212  operands[1] = GEN_INT (((value & 0xffffffff) ^ 0x80000000) - 0x80000000);
213#endif
214}")
215
216(define_split
217  [(set (match_operand:DD 0 "gpc_reg_operand" "")
218	(match_operand:DD 1 "const_double_operand" ""))]
219  "! TARGET_POWERPC64 && reload_completed
220   && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
221       || (GET_CODE (operands[0]) == SUBREG
222	   && GET_CODE (SUBREG_REG (operands[0])) == REG
223	   && REGNO (SUBREG_REG (operands[0])) <= 31))"
224  [(set (match_dup 2) (match_dup 4))
225   (set (match_dup 3) (match_dup 5))]
226  "
227{
228  int endian = (WORDS_BIG_ENDIAN == 0);
229  long l[2];
230  REAL_VALUE_TYPE rv;
231
232  REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
233  REAL_VALUE_TO_TARGET_DECIMAL64 (rv, l);
234
235  operands[2] = operand_subword (operands[0], endian, 0, DDmode);
236  operands[3] = operand_subword (operands[0], 1 - endian, 0, DDmode);
237  operands[4] = gen_int_mode (l[endian], SImode);
238  operands[5] = gen_int_mode (l[1 - endian], SImode);
239}")
240
241(define_split
242  [(set (match_operand:DD 0 "gpc_reg_operand" "")
243	(match_operand:DD 1 "const_double_operand" ""))]
244  "TARGET_POWERPC64 && reload_completed
245   && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
246       || (GET_CODE (operands[0]) == SUBREG
247	   && GET_CODE (SUBREG_REG (operands[0])) == REG
248	   && REGNO (SUBREG_REG (operands[0])) <= 31))"
249  [(set (match_dup 2) (match_dup 3))]
250  "
251{
252  int endian = (WORDS_BIG_ENDIAN == 0);
253  long l[2];
254  REAL_VALUE_TYPE rv;
255#if HOST_BITS_PER_WIDE_INT >= 64
256  HOST_WIDE_INT val;
257#endif
258
259  REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
260  REAL_VALUE_TO_TARGET_DECIMAL64 (rv, l);
261
262  operands[2] = gen_lowpart (DImode, operands[0]);
263  /* HIGHPART is lower memory address when WORDS_BIG_ENDIAN.  */
264#if HOST_BITS_PER_WIDE_INT >= 64
265  val = ((HOST_WIDE_INT)(unsigned long)l[endian] << 32
266	 | ((HOST_WIDE_INT)(unsigned long)l[1 - endian]));
267
268  operands[3] = gen_int_mode (val, DImode);
269#else
270  operands[3] = immed_double_const (l[1 - endian], l[endian], DImode);
271#endif
272}")
273
274;; Don't have reload use general registers to load a constant.  First,
275;; it might not work if the output operand is the equivalent of
276;; a non-offsettable memref, but also it is less efficient than loading
277;; the constant into an FP register, since it will probably be used there.
278;; The "??" is a kludge until we can figure out a more reasonable way
279;; of handling these non-offsettable values.
280(define_insn "*movdd_hardfloat32"
281  [(set (match_operand:DD 0 "nonimmediate_operand" "=!r,??r,m,d,d,m,!r,!r,!r")
282	(match_operand:DD 1 "input_operand" "r,m,r,d,m,d,G,H,F"))]
283  "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS
284   && (gpc_reg_operand (operands[0], DDmode)
285       || gpc_reg_operand (operands[1], DDmode))"
286  "*
287{
288  switch (which_alternative)
289    {
290    default:
291      gcc_unreachable ();
292    case 0:
293    case 1:
294    case 2:
295      return \"#\";
296    case 3:
297      return \"fmr %0,%1\";
298    case 4:
299      return \"lfd%U1%X1 %0,%1\";
300    case 5:
301      return \"stfd%U0%X0 %1,%0\";
302    case 6:
303    case 7:
304    case 8:
305      return \"#\";
306    }
307}"
308  [(set_attr "type" "two,load,store,fp,fpload,fpstore,*,*,*")
309   (set_attr "length" "8,16,16,4,4,4,8,12,16")])
310
311(define_insn "*movdd_softfloat32"
312  [(set (match_operand:DD 0 "nonimmediate_operand" "=r,r,m,r,r,r")
313	(match_operand:DD 1 "input_operand" "r,m,r,G,H,F"))]
314  "! TARGET_POWERPC64 && (TARGET_SOFT_FLOAT || !TARGET_FPRS)
315   && (gpc_reg_operand (operands[0], DDmode)
316       || gpc_reg_operand (operands[1], DDmode))"
317  "#"
318  [(set_attr "type" "two,load,store,*,*,*")
319   (set_attr "length" "8,8,8,8,12,16")])
320
321; ld/std require word-aligned displacements -> 'Y' constraint.
322; List Y->r and r->Y before r->r for reload.
323(define_insn "*movdd_hardfloat64_mfpgpr"
324  [(set (match_operand:DD 0 "nonimmediate_operand" "=Y,r,!r,d,d,m,*c*l,!r,*h,!r,!r,!r,r,d")
325	(match_operand:DD 1 "input_operand" "r,Y,r,d,m,d,r,h,0,G,H,F,d,r"))]
326  "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
327   && (gpc_reg_operand (operands[0], DDmode)
328       || gpc_reg_operand (operands[1], DDmode))"
329  "@
330   std%U0%X0 %1,%0
331   ld%U1%X1 %0,%1
332   mr %0,%1
333   fmr %0,%1
334   lfd%U1%X1 %0,%1
335   stfd%U0%X0 %1,%0
336   mt%0 %1
337   mf%1 %0
338   nop
339   #
340   #
341   #
342   mftgpr %0,%1
343   mffgpr %0,%1"
344  [(set_attr "type" "store,load,*,fp,fpload,fpstore,mtjmpr,mfjmpr,*,*,*,*,mftgpr,mffgpr")
345   (set_attr "length" "4,4,4,4,4,4,4,4,4,8,12,16,4,4")])
346
347; ld/std require word-aligned displacements -> 'Y' constraint.
348; List Y->r and r->Y before r->r for reload.
349(define_insn "*movdd_hardfloat64"
350  [(set (match_operand:DD 0 "nonimmediate_operand" "=Y,r,!r,d,d,m,*c*l,!r,*h,!r,!r,!r")
351	(match_operand:DD 1 "input_operand" "r,Y,r,d,m,d,r,h,0,G,H,F"))]
352  "TARGET_POWERPC64 && !TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
353   && (gpc_reg_operand (operands[0], DDmode)
354       || gpc_reg_operand (operands[1], DDmode))"
355  "@
356   std%U0%X0 %1,%0
357   ld%U1%X1 %0,%1
358   mr %0,%1
359   fmr %0,%1
360   lfd%U1%X1 %0,%1
361   stfd%U0%X0 %1,%0
362   mt%0 %1
363   mf%1 %0
364   nop
365   #
366   #
367   #"
368  [(set_attr "type" "store,load,*,fp,fpload,fpstore,mtjmpr,mfjmpr,*,*,*,*")
369   (set_attr "length" "4,4,4,4,4,4,4,4,4,8,12,16")])
370
371(define_insn "*movdd_softfloat64"
372  [(set (match_operand:DD 0 "nonimmediate_operand" "=r,Y,r,cl,r,r,r,r,*h")
373	(match_operand:DD 1 "input_operand" "Y,r,r,r,h,G,H,F,0"))]
374  "TARGET_POWERPC64 && (TARGET_SOFT_FLOAT || !TARGET_FPRS)
375   && (gpc_reg_operand (operands[0], DDmode)
376       || gpc_reg_operand (operands[1], DDmode))"
377  "@
378   ld%U1%X1 %0,%1
379   std%U0%X0 %1,%0
380   mr %0,%1
381   mt%0 %1
382   mf%1 %0
383   #
384   #
385   #
386   nop"
387  [(set_attr "type" "load,store,*,mtjmpr,mfjmpr,*,*,*,*")
388   (set_attr "length" "4,4,4,4,4,8,12,16,4")])
389
390(define_expand "negtd2"
391  [(set (match_operand:TD 0 "gpc_reg_operand" "")
392	(neg:TD (match_operand:TD 1 "gpc_reg_operand" "")))]
393  "TARGET_HARD_FLOAT && TARGET_FPRS"
394  "")
395
396(define_insn "*negtd2_fpr"
397  [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
398	(neg:TD (match_operand:TD 1 "gpc_reg_operand" "d")))]
399  "TARGET_HARD_FLOAT && TARGET_FPRS"
400  "fneg %0,%1"
401  [(set_attr "type" "fp")])
402
403(define_expand "abstd2"
404  [(set (match_operand:TD 0 "gpc_reg_operand" "")
405	(abs:TD (match_operand:TD 1 "gpc_reg_operand" "")))]
406  "TARGET_HARD_FLOAT && TARGET_FPRS"
407  "")
408
409(define_insn "*abstd2_fpr"
410  [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
411	(abs:TD (match_operand:TD 1 "gpc_reg_operand" "d")))]
412  "TARGET_HARD_FLOAT && TARGET_FPRS"
413  "fabs %0,%1"
414  [(set_attr "type" "fp")])
415
416(define_insn "*nabstd2_fpr"
417  [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
418	(neg:TD (abs:TD (match_operand:TD 1 "gpc_reg_operand" "d"))))]
419  "TARGET_HARD_FLOAT && TARGET_FPRS"
420  "fnabs %0,%1"
421  [(set_attr "type" "fp")])
422
423(define_expand "movtd"
424  [(set (match_operand:TD 0 "general_operand" "")
425	(match_operand:TD 1 "any_operand" ""))]
426  "TARGET_HARD_FLOAT && TARGET_FPRS"
427  "{ rs6000_emit_move (operands[0], operands[1], TDmode); DONE; }")
428
429; It's important to list the Y->r and r->Y moves before r->r because
430; otherwise reload, given m->r, will try to pick r->r and reload it,
431; which doesn't make progress.
432(define_insn_and_split "*movtd_internal"
433  [(set (match_operand:TD 0 "nonimmediate_operand" "=m,d,d,Y,r,r")
434	(match_operand:TD 1 "input_operand"         "d,m,d,r,YGHF,r"))]
435  "TARGET_HARD_FLOAT && TARGET_FPRS
436   && (gpc_reg_operand (operands[0], TDmode)
437       || gpc_reg_operand (operands[1], TDmode))"
438  "#"
439  "&& reload_completed"
440  [(pc)]
441{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; }
442  [(set_attr "length" "8,8,8,20,20,16")])
443
444;; Hardware support for decimal floating point operations.
445
446(define_insn "extendddtd2"
447  [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
448	(float_extend:TD (match_operand:DD 1 "gpc_reg_operand" "d")))]
449  "TARGET_DFP"
450  "dctqpq %0,%1"
451  [(set_attr "type" "fp")])
452
453;; The result of drdpq is an even/odd register pair with the converted
454;; value in the even register and zero in the odd register.
455;; FIXME: Avoid the register move by using a reload constraint to ensure
456;; that the result is the first of the pair receiving the result of drdpq.
457
458(define_insn "trunctddd2"
459  [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
460	(float_truncate:DD (match_operand:TD 1 "gpc_reg_operand" "d")))
461   (clobber (match_scratch:TD 2 "=d"))]
462  "TARGET_DFP"
463  "drdpq %2,%1\;fmr %0,%2"
464  [(set_attr "type" "fp")])
465
466(define_insn "adddd3"
467  [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
468	(plus:DD (match_operand:DD 1 "gpc_reg_operand" "%d")
469		 (match_operand:DD 2 "gpc_reg_operand" "d")))]
470  "TARGET_DFP"
471  "dadd %0,%1,%2"
472  [(set_attr "type" "fp")])
473
474(define_insn "addtd3"
475  [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
476	(plus:TD (match_operand:TD 1 "gpc_reg_operand" "%d")
477		 (match_operand:TD 2 "gpc_reg_operand" "d")))]
478  "TARGET_DFP"
479  "daddq %0,%1,%2"
480  [(set_attr "type" "fp")])
481
482(define_insn "subdd3"
483  [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
484	(minus:DD (match_operand:DD 1 "gpc_reg_operand" "d")
485		  (match_operand:DD 2 "gpc_reg_operand" "d")))]
486  "TARGET_DFP"
487  "dsub %0,%1,%2"
488  [(set_attr "type" "fp")])
489
490(define_insn "subtd3"
491  [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
492	(minus:TD (match_operand:TD 1 "gpc_reg_operand" "d")
493		  (match_operand:TD 2 "gpc_reg_operand" "d")))]
494  "TARGET_DFP"
495  "dsubq %0,%1,%2"
496  [(set_attr "type" "fp")])
497
498(define_insn "muldd3"
499  [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
500	(mult:DD (match_operand:DD 1 "gpc_reg_operand" "%d")
501		 (match_operand:DD 2 "gpc_reg_operand" "d")))]
502  "TARGET_DFP"
503  "dmul %0,%1,%2"
504  [(set_attr "type" "fp")])
505
506(define_insn "multd3"
507  [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
508	(mult:TD (match_operand:TD 1 "gpc_reg_operand" "%d")
509		 (match_operand:TD 2 "gpc_reg_operand" "d")))]
510  "TARGET_DFP"
511  "dmulq %0,%1,%2"
512  [(set_attr "type" "fp")])
513
514(define_insn "divdd3"
515  [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
516	(div:DD (match_operand:DD 1 "gpc_reg_operand" "d")
517		(match_operand:DD 2 "gpc_reg_operand" "d")))]
518  "TARGET_DFP"
519  "ddiv %0,%1,%2"
520  [(set_attr "type" "fp")])
521
522(define_insn "divtd3"
523  [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
524	(div:TD (match_operand:TD 1 "gpc_reg_operand" "d")
525		(match_operand:TD 2 "gpc_reg_operand" "d")))]
526  "TARGET_DFP"
527  "ddivq %0,%1,%2"
528  [(set_attr "type" "fp")])
529
530(define_insn "*cmpdd_internal1"
531  [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
532	(compare:CCFP (match_operand:DD 1 "gpc_reg_operand" "d")
533		      (match_operand:DD 2 "gpc_reg_operand" "d")))]
534  "TARGET_DFP"
535  "dcmpu %0,%1,%2"
536  [(set_attr "type" "fpcompare")])
537
538(define_insn "*cmptd_internal1"
539  [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
540	(compare:CCFP (match_operand:TD 1 "gpc_reg_operand" "d")
541		      (match_operand:TD 2 "gpc_reg_operand" "d")))]
542  "TARGET_DFP"
543  "dcmpuq %0,%1,%2"
544  [(set_attr "type" "fpcompare")])
545
546(define_insn "floatdidd2"
547  [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
548	(float:DD (match_operand:DI 1 "gpc_reg_operand" "d")))]
549  "TARGET_DFP && TARGET_POPCNTD"
550  "dcffix %0,%1"
551  [(set_attr "type" "fp")])
552
553(define_insn "floatditd2"
554  [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
555	(float:TD (match_operand:DI 1 "gpc_reg_operand" "d")))]
556  "TARGET_DFP"
557  "dcffixq %0,%1"
558  [(set_attr "type" "fp")])
559
560;; Convert a decimal64 to a decimal64 whose value is an integer.
561;; This is the first stage of converting it to an integer type.
562
563(define_insn "ftruncdd2"
564  [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
565	(fix:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
566  "TARGET_DFP"
567  "drintn. 0,%0,%1,1"
568  [(set_attr "type" "fp")])
569
570;; Convert a decimal64 whose value is an integer to an actual integer.
571;; This is the second stage of converting decimal float to integer type.
572
573(define_insn "fixdddi2"
574  [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
575	(fix:DI (match_operand:DD 1 "gpc_reg_operand" "d")))]
576  "TARGET_DFP"
577  "dctfix %0,%1"
578  [(set_attr "type" "fp")])
579
580;; Convert a decimal128 to a decimal128 whose value is an integer.
581;; This is the first stage of converting it to an integer type.
582
583(define_insn "ftrunctd2"
584  [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
585	(fix:TD (match_operand:TD 1 "gpc_reg_operand" "d")))]
586  "TARGET_DFP"
587  "drintnq. 0,%0,%1,1"
588  [(set_attr "type" "fp")])
589
590;; Convert a decimal128 whose value is an integer to an actual integer.
591;; This is the second stage of converting decimal float to integer type.
592
593(define_insn "fixtddi2"
594  [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
595	(fix:DI (match_operand:TD 1 "gpc_reg_operand" "d")))]
596  "TARGET_DFP"
597  "dctfixq %0,%1"
598  [(set_attr "type" "fp")])
599