2007-05-30 H.J. Lu <hongjiu.lu@intel.com>
[official-gcc.git] / gcc / config / rs6000 / dfp.md
blob8c78d818f26b6f239888306c84dbd023335e0d5c
1 ;; Decimal Floating Point (DFP) patterns.
2 ;; Copyright (C) 2007
3 ;; Free Software Foundation, Inc.
4 ;; Contributed by Ben Elliston (bje@au.ibm.com) and Peter Bergner
5 ;; (bergner@vnet.ibm.com).
7 ;; This file is part of GCC.
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 2, or (at your
12 ;; option) any later version.
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.
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GCC; see the file COPYING.  If not, write to the
21 ;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
22 ;; MA 02110-1301, USA.
24 (define_expand "negdd2"
25   [(set (match_operand:DD 0 "gpc_reg_operand" "")
26         (neg:DD (match_operand:DD 1 "gpc_reg_operand" "")))]
27   "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
28   "")
30 (define_insn "*negdd2_fpr"
31   [(set (match_operand:DD 0 "gpc_reg_operand" "=f")
32         (neg:DD (match_operand:DD 1 "gpc_reg_operand" "f")))]
33   "TARGET_HARD_FLOAT && TARGET_FPRS"
34   "fneg %0,%1"
35   [(set_attr "type" "fp")])
37 (define_expand "absdd2"
38   [(set (match_operand:DD 0 "gpc_reg_operand" "")
39         (abs:DD (match_operand:DD 1 "gpc_reg_operand" "")))]
40   "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
41   "")
43 (define_insn "*absdd2_fpr"
44   [(set (match_operand:DD 0 "gpc_reg_operand" "=f")
45         (abs:DD (match_operand:DD 1 "gpc_reg_operand" "f")))]
46   "TARGET_HARD_FLOAT && TARGET_FPRS"
47   "fabs %0,%1"
48   [(set_attr "type" "fp")])
50 (define_insn "*nabsdd2_fpr"
51   [(set (match_operand:DD 0 "gpc_reg_operand" "=f")
52         (neg:DD (abs:DD (match_operand:DF 1 "gpc_reg_operand" "f"))))]
53   "TARGET_HARD_FLOAT && TARGET_FPRS"
54   "fnabs %0,%1"
55   [(set_attr "type" "fp")])
57 (define_expand "movdd"
58   [(set (match_operand:DD 0 "nonimmediate_operand" "")
59         (match_operand:DD 1 "any_operand" ""))]
60   ""
61   "{ rs6000_emit_move (operands[0], operands[1], DDmode); DONE; }")
63 (define_split
64   [(set (match_operand:DD 0 "gpc_reg_operand" "")
65         (match_operand:DD 1 "const_int_operand" ""))]
66   "! TARGET_POWERPC64 && reload_completed
67    && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
68        || (GET_CODE (operands[0]) == SUBREG
69            && GET_CODE (SUBREG_REG (operands[0])) == REG
70            && REGNO (SUBREG_REG (operands[0])) <= 31))"
71   [(set (match_dup 2) (match_dup 4))
72    (set (match_dup 3) (match_dup 1))]
73   "
75   int endian = (WORDS_BIG_ENDIAN == 0);
76   HOST_WIDE_INT value = INTVAL (operands[1]);
78   operands[2] = operand_subword (operands[0], endian, 0, DDmode);
79   operands[3] = operand_subword (operands[0], 1 - endian, 0, DDmode);
80 #if HOST_BITS_PER_WIDE_INT == 32
81   operands[4] = (value & 0x80000000) ? constm1_rtx : const0_rtx;
82 #else
83   operands[4] = GEN_INT (value >> 32);
84   operands[1] = GEN_INT (((value & 0xffffffff) ^ 0x80000000) - 0x80000000);
85 #endif
86 }")
88 (define_split
89   [(set (match_operand:DD 0 "gpc_reg_operand" "")
90         (match_operand:DD 1 "const_double_operand" ""))]
91   "! TARGET_POWERPC64 && reload_completed
92    && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
93        || (GET_CODE (operands[0]) == SUBREG
94            && GET_CODE (SUBREG_REG (operands[0])) == REG
95            && REGNO (SUBREG_REG (operands[0])) <= 31))"
96   [(set (match_dup 2) (match_dup 4))
97    (set (match_dup 3) (match_dup 5))]
98   "
100   int endian = (WORDS_BIG_ENDIAN == 0);
101   long l[2];
102   REAL_VALUE_TYPE rv;
104   REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
105   REAL_VALUE_TO_TARGET_DECIMAL64 (rv, l);
107   operands[2] = operand_subword (operands[0], endian, 0, DDmode);
108   operands[3] = operand_subword (operands[0], 1 - endian, 0, DDmode);
109   operands[4] = gen_int_mode (l[endian], SImode);
110   operands[5] = gen_int_mode (l[1 - endian], SImode);
113 (define_split
114   [(set (match_operand:DD 0 "gpc_reg_operand" "")
115         (match_operand:DD 1 "const_double_operand" ""))]
116   "TARGET_POWERPC64 && reload_completed
117    && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
118        || (GET_CODE (operands[0]) == SUBREG
119            && GET_CODE (SUBREG_REG (operands[0])) == REG
120            && REGNO (SUBREG_REG (operands[0])) <= 31))"
121   [(set (match_dup 2) (match_dup 3))]
122   "
124   int endian = (WORDS_BIG_ENDIAN == 0);
125   long l[2];
126   REAL_VALUE_TYPE rv;
127 #if HOST_BITS_PER_WIDE_INT >= 64
128   HOST_WIDE_INT val;
129 #endif
131   REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
132   REAL_VALUE_TO_TARGET_DECIMAL64 (rv, l);
134   operands[2] = gen_lowpart (DImode, operands[0]);
135   /* HIGHPART is lower memory address when WORDS_BIG_ENDIAN.  */
136 #if HOST_BITS_PER_WIDE_INT >= 64
137   val = ((HOST_WIDE_INT)(unsigned long)l[endian] << 32
138          | ((HOST_WIDE_INT)(unsigned long)l[1 - endian]));
140   operands[3] = gen_int_mode (val, DImode);
141 #else
142   operands[3] = immed_double_const (l[1 - endian], l[endian], DImode);
143 #endif
146 ;; Don't have reload use general registers to load a constant.  First,
147 ;; it might not work if the output operand is the equivalent of
148 ;; a non-offsettable memref, but also it is less efficient than loading
149 ;; the constant into an FP register, since it will probably be used there.
150 ;; The "??" is a kludge until we can figure out a more reasonable way
151 ;; of handling these non-offsettable values.
152 (define_insn "*movdd_hardfloat32"
153   [(set (match_operand:DD 0 "nonimmediate_operand" "=!r,??r,m,f,f,m,!r,!r,!r")
154         (match_operand:DD 1 "input_operand" "r,m,r,f,m,f,G,H,F"))]
155   "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS
156    && (gpc_reg_operand (operands[0], DDmode)
157        || gpc_reg_operand (operands[1], DDmode))"
158   "*
160   switch (which_alternative)
161     {
162     default:
163       gcc_unreachable ();
164     case 0:
165       /* We normally copy the low-numbered register first.  However, if
166          the first register operand 0 is the same as the second register
167          of operand 1, we must copy in the opposite order.  */
168       if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
169         return \"mr %L0,%L1\;mr %0,%1\";
170       else
171         return \"mr %0,%1\;mr %L0,%L1\";
172     case 1:
173       if (rs6000_offsettable_memref_p (operands[1])
174           || (GET_CODE (operands[1]) == MEM
175               && (GET_CODE (XEXP (operands[1], 0)) == LO_SUM
176                   || GET_CODE (XEXP (operands[1], 0)) == PRE_INC
177                   || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)))
178         {
179           /* If the low-address word is used in the address, we must load
180              it last.  Otherwise, load it first.  Note that we cannot have
181              auto-increment in that case since the address register is
182              known to be dead.  */
183           if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
184                                  operands[1], 0))
185             return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\";
186           else
187             return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\";
188         }
189       else
190         {
191           rtx addreg;
193           addreg = find_addr_reg (XEXP (operands[1], 0));
194           if (refers_to_regno_p (REGNO (operands[0]),
195                                  REGNO (operands[0]) + 1,
196                                  operands[1], 0))
197             {
198               output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
199               output_asm_insn (\"{lx|lwzx} %L0,%1\", operands);
200               output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
201               return \"{lx|lwzx} %0,%1\";
202             }
203           else
204             {
205               output_asm_insn (\"{lx|lwzx} %0,%1\", operands);
206               output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
207               output_asm_insn (\"{lx|lwzx} %L0,%1\", operands);
208               output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
209               return \"\";
210             }
211         }
212     case 2:
213       if (rs6000_offsettable_memref_p (operands[0])
214           || (GET_CODE (operands[0]) == MEM
215               && (GET_CODE (XEXP (operands[0], 0)) == LO_SUM
216                   || GET_CODE (XEXP (operands[0], 0)) == PRE_INC
217                   || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)))
218         return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\";
219       else
220         {
221           rtx addreg;
223           addreg = find_addr_reg (XEXP (operands[0], 0));
224           output_asm_insn (\"{stx|stwx} %1,%0\", operands);
225           output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
226           output_asm_insn (\"{stx|stwx} %L1,%0\", operands);
227           output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
228           return \"\";
229         }
230     case 3:
231       return \"fmr %0,%1\";
232     case 4:
233       return \"lfd%U1%X1 %0,%1\";
234     case 5:
235       return \"stfd%U0%X0 %1,%0\";
236     case 6:
237     case 7:
238     case 8:
239       return \"#\";
240     }
242   [(set_attr "type" "two,load,store,fp,fpload,fpstore,*,*,*")
243    (set_attr "length" "8,16,16,4,4,4,8,12,16")])
245 (define_insn "*movdd_softfloat32"
246   [(set (match_operand:DD 0 "nonimmediate_operand" "=r,r,m,r,r,r")
247         (match_operand:DD 1 "input_operand" "r,m,r,G,H,F"))]
248   "! TARGET_POWERPC64 && TARGET_SOFT_FLOAT
249    && (gpc_reg_operand (operands[0], DDmode)
250        || gpc_reg_operand (operands[1], DDmode))"
251   "*
253   switch (which_alternative)
254     {
255     default:
256       gcc_unreachable ();
257     case 0:
258       /* We normally copy the low-numbered register first.  However, if
259          the first register operand 0 is the same as the second register of
260          operand 1, we must copy in the opposite order.  */
261       if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
262         return \"mr %L0,%L1\;mr %0,%1\";
263       else
264         return \"mr %0,%1\;mr %L0,%L1\";
265     case 1:
266       /* If the low-address word is used in the address, we must load
267          it last.  Otherwise, load it first.  Note that we cannot have
268          auto-increment in that case since the address register is
269          known to be dead.  */
270       if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
271                              operands[1], 0))
272         return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\";
273       else
274         return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\";
275     case 2:
276       return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\";
277     case 3:
278     case 4:
279     case 5:
280       return \"#\";
281     }
283   [(set_attr "type" "two,load,store,*,*,*")
284    (set_attr "length" "8,8,8,8,12,16")])
286 ; ld/std require word-aligned displacements -> 'Y' constraint.
287 ; List Y->r and r->Y before r->r for reload.
288 (define_insn "*movdd_hardfloat64_mfpgpr"
289   [(set (match_operand:DD 0 "nonimmediate_operand" "=Y,r,!r,f,f,m,*c*l,!r,*h,!r,!r,!r,r,f")
290         (match_operand:DD 1 "input_operand" "r,Y,r,f,m,f,r,h,0,G,H,F,f,r"))]
291   "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
292    && (gpc_reg_operand (operands[0], DDmode)
293        || gpc_reg_operand (operands[1], DDmode))"
294   "@
295    std%U0%X0 %1,%0
296    ld%U1%X1 %0,%1
297    mr %0,%1
298    fmr %0,%1
299    lfd%U1%X1 %0,%1
300    stfd%U0%X0 %1,%0
301    mt%0 %1
302    mf%1 %0
303    {cror 0,0,0|nop}
304    #
305    #
306    #
307    mftgpr %0,%1
308    mffgpr %0,%1"
309   [(set_attr "type" "store,load,*,fp,fpload,fpstore,mtjmpr,mfjmpr,*,*,*,*,mftgpr,mffgpr")
310    (set_attr "length" "4,4,4,4,4,4,4,4,4,8,12,16,4,4")])
312 ; ld/std require word-aligned displacements -> 'Y' constraint.
313 ; List Y->r and r->Y before r->r for reload.(define_insn "*movdd_hardfloat64"
314 (define_insn "*movdd_hardfloat64"
315   [(set (match_operand:DD 0 "nonimmediate_operand" "=Y,r,!r,f,f,m,*c*l,!r,*h,!r,!r,!r")
316         (match_operand:DD 1 "input_operand" "r,Y,r,f,m,f,r,h,0,G,H,F"))]
317   "TARGET_POWERPC64 && !TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
318    && (gpc_reg_operand (operands[0], DDmode)
319        || gpc_reg_operand (operands[1], DDmode))"
320   "@
321    std%U0%X0 %1,%0
322    ld%U1%X1 %0,%1
323    mr %0,%1
324    fmr %0,%1
325    lfd%U1%X1 %0,%1
326    stfd%U0%X0 %1,%0
327    mt%0 %1
328    mf%1 %0
329    {cror 0,0,0|nop}
330    #
331    #
332    #"
333   [(set_attr "type" "store,load,*,fp,fpload,fpstore,mtjmpr,mfjmpr,*,*,*,*")
334    (set_attr "length" "4,4,4,4,4,4,4,4,4,8,12,16")])
336 (define_insn "*movdd_softfloat64"
337   [(set (match_operand:DD 0 "nonimmediate_operand" "=r,Y,r,cl,r,r,r,r,*h")
338         (match_operand:DD 1 "input_operand" "Y,r,r,r,h,G,H,F,0"))]
339   "TARGET_POWERPC64 && (TARGET_SOFT_FLOAT || !TARGET_FPRS)
340    && (gpc_reg_operand (operands[0], DDmode)
341        || gpc_reg_operand (operands[1], DDmode))"
342   "@
343    ld%U1%X1 %0,%1
344    std%U0%X0 %1,%0
345    mr %0,%1
346    mt%0 %1
347    mf%1 %0
348    #
349    #
350    #
351    {cror 0,0,0|nop}"
352   [(set_attr "type" "load,store,*,mtjmpr,mfjmpr,*,*,*,*")
353    (set_attr "length" "4,4,4,4,4,8,12,16,4")])
355 (define_expand "negtd2"
356   [(set (match_operand:TD 0 "gpc_reg_operand" "")
357         (neg:TD (match_operand:TD 1 "gpc_reg_operand" "")))]
358   "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
359   "")
361 (define_insn "*negtd2_fpr"
362   [(set (match_operand:TD 0 "gpc_reg_operand" "=f")
363         (neg:TD (match_operand:TD 1 "gpc_reg_operand" "f")))]
364   "TARGET_HARD_FLOAT && TARGET_FPRS"
365   "fneg %0,%1"
366   [(set_attr "type" "fp")])
368 (define_expand "abstd2"
369   [(set (match_operand:TD 0 "gpc_reg_operand" "")
370         (abs:TD (match_operand:TD 1 "gpc_reg_operand" "")))]
371   "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
372   "")
374 (define_insn "*abstd2_fpr"
375   [(set (match_operand:TD 0 "gpc_reg_operand" "=f")
376         (abs:TD (match_operand:TD 1 "gpc_reg_operand" "f")))]
377   "TARGET_HARD_FLOAT && TARGET_FPRS"
378   "fabs %0,%1"
379   [(set_attr "type" "fp")])
381 (define_insn "*nabstd2_fpr"
382   [(set (match_operand:TD 0 "gpc_reg_operand" "=f")
383         (neg:TD (abs:TD (match_operand:DF 1 "gpc_reg_operand" "f"))))]
384   "TARGET_HARD_FLOAT && TARGET_FPRS"
385   "fnabs %0,%1"
386   [(set_attr "type" "fp")])
388 (define_expand "movtd"
389   [(set (match_operand:TD 0 "general_operand" "")
390         (match_operand:TD 1 "any_operand" ""))]
391   "TARGET_HARD_FLOAT && TARGET_FPRS"
392   "{ rs6000_emit_move (operands[0], operands[1], TDmode); DONE; }")
394 ; It's important to list the o->f and f->o moves before f->f because
395 ; otherwise reload, given m->f, will try to pick f->f and reload it,
396 ; which doesn't make progress.  Likewise r->Y must be before r->r.
397 (define_insn_and_split "*movtd_internal"
398   [(set (match_operand:TD 0 "nonimmediate_operand" "=o,f,f,r,Y,r")
399         (match_operand:TD 1 "input_operand"         "f,o,f,YGHF,r,r"))]
400   "TARGET_HARD_FLOAT && TARGET_FPRS
401    && (gpc_reg_operand (operands[0], TDmode)
402        || gpc_reg_operand (operands[1], TDmode))"
403   "#"
404   "&& reload_completed"
405   [(pc)]
406 { rs6000_split_multireg_move (operands[0], operands[1]); DONE; }
407   [(set_attr "length" "8,8,8,20,20,16")])