Add power6 copysign/parity support
[official-gcc.git] / gcc / config / rs6000 / vsx.md
blobadd969c4c1c202e8b1d924ea8a0a776bd3a18222
1 ;; VSX patterns.
2 ;; Copyright (C) 2009
3 ;; Free Software Foundation, Inc.
4 ;; Contributed by Michael Meissner <meissner@linux.vnet.ibm.com>
6 ;; This file is part of GCC.
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.
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.
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/>.
22 ;; Iterator for both scalar and vector floating point types supported by VSX
23 (define_mode_iterator VSX_B [DF V4SF V2DF])
25 ;; Iterator for the 2 64-bit vector types
26 (define_mode_iterator VSX_D [V2DF V2DI])
28 ;; Iterator for the 2 32-bit vector types
29 (define_mode_iterator VSX_W [V4SF V4SI])
31 ;; Iterator for vector floating point types supported by VSX
32 (define_mode_iterator VSX_F [V4SF V2DF])
34 ;; Iterator for logical types supported by VSX
35 (define_mode_iterator VSX_L [V16QI V8HI V4SI V2DI V4SF V2DF TI])
37 ;; Iterator for memory move.  Handle TImode specially to allow
38 ;; it to use gprs as well as vsx registers.
39 (define_mode_iterator VSX_M [V16QI V8HI V4SI V2DI V4SF V2DF])
41 ;; Map into the appropriate load/store name based on the type
42 (define_mode_attr VSm  [(V16QI "vw4")
43                         (V8HI  "vw4")
44                         (V4SI  "vw4")
45                         (V4SF  "vw4")
46                         (V2DF  "vd2")
47                         (V2DI  "vd2")
48                         (DF    "d")
49                         (TI    "vw4")])
51 ;; Map into the appropriate suffix based on the type
52 (define_mode_attr VSs   [(V16QI "sp")
53                          (V8HI  "sp")
54                          (V4SI  "sp")
55                          (V4SF  "sp")
56                          (V2DF  "dp")
57                          (V2DI  "dp")
58                          (DF    "dp")
59                          (SF    "sp")
60                          (TI    "sp")])
62 ;; Map the register class used
63 (define_mode_attr VSr   [(V16QI "v")
64                          (V8HI  "v")
65                          (V4SI  "v")
66                          (V4SF  "wf")
67                          (V2DI  "wd")
68                          (V2DF  "wd")
69                          (DF    "ws")
70                          (SF    "d")
71                          (TI    "wd")])
73 ;; Map the register class used for float<->int conversions
74 (define_mode_attr VSr2  [(V2DF  "wd")
75                          (V4SF  "wf")
76                          (DF    "!f#r")])
78 (define_mode_attr VSr3  [(V2DF  "wa")
79                          (V4SF  "wa")
80                          (DF    "!f#r")])
82 ;; Map the register class for sp<->dp float conversions, destination
83 (define_mode_attr VSr4  [(SF    "ws")
84                          (DF    "f")
85                          (V2DF  "wd")
86                          (V4SF  "v")])
88 ;; Map the register class for sp<->dp float conversions, destination
89 (define_mode_attr VSr5  [(SF    "ws")
90                          (DF    "f")
91                          (V2DF  "v")
92                          (V4SF  "wd")])
94 ;; Same size integer type for floating point data
95 (define_mode_attr VSi [(V4SF  "v4si")
96                        (V2DF  "v2di")
97                        (DF    "di")])
99 (define_mode_attr VSI [(V4SF  "V4SI")
100                        (V2DF  "V2DI")
101                        (DF    "DI")])
103 ;; Word size for same size conversion
104 (define_mode_attr VSc [(V4SF "w")
105                        (V2DF "d")
106                        (DF   "d")])
108 ;; Map into either s or v, depending on whether this is a scalar or vector
109 ;; operation
110 (define_mode_attr VSv   [(V16QI "v")
111                          (V8HI  "v")
112                          (V4SI  "v")
113                          (V4SF  "v")
114                          (V2DI  "v")
115                          (V2DF  "v")
116                          (TI    "v")
117                          (DF    "s")])
119 ;; Appropriate type for add ops (and other simple FP ops)
120 (define_mode_attr VStype_simple [(V2DF "vecfloat")
121                                  (V4SF "vecfloat")
122                                  (DF   "fp")])
124 (define_mode_attr VSfptype_simple [(V2DF "fp_addsub_d")
125                                    (V4SF "fp_addsub_s")
126                                    (DF   "fp_addsub_d")])
128 ;; Appropriate type for multiply ops
129 (define_mode_attr VStype_mul    [(V2DF "vecfloat")
130                                  (V4SF "vecfloat")
131                                  (DF   "dmul")])
133 (define_mode_attr VSfptype_mul  [(V2DF "fp_mul_d")
134                                  (V4SF "fp_mul_s")
135                                  (DF   "fp_mul_d")])
137 ;; Appropriate type for divide ops.  For now, just lump the vector divide with
138 ;; the scalar divides
139 (define_mode_attr VStype_div    [(V2DF "ddiv")
140                                  (V4SF "sdiv")
141                                  (DF   "ddiv")])
143 (define_mode_attr VSfptype_div  [(V2DF "fp_div_d")
144                                  (V4SF "fp_div_s")
145                                  (DF   "fp_div_d")])
147 ;; Appropriate type for sqrt ops.  For now, just lump the vector sqrt with
148 ;; the scalar sqrt
149 (define_mode_attr VStype_sqrt   [(V2DF "dsqrt")
150                                  (V4SF "sdiv")
151                                  (DF   "ddiv")])
153 (define_mode_attr VSfptype_sqrt [(V2DF "fp_sqrt_d")
154                                  (V4SF "fp_sqrt_s")
155                                  (DF   "fp_sqrt_d")])
157 ;; Iterator and modes for sp<->dp conversions
158 ;; Because scalar SF values are represented internally as double, use the
159 ;; V4SF type to represent this than SF.
160 (define_mode_iterator VSX_SPDP [DF V4SF V2DF])
162 (define_mode_attr VS_spdp_res [(DF      "V4SF")
163                                (V4SF    "V2DF")
164                                (V2DF    "V4SF")])
166 (define_mode_attr VS_spdp_insn [(DF     "xscvdpsp")
167                                 (V4SF   "xvcvspdp")
168                                 (V2DF   "xvcvdpsp")])
170 (define_mode_attr VS_spdp_type [(DF     "fp")
171                                 (V4SF   "vecfloat")
172                                 (V2DF   "vecfloat")])
174 ;; Map the scalar mode for a vector type
175 (define_mode_attr VS_scalar [(V2DF      "DF")
176                              (V2DI      "DI")
177                              (V4SF      "SF")
178                              (V4SI      "SI")
179                              (V8HI      "HI")
180                              (V16QI     "QI")])
181                              
182 ;; Constants for creating unspecs
183 (define_constants
184   [(UNSPEC_VSX_CONCAT           500)
185    (UNSPEC_VSX_CVDPSXWS         501)
186    (UNSPEC_VSX_CVDPUXWS         502)
187    (UNSPEC_VSX_CVSPDP           503)
188    (UNSPEC_VSX_CVSXWDP          504)
189    (UNSPEC_VSX_CVUXWDP          505)
190    (UNSPEC_VSX_CVSXDSP          506)
191    (UNSPEC_VSX_CVUXDSP          507)
192    (UNSPEC_VSX_CVSPSXDS         508)
193    (UNSPEC_VSX_CVSPUXDS         509)
194    (UNSPEC_VSX_MADD             510)
195    (UNSPEC_VSX_MSUB             511)
196    (UNSPEC_VSX_NMADD            512)
197    (UNSPEC_VSX_NMSUB            513)
198    ;; 514 deleted
199    (UNSPEC_VSX_TDIV             515)
200    (UNSPEC_VSX_TSQRT            516)
201    (UNSPEC_VSX_XXPERMDI         517)
202    (UNSPEC_VSX_SET              518)
203    (UNSPEC_VSX_ROUND_I          519)
204    (UNSPEC_VSX_ROUND_IC         520)
205    (UNSPEC_VSX_SLDWI            521)])
207 ;; VSX moves
208 (define_insn "*vsx_mov<mode>"
209   [(set (match_operand:VSX_M 0 "nonimmediate_operand" "=Z,<VSr>,<VSr>,?Z,?wa,?wa,*o,*r,*r,<VSr>,?wa,v,wZ,v")
210         (match_operand:VSX_M 1 "input_operand" "<VSr>,Z,<VSr>,wa,Z,wa,r,o,r,j,j,W,v,wZ"))]
211   "VECTOR_MEM_VSX_P (<MODE>mode)
212    && (register_operand (operands[0], <MODE>mode) 
213        || register_operand (operands[1], <MODE>mode))"
215   switch (which_alternative)
216     {
217     case 0:
218     case 3:
219       gcc_assert (MEM_P (operands[0])
220                   && GET_CODE (XEXP (operands[0], 0)) != PRE_INC
221                   && GET_CODE (XEXP (operands[0], 0)) != PRE_DEC
222                   && GET_CODE (XEXP (operands[0], 0)) != PRE_MODIFY);
223       return "stx<VSm>x %x1,%y0";
225     case 1:
226     case 4:
227       gcc_assert (MEM_P (operands[1])
228                   && GET_CODE (XEXP (operands[1], 0)) != PRE_INC
229                   && GET_CODE (XEXP (operands[1], 0)) != PRE_DEC
230                   && GET_CODE (XEXP (operands[1], 0)) != PRE_MODIFY);
231       return "lx<VSm>x %x0,%y1";
233     case 2:
234     case 5:
235       return "xxlor %x0,%x1,%x1";
237     case 6:
238     case 7:
239     case 8:
240       return "#";
242     case 9:
243     case 10:
244       return "xxlxor %x0,%x0,%x0";
246     case 11:
247       return output_vec_const_move (operands);
249     case 12:
250       gcc_assert (MEM_P (operands[0])
251                   && GET_CODE (XEXP (operands[0], 0)) != PRE_INC
252                   && GET_CODE (XEXP (operands[0], 0)) != PRE_DEC
253                   && GET_CODE (XEXP (operands[0], 0)) != PRE_MODIFY);
254       return "stvx %1,%y0";
256     case 13:
257       gcc_assert (MEM_P (operands[0])
258                   && GET_CODE (XEXP (operands[0], 0)) != PRE_INC
259                   && GET_CODE (XEXP (operands[0], 0)) != PRE_DEC
260                   && GET_CODE (XEXP (operands[0], 0)) != PRE_MODIFY);
261       return "lvx %0,%y1";
263     default:
264       gcc_unreachable ();
265     }
267   [(set_attr "type" "vecstore,vecload,vecsimple,vecstore,vecload,vecsimple,*,*,*,vecsimple,vecsimple,*,vecstore,vecload")])
269 ;; Unlike other VSX moves, allow the GPRs, since a normal use of TImode is for
270 ;; unions.  However for plain data movement, slightly favor the vector loads
271 (define_insn "*vsx_movti"
272   [(set (match_operand:TI 0 "nonimmediate_operand" "=Z,wa,wa,?o,?r,?r,wa,v,v,wZ")
273         (match_operand:TI 1 "input_operand" "wa,Z,wa,r,o,r,j,W,wZ,v"))]
274   "VECTOR_MEM_VSX_P (TImode)
275    && (register_operand (operands[0], TImode) 
276        || register_operand (operands[1], TImode))"
278   switch (which_alternative)
279     {
280     case 0:
281       return "stxvd2x %x1,%y0";
283     case 1:
284       return "lxvd2x %x0,%y1";
286     case 2:
287       return "xxlor %x0,%x1,%x1";
289     case 3:
290     case 4:
291     case 5:
292       return "#";
294     case 6:
295       return "xxlxor %x0,%x0,%x0";
297     case 7:
298       return output_vec_const_move (operands);
300     case 8:
301       return "stvx %1,%y0";
303     case 9:
304       return "lvx %0,%y1";
306     default:
307       gcc_unreachable ();
308     }
310   [(set_attr "type" "vecstore,vecload,vecsimple,*,*,*,vecsimple,*,vecstore,vecload")])
313 ;; VSX scalar and vector floating point arithmetic instructions
314 (define_insn "*vsx_add<mode>3"
315   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
316         (plus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
317                     (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
318   "VECTOR_UNIT_VSX_P (<MODE>mode)"
319   "x<VSv>add<VSs> %x0,%x1,%x2"
320   [(set_attr "type" "<VStype_simple>")
321    (set_attr "fp_type" "<VSfptype_simple>")])
323 (define_insn "*vsx_sub<mode>3"
324   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
325         (minus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
326                      (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
327   "VECTOR_UNIT_VSX_P (<MODE>mode)"
328   "x<VSv>sub<VSs> %x0,%x1,%x2"
329   [(set_attr "type" "<VStype_simple>")
330    (set_attr "fp_type" "<VSfptype_simple>")])
332 (define_insn "*vsx_mul<mode>3"
333   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
334         (mult:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
335                     (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
336   "VECTOR_UNIT_VSX_P (<MODE>mode)"
337   "x<VSv>mul<VSs> %x0,%x1,%x2"
338   [(set_attr "type" "<VStype_mul>")
339    (set_attr "fp_type" "<VSfptype_mul>")])
341 (define_insn "*vsx_div<mode>3"
342   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
343         (div:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
344                    (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
345   "VECTOR_UNIT_VSX_P (<MODE>mode)"
346   "x<VSv>div<VSs> %x0,%x1,%x2"
347   [(set_attr "type" "<VStype_div>")
348    (set_attr "fp_type" "<VSfptype_div>")])
350 ;; *tdiv* instruction returning the FG flag
351 (define_expand "vsx_tdiv<mode>3_fg"
352   [(set (match_dup 3)
353         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
354                       (match_operand:VSX_B 2 "vsx_register_operand" "")]
355                      UNSPEC_VSX_TDIV))
356    (set (match_operand:SI 0 "gpc_reg_operand" "")
357         (gt:SI (match_dup 3)
358                (const_int 0)))]
359   "VECTOR_UNIT_VSX_P (<MODE>mode)"
361   operands[3] = gen_reg_rtx (CCFPmode);
364 ;; *tdiv* instruction returning the FE flag
365 (define_expand "vsx_tdiv<mode>3_fe"
366   [(set (match_dup 3)
367         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
368                       (match_operand:VSX_B 2 "vsx_register_operand" "")]
369                      UNSPEC_VSX_TDIV))
370    (set (match_operand:SI 0 "gpc_reg_operand" "")
371         (eq:SI (match_dup 3)
372                (const_int 0)))]
373   "VECTOR_UNIT_VSX_P (<MODE>mode)"
375   operands[3] = gen_reg_rtx (CCFPmode);
378 (define_insn "*vsx_tdiv<mode>3_internal"
379   [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
380         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
381                       (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")]
382                    UNSPEC_VSX_TDIV))]
383   "VECTOR_UNIT_VSX_P (<MODE>mode)"
384   "x<VSv>tdiv<VSs> %0,%x1,%x2"
385   [(set_attr "type" "<VStype_simple>")
386    (set_attr "fp_type" "<VSfptype_simple>")])
388 (define_insn "vsx_fre<mode>2"
389   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
390         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
391                       UNSPEC_FRES))]
392   "VECTOR_UNIT_VSX_P (<MODE>mode)"
393   "x<VSv>re<VSs> %x0,%x1"
394   [(set_attr "type" "<VStype_simple>")
395    (set_attr "fp_type" "<VSfptype_simple>")])
397 (define_insn "*vsx_neg<mode>2"
398   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
399         (neg:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
400   "VECTOR_UNIT_VSX_P (<MODE>mode)"
401   "x<VSv>neg<VSs> %x0,%x1"
402   [(set_attr "type" "<VStype_simple>")
403    (set_attr "fp_type" "<VSfptype_simple>")])
405 (define_insn "*vsx_abs<mode>2"
406   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
407         (abs:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
408   "VECTOR_UNIT_VSX_P (<MODE>mode)"
409   "x<VSv>abs<VSs> %x0,%x1"
410   [(set_attr "type" "<VStype_simple>")
411    (set_attr "fp_type" "<VSfptype_simple>")])
413 (define_insn "vsx_nabs<mode>2"
414   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
415         (neg:VSX_B
416          (abs:VSX_B
417           (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa"))))]
418   "VECTOR_UNIT_VSX_P (<MODE>mode)"
419   "x<VSv>nabs<VSs> %x0,%x1"
420   [(set_attr "type" "<VStype_simple>")
421    (set_attr "fp_type" "<VSfptype_simple>")])
423 (define_insn "vsx_smax<mode>3"
424   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
425         (smax:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
426                     (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
427   "VECTOR_UNIT_VSX_P (<MODE>mode)"
428   "x<VSv>max<VSs> %x0,%x1,%x2"
429   [(set_attr "type" "<VStype_simple>")
430    (set_attr "fp_type" "<VSfptype_simple>")])
432 (define_insn "*vsx_smin<mode>3"
433   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
434         (smin:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
435                     (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
436   "VECTOR_UNIT_VSX_P (<MODE>mode)"
437   "x<VSv>min<VSs> %x0,%x1,%x2"
438   [(set_attr "type" "<VStype_simple>")
439    (set_attr "fp_type" "<VSfptype_simple>")])
441 (define_insn "*vsx_sqrt<mode>2"
442   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
443         (sqrt:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
444   "VECTOR_UNIT_VSX_P (<MODE>mode)"
445   "x<VSv>sqrt<VSs> %x0,%x1"
446   [(set_attr "type" "<VStype_sqrt>")
447    (set_attr "fp_type" "<VSfptype_sqrt>")])
449 (define_insn "*vsx_rsqrte<mode>2"
450   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
451         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
452                       UNSPEC_RSQRT))]
453   "VECTOR_UNIT_VSX_P (<MODE>mode)"
454   "x<VSv>rsqrte<VSs> %x0,%x1"
455   [(set_attr "type" "<VStype_simple>")
456    (set_attr "fp_type" "<VSfptype_simple>")])
458 ;; *tsqrt* returning the fg flag
459 (define_expand "vsx_tsqrt<mode>2_fg"
460   [(set (match_dup 3)
461         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
462                      UNSPEC_VSX_TSQRT))
463    (set (match_operand:SI 0 "gpc_reg_operand" "")
464         (gt:SI (match_dup 3)
465                (const_int 0)))]
466   "VECTOR_UNIT_VSX_P (<MODE>mode)"
468   operands[3] = gen_reg_rtx (CCFPmode);
471 ;; *tsqrt* returning the fe flag
472 (define_expand "vsx_tsqrt<mode>2_fe"
473   [(set (match_dup 3)
474         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
475                      UNSPEC_VSX_TSQRT))
476    (set (match_operand:SI 0 "gpc_reg_operand" "")
477         (eq:SI (match_dup 3)
478                (const_int 0)))]
479   "VECTOR_UNIT_VSX_P (<MODE>mode)"
481   operands[3] = gen_reg_rtx (CCFPmode);
484 (define_insn "*vsx_tsqrt<mode>2_internal"
485   [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
486         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
487                      UNSPEC_VSX_TSQRT))]
488   "VECTOR_UNIT_VSX_P (<MODE>mode)"
489   "x<VSv>tsqrt<VSs> %0,%x1"
490   [(set_attr "type" "<VStype_simple>")
491    (set_attr "fp_type" "<VSfptype_simple>")])
493 ;; Fused vector multiply/add instructions
495 ;; Note we have a pattern for the multiply/add operations that uses unspec and
496 ;; does not check -mfused-madd to allow users to use these ops when they know
497 ;; they want the fused multiply/add.
499 (define_expand "vsx_fmadd<mode>4"
500   [(set (match_operand:VSX_B 0 "vsx_register_operand" "")
501         (plus:VSX_B
502          (mult:VSX_B
503           (match_operand:VSX_B 1 "vsx_register_operand" "")
504           (match_operand:VSX_B 2 "vsx_register_operand" ""))
505          (match_operand:VSX_B 3 "vsx_register_operand" "")))]
506   "VECTOR_UNIT_VSX_P (<MODE>mode)"
508   if (!TARGET_FUSED_MADD)
509     {
510       emit_insn (gen_vsx_fmadd<mode>4_2 (operands[0], operands[1], operands[2],
511                                          operands[3]));
512       DONE;
513     }
516 (define_insn "*vsx_fmadd<mode>4_1"
517   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
518         (plus:VSX_B
519          (mult:VSX_B
520           (match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
521           (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0"))
522          (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")))]
523   "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD"
524   "@
525    x<VSv>madda<VSs> %x0,%x1,%x2
526    x<VSv>maddm<VSs> %x0,%x1,%x3
527    x<VSv>madda<VSs> %x0,%x1,%x2
528    x<VSv>maddm<VSs> %x0,%x1,%x3"
529   [(set_attr "type" "<VStype_mul>")
530    (set_attr "fp_type" "<VSfptype_mul>")])
532 (define_insn "vsx_fmadd<mode>4_2"
533   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
534         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
535                        (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
536                        (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")]
537                       UNSPEC_VSX_MADD))]
538   "VECTOR_UNIT_VSX_P (<MODE>mode)"
539   "@
540    x<VSv>madda<VSs> %x0,%x1,%x2
541    x<VSv>maddm<VSs> %x0,%x1,%x3
542    x<VSv>madda<VSs> %x0,%x1,%x2
543    x<VSv>maddm<VSs> %x0,%x1,%x3"
544   [(set_attr "type" "<VStype_mul>")
545    (set_attr "fp_type" "<VSfptype_mul>")])
547 (define_expand "vsx_fmsub<mode>4"
548   [(set (match_operand:VSX_B 0 "vsx_register_operand" "")
549         (minus:VSX_B
550          (mult:VSX_B
551           (match_operand:VSX_B 1 "vsx_register_operand" "")
552           (match_operand:VSX_B 2 "vsx_register_operand" ""))
553          (match_operand:VSX_B 3 "vsx_register_operand" "")))]
554   "VECTOR_UNIT_VSX_P (<MODE>mode)"
556   if (!TARGET_FUSED_MADD)
557     {
558       emit_insn (gen_vsx_fmsub<mode>4_2 (operands[0], operands[1], operands[2],
559                                          operands[3]));
560       DONE;
561     }
564 (define_insn "*vsx_fmsub<mode>4_1"
565   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
566         (minus:VSX_B
567          (mult:VSX_B
568           (match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
569           (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0"))
570          (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")))]
571   "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD"
572   "@
573    x<VSv>msuba<VSs> %x0,%x1,%x2
574    x<VSv>msubm<VSs> %x0,%x1,%x3
575    x<VSv>msuba<VSs> %x0,%x1,%x2
576    x<VSv>msubm<VSs> %x0,%x1,%x3"
577   [(set_attr "type" "<VStype_mul>")
578    (set_attr "fp_type" "<VSfptype_mul>")])
580 (define_insn "vsx_fmsub<mode>4_2"
581   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
582         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
583                        (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
584                        (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")]
585                       UNSPEC_VSX_MSUB))]
586   "VECTOR_UNIT_VSX_P (<MODE>mode)"
587   "@
588    x<VSv>msuba<VSs> %x0,%x1,%x2
589    x<VSv>msubm<VSs> %x0,%x1,%x3
590    x<VSv>msuba<VSs> %x0,%x1,%x2
591    x<VSv>msubm<VSs> %x0,%x1,%x3"
592   [(set_attr "type" "<VStype_mul>")
593    (set_attr "fp_type" "<VSfptype_mul>")])
595 (define_expand "vsx_fnmadd<mode>4"
596   [(match_operand:VSX_B 0 "vsx_register_operand" "")
597    (match_operand:VSX_B 1 "vsx_register_operand" "")
598    (match_operand:VSX_B 2 "vsx_register_operand" "")
599    (match_operand:VSX_B 3 "vsx_register_operand" "")]
600   "VECTOR_UNIT_VSX_P (<MODE>mode)"
602   if (TARGET_FUSED_MADD && HONOR_SIGNED_ZEROS (DFmode))
603     {
604        emit_insn (gen_vsx_fnmadd<mode>4_1 (operands[0], operands[1],
605                                            operands[2], operands[3]));
606        DONE;
607     }
608   else if (TARGET_FUSED_MADD && !HONOR_SIGNED_ZEROS (DFmode))
609     {
610        emit_insn (gen_vsx_fnmadd<mode>4_2 (operands[0], operands[1],
611                                            operands[2], operands[3]));
612        DONE;
613     }
614   else
615     {
616        emit_insn (gen_vsx_fnmadd<mode>4_3 (operands[0], operands[1],
617                                            operands[2], operands[3]));
618        DONE;
619     }
622 (define_insn "vsx_fnmadd<mode>4_1"
623   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
624         (neg:VSX_B
625          (plus:VSX_B
626           (mult:VSX_B
627            (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSr>,wa,wa")
628            (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0"))
629           (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
630   "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD
631    && HONOR_SIGNED_ZEROS (DFmode)"
632   "@
633    x<VSv>nmadda<VSs> %x0,%x1,%x2
634    x<VSv>nmaddm<VSs> %x0,%x1,%x3
635    x<VSv>nmadda<VSs> %x0,%x1,%x2
636    x<VSv>nmaddm<VSs> %x0,%x1,%x3"
637   [(set_attr "type" "<VStype_mul>")
638    (set_attr "fp_type" "<VSfptype_mul>")])
640 (define_insn "vsx_fnmadd<mode>4_2"
641   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
642         (minus:VSX_B
643          (mult:VSX_B
644           (neg:VSX_B
645            (match_operand:VSX_B 1 "gpc_reg_operand" "<VSr>,<VSr>,wa,wa"))
646           (match_operand:VSX_B 2 "gpc_reg_operand" "<VSr>,0,wa,0"))
647          (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")))]
648   "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD
649    && !HONOR_SIGNED_ZEROS (DFmode)"
650   "@
651    x<VSv>nmadda<VSs> %x0,%x1,%x2
652    x<VSv>nmaddm<VSs> %x0,%x1,%x3
653    x<VSv>nmadda<VSs> %x0,%x1,%x2
654    x<VSv>nmaddm<VSs> %x0,%x1,%x3"
655   [(set_attr "type" "<VStype_mul>")
656    (set_attr "fp_type" "<VSfptype_mul>")])
658 (define_insn "vsx_fnmadd<mode>4_3"
659   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
660         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSr>,wa,wa")
661                        (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
662                        (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")]
663                       UNSPEC_VSX_NMADD))]
664   "VECTOR_UNIT_VSX_P (<MODE>mode)"
665   "@
666    x<VSv>nmadda<VSs> %x0,%x1,%x2
667    x<VSv>nmaddm<VSs> %x0,%x1,%x3
668    x<VSv>nmadda<VSs> %x0,%x1,%x2
669    x<VSv>nmaddm<VSs> %x0,%x1,%x3"
670   [(set_attr "type" "<VStype_mul>")
671    (set_attr "fp_type" "<VSfptype_mul>")])
673 (define_expand "vsx_fnmsub<mode>4"
674   [(match_operand:VSX_B 0 "vsx_register_operand" "")
675    (match_operand:VSX_B 1 "vsx_register_operand" "")
676    (match_operand:VSX_B 2 "vsx_register_operand" "")
677    (match_operand:VSX_B 3 "vsx_register_operand" "")]
678   "VECTOR_UNIT_VSX_P (<MODE>mode)"
680   if (TARGET_FUSED_MADD && HONOR_SIGNED_ZEROS (DFmode))
681     {
682        emit_insn (gen_vsx_fnmsub<mode>4_1 (operands[0], operands[1],
683                                            operands[2], operands[3]));
684        DONE;
685     }
686   else if (TARGET_FUSED_MADD && !HONOR_SIGNED_ZEROS (DFmode))
687     {
688        emit_insn (gen_vsx_fnmsub<mode>4_2 (operands[0], operands[1],
689                                            operands[2], operands[3]));
690        DONE;
691     }
692   else
693     {
694        emit_insn (gen_vsx_fnmsub<mode>4_3 (operands[0], operands[1],
695                                            operands[2], operands[3]));
696        DONE;
697     }
700 (define_insn "vsx_fnmsub<mode>4_1"
701   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
702         (neg:VSX_B
703          (minus:VSX_B
704           (mult:VSX_B
705            (match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
706            (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0"))
707           (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
708   "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD
709    && HONOR_SIGNED_ZEROS (DFmode)"
710   "@
711    x<VSv>nmsuba<VSs> %x0,%x1,%x2
712    x<VSv>nmsubm<VSs> %x0,%x1,%x3
713    x<VSv>nmsuba<VSs> %x0,%x1,%x2
714    x<VSv>nmsubm<VSs> %x0,%x1,%x3"
715   [(set_attr "type" "<VStype_mul>")
716    (set_attr "fp_type" "<VSfptype_mul>")])
718 (define_insn "vsx_fnmsub<mode>4_2"
719   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
720         (minus:VSX_B
721          (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")
722          (mult:VSX_B
723           (match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
724           (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0"))))]
725   "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD
726    && !HONOR_SIGNED_ZEROS (DFmode)"
727   "@
728    x<VSv>nmsuba<VSs> %x0,%x1,%x2
729    x<VSv>nmsubm<VSs> %x0,%x1,%x3
730    x<VSv>nmsuba<VSs> %x0,%x1,%x2
731    x<VSv>nmsubm<VSs> %x0,%x1,%x3"
732   [(set_attr "type" "<VStype_mul>")
733    (set_attr "fp_type" "<VSfptype_mul>")])
735 (define_insn "vsx_fnmsub<mode>4_3"
736   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
737         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
738                        (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
739                        (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")]
740                       UNSPEC_VSX_NMSUB))]
741   "VECTOR_UNIT_VSX_P (<MODE>mode)"
742   "@
743    x<VSv>nmsuba<VSs> %x0,%x1,%x2
744    x<VSv>nmsubm<VSs> %x0,%x1,%x3
745    x<VSv>nmsuba<VSs> %x0,%x1,%x2
746    x<VSv>nmsubm<VSs> %x0,%x1,%x3"
747   [(set_attr "type" "<VStype_mul>")
748    (set_attr "fp_type" "<VSfptype_mul>")])
750 ;; Vector conditional expressions (no scalar version for these instructions)
751 (define_insn "vsx_eq<mode>"
752   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
753         (eq:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
754                   (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
755   "VECTOR_UNIT_VSX_P (<MODE>mode)"
756   "xvcmpeq<VSs> %x0,%x1,%x2"
757   [(set_attr "type" "<VStype_simple>")
758    (set_attr "fp_type" "<VSfptype_simple>")])
760 (define_insn "vsx_gt<mode>"
761   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
762         (gt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
763                   (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
764   "VECTOR_UNIT_VSX_P (<MODE>mode)"
765   "xvcmpgt<VSs> %x0,%x1,%x2"
766   [(set_attr "type" "<VStype_simple>")
767    (set_attr "fp_type" "<VSfptype_simple>")])
769 (define_insn "*vsx_ge<mode>"
770   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
771         (ge:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
772                   (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
773   "VECTOR_UNIT_VSX_P (<MODE>mode)"
774   "xvcmpge<VSs> %x0,%x1,%x2"
775   [(set_attr "type" "<VStype_simple>")
776    (set_attr "fp_type" "<VSfptype_simple>")])
778 ;; Floating point scalar compare
779 (define_insn "*vsx_cmpdf_internal1"
780   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y,?y")
781         (compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "ws,wa")
782                       (match_operand:DF 2 "gpc_reg_operand" "ws,wa")))]
783   "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
784    && VECTOR_UNIT_VSX_P (DFmode)"
785   "xscmpudp %0,%x1,%x2"
786   [(set_attr "type" "fpcompare")])
788 ;; Compare vectors producing a vector result and a predicate, setting CR6 to
789 ;; indicate a combined status
790 (define_insn "*vsx_eq_<mode>_p"
791   [(set (reg:CC 74)
792         (unspec:CC
793          [(eq:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
794                  (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
795          UNSPEC_PREDICATE))
796    (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
797         (eq:VSX_F (match_dup 1)
798                   (match_dup 2)))]
799   "VECTOR_UNIT_VSX_P (<MODE>mode)"
800   "xvcmpeq<VSs>. %x0,%x1,%x2"
801   [(set_attr "type" "veccmp")])
803 (define_insn "*vsx_gt_<mode>_p"
804   [(set (reg:CC 74)
805         (unspec:CC
806          [(gt:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
807                  (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
808          UNSPEC_PREDICATE))
809    (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
810         (gt:VSX_F (match_dup 1)
811                   (match_dup 2)))]
812   "VECTOR_UNIT_VSX_P (<MODE>mode)"
813   "xvcmpgt<VSs>. %x0,%x1,%x2"
814   [(set_attr "type" "veccmp")])
816 (define_insn "*vsx_ge_<mode>_p"
817   [(set (reg:CC 74)
818         (unspec:CC
819          [(ge:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
820                  (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
821          UNSPEC_PREDICATE))
822    (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
823         (ge:VSX_F (match_dup 1)
824                   (match_dup 2)))]
825   "VECTOR_UNIT_VSX_P (<MODE>mode)"
826   "xvcmpge<VSs>. %x0,%x1,%x2"
827   [(set_attr "type" "veccmp")])
829 ;; Vector select
830 (define_insn "*vsx_xxsel<mode>"
831   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
832         (if_then_else:VSX_L
833          (ne:CC (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
834                 (const_int 0))
835          (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
836          (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
837   "VECTOR_MEM_VSX_P (<MODE>mode)"
838   "xxsel %x0,%x3,%x2,%x1"
839   [(set_attr "type" "vecperm")])
841 (define_insn "*vsx_xxsel<mode>_uns"
842   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
843         (if_then_else:VSX_L
844          (ne:CCUNS (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
845                    (const_int 0))
846          (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
847          (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
848   "VECTOR_MEM_VSX_P (<MODE>mode)"
849   "xxsel %x0,%x3,%x2,%x1"
850   [(set_attr "type" "vecperm")])
852 ;; Copy sign
853 (define_insn "vsx_copysign<mode>3"
854   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
855         (unspec:VSX_B
856          [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
857           (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")]
858          UNSPEC_COPYSIGN))]
859   "VECTOR_UNIT_VSX_P (<MODE>mode)"
860   "x<VSv>cpsgn<VSs> %x0,%x2,%x1"
861   [(set_attr "type" "<VStype_simple>")
862    (set_attr "fp_type" "<VSfptype_simple>")])
864 ;; For the conversions, limit the register class for the integer value to be
865 ;; the fprs because we don't want to add the altivec registers to movdi/movsi.
866 ;; For the unsigned tests, there isn't a generic double -> unsigned conversion
867 ;; in rs6000.md so don't test VECTOR_UNIT_VSX_P, just test against VSX.
868 (define_insn "vsx_float<VSi><mode>2"
869   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
870         (float:VSX_B (match_operand:<VSI> 1 "vsx_register_operand" "<VSr2>,<VSr3>")))]
871   "VECTOR_UNIT_VSX_P (<MODE>mode)"
872   "x<VSv>cvsx<VSc><VSs> %x0,%x1"
873   [(set_attr "type" "<VStype_simple>")
874    (set_attr "fp_type" "<VSfptype_simple>")])
876 (define_insn "vsx_floatuns<VSi><mode>2"
877   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
878         (unsigned_float:VSX_B (match_operand:<VSI> 1 "vsx_register_operand" "<VSr2>,<VSr3>")))]
879   "VECTOR_UNIT_VSX_P (<MODE>mode)"
880   "x<VSv>cvux<VSc><VSs> %x0,%x1"
881   [(set_attr "type" "<VStype_simple>")
882    (set_attr "fp_type" "<VSfptype_simple>")])
884 (define_insn "vsx_fix_trunc<mode><VSi>2"
885   [(set (match_operand:<VSI> 0 "vsx_register_operand" "=<VSr2>,?<VSr3>")
886         (fix:<VSI> (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
887   "VECTOR_UNIT_VSX_P (<MODE>mode)"
888   "x<VSv>cv<VSs>sx<VSc>s %x0,%x1"
889   [(set_attr "type" "<VStype_simple>")
890    (set_attr "fp_type" "<VSfptype_simple>")])
892 (define_insn "vsx_fixuns_trunc<mode><VSi>2"
893   [(set (match_operand:<VSI> 0 "vsx_register_operand" "=<VSr2>,?<VSr3>")
894         (unsigned_fix:<VSI> (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
895   "VECTOR_UNIT_VSX_P (<MODE>mode)"
896   "x<VSv>cv<VSs>ux<VSc>s %x0,%x1"
897   [(set_attr "type" "<VStype_simple>")
898    (set_attr "fp_type" "<VSfptype_simple>")])
900 ;; Math rounding functions
901 (define_insn "vsx_x<VSv>r<VSs>i"
902   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
903         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
904                       UNSPEC_VSX_ROUND_I))]
905   "VECTOR_UNIT_VSX_P (<MODE>mode)"
906   "x<VSv>r<VSs>i %x0,%x1"
907   [(set_attr "type" "<VStype_simple>")
908    (set_attr "fp_type" "<VSfptype_simple>")])
910 (define_insn "vsx_x<VSv>r<VSs>ic"
911   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
912         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
913                       UNSPEC_VSX_ROUND_IC))]
914   "VECTOR_UNIT_VSX_P (<MODE>mode)"
915   "x<VSv>r<VSs>ic %x0,%x1"
916   [(set_attr "type" "<VStype_simple>")
917    (set_attr "fp_type" "<VSfptype_simple>")])
919 (define_insn "vsx_btrunc<mode>2"
920   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
921         (fix:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
922   "VECTOR_UNIT_VSX_P (<MODE>mode)"
923   "x<VSv>r<VSs>iz %x0,%x1"
924   [(set_attr "type" "<VStype_simple>")
925    (set_attr "fp_type" "<VSfptype_simple>")])
927 (define_insn "*vsx_b2trunc<mode>2"
928   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
929         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
930                       UNSPEC_FRIZ))]
931   "VECTOR_UNIT_VSX_P (<MODE>mode)"
932   "x<VSv>r<VSs>iz %x0,%x1"
933   [(set_attr "type" "<VStype_simple>")
934    (set_attr "fp_type" "<VSfptype_simple>")])
936 (define_insn "vsx_floor<mode>2"
937   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
938         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
939                       UNSPEC_FRIM))]
940   "VECTOR_UNIT_VSX_P (<MODE>mode)"
941   "x<VSv>r<VSs>im %x0,%x1"
942   [(set_attr "type" "<VStype_simple>")
943    (set_attr "fp_type" "<VSfptype_simple>")])
945 (define_insn "vsx_ceil<mode>2"
946   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
947         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
948                       UNSPEC_FRIP))]
949   "VECTOR_UNIT_VSX_P (<MODE>mode)"
950   "x<VSv>r<VSs>ip %x0,%x1"
951   [(set_attr "type" "<VStype_simple>")
952    (set_attr "fp_type" "<VSfptype_simple>")])
955 ;; VSX convert to/from double vector
957 ;; Convert between single and double precision
958 ;; Don't use xscvspdp and xscvdpsp for scalar conversions, since the normal
959 ;; scalar single precision instructions internally use the double format.
960 ;; Prefer the altivec registers, since we likely will need to do a vperm
961 (define_insn "vsx_<VS_spdp_insn>"
962   [(set (match_operand:<VS_spdp_res> 0 "vsx_register_operand" "=<VSr4>,?wa")
963         (unspec:<VS_spdp_res> [(match_operand:VSX_SPDP 1 "vsx_register_operand" "<VSr5>,wa")]
964                               UNSPEC_VSX_CVSPDP))]
965   "VECTOR_UNIT_VSX_P (<MODE>mode)"
966   "<VS_spdp_insn> %x0,%x1"
967   [(set_attr "type" "<VS_spdp_type>")])
969 ;; xscvspdp, represent the scalar SF type as V4SF
970 (define_insn "vsx_xscvspdp"
971   [(set (match_operand:DF 0 "vsx_register_operand" "=ws,?wa")
972         (unspec:DF [(match_operand:V4SF 1 "vsx_register_operand" "wa,wa")]
973                    UNSPEC_VSX_CVSPDP))]
974   "VECTOR_UNIT_VSX_P (DFmode)"
975   "xscvspdp %x0,%x1"
976   [(set_attr "type" "fp")])
978 ;; xscvdpsp used for splat'ing a scalar to V4SF, knowing that the internal SF
979 ;; format of scalars is actually DF.
980 (define_insn "vsx_xscvdpsp_scalar"
981   [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
982         (unspec:V4SF [(match_operand:SF 1 "vsx_register_operand" "f")]
983                      UNSPEC_VSX_CVSPDP))]
984   "VECTOR_UNIT_VSX_P (DFmode)"
985   "xscvdpsp %x0,%x1"
986   [(set_attr "type" "fp")])
988 ;; Convert from 64-bit to 32-bit types
989 ;; Note, favor the Altivec registers since the usual use of these instructions
990 ;; is in vector converts and we need to use the Altivec vperm instruction.
992 (define_insn "vsx_xvcvdpsxws"
993   [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
994         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
995                      UNSPEC_VSX_CVDPSXWS))]
996   "VECTOR_UNIT_VSX_P (V2DFmode)"
997   "xvcvdpsxws %x0,%x1"
998   [(set_attr "type" "vecfloat")])
1000 (define_insn "vsx_xvcvdpuxws"
1001   [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
1002         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
1003                      UNSPEC_VSX_CVDPUXWS))]
1004   "VECTOR_UNIT_VSX_P (V2DFmode)"
1005   "xvcvdpuxws %x0,%x1"
1006   [(set_attr "type" "vecfloat")])
1008 (define_insn "vsx_xvcvsxdsp"
1009   [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
1010         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
1011                      UNSPEC_VSX_CVSXDSP))]
1012   "VECTOR_UNIT_VSX_P (V2DFmode)"
1013   "xvcvsxdsp %x0,%x1"
1014   [(set_attr "type" "vecfloat")])
1016 (define_insn "vsx_xvcvuxdsp"
1017   [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
1018         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
1019                      UNSPEC_VSX_CVUXDSP))]
1020   "VECTOR_UNIT_VSX_P (V2DFmode)"
1021   "xvcvuxwdp %x0,%x1"
1022   [(set_attr "type" "vecfloat")])
1024 ;; Convert from 32-bit to 64-bit types
1025 (define_insn "vsx_xvcvsxwdp"
1026   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1027         (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
1028                      UNSPEC_VSX_CVSXWDP))]
1029   "VECTOR_UNIT_VSX_P (V2DFmode)"
1030   "xvcvsxwdp %x0,%x1"
1031   [(set_attr "type" "vecfloat")])
1033 (define_insn "vsx_xvcvuxwdp"
1034   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1035         (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
1036                      UNSPEC_VSX_CVUXWDP))]
1037   "VECTOR_UNIT_VSX_P (V2DFmode)"
1038   "xvcvuxwdp %x0,%x1"
1039   [(set_attr "type" "vecfloat")])
1041 (define_insn "vsx_xvcvspsxds"
1042   [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
1043         (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
1044                      UNSPEC_VSX_CVSPSXDS))]
1045   "VECTOR_UNIT_VSX_P (V2DFmode)"
1046   "xvcvspsxds %x0,%x1"
1047   [(set_attr "type" "vecfloat")])
1049 (define_insn "vsx_xvcvspuxds"
1050   [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
1051         (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
1052                      UNSPEC_VSX_CVSPUXDS))]
1053   "VECTOR_UNIT_VSX_P (V2DFmode)"
1054   "xvcvspuxds %x0,%x1"
1055   [(set_attr "type" "vecfloat")])
1057 ;; Logical and permute operations
1058 (define_insn "*vsx_and<mode>3"
1059   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1060         (and:VSX_L
1061          (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
1062          (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
1063   "VECTOR_MEM_VSX_P (<MODE>mode)"
1064   "xxland %x0,%x1,%x2"
1065   [(set_attr "type" "vecsimple")])
1067 (define_insn "*vsx_ior<mode>3"
1068   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1069         (ior:VSX_L (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
1070                    (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
1071   "VECTOR_MEM_VSX_P (<MODE>mode)"
1072   "xxlor %x0,%x1,%x2"
1073   [(set_attr "type" "vecsimple")])
1075 (define_insn "*vsx_xor<mode>3"
1076   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1077         (xor:VSX_L
1078          (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
1079          (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
1080   "VECTOR_MEM_VSX_P (<MODE>mode)"
1081   "xxlxor %x0,%x1,%x2"
1082   [(set_attr "type" "vecsimple")])
1084 (define_insn "*vsx_one_cmpl<mode>2"
1085   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1086         (not:VSX_L
1087          (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")))]
1088   "VECTOR_MEM_VSX_P (<MODE>mode)"
1089   "xxlnor %x0,%x1,%x1"
1090   [(set_attr "type" "vecsimple")])
1091   
1092 (define_insn "*vsx_nor<mode>3"
1093   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1094         (not:VSX_L
1095          (ior:VSX_L
1096           (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
1097           (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa"))))]
1098   "VECTOR_MEM_VSX_P (<MODE>mode)"
1099   "xxlnor %x0,%x1,%x2"
1100   [(set_attr "type" "vecsimple")])
1102 (define_insn "*vsx_andc<mode>3"
1103   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1104         (and:VSX_L
1105          (not:VSX_L
1106           (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa"))
1107          (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")))]
1108   "VECTOR_MEM_VSX_P (<MODE>mode)"
1109   "xxlandc %x0,%x1,%x2"
1110   [(set_attr "type" "vecsimple")])
1113 ;; Permute operations
1115 ;; Build a V2DF/V2DI vector from two scalars
1116 (define_insn "vsx_concat_<mode>"
1117   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
1118         (unspec:VSX_D
1119          [(match_operand:<VS_scalar> 1 "vsx_register_operand" "ws,wa")
1120           (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")]
1121          UNSPEC_VSX_CONCAT))]
1122   "VECTOR_MEM_VSX_P (<MODE>mode)"
1123   "xxpermdi %x0,%x1,%x2,0"
1124   [(set_attr "type" "vecperm")])
1126 ;; Special purpose concat using xxpermdi to glue two single precision values
1127 ;; together, relying on the fact that internally scalar floats are represented
1128 ;; as doubles.  This is used to initialize a V4SF vector with 4 floats
1129 (define_insn "vsx_concat_v2sf"
1130   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1131         (unspec:V2DF
1132          [(match_operand:SF 1 "vsx_register_operand" "f,f")
1133           (match_operand:SF 2 "vsx_register_operand" "f,f")]
1134          UNSPEC_VSX_CONCAT))]
1135   "VECTOR_MEM_VSX_P (V2DFmode)"
1136   "xxpermdi %x0,%x1,%x2,0"
1137   [(set_attr "type" "vecperm")])
1139 ;; Set the element of a V2DI/VD2F mode
1140 (define_insn "vsx_set_<mode>"
1141   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
1142         (unspec:VSX_D [(match_operand:VSX_D 1 "vsx_register_operand" "wd,wa")
1143                        (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")
1144                        (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
1145                       UNSPEC_VSX_SET))]
1146   "VECTOR_MEM_VSX_P (<MODE>mode)"
1148   if (INTVAL (operands[3]) == 0)
1149     return \"xxpermdi %x0,%x1,%x2,1\";
1150   else if (INTVAL (operands[3]) == 1)
1151     return \"xxpermdi %x0,%x2,%x1,0\";
1152   else
1153     gcc_unreachable ();
1155   [(set_attr "type" "vecperm")])
1157 ;; Extract a DF/DI element from V2DF/V2DI
1158 (define_insn "vsx_extract_<mode>"
1159   [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,d,?wa")
1160         (vec_select:<VS_scalar> (match_operand:VSX_D 1 "vsx_register_operand" "wd,wd,wa")
1161                        (parallel
1162                         [(match_operand:QI 2 "u5bit_cint_operand" "i,i,i")])))]
1163   "VECTOR_MEM_VSX_P (<MODE>mode)"
1165   gcc_assert (UINTVAL (operands[2]) <= 1);
1166   operands[3] = GEN_INT (INTVAL (operands[2]) << 1);
1167   return \"xxpermdi %x0,%x1,%x1,%3\";
1169   [(set_attr "type" "vecperm")])
1171 ;; Optimize extracting element 0 from memory
1172 (define_insn "*vsx_extract_<mode>_zero"
1173   [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,d,?wa")
1174         (vec_select:<VS_scalar>
1175          (match_operand:VSX_D 1 "indexed_or_indirect_operand" "Z,Z,Z")
1176          (parallel [(const_int 0)])))]
1177   "VECTOR_MEM_VSX_P (<MODE>mode) && WORDS_BIG_ENDIAN"
1178   "lxsd%U1x %x0,%y1"
1179   [(set_attr "type" "fpload")
1180    (set_attr "length" "4")])  
1182 ;; General double word oriented permute, allow the other vector types for
1183 ;; optimizing the permute instruction.
1184 (define_insn "vsx_xxpermdi_<mode>"
1185   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=wd,?wa")
1186         (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "wd,wa")
1187                        (match_operand:VSX_L 2 "vsx_register_operand" "wd,wa")
1188                        (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
1189                       UNSPEC_VSX_XXPERMDI))]
1190   "VECTOR_MEM_VSX_P (<MODE>mode)"
1191   "xxpermdi %x0,%x1,%x2,%3"
1192   [(set_attr "type" "vecperm")])
1194 ;; Varient of xxpermdi that is emitted by the vec_interleave functions
1195 (define_insn "*vsx_xxpermdi2_<mode>"
1196   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd")
1197         (vec_concat:VSX_D
1198          (vec_select:<VS_scalar>
1199           (match_operand:VSX_D 1 "vsx_register_operand" "wd")
1200           (parallel
1201            [(match_operand:QI 2 "u5bit_cint_operand" "i")]))
1202          (vec_select:<VS_scalar>
1203           (match_operand:VSX_D 3 "vsx_register_operand" "wd")
1204           (parallel
1205            [(match_operand:QI 4 "u5bit_cint_operand" "i")]))))]
1206   "VECTOR_MEM_VSX_P (<MODE>mode)"
1208   gcc_assert ((UINTVAL (operands[2]) <= 1) && (UINTVAL (operands[4]) <= 1));
1209   operands[5] = GEN_INT (((INTVAL (operands[2]) & 1) << 1)
1210                          | (INTVAL (operands[4]) & 1));
1211   return \"xxpermdi %x0,%x1,%x3,%5\";
1213   [(set_attr "type" "vecperm")])
1215 ;; V2DF/V2DI splat
1216 (define_insn "vsx_splat_<mode>"
1217   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,wd,wd,?wa,?wa,?wa")
1218         (vec_duplicate:VSX_D
1219          (match_operand:<VS_scalar> 1 "input_operand" "ws,f,Z,wa,wa,Z")))]
1220   "VECTOR_MEM_VSX_P (<MODE>mode)"
1221   "@
1222    xxpermdi %x0,%x1,%x1,0
1223    xxpermdi %x0,%x1,%x1,0
1224    lxvdsx %x0,%y1
1225    xxpermdi %x0,%x1,%x1,0
1226    xxpermdi %x0,%x1,%x1,0
1227    lxvdsx %x0,%y1"
1228   [(set_attr "type" "vecperm,vecperm,vecload,vecperm,vecperm,vecload")])
1230 ;; V4SF/V4SI splat
1231 (define_insn "vsx_xxspltw_<mode>"
1232   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1233         (vec_duplicate:VSX_W
1234          (vec_select:<VS_scalar>
1235           (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1236           (parallel
1237            [(match_operand:QI 2 "u5bit_cint_operand" "i,i")]))))]
1238   "VECTOR_MEM_VSX_P (<MODE>mode)"
1239   "xxspltw %x0,%x1,%2"
1240   [(set_attr "type" "vecperm")])
1242 ;; V4SF/V4SI interleave
1243 (define_insn "vsx_xxmrghw_<mode>"
1244   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1245         (vec_merge:VSX_W
1246          (vec_select:VSX_W
1247           (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1248           (parallel [(const_int 0)
1249                      (const_int 2)
1250                      (const_int 1)
1251                      (const_int 3)]))
1252          (vec_select:VSX_W
1253           (match_operand:VSX_W 2 "vsx_register_operand" "wf,wa")
1254           (parallel [(const_int 2)
1255                      (const_int 0)
1256                      (const_int 3)
1257                      (const_int 1)]))
1258          (const_int 5)))]
1259   "VECTOR_MEM_VSX_P (<MODE>mode)"
1260   "xxmrghw %x0,%x1,%x2"
1261   [(set_attr "type" "vecperm")])
1263 (define_insn "vsx_xxmrglw_<mode>"
1264   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1265         (vec_merge:VSX_W
1266          (vec_select:VSX_W
1267           (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1268           (parallel [(const_int 2)
1269                      (const_int 0)
1270                      (const_int 3)
1271                      (const_int 1)]))
1272          (vec_select:VSX_W
1273           (match_operand:VSX_W 2 "vsx_register_operand" "wf,?wa")
1274           (parallel [(const_int 0)
1275                      (const_int 2)
1276                      (const_int 1)
1277                      (const_int 3)]))
1278          (const_int 5)))]
1279   "VECTOR_MEM_VSX_P (<MODE>mode)"
1280   "xxmrglw %x0,%x1,%x2"
1281   [(set_attr "type" "vecperm")])
1283 ;; Shift left double by word immediate
1284 (define_insn "vsx_xxsldwi_<mode>"
1285   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=wa")
1286         (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "wa")
1287                        (match_operand:VSX_L 2 "vsx_register_operand" "wa")
1288                        (match_operand:QI 3 "u5bit_cint_operand" "i")]
1289                       UNSPEC_VSX_SLDWI))]
1290   "VECTOR_MEM_VSX_P (<MODE>mode)"
1291   "xxsldwi %x0,%x1,%x2,%3"
1292   [(set_attr "type" "vecperm")])