1 ;; Decimal Floating Point (DFP) patterns.
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)"
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"
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)"
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"
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"
55 [(set_attr "type" "fp")])
57 (define_expand "movdd"
58 [(set (match_operand:DD 0 "nonimmediate_operand" "")
59 (match_operand:DD 1 "any_operand" ""))]
61 "{ rs6000_emit_move (operands[0], operands[1], DDmode); DONE; }")
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))]
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;
83 operands[4] = GEN_INT (value >> 32);
84 operands[1] = GEN_INT (((value & 0xffffffff) ^ 0x80000000) - 0x80000000);
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))]
100 int endian = (WORDS_BIG_ENDIAN == 0);
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);
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))]
124 int endian = (WORDS_BIG_ENDIAN == 0);
127 #if HOST_BITS_PER_WIDE_INT >= 64
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);
142 operands[3] = immed_double_const (l[1 - endian], l[endian], DImode);
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))"
160 switch (which_alternative)
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\";
171 return \"mr %0,%1\;mr %L0,%L1\";
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)))
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
183 if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
185 return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\";
187 return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\";
193 addreg = find_addr_reg (XEXP (operands[1], 0));
194 if (refers_to_regno_p (REGNO (operands[0]),
195 REGNO (operands[0]) + 1,
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\";
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);
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\";
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);
231 return \"fmr %0,%1\";
233 return \"lfd%U1%X1 %0,%1\";
235 return \"stfd%U0%X0 %1,%0\";
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))"
253 switch (which_alternative)
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\";
264 return \"mr %0,%1\;mr %L0,%L1\";
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
270 if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
272 return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\";
274 return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\";
276 return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\";
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))"
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))"
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))"
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)"
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"
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)"
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"
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"
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))"
404 "&& reload_completed"
406 { rs6000_split_multireg_move (operands[0], operands[1]); DONE; }
407 [(set_attr "length" "8,8,8,20,20,16")])