OSDN Git Service

Add CPP_SPEC for -mxilinx-fpu.
[pf3gnuchains/gcc-fork.git] / gcc / config / rs6000 / dfp.md
1 ;; Decimal Floating Point (DFP) patterns.
2 ;; Copyright (C) 2007, 2008
3 ;; Free Software Foundation, Inc.
4 ;; Contributed by Ben Elliston (bje@au.ibm.com) and Peter Bergner
5 ;; (bergner@vnet.ibm.com).
6
7 ;; This file is part of GCC.
8
9 ;; GCC is free software; you can redistribute it and/or modify it
10 ;; under the terms of the GNU General Public License as published
11 ;; by the Free Software Foundation; either version 3, or (at your
12 ;; option) any later version.
13
14 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
15 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
17 ;; License for more details.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GCC; see the file COPYING3.  If not see
21 ;; <http://www.gnu.org/licenses/>.
22
23 ;;
24 ;; UNSPEC usage
25 ;;
26
27 (define_constants
28   [(UNSPEC_MOVSD_LOAD           400)
29    (UNSPEC_MOVSD_STORE          401)
30   ])
31
32
33 (define_expand "movsd"
34   [(set (match_operand:SD 0 "nonimmediate_operand" "")
35         (match_operand:SD 1 "any_operand" ""))]
36   "TARGET_HARD_FLOAT && TARGET_FPRS"
37   "{ rs6000_emit_move (operands[0], operands[1], SDmode); DONE; }")
38
39 (define_split
40   [(set (match_operand:SD 0 "gpc_reg_operand" "")
41         (match_operand:SD 1 "const_double_operand" ""))]
42   "reload_completed
43    && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
44        || (GET_CODE (operands[0]) == SUBREG
45            && GET_CODE (SUBREG_REG (operands[0])) == REG
46            && REGNO (SUBREG_REG (operands[0])) <= 31))"
47   [(set (match_dup 2) (match_dup 3))]
48   "
49 {
50   long l;
51   REAL_VALUE_TYPE rv;
52
53   REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
54   REAL_VALUE_TO_TARGET_DECIMAL32 (rv, l);
55
56   if (! TARGET_POWERPC64)
57     operands[2] = operand_subword (operands[0], 0, 0, SDmode);
58   else
59     operands[2] = gen_lowpart (SImode, operands[0]);
60
61   operands[3] = gen_int_mode (l, SImode);
62 }")
63
64 (define_insn "movsd_hardfloat"
65   [(set (match_operand:SD 0 "nonimmediate_operand" "=r,r,m,f,*c*l,*q,!r,*h,!r,!r")
66         (match_operand:SD 1 "input_operand"        "r,m,r,f,r,r,h,0,G,Fn"))]
67   "(gpc_reg_operand (operands[0], SDmode)
68    || gpc_reg_operand (operands[1], SDmode))
69    && (TARGET_HARD_FLOAT && TARGET_FPRS)"
70   "@
71    mr %0,%1
72    {l%U1%X1|lwz%U1%X1} %0,%1
73    {st%U0%X0|stw%U0%X0} %1,%0
74    fmr %0,%1
75    mt%0 %1
76    mt%0 %1
77    mf%1 %0
78    {cror 0,0,0|nop}
79    #
80    #"
81   [(set_attr "type" "*,load,store,fp,mtjmpr,*,mfjmpr,*,*,*")
82    (set_attr "length" "4,4,4,4,4,4,4,4,4,8")])
83
84 (define_insn "movsd_softfloat"
85   [(set (match_operand:SD 0 "nonimmediate_operand" "=r,cl,q,r,r,m,r,r,r,r,r,*h")
86         (match_operand:SD 1 "input_operand" "r,r,r,h,m,r,I,L,R,G,Fn,0"))]
87   "(gpc_reg_operand (operands[0], SDmode)
88    || gpc_reg_operand (operands[1], SDmode))
89    && (TARGET_SOFT_FLOAT || !TARGET_FPRS)"
90   "@
91    mr %0,%1
92    mt%0 %1
93    mt%0 %1
94    mf%1 %0
95    {l%U1%X1|lwz%U1%X1} %0,%1
96    {st%U0%X0|stw%U0%X0} %1,%0
97    {lil|li} %0,%1
98    {liu|lis} %0,%v1
99    {cal|la} %0,%a1
100    #
101    #
102    {cror 0,0,0|nop}"
103   [(set_attr "type" "*,mtjmpr,*,mfjmpr,load,store,*,*,*,*,*,*")
104    (set_attr "length" "4,4,4,4,4,4,4,4,4,4,8,4")])
105
106 (define_insn "movsd_store"
107   [(set (match_operand:DD 0 "nonimmediate_operand" "=m")
108         (unspec:DD [(match_operand:SD 1 "input_operand" "f")]
109                    UNSPEC_MOVSD_STORE))]
110   "(gpc_reg_operand (operands[0], DDmode)
111    || gpc_reg_operand (operands[1], SDmode))
112    && TARGET_HARD_FLOAT && TARGET_FPRS"
113   "stfd%U0%X0 %1,%0"
114   [(set_attr "type" "fpstore")
115    (set_attr "length" "4")])
116
117 (define_insn "movsd_load"
118   [(set (match_operand:SD 0 "nonimmediate_operand" "=f")
119         (unspec:SD [(match_operand:DD 1 "input_operand" "m")]
120                    UNSPEC_MOVSD_LOAD))]
121   "(gpc_reg_operand (operands[0], SDmode)
122    || gpc_reg_operand (operands[1], DDmode))
123    && TARGET_HARD_FLOAT && TARGET_FPRS"
124   "lfd%U1%X1 %0,%1"
125   [(set_attr "type" "fpload")
126    (set_attr "length" "4")])
127
128 ;; Hardware support for decimal floating point operations.
129
130 (define_insn "extendsddd2"
131   [(set (match_operand:DD 0 "gpc_reg_operand" "=f")
132         (float_extend:DD (match_operand:SD 1 "gpc_reg_operand" "f")))]
133   "TARGET_DFP"
134   "dctdp %0,%1"
135   [(set_attr "type" "fp")])
136
137 (define_expand "extendsdtd2"
138   [(set (match_operand:TD 0 "gpc_reg_operand" "=f")
139         (float_extend:TD (match_operand:SD 1 "gpc_reg_operand" "f")))]
140   "TARGET_DFP"
141 {
142   rtx tmp = gen_reg_rtx (DDmode);
143   emit_insn (gen_extendsddd2 (tmp, operands[1]));
144   emit_insn (gen_extendddtd2 (operands[0], tmp));
145   DONE;
146 })
147
148 (define_insn "truncddsd2"
149   [(set (match_operand:SD 0 "gpc_reg_operand" "=f")
150         (float_truncate:SD (match_operand:DD 1 "gpc_reg_operand" "f")))]
151   "TARGET_DFP"
152   "drsp %0,%1"
153   [(set_attr "type" "fp")])
154
155 (define_expand "negdd2"
156   [(set (match_operand:DD 0 "gpc_reg_operand" "")
157         (neg:DD (match_operand:DD 1 "gpc_reg_operand" "")))]
158   "TARGET_HARD_FLOAT && TARGET_FPRS"
159   "")
160
161 (define_insn "*negdd2_fpr"
162   [(set (match_operand:DD 0 "gpc_reg_operand" "=f")
163         (neg:DD (match_operand:DD 1 "gpc_reg_operand" "f")))]
164   "TARGET_HARD_FLOAT && TARGET_FPRS"
165   "fneg %0,%1"
166   [(set_attr "type" "fp")])
167
168 (define_expand "absdd2"
169   [(set (match_operand:DD 0 "gpc_reg_operand" "")
170         (abs:DD (match_operand:DD 1 "gpc_reg_operand" "")))]
171   "TARGET_HARD_FLOAT && TARGET_FPRS"
172   "")
173
174 (define_insn "*absdd2_fpr"
175   [(set (match_operand:DD 0 "gpc_reg_operand" "=f")
176         (abs:DD (match_operand:DD 1 "gpc_reg_operand" "f")))]
177   "TARGET_HARD_FLOAT && TARGET_FPRS"
178   "fabs %0,%1"
179   [(set_attr "type" "fp")])
180
181 (define_insn "*nabsdd2_fpr"
182   [(set (match_operand:DD 0 "gpc_reg_operand" "=f")
183         (neg:DD (abs:DD (match_operand:DF 1 "gpc_reg_operand" "f"))))]
184   "TARGET_HARD_FLOAT && TARGET_FPRS"
185   "fnabs %0,%1"
186   [(set_attr "type" "fp")])
187
188 (define_expand "movdd"
189   [(set (match_operand:DD 0 "nonimmediate_operand" "")
190         (match_operand:DD 1 "any_operand" ""))]
191   ""
192   "{ rs6000_emit_move (operands[0], operands[1], DDmode); DONE; }")
193
194 (define_split
195   [(set (match_operand:DD 0 "gpc_reg_operand" "")
196         (match_operand:DD 1 "const_int_operand" ""))]
197   "! TARGET_POWERPC64 && reload_completed
198    && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
199        || (GET_CODE (operands[0]) == SUBREG
200            && GET_CODE (SUBREG_REG (operands[0])) == REG
201            && REGNO (SUBREG_REG (operands[0])) <= 31))"
202   [(set (match_dup 2) (match_dup 4))
203    (set (match_dup 3) (match_dup 1))]
204   "
205 {
206   int endian = (WORDS_BIG_ENDIAN == 0);
207   HOST_WIDE_INT value = INTVAL (operands[1]);
208
209   operands[2] = operand_subword (operands[0], endian, 0, DDmode);
210   operands[3] = operand_subword (operands[0], 1 - endian, 0, DDmode);
211 #if HOST_BITS_PER_WIDE_INT == 32
212   operands[4] = (value & 0x80000000) ? constm1_rtx : const0_rtx;
213 #else
214   operands[4] = GEN_INT (value >> 32);
215   operands[1] = GEN_INT (((value & 0xffffffff) ^ 0x80000000) - 0x80000000);
216 #endif
217 }")
218
219 (define_split
220   [(set (match_operand:DD 0 "gpc_reg_operand" "")
221         (match_operand:DD 1 "const_double_operand" ""))]
222   "! TARGET_POWERPC64 && reload_completed
223    && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
224        || (GET_CODE (operands[0]) == SUBREG
225            && GET_CODE (SUBREG_REG (operands[0])) == REG
226            && REGNO (SUBREG_REG (operands[0])) <= 31))"
227   [(set (match_dup 2) (match_dup 4))
228    (set (match_dup 3) (match_dup 5))]
229   "
230 {
231   int endian = (WORDS_BIG_ENDIAN == 0);
232   long l[2];
233   REAL_VALUE_TYPE rv;
234
235   REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
236   REAL_VALUE_TO_TARGET_DECIMAL64 (rv, l);
237
238   operands[2] = operand_subword (operands[0], endian, 0, DDmode);
239   operands[3] = operand_subword (operands[0], 1 - endian, 0, DDmode);
240   operands[4] = gen_int_mode (l[endian], SImode);
241   operands[5] = gen_int_mode (l[1 - endian], SImode);
242 }")
243
244 (define_split
245   [(set (match_operand:DD 0 "gpc_reg_operand" "")
246         (match_operand:DD 1 "const_double_operand" ""))]
247   "TARGET_POWERPC64 && reload_completed
248    && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
249        || (GET_CODE (operands[0]) == SUBREG
250            && GET_CODE (SUBREG_REG (operands[0])) == REG
251            && REGNO (SUBREG_REG (operands[0])) <= 31))"
252   [(set (match_dup 2) (match_dup 3))]
253   "
254 {
255   int endian = (WORDS_BIG_ENDIAN == 0);
256   long l[2];
257   REAL_VALUE_TYPE rv;
258 #if HOST_BITS_PER_WIDE_INT >= 64
259   HOST_WIDE_INT val;
260 #endif
261
262   REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
263   REAL_VALUE_TO_TARGET_DECIMAL64 (rv, l);
264
265   operands[2] = gen_lowpart (DImode, operands[0]);
266   /* HIGHPART is lower memory address when WORDS_BIG_ENDIAN.  */
267 #if HOST_BITS_PER_WIDE_INT >= 64
268   val = ((HOST_WIDE_INT)(unsigned long)l[endian] << 32
269          | ((HOST_WIDE_INT)(unsigned long)l[1 - endian]));
270
271   operands[3] = gen_int_mode (val, DImode);
272 #else
273   operands[3] = immed_double_const (l[1 - endian], l[endian], DImode);
274 #endif
275 }")
276
277 ;; Don't have reload use general registers to load a constant.  First,
278 ;; it might not work if the output operand is the equivalent of
279 ;; a non-offsettable memref, but also it is less efficient than loading
280 ;; the constant into an FP register, since it will probably be used there.
281 ;; The "??" is a kludge until we can figure out a more reasonable way
282 ;; of handling these non-offsettable values.
283 (define_insn "*movdd_hardfloat32"
284   [(set (match_operand:DD 0 "nonimmediate_operand" "=!r,??r,m,f,f,m,!r,!r,!r")
285         (match_operand:DD 1 "input_operand" "r,m,r,f,m,f,G,H,F"))]
286   "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS
287    && (gpc_reg_operand (operands[0], DDmode)
288        || gpc_reg_operand (operands[1], DDmode))"
289   "*
290 {
291   switch (which_alternative)
292     {
293     default:
294       gcc_unreachable ();
295     case 0:
296       /* We normally copy the low-numbered register first.  However, if
297          the first register operand 0 is the same as the second register
298          of operand 1, we must copy in the opposite order.  */
299       if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
300         return \"mr %L0,%L1\;mr %0,%1\";
301       else
302         return \"mr %0,%1\;mr %L0,%L1\";
303     case 1:
304       if (rs6000_offsettable_memref_p (operands[1])
305           || (GET_CODE (operands[1]) == MEM
306               && (GET_CODE (XEXP (operands[1], 0)) == LO_SUM
307                   || GET_CODE (XEXP (operands[1], 0)) == PRE_INC
308                   || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)))
309         {
310           /* If the low-address word is used in the address, we must load
311              it last.  Otherwise, load it first.  Note that we cannot have
312              auto-increment in that case since the address register is
313              known to be dead.  */
314           if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
315                                  operands[1], 0))
316             return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\";
317           else
318             return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\";
319         }
320       else
321         {
322           rtx addreg;
323
324           addreg = find_addr_reg (XEXP (operands[1], 0));
325           if (refers_to_regno_p (REGNO (operands[0]),
326                                  REGNO (operands[0]) + 1,
327                                  operands[1], 0))
328             {
329               output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
330               output_asm_insn (\"{lx|lwzx} %L0,%1\", operands);
331               output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
332               return \"{lx|lwzx} %0,%1\";
333             }
334           else
335             {
336               output_asm_insn (\"{lx|lwzx} %0,%1\", operands);
337               output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
338               output_asm_insn (\"{lx|lwzx} %L0,%1\", operands);
339               output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
340               return \"\";
341             }
342         }
343     case 2:
344       if (rs6000_offsettable_memref_p (operands[0])
345           || (GET_CODE (operands[0]) == MEM
346               && (GET_CODE (XEXP (operands[0], 0)) == LO_SUM
347                   || GET_CODE (XEXP (operands[0], 0)) == PRE_INC
348                   || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)))
349         return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\";
350       else
351         {
352           rtx addreg;
353
354           addreg = find_addr_reg (XEXP (operands[0], 0));
355           output_asm_insn (\"{stx|stwx} %1,%0\", operands);
356           output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
357           output_asm_insn (\"{stx|stwx} %L1,%0\", operands);
358           output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
359           return \"\";
360         }
361     case 3:
362       return \"fmr %0,%1\";
363     case 4:
364       return \"lfd%U1%X1 %0,%1\";
365     case 5:
366       return \"stfd%U0%X0 %1,%0\";
367     case 6:
368     case 7:
369     case 8:
370       return \"#\";
371     }
372 }"
373   [(set_attr "type" "two,load,store,fp,fpload,fpstore,*,*,*")
374    (set_attr "length" "8,16,16,4,4,4,8,12,16")])
375
376 (define_insn "*movdd_softfloat32"
377   [(set (match_operand:DD 0 "nonimmediate_operand" "=r,r,m,r,r,r")
378         (match_operand:DD 1 "input_operand" "r,m,r,G,H,F"))]
379   "! TARGET_POWERPC64 && (TARGET_SOFT_FLOAT || !TARGET_FPRS)
380    && (gpc_reg_operand (operands[0], DDmode)
381        || gpc_reg_operand (operands[1], DDmode))"
382   "*
383 {
384   switch (which_alternative)
385     {
386     default:
387       gcc_unreachable ();
388     case 0:
389       /* We normally copy the low-numbered register first.  However, if
390          the first register operand 0 is the same as the second register of
391          operand 1, we must copy in the opposite order.  */
392       if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
393         return \"mr %L0,%L1\;mr %0,%1\";
394       else
395         return \"mr %0,%1\;mr %L0,%L1\";
396     case 1:
397       /* If the low-address word is used in the address, we must load
398          it last.  Otherwise, load it first.  Note that we cannot have
399          auto-increment in that case since the address register is
400          known to be dead.  */
401       if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
402                              operands[1], 0))
403         return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\";
404       else
405         return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\";
406     case 2:
407       return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\";
408     case 3:
409     case 4:
410     case 5:
411       return \"#\";
412     }
413 }"
414   [(set_attr "type" "two,load,store,*,*,*")
415    (set_attr "length" "8,8,8,8,12,16")])
416
417 ; ld/std require word-aligned displacements -> 'Y' constraint.
418 ; List Y->r and r->Y before r->r for reload.
419 (define_insn "*movdd_hardfloat64_mfpgpr"
420   [(set (match_operand:DD 0 "nonimmediate_operand" "=Y,r,!r,f,f,m,*c*l,!r,*h,!r,!r,!r,r,f")
421         (match_operand:DD 1 "input_operand" "r,Y,r,f,m,f,r,h,0,G,H,F,f,r"))]
422   "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
423    && (gpc_reg_operand (operands[0], DDmode)
424        || gpc_reg_operand (operands[1], DDmode))"
425   "@
426    std%U0%X0 %1,%0
427    ld%U1%X1 %0,%1
428    mr %0,%1
429    fmr %0,%1
430    lfd%U1%X1 %0,%1
431    stfd%U0%X0 %1,%0
432    mt%0 %1
433    mf%1 %0
434    {cror 0,0,0|nop}
435    #
436    #
437    #
438    mftgpr %0,%1
439    mffgpr %0,%1"
440   [(set_attr "type" "store,load,*,fp,fpload,fpstore,mtjmpr,mfjmpr,*,*,*,*,mftgpr,mffgpr")
441    (set_attr "length" "4,4,4,4,4,4,4,4,4,8,12,16,4,4")])
442
443 ; ld/std require word-aligned displacements -> 'Y' constraint.
444 ; List Y->r and r->Y before r->r for reload.
445 (define_insn "*movdd_hardfloat64"
446   [(set (match_operand:DD 0 "nonimmediate_operand" "=Y,r,!r,f,f,m,*c*l,!r,*h,!r,!r,!r")
447         (match_operand:DD 1 "input_operand" "r,Y,r,f,m,f,r,h,0,G,H,F"))]
448   "TARGET_POWERPC64 && !TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
449    && (gpc_reg_operand (operands[0], DDmode)
450        || gpc_reg_operand (operands[1], DDmode))"
451   "@
452    std%U0%X0 %1,%0
453    ld%U1%X1 %0,%1
454    mr %0,%1
455    fmr %0,%1
456    lfd%U1%X1 %0,%1
457    stfd%U0%X0 %1,%0
458    mt%0 %1
459    mf%1 %0
460    {cror 0,0,0|nop}
461    #
462    #
463    #"
464   [(set_attr "type" "store,load,*,fp,fpload,fpstore,mtjmpr,mfjmpr,*,*,*,*")
465    (set_attr "length" "4,4,4,4,4,4,4,4,4,8,12,16")])
466
467 (define_insn "*movdd_softfloat64"
468   [(set (match_operand:DD 0 "nonimmediate_operand" "=r,Y,r,cl,r,r,r,r,*h")
469         (match_operand:DD 1 "input_operand" "Y,r,r,r,h,G,H,F,0"))]
470   "TARGET_POWERPC64 && (TARGET_SOFT_FLOAT || !TARGET_FPRS)
471    && (gpc_reg_operand (operands[0], DDmode)
472        || gpc_reg_operand (operands[1], DDmode))"
473   "@
474    ld%U1%X1 %0,%1
475    std%U0%X0 %1,%0
476    mr %0,%1
477    mt%0 %1
478    mf%1 %0
479    #
480    #
481    #
482    {cror 0,0,0|nop}"
483   [(set_attr "type" "load,store,*,mtjmpr,mfjmpr,*,*,*,*")
484    (set_attr "length" "4,4,4,4,4,8,12,16,4")])
485
486 (define_expand "negtd2"
487   [(set (match_operand:TD 0 "gpc_reg_operand" "")
488         (neg:TD (match_operand:TD 1 "gpc_reg_operand" "")))]
489   "TARGET_HARD_FLOAT && TARGET_FPRS"
490   "")
491
492 (define_insn "*negtd2_fpr"
493   [(set (match_operand:TD 0 "gpc_reg_operand" "=f")
494         (neg:TD (match_operand:TD 1 "gpc_reg_operand" "f")))]
495   "TARGET_HARD_FLOAT && TARGET_FPRS"
496   "fneg %0,%1"
497   [(set_attr "type" "fp")])
498
499 (define_expand "abstd2"
500   [(set (match_operand:TD 0 "gpc_reg_operand" "")
501         (abs:TD (match_operand:TD 1 "gpc_reg_operand" "")))]
502   "TARGET_HARD_FLOAT && TARGET_FPRS"
503   "")
504
505 (define_insn "*abstd2_fpr"
506   [(set (match_operand:TD 0 "gpc_reg_operand" "=f")
507         (abs:TD (match_operand:TD 1 "gpc_reg_operand" "f")))]
508   "TARGET_HARD_FLOAT && TARGET_FPRS"
509   "fabs %0,%1"
510   [(set_attr "type" "fp")])
511
512 (define_insn "*nabstd2_fpr"
513   [(set (match_operand:TD 0 "gpc_reg_operand" "=f")
514         (neg:TD (abs:TD (match_operand:DF 1 "gpc_reg_operand" "f"))))]
515   "TARGET_HARD_FLOAT && TARGET_FPRS"
516   "fnabs %0,%1"
517   [(set_attr "type" "fp")])
518
519 (define_expand "movtd"
520   [(set (match_operand:TD 0 "general_operand" "")
521         (match_operand:TD 1 "any_operand" ""))]
522   "TARGET_HARD_FLOAT && TARGET_FPRS"
523   "{ rs6000_emit_move (operands[0], operands[1], TDmode); DONE; }")
524
525 ; It's important to list the o->f and f->o moves before f->f because
526 ; otherwise reload, given m->f, will try to pick f->f and reload it,
527 ; which doesn't make progress.  Likewise r->Y must be before r->r.
528 (define_insn_and_split "*movtd_internal"
529   [(set (match_operand:TD 0 "nonimmediate_operand" "=o,f,f,r,Y,r")
530         (match_operand:TD 1 "input_operand"         "f,o,f,YGHF,r,r"))]
531   "TARGET_HARD_FLOAT && TARGET_FPRS
532    && (gpc_reg_operand (operands[0], TDmode)
533        || gpc_reg_operand (operands[1], TDmode))"
534   "#"
535   "&& reload_completed"
536   [(pc)]
537 { rs6000_split_multireg_move (operands[0], operands[1]); DONE; }
538   [(set_attr "length" "8,8,8,20,20,16")])
539
540 ;; Hardware support for decimal floating point operations.
541
542 (define_insn "extendddtd2"
543   [(set (match_operand:TD 0 "gpc_reg_operand" "=f")
544         (float_extend:TD (match_operand:DD 1 "gpc_reg_operand" "f")))]
545   "TARGET_DFP"
546   "dctqpq %0,%1"
547   [(set_attr "type" "fp")])
548
549 ;; The result of drdpq is an even/odd register pair with the converted
550 ;; value in the even register and zero in the odd register.
551 ;; FIXME: Avoid the register move by using a reload constraint to ensure
552 ;; that the result is the first of the pair receiving the result of drdpq.
553
554 (define_insn "trunctddd2"
555   [(set (match_operand:DD 0 "gpc_reg_operand" "=f")
556         (float_truncate:DD (match_operand:TD 1 "gpc_reg_operand" "f")))
557    (clobber (match_scratch:TD 2 "=f"))]
558   "TARGET_DFP"
559   "drdpq %2,%1\;fmr %0,%2"
560   [(set_attr "type" "fp")])
561
562 (define_insn "adddd3"
563   [(set (match_operand:DD 0 "gpc_reg_operand" "=f")
564         (plus:DD (match_operand:DD 1 "gpc_reg_operand" "%f")
565                  (match_operand:DD 2 "gpc_reg_operand" "f")))]
566   "TARGET_DFP"
567   "dadd %0,%1,%2"
568   [(set_attr "type" "fp")])
569
570 (define_insn "addtd3"
571   [(set (match_operand:TD 0 "gpc_reg_operand" "=f")
572         (plus:TD (match_operand:TD 1 "gpc_reg_operand" "%f")
573                  (match_operand:TD 2 "gpc_reg_operand" "f")))]
574   "TARGET_DFP"
575   "daddq %0,%1,%2"
576   [(set_attr "type" "fp")])
577
578 (define_insn "subdd3"
579   [(set (match_operand:DD 0 "gpc_reg_operand" "=f")
580         (minus:DD (match_operand:DD 1 "gpc_reg_operand" "f")
581                   (match_operand:DD 2 "gpc_reg_operand" "f")))]
582   "TARGET_DFP"
583   "dsub %0,%1,%2"
584   [(set_attr "type" "fp")])
585
586 (define_insn "subtd3"
587   [(set (match_operand:TD 0 "gpc_reg_operand" "=f")
588         (minus:TD (match_operand:TD 1 "gpc_reg_operand" "f")
589                   (match_operand:TD 2 "gpc_reg_operand" "f")))]
590   "TARGET_DFP"
591   "dsubq %0,%1,%2"
592   [(set_attr "type" "fp")])
593
594 (define_insn "muldd3"
595   [(set (match_operand:DD 0 "gpc_reg_operand" "=f")
596         (mult:DD (match_operand:DD 1 "gpc_reg_operand" "%f")
597                  (match_operand:DD 2 "gpc_reg_operand" "f")))]
598   "TARGET_DFP"
599   "dmul %0,%1,%2"
600   [(set_attr "type" "fp")])
601
602 (define_insn "multd3"
603   [(set (match_operand:TD 0 "gpc_reg_operand" "=f")
604         (mult:TD (match_operand:TD 1 "gpc_reg_operand" "%f")
605                  (match_operand:TD 2 "gpc_reg_operand" "f")))]
606   "TARGET_DFP"
607   "dmulq %0,%1,%2"
608   [(set_attr "type" "fp")])
609
610 (define_insn "divdd3"
611   [(set (match_operand:DD 0 "gpc_reg_operand" "=f")
612         (div:DD (match_operand:DD 1 "gpc_reg_operand" "f")
613                 (match_operand:DD 2 "gpc_reg_operand" "f")))]
614   "TARGET_DFP"
615   "ddiv %0,%1,%2"
616   [(set_attr "type" "fp")])
617
618 (define_insn "divtd3"
619   [(set (match_operand:TD 0 "gpc_reg_operand" "=f")
620         (div:TD (match_operand:TD 1 "gpc_reg_operand" "f")
621                 (match_operand:TD 2 "gpc_reg_operand" "f")))]
622   "TARGET_DFP"
623   "ddivq %0,%1,%2"
624   [(set_attr "type" "fp")])
625
626 (define_insn "*cmpdd_internal1"
627   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
628         (compare:CCFP (match_operand:DD 1 "gpc_reg_operand" "f")
629                       (match_operand:DD 2 "gpc_reg_operand" "f")))]
630   "TARGET_DFP"
631   "dcmpu %0,%1,%2"
632   [(set_attr "type" "fpcompare")])
633
634 (define_insn "*cmptd_internal1"
635   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
636         (compare:CCFP (match_operand:TD 1 "gpc_reg_operand" "f")
637                       (match_operand:TD 2 "gpc_reg_operand" "f")))]
638   "TARGET_DFP"
639   "dcmpuq %0,%1,%2"
640   [(set_attr "type" "fpcompare")])
641
642 (define_insn "floatditd2"
643   [(set (match_operand:TD 0 "gpc_reg_operand" "=f")
644         (float:TD (match_operand:DI 1 "gpc_reg_operand" "f")))]
645   "TARGET_DFP"
646   "dcffixq %0,%1"
647   [(set_attr "type" "fp")])
648
649 ;; Convert a decimal64 to a decimal64 whose value is an integer.
650 ;; This is the first stage of converting it to an integer type.
651
652 (define_insn "ftruncdd2"
653   [(set (match_operand:DD 0 "gpc_reg_operand" "=f")
654         (fix:DD (match_operand:DD 1 "gpc_reg_operand" "f")))]
655   "TARGET_DFP"
656   "drintn. 0,%0,%1,1"
657   [(set_attr "type" "fp")])
658
659 ;; Convert a decimal64 whose value is an integer to an actual integer.
660 ;; This is the second stage of converting decimal float to integer type.
661
662 (define_insn "fixdddi2"
663   [(set (match_operand:DI 0 "gpc_reg_operand" "=f")
664         (fix:DI (match_operand:DD 1 "gpc_reg_operand" "f")))]
665   "TARGET_DFP"
666   "dctfix %0,%1"
667   [(set_attr "type" "fp")])
668
669 ;; Convert a decimal128 to a decimal128 whose value is an integer.
670 ;; This is the first stage of converting it to an integer type.
671
672 (define_insn "ftrunctd2"
673   [(set (match_operand:TD 0 "gpc_reg_operand" "=f")
674         (fix:TD (match_operand:TD 1 "gpc_reg_operand" "f")))]
675   "TARGET_DFP"
676   "drintnq. 0,%0,%1,1"
677   [(set_attr "type" "fp")])
678
679 ;; Convert a decimal128 whose value is an integer to an actual integer.
680 ;; This is the second stage of converting decimal float to integer type.
681
682 (define_insn "fixtddi2"
683   [(set (match_operand:DI 0 "gpc_reg_operand" "=f")
684         (fix:DI (match_operand:TD 1 "gpc_reg_operand" "f")))]
685   "TARGET_DFP"
686   "dctfixq %0,%1"
687   [(set_attr "type" "fp")])