Merge from mainline (165734:167278).
[official-gcc/graphite-test-results.git] / gcc / config / rs6000 / vsx.md
blobe241e26db8960995196a2dcfeb60f1b6a3128538
1 ;; VSX patterns.
2 ;; Copyright (C) 2009, 2010
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 the DF types
32 (define_mode_iterator VSX_DF [V2DF DF])
34 ;; Iterator for vector floating point types supported by VSX
35 (define_mode_iterator VSX_F [V4SF V2DF])
37 ;; Iterator for logical types supported by VSX
38 (define_mode_iterator VSX_L [V16QI V8HI V4SI V2DI V4SF V2DF TI])
40 ;; Iterator for memory move.  Handle TImode specially to allow
41 ;; it to use gprs as well as vsx registers.
42 (define_mode_iterator VSX_M [V16QI V8HI V4SI V2DI V4SF V2DF])
44 ;; Map into the appropriate load/store name based on the type
45 (define_mode_attr VSm  [(V16QI "vw4")
46                         (V8HI  "vw4")
47                         (V4SI  "vw4")
48                         (V4SF  "vw4")
49                         (V2DF  "vd2")
50                         (V2DI  "vd2")
51                         (DF    "d")
52                         (TI    "vw4")])
54 ;; Map into the appropriate suffix based on the type
55 (define_mode_attr VSs   [(V16QI "sp")
56                          (V8HI  "sp")
57                          (V4SI  "sp")
58                          (V4SF  "sp")
59                          (V2DF  "dp")
60                          (V2DI  "dp")
61                          (DF    "dp")
62                          (SF    "sp")
63                          (TI    "sp")])
65 ;; Map the register class used
66 (define_mode_attr VSr   [(V16QI "v")
67                          (V8HI  "v")
68                          (V4SI  "v")
69                          (V4SF  "wf")
70                          (V2DI  "wd")
71                          (V2DF  "wd")
72                          (DF    "ws")
73                          (SF    "d")
74                          (TI    "wd")])
76 ;; Map the register class used for float<->int conversions
77 (define_mode_attr VSr2  [(V2DF  "wd")
78                          (V4SF  "wf")
79                          (DF    "ws")])
81 (define_mode_attr VSr3  [(V2DF  "wa")
82                          (V4SF  "wa")
83                          (DF    "ws")])
85 ;; Map the register class for sp<->dp float conversions, destination
86 (define_mode_attr VSr4  [(SF    "ws")
87                          (DF    "f")
88                          (V2DF  "wd")
89                          (V4SF  "v")])
91 ;; Map the register class for sp<->dp float conversions, destination
92 (define_mode_attr VSr5  [(SF    "ws")
93                          (DF    "f")
94                          (V2DF  "v")
95                          (V4SF  "wd")])
97 ;; Same size integer type for floating point data
98 (define_mode_attr VSi [(V4SF  "v4si")
99                        (V2DF  "v2di")
100                        (DF    "di")])
102 (define_mode_attr VSI [(V4SF  "V4SI")
103                        (V2DF  "V2DI")
104                        (DF    "DI")])
106 ;; Word size for same size conversion
107 (define_mode_attr VSc [(V4SF "w")
108                        (V2DF "d")
109                        (DF   "d")])
111 ;; Map into either s or v, depending on whether this is a scalar or vector
112 ;; operation
113 (define_mode_attr VSv   [(V16QI "v")
114                          (V8HI  "v")
115                          (V4SI  "v")
116                          (V4SF  "v")
117                          (V2DI  "v")
118                          (V2DF  "v")
119                          (TI    "v")
120                          (DF    "s")])
122 ;; Appropriate type for add ops (and other simple FP ops)
123 (define_mode_attr VStype_simple [(V2DF "vecfloat")
124                                  (V4SF "vecfloat")
125                                  (DF   "fp")])
127 (define_mode_attr VSfptype_simple [(V2DF "fp_addsub_d")
128                                    (V4SF "fp_addsub_s")
129                                    (DF   "fp_addsub_d")])
131 ;; Appropriate type for multiply ops
132 (define_mode_attr VStype_mul    [(V2DF "vecfloat")
133                                  (V4SF "vecfloat")
134                                  (DF   "dmul")])
136 (define_mode_attr VSfptype_mul  [(V2DF "fp_mul_d")
137                                  (V4SF "fp_mul_s")
138                                  (DF   "fp_mul_d")])
140 ;; Appropriate type for divide ops.  For now, just lump the vector divide with
141 ;; the scalar divides
142 (define_mode_attr VStype_div    [(V2DF "ddiv")
143                                  (V4SF "sdiv")
144                                  (DF   "ddiv")])
146 (define_mode_attr VSfptype_div  [(V2DF "fp_div_d")
147                                  (V4SF "fp_div_s")
148                                  (DF   "fp_div_d")])
150 ;; Appropriate type for sqrt ops.  For now, just lump the vector sqrt with
151 ;; the scalar sqrt
152 (define_mode_attr VStype_sqrt   [(V2DF "dsqrt")
153                                  (V4SF "sdiv")
154                                  (DF   "ddiv")])
156 (define_mode_attr VSfptype_sqrt [(V2DF "fp_sqrt_d")
157                                  (V4SF "fp_sqrt_s")
158                                  (DF   "fp_sqrt_d")])
160 ;; Iterator and modes for sp<->dp conversions
161 ;; Because scalar SF values are represented internally as double, use the
162 ;; V4SF type to represent this than SF.
163 (define_mode_iterator VSX_SPDP [DF V4SF V2DF])
165 (define_mode_attr VS_spdp_res [(DF      "V4SF")
166                                (V4SF    "V2DF")
167                                (V2DF    "V4SF")])
169 (define_mode_attr VS_spdp_insn [(DF     "xscvdpsp")
170                                 (V4SF   "xvcvspdp")
171                                 (V2DF   "xvcvdpsp")])
173 (define_mode_attr VS_spdp_type [(DF     "fp")
174                                 (V4SF   "vecfloat")
175                                 (V2DF   "vecfloat")])
177 ;; Map the scalar mode for a vector type
178 (define_mode_attr VS_scalar [(V2DF      "DF")
179                              (V2DI      "DI")
180                              (V4SF      "SF")
181                              (V4SI      "SI")
182                              (V8HI      "HI")
183                              (V16QI     "QI")])
184                              
185 ;; Constants for creating unspecs
186 (define_constants
187   [(UNSPEC_VSX_CONCAT           500)
188    (UNSPEC_VSX_CVDPSXWS         501)
189    (UNSPEC_VSX_CVDPUXWS         502)
190    (UNSPEC_VSX_CVSPDP           503)
191    (UNSPEC_VSX_CVSXWDP          504)
192    (UNSPEC_VSX_CVUXWDP          505)
193    (UNSPEC_VSX_CVSXDSP          506)
194    (UNSPEC_VSX_CVUXDSP          507)
195    (UNSPEC_VSX_CVSPSXDS         508)
196    (UNSPEC_VSX_CVSPUXDS         509)
197    ;; 510-514 deleted
198    (UNSPEC_VSX_TDIV             515)
199    (UNSPEC_VSX_TSQRT            516)
200    (UNSPEC_VSX_XXPERMDI         517)
201    (UNSPEC_VSX_SET              518)
202    (UNSPEC_VSX_ROUND_I          519)
203    (UNSPEC_VSX_ROUND_IC         520)
204    (UNSPEC_VSX_SLDWI            521)])
206 ;; VSX moves
207 (define_insn "*vsx_mov<mode>"
208   [(set (match_operand:VSX_M 0 "nonimmediate_operand" "=Z,<VSr>,<VSr>,?Z,?wa,?wa,*o,*r,*r,<VSr>,?wa,v,wZ,v")
209         (match_operand:VSX_M 1 "input_operand" "<VSr>,Z,<VSr>,wa,Z,wa,r,o,r,j,j,W,v,wZ"))]
210   "VECTOR_MEM_VSX_P (<MODE>mode)
211    && (register_operand (operands[0], <MODE>mode) 
212        || register_operand (operands[1], <MODE>mode))"
214   switch (which_alternative)
215     {
216     case 0:
217     case 3:
218       gcc_assert (MEM_P (operands[0])
219                   && GET_CODE (XEXP (operands[0], 0)) != PRE_INC
220                   && GET_CODE (XEXP (operands[0], 0)) != PRE_DEC
221                   && GET_CODE (XEXP (operands[0], 0)) != PRE_MODIFY);
222       return "stx<VSm>x %x1,%y0";
224     case 1:
225     case 4:
226       gcc_assert (MEM_P (operands[1])
227                   && GET_CODE (XEXP (operands[1], 0)) != PRE_INC
228                   && GET_CODE (XEXP (operands[1], 0)) != PRE_DEC
229                   && GET_CODE (XEXP (operands[1], 0)) != PRE_MODIFY);
230       return "lx<VSm>x %x0,%y1";
232     case 2:
233     case 5:
234       return "xxlor %x0,%x1,%x1";
236     case 6:
237     case 7:
238     case 8:
239       return "#";
241     case 9:
242     case 10:
243       return "xxlxor %x0,%x0,%x0";
245     case 11:
246       return output_vec_const_move (operands);
248     case 12:
249       gcc_assert (MEM_P (operands[0])
250                   && GET_CODE (XEXP (operands[0], 0)) != PRE_INC
251                   && GET_CODE (XEXP (operands[0], 0)) != PRE_DEC
252                   && GET_CODE (XEXP (operands[0], 0)) != PRE_MODIFY);
253       return "stvx %1,%y0";
255     case 13:
256       gcc_assert (MEM_P (operands[0])
257                   && GET_CODE (XEXP (operands[0], 0)) != PRE_INC
258                   && GET_CODE (XEXP (operands[0], 0)) != PRE_DEC
259                   && GET_CODE (XEXP (operands[0], 0)) != PRE_MODIFY);
260       return "lvx %0,%y1";
262     default:
263       gcc_unreachable ();
264     }
266   [(set_attr "type" "vecstore,vecload,vecsimple,vecstore,vecload,vecsimple,*,*,*,vecsimple,vecsimple,*,vecstore,vecload")])
268 ;; Unlike other VSX moves, allow the GPRs, since a normal use of TImode is for
269 ;; unions.  However for plain data movement, slightly favor the vector loads
270 (define_insn "*vsx_movti"
271   [(set (match_operand:TI 0 "nonimmediate_operand" "=Z,wa,wa,?o,?r,?r,wa,v,v,wZ")
272         (match_operand:TI 1 "input_operand" "wa,Z,wa,r,o,r,j,W,wZ,v"))]
273   "VECTOR_MEM_VSX_P (TImode)
274    && (register_operand (operands[0], TImode) 
275        || register_operand (operands[1], TImode))"
277   switch (which_alternative)
278     {
279     case 0:
280       return "stxvd2x %x1,%y0";
282     case 1:
283       return "lxvd2x %x0,%y1";
285     case 2:
286       return "xxlor %x0,%x1,%x1";
288     case 3:
289     case 4:
290     case 5:
291       return "#";
293     case 6:
294       return "xxlxor %x0,%x0,%x0";
296     case 7:
297       return output_vec_const_move (operands);
299     case 8:
300       return "stvx %1,%y0";
302     case 9:
303       return "lvx %0,%y1";
305     default:
306       gcc_unreachable ();
307     }
309   [(set_attr "type" "vecstore,vecload,vecsimple,*,*,*,vecsimple,*,vecstore,vecload")])
312 ;; VSX scalar and vector floating point arithmetic instructions
313 (define_insn "*vsx_add<mode>3"
314   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
315         (plus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
316                     (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
317   "VECTOR_UNIT_VSX_P (<MODE>mode)"
318   "x<VSv>add<VSs> %x0,%x1,%x2"
319   [(set_attr "type" "<VStype_simple>")
320    (set_attr "fp_type" "<VSfptype_simple>")])
322 (define_insn "*vsx_sub<mode>3"
323   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
324         (minus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
325                      (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
326   "VECTOR_UNIT_VSX_P (<MODE>mode)"
327   "x<VSv>sub<VSs> %x0,%x1,%x2"
328   [(set_attr "type" "<VStype_simple>")
329    (set_attr "fp_type" "<VSfptype_simple>")])
331 (define_insn "*vsx_mul<mode>3"
332   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
333         (mult:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
334                     (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
335   "VECTOR_UNIT_VSX_P (<MODE>mode)"
336   "x<VSv>mul<VSs> %x0,%x1,%x2"
337   [(set_attr "type" "<VStype_mul>")
338    (set_attr "fp_type" "<VSfptype_mul>")])
340 (define_insn "*vsx_div<mode>3"
341   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
342         (div:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
343                    (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
344   "VECTOR_UNIT_VSX_P (<MODE>mode)"
345   "x<VSv>div<VSs> %x0,%x1,%x2"
346   [(set_attr "type" "<VStype_div>")
347    (set_attr "fp_type" "<VSfptype_div>")])
349 ;; *tdiv* instruction returning the FG flag
350 (define_expand "vsx_tdiv<mode>3_fg"
351   [(set (match_dup 3)
352         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
353                       (match_operand:VSX_B 2 "vsx_register_operand" "")]
354                      UNSPEC_VSX_TDIV))
355    (set (match_operand:SI 0 "gpc_reg_operand" "")
356         (gt:SI (match_dup 3)
357                (const_int 0)))]
358   "VECTOR_UNIT_VSX_P (<MODE>mode)"
360   operands[3] = gen_reg_rtx (CCFPmode);
363 ;; *tdiv* instruction returning the FE flag
364 (define_expand "vsx_tdiv<mode>3_fe"
365   [(set (match_dup 3)
366         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
367                       (match_operand:VSX_B 2 "vsx_register_operand" "")]
368                      UNSPEC_VSX_TDIV))
369    (set (match_operand:SI 0 "gpc_reg_operand" "")
370         (eq:SI (match_dup 3)
371                (const_int 0)))]
372   "VECTOR_UNIT_VSX_P (<MODE>mode)"
374   operands[3] = gen_reg_rtx (CCFPmode);
377 (define_insn "*vsx_tdiv<mode>3_internal"
378   [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
379         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
380                       (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")]
381                    UNSPEC_VSX_TDIV))]
382   "VECTOR_UNIT_VSX_P (<MODE>mode)"
383   "x<VSv>tdiv<VSs> %0,%x1,%x2"
384   [(set_attr "type" "<VStype_simple>")
385    (set_attr "fp_type" "<VSfptype_simple>")])
387 (define_insn "vsx_fre<mode>2"
388   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
389         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
390                       UNSPEC_FRES))]
391   "VECTOR_UNIT_VSX_P (<MODE>mode)"
392   "x<VSv>re<VSs> %x0,%x1"
393   [(set_attr "type" "<VStype_simple>")
394    (set_attr "fp_type" "<VSfptype_simple>")])
396 (define_insn "*vsx_neg<mode>2"
397   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
398         (neg:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
399   "VECTOR_UNIT_VSX_P (<MODE>mode)"
400   "x<VSv>neg<VSs> %x0,%x1"
401   [(set_attr "type" "<VStype_simple>")
402    (set_attr "fp_type" "<VSfptype_simple>")])
404 (define_insn "*vsx_abs<mode>2"
405   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
406         (abs:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
407   "VECTOR_UNIT_VSX_P (<MODE>mode)"
408   "x<VSv>abs<VSs> %x0,%x1"
409   [(set_attr "type" "<VStype_simple>")
410    (set_attr "fp_type" "<VSfptype_simple>")])
412 (define_insn "vsx_nabs<mode>2"
413   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
414         (neg:VSX_B
415          (abs:VSX_B
416           (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa"))))]
417   "VECTOR_UNIT_VSX_P (<MODE>mode)"
418   "x<VSv>nabs<VSs> %x0,%x1"
419   [(set_attr "type" "<VStype_simple>")
420    (set_attr "fp_type" "<VSfptype_simple>")])
422 (define_insn "vsx_smax<mode>3"
423   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
424         (smax:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
425                     (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
426   "VECTOR_UNIT_VSX_P (<MODE>mode)"
427   "x<VSv>max<VSs> %x0,%x1,%x2"
428   [(set_attr "type" "<VStype_simple>")
429    (set_attr "fp_type" "<VSfptype_simple>")])
431 (define_insn "*vsx_smin<mode>3"
432   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
433         (smin:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
434                     (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
435   "VECTOR_UNIT_VSX_P (<MODE>mode)"
436   "x<VSv>min<VSs> %x0,%x1,%x2"
437   [(set_attr "type" "<VStype_simple>")
438    (set_attr "fp_type" "<VSfptype_simple>")])
440 ;; Special VSX version of smin/smax for single precision floating point.  Since
441 ;; both numbers are rounded to single precision, we can just use the DP version
442 ;; of the instruction.
444 (define_insn "*vsx_smaxsf3"
445   [(set (match_operand:SF 0 "vsx_register_operand" "=f")
446         (smax:SF (match_operand:SF 1 "vsx_register_operand" "f")
447                  (match_operand:SF 2 "vsx_register_operand" "f")))]
448   "VECTOR_UNIT_VSX_P (DFmode)"
449   "xsmaxdp %x0,%x1,%x2"
450   [(set_attr "type" "fp")
451    (set_attr "fp_type" "fp_addsub_d")])
453 (define_insn "*vsx_sminsf3"
454   [(set (match_operand:SF 0 "vsx_register_operand" "=f")
455         (smin:SF (match_operand:SF 1 "vsx_register_operand" "f")
456                  (match_operand:SF 2 "vsx_register_operand" "f")))]
457   "VECTOR_UNIT_VSX_P (DFmode)"
458   "xsmindp %x0,%x1,%x2"
459   [(set_attr "type" "fp")
460    (set_attr "fp_type" "fp_addsub_d")])
462 (define_insn "*vsx_sqrt<mode>2"
463   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
464         (sqrt:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
465   "VECTOR_UNIT_VSX_P (<MODE>mode)"
466   "x<VSv>sqrt<VSs> %x0,%x1"
467   [(set_attr "type" "<VStype_sqrt>")
468    (set_attr "fp_type" "<VSfptype_sqrt>")])
470 (define_insn "*vsx_rsqrte<mode>2"
471   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
472         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
473                       UNSPEC_RSQRT))]
474   "VECTOR_UNIT_VSX_P (<MODE>mode)"
475   "x<VSv>rsqrte<VSs> %x0,%x1"
476   [(set_attr "type" "<VStype_simple>")
477    (set_attr "fp_type" "<VSfptype_simple>")])
479 ;; *tsqrt* returning the fg flag
480 (define_expand "vsx_tsqrt<mode>2_fg"
481   [(set (match_dup 3)
482         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
483                      UNSPEC_VSX_TSQRT))
484    (set (match_operand:SI 0 "gpc_reg_operand" "")
485         (gt:SI (match_dup 3)
486                (const_int 0)))]
487   "VECTOR_UNIT_VSX_P (<MODE>mode)"
489   operands[3] = gen_reg_rtx (CCFPmode);
492 ;; *tsqrt* returning the fe flag
493 (define_expand "vsx_tsqrt<mode>2_fe"
494   [(set (match_dup 3)
495         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
496                      UNSPEC_VSX_TSQRT))
497    (set (match_operand:SI 0 "gpc_reg_operand" "")
498         (eq:SI (match_dup 3)
499                (const_int 0)))]
500   "VECTOR_UNIT_VSX_P (<MODE>mode)"
502   operands[3] = gen_reg_rtx (CCFPmode);
505 (define_insn "*vsx_tsqrt<mode>2_internal"
506   [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
507         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
508                      UNSPEC_VSX_TSQRT))]
509   "VECTOR_UNIT_VSX_P (<MODE>mode)"
510   "x<VSv>tsqrt<VSs> %0,%x1"
511   [(set_attr "type" "<VStype_simple>")
512    (set_attr "fp_type" "<VSfptype_simple>")])
514 ;; Fused vector multiply/add instructions
516 (define_insn "*vsx_fma<mode>4"
517   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
518         (fma:VSX_B
519           (match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
520           (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
521           (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")))]
522   "VECTOR_UNIT_VSX_P (<MODE>mode)"
523   "@
524    x<VSv>madda<VSs> %x0,%x1,%x2
525    x<VSv>maddm<VSs> %x0,%x1,%x3
526    x<VSv>madda<VSs> %x0,%x1,%x2
527    x<VSv>maddm<VSs> %x0,%x1,%x3"
528   [(set_attr "type" "<VStype_mul>")
529    (set_attr "fp_type" "<VSfptype_mul>")])
531 (define_insn "*vsx_fms<mode>4"
532   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
533         (fma:VSX_B
534           (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           (neg:VSX_B
537             (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
538   "VECTOR_UNIT_VSX_P (<MODE>mode)"
539   "@
540    x<VSv>msuba<VSs> %x0,%x1,%x2
541    x<VSv>msubm<VSs> %x0,%x1,%x3
542    x<VSv>msuba<VSs> %x0,%x1,%x2
543    x<VSv>msubm<VSs> %x0,%x1,%x3"
544   [(set_attr "type" "<VStype_mul>")
545    (set_attr "fp_type" "<VSfptype_mul>")])
547 (define_insn "*vsx_nfma<mode>4"
548   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
549         (neg:VSX_B
550          (fma:VSX_B
551           (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSr>,wa,wa")
552           (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
553           (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
554   "VECTOR_UNIT_VSX_P (<MODE>mode)"
555   "@
556    x<VSv>nmadda<VSs> %x0,%x1,%x2
557    x<VSv>nmaddm<VSs> %x0,%x1,%x3
558    x<VSv>nmadda<VSs> %x0,%x1,%x2
559    x<VSv>nmaddm<VSs> %x0,%x1,%x3"
560   [(set_attr "type" "<VStype_mul>")
561    (set_attr "fp_type" "<VSfptype_mul>")])
563 (define_insn "*vsx_nfms<mode>4"
564   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
565         (neg:VSX_B
566          (fma:VSX_B
567            (match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
568            (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
569            (neg:VSX_B
570              (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")))))]
571   "VECTOR_UNIT_VSX_P (<MODE>mode)"
572   "@
573    x<VSv>nmsuba<VSs> %x0,%x1,%x2
574    x<VSv>nmsubm<VSs> %x0,%x1,%x3
575    x<VSv>nmsuba<VSs> %x0,%x1,%x2
576    x<VSv>nmsubm<VSs> %x0,%x1,%x3"
577   [(set_attr "type" "<VStype_mul>")
578    (set_attr "fp_type" "<VSfptype_mul>")])
580 ;; Vector conditional expressions (no scalar version for these instructions)
581 (define_insn "vsx_eq<mode>"
582   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
583         (eq:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
584                   (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
585   "VECTOR_UNIT_VSX_P (<MODE>mode)"
586   "xvcmpeq<VSs> %x0,%x1,%x2"
587   [(set_attr "type" "<VStype_simple>")
588    (set_attr "fp_type" "<VSfptype_simple>")])
590 (define_insn "vsx_gt<mode>"
591   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
592         (gt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
593                   (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
594   "VECTOR_UNIT_VSX_P (<MODE>mode)"
595   "xvcmpgt<VSs> %x0,%x1,%x2"
596   [(set_attr "type" "<VStype_simple>")
597    (set_attr "fp_type" "<VSfptype_simple>")])
599 (define_insn "*vsx_ge<mode>"
600   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
601         (ge:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
602                   (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
603   "VECTOR_UNIT_VSX_P (<MODE>mode)"
604   "xvcmpge<VSs> %x0,%x1,%x2"
605   [(set_attr "type" "<VStype_simple>")
606    (set_attr "fp_type" "<VSfptype_simple>")])
608 ;; Floating point scalar compare
609 (define_insn "*vsx_cmpdf_internal1"
610   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y,?y")
611         (compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "ws,wa")
612                       (match_operand:DF 2 "gpc_reg_operand" "ws,wa")))]
613   "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
614    && VECTOR_UNIT_VSX_P (DFmode)"
615   "xscmpudp %0,%x1,%x2"
616   [(set_attr "type" "fpcompare")])
618 ;; Compare vectors producing a vector result and a predicate, setting CR6 to
619 ;; indicate a combined status
620 (define_insn "*vsx_eq_<mode>_p"
621   [(set (reg:CC 74)
622         (unspec:CC
623          [(eq:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
624                  (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
625          UNSPEC_PREDICATE))
626    (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
627         (eq:VSX_F (match_dup 1)
628                   (match_dup 2)))]
629   "VECTOR_UNIT_VSX_P (<MODE>mode)"
630   "xvcmpeq<VSs>. %x0,%x1,%x2"
631   [(set_attr "type" "veccmp")])
633 (define_insn "*vsx_gt_<mode>_p"
634   [(set (reg:CC 74)
635         (unspec:CC
636          [(gt:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
637                  (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
638          UNSPEC_PREDICATE))
639    (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
640         (gt:VSX_F (match_dup 1)
641                   (match_dup 2)))]
642   "VECTOR_UNIT_VSX_P (<MODE>mode)"
643   "xvcmpgt<VSs>. %x0,%x1,%x2"
644   [(set_attr "type" "veccmp")])
646 (define_insn "*vsx_ge_<mode>_p"
647   [(set (reg:CC 74)
648         (unspec:CC
649          [(ge:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
650                  (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
651          UNSPEC_PREDICATE))
652    (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
653         (ge:VSX_F (match_dup 1)
654                   (match_dup 2)))]
655   "VECTOR_UNIT_VSX_P (<MODE>mode)"
656   "xvcmpge<VSs>. %x0,%x1,%x2"
657   [(set_attr "type" "veccmp")])
659 ;; Vector select
660 (define_insn "*vsx_xxsel<mode>"
661   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
662         (if_then_else:VSX_L
663          (ne:CC (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
664                 (const_int 0))
665          (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
666          (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
667   "VECTOR_MEM_VSX_P (<MODE>mode)"
668   "xxsel %x0,%x3,%x2,%x1"
669   [(set_attr "type" "vecperm")])
671 (define_insn "*vsx_xxsel<mode>_uns"
672   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
673         (if_then_else:VSX_L
674          (ne:CCUNS (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
675                    (const_int 0))
676          (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
677          (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
678   "VECTOR_MEM_VSX_P (<MODE>mode)"
679   "xxsel %x0,%x3,%x2,%x1"
680   [(set_attr "type" "vecperm")])
682 ;; Copy sign
683 (define_insn "vsx_copysign<mode>3"
684   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
685         (unspec:VSX_B
686          [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
687           (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")]
688          UNSPEC_COPYSIGN))]
689   "VECTOR_UNIT_VSX_P (<MODE>mode)"
690   "x<VSv>cpsgn<VSs> %x0,%x2,%x1"
691   [(set_attr "type" "<VStype_simple>")
692    (set_attr "fp_type" "<VSfptype_simple>")])
694 ;; For the conversions, limit the register class for the integer value to be
695 ;; the fprs because we don't want to add the altivec registers to movdi/movsi.
696 ;; For the unsigned tests, there isn't a generic double -> unsigned conversion
697 ;; in rs6000.md so don't test VECTOR_UNIT_VSX_P, just test against VSX.
698 (define_insn "vsx_float<VSi><mode>2"
699   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
700         (float:VSX_B (match_operand:<VSI> 1 "vsx_register_operand" "<VSr2>,<VSr3>")))]
701   "VECTOR_UNIT_VSX_P (<MODE>mode)"
702   "x<VSv>cvsx<VSc><VSs> %x0,%x1"
703   [(set_attr "type" "<VStype_simple>")
704    (set_attr "fp_type" "<VSfptype_simple>")])
706 (define_insn "vsx_floatuns<VSi><mode>2"
707   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
708         (unsigned_float:VSX_B (match_operand:<VSI> 1 "vsx_register_operand" "<VSr2>,<VSr3>")))]
709   "VECTOR_UNIT_VSX_P (<MODE>mode)"
710   "x<VSv>cvux<VSc><VSs> %x0,%x1"
711   [(set_attr "type" "<VStype_simple>")
712    (set_attr "fp_type" "<VSfptype_simple>")])
714 (define_insn "vsx_fix_trunc<mode><VSi>2"
715   [(set (match_operand:<VSI> 0 "vsx_register_operand" "=<VSr2>,?<VSr3>")
716         (fix:<VSI> (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
717   "VECTOR_UNIT_VSX_P (<MODE>mode)"
718   "x<VSv>cv<VSs>sx<VSc>s %x0,%x1"
719   [(set_attr "type" "<VStype_simple>")
720    (set_attr "fp_type" "<VSfptype_simple>")])
722 (define_insn "vsx_fixuns_trunc<mode><VSi>2"
723   [(set (match_operand:<VSI> 0 "vsx_register_operand" "=<VSr2>,?<VSr3>")
724         (unsigned_fix:<VSI> (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
725   "VECTOR_UNIT_VSX_P (<MODE>mode)"
726   "x<VSv>cv<VSs>ux<VSc>s %x0,%x1"
727   [(set_attr "type" "<VStype_simple>")
728    (set_attr "fp_type" "<VSfptype_simple>")])
730 ;; Math rounding functions
731 (define_insn "vsx_x<VSv>r<VSs>i"
732   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
733         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
734                       UNSPEC_VSX_ROUND_I))]
735   "VECTOR_UNIT_VSX_P (<MODE>mode)"
736   "x<VSv>r<VSs>i %x0,%x1"
737   [(set_attr "type" "<VStype_simple>")
738    (set_attr "fp_type" "<VSfptype_simple>")])
740 (define_insn "vsx_x<VSv>r<VSs>ic"
741   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
742         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
743                       UNSPEC_VSX_ROUND_IC))]
744   "VECTOR_UNIT_VSX_P (<MODE>mode)"
745   "x<VSv>r<VSs>ic %x0,%x1"
746   [(set_attr "type" "<VStype_simple>")
747    (set_attr "fp_type" "<VSfptype_simple>")])
749 (define_insn "vsx_btrunc<mode>2"
750   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
751         (fix:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
752   "VECTOR_UNIT_VSX_P (<MODE>mode)"
753   "x<VSv>r<VSs>iz %x0,%x1"
754   [(set_attr "type" "<VStype_simple>")
755    (set_attr "fp_type" "<VSfptype_simple>")])
757 (define_insn "*vsx_b2trunc<mode>2"
758   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
759         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
760                       UNSPEC_FRIZ))]
761   "VECTOR_UNIT_VSX_P (<MODE>mode)"
762   "x<VSv>r<VSs>iz %x0,%x1"
763   [(set_attr "type" "<VStype_simple>")
764    (set_attr "fp_type" "<VSfptype_simple>")])
766 (define_insn "vsx_floor<mode>2"
767   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
768         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
769                       UNSPEC_FRIM))]
770   "VECTOR_UNIT_VSX_P (<MODE>mode)"
771   "x<VSv>r<VSs>im %x0,%x1"
772   [(set_attr "type" "<VStype_simple>")
773    (set_attr "fp_type" "<VSfptype_simple>")])
775 (define_insn "vsx_ceil<mode>2"
776   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
777         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
778                       UNSPEC_FRIP))]
779   "VECTOR_UNIT_VSX_P (<MODE>mode)"
780   "x<VSv>r<VSs>ip %x0,%x1"
781   [(set_attr "type" "<VStype_simple>")
782    (set_attr "fp_type" "<VSfptype_simple>")])
785 ;; VSX convert to/from double vector
787 ;; Convert between single and double precision
788 ;; Don't use xscvspdp and xscvdpsp for scalar conversions, since the normal
789 ;; scalar single precision instructions internally use the double format.
790 ;; Prefer the altivec registers, since we likely will need to do a vperm
791 (define_insn "vsx_<VS_spdp_insn>"
792   [(set (match_operand:<VS_spdp_res> 0 "vsx_register_operand" "=<VSr4>,?wa")
793         (unspec:<VS_spdp_res> [(match_operand:VSX_SPDP 1 "vsx_register_operand" "<VSr5>,wa")]
794                               UNSPEC_VSX_CVSPDP))]
795   "VECTOR_UNIT_VSX_P (<MODE>mode)"
796   "<VS_spdp_insn> %x0,%x1"
797   [(set_attr "type" "<VS_spdp_type>")])
799 ;; xscvspdp, represent the scalar SF type as V4SF
800 (define_insn "vsx_xscvspdp"
801   [(set (match_operand:DF 0 "vsx_register_operand" "=ws,?wa")
802         (unspec:DF [(match_operand:V4SF 1 "vsx_register_operand" "wa,wa")]
803                    UNSPEC_VSX_CVSPDP))]
804   "VECTOR_UNIT_VSX_P (DFmode)"
805   "xscvspdp %x0,%x1"
806   [(set_attr "type" "fp")])
808 ;; xscvdpsp used for splat'ing a scalar to V4SF, knowing that the internal SF
809 ;; format of scalars is actually DF.
810 (define_insn "vsx_xscvdpsp_scalar"
811   [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
812         (unspec:V4SF [(match_operand:SF 1 "vsx_register_operand" "f")]
813                      UNSPEC_VSX_CVSPDP))]
814   "VECTOR_UNIT_VSX_P (DFmode)"
815   "xscvdpsp %x0,%x1"
816   [(set_attr "type" "fp")])
818 ;; Convert from 64-bit to 32-bit types
819 ;; Note, favor the Altivec registers since the usual use of these instructions
820 ;; is in vector converts and we need to use the Altivec vperm instruction.
822 (define_insn "vsx_xvcvdpsxws"
823   [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
824         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
825                      UNSPEC_VSX_CVDPSXWS))]
826   "VECTOR_UNIT_VSX_P (V2DFmode)"
827   "xvcvdpsxws %x0,%x1"
828   [(set_attr "type" "vecfloat")])
830 (define_insn "vsx_xvcvdpuxws"
831   [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
832         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
833                      UNSPEC_VSX_CVDPUXWS))]
834   "VECTOR_UNIT_VSX_P (V2DFmode)"
835   "xvcvdpuxws %x0,%x1"
836   [(set_attr "type" "vecfloat")])
838 (define_insn "vsx_xvcvsxdsp"
839   [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
840         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
841                      UNSPEC_VSX_CVSXDSP))]
842   "VECTOR_UNIT_VSX_P (V2DFmode)"
843   "xvcvsxdsp %x0,%x1"
844   [(set_attr "type" "vecfloat")])
846 (define_insn "vsx_xvcvuxdsp"
847   [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
848         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
849                      UNSPEC_VSX_CVUXDSP))]
850   "VECTOR_UNIT_VSX_P (V2DFmode)"
851   "xvcvuxwdp %x0,%x1"
852   [(set_attr "type" "vecfloat")])
854 ;; Convert from 32-bit to 64-bit types
855 (define_insn "vsx_xvcvsxwdp"
856   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
857         (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
858                      UNSPEC_VSX_CVSXWDP))]
859   "VECTOR_UNIT_VSX_P (V2DFmode)"
860   "xvcvsxwdp %x0,%x1"
861   [(set_attr "type" "vecfloat")])
863 (define_insn "vsx_xvcvuxwdp"
864   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
865         (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
866                      UNSPEC_VSX_CVUXWDP))]
867   "VECTOR_UNIT_VSX_P (V2DFmode)"
868   "xvcvuxwdp %x0,%x1"
869   [(set_attr "type" "vecfloat")])
871 (define_insn "vsx_xvcvspsxds"
872   [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
873         (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
874                      UNSPEC_VSX_CVSPSXDS))]
875   "VECTOR_UNIT_VSX_P (V2DFmode)"
876   "xvcvspsxds %x0,%x1"
877   [(set_attr "type" "vecfloat")])
879 (define_insn "vsx_xvcvspuxds"
880   [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
881         (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
882                      UNSPEC_VSX_CVSPUXDS))]
883   "VECTOR_UNIT_VSX_P (V2DFmode)"
884   "xvcvspuxds %x0,%x1"
885   [(set_attr "type" "vecfloat")])
887 ;; Only optimize (float (fix x)) -> frz if we are in fast-math mode, since
888 ;; since the xsrdpiz instruction does not truncate the value if the floating
889 ;; point value is < LONG_MIN or > LONG_MAX.
890 (define_insn "*vsx_float_fix_<mode>2"
891   [(set (match_operand:VSX_DF 0 "vsx_register_operand" "=<VSr>,?wa")
892         (float:VSX_DF
893          (fix:<VSI>
894           (match_operand:VSX_DF 1 "vsx_register_operand" "<VSr>,?wa"))))]
895   "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
896    && VECTOR_UNIT_VSX_P (<MODE>mode) && flag_unsafe_math_optimizations
897    && !flag_trapping_math && TARGET_FRIZ"
898   "x<VSv>r<VSs>iz %x0,%x1"
899   [(set_attr "type" "<VStype_simple>")
900    (set_attr "fp_type" "<VSfptype_simple>")])
903 ;; Logical and permute operations
904 (define_insn "*vsx_and<mode>3"
905   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
906         (and:VSX_L
907          (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
908          (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
909   "VECTOR_MEM_VSX_P (<MODE>mode)"
910   "xxland %x0,%x1,%x2"
911   [(set_attr "type" "vecsimple")])
913 (define_insn "*vsx_ior<mode>3"
914   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
915         (ior:VSX_L (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
916                    (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
917   "VECTOR_MEM_VSX_P (<MODE>mode)"
918   "xxlor %x0,%x1,%x2"
919   [(set_attr "type" "vecsimple")])
921 (define_insn "*vsx_xor<mode>3"
922   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
923         (xor:VSX_L
924          (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
925          (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
926   "VECTOR_MEM_VSX_P (<MODE>mode)"
927   "xxlxor %x0,%x1,%x2"
928   [(set_attr "type" "vecsimple")])
930 (define_insn "*vsx_one_cmpl<mode>2"
931   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
932         (not:VSX_L
933          (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")))]
934   "VECTOR_MEM_VSX_P (<MODE>mode)"
935   "xxlnor %x0,%x1,%x1"
936   [(set_attr "type" "vecsimple")])
937   
938 (define_insn "*vsx_nor<mode>3"
939   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
940         (not:VSX_L
941          (ior:VSX_L
942           (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
943           (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa"))))]
944   "VECTOR_MEM_VSX_P (<MODE>mode)"
945   "xxlnor %x0,%x1,%x2"
946   [(set_attr "type" "vecsimple")])
948 (define_insn "*vsx_andc<mode>3"
949   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
950         (and:VSX_L
951          (not:VSX_L
952           (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa"))
953          (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")))]
954   "VECTOR_MEM_VSX_P (<MODE>mode)"
955   "xxlandc %x0,%x1,%x2"
956   [(set_attr "type" "vecsimple")])
959 ;; Permute operations
961 ;; Build a V2DF/V2DI vector from two scalars
962 (define_insn "vsx_concat_<mode>"
963   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
964         (unspec:VSX_D
965          [(match_operand:<VS_scalar> 1 "vsx_register_operand" "ws,wa")
966           (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")]
967          UNSPEC_VSX_CONCAT))]
968   "VECTOR_MEM_VSX_P (<MODE>mode)"
969   "xxpermdi %x0,%x1,%x2,0"
970   [(set_attr "type" "vecperm")])
972 ;; Special purpose concat using xxpermdi to glue two single precision values
973 ;; together, relying on the fact that internally scalar floats are represented
974 ;; as doubles.  This is used to initialize a V4SF vector with 4 floats
975 (define_insn "vsx_concat_v2sf"
976   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
977         (unspec:V2DF
978          [(match_operand:SF 1 "vsx_register_operand" "f,f")
979           (match_operand:SF 2 "vsx_register_operand" "f,f")]
980          UNSPEC_VSX_CONCAT))]
981   "VECTOR_MEM_VSX_P (V2DFmode)"
982   "xxpermdi %x0,%x1,%x2,0"
983   [(set_attr "type" "vecperm")])
985 ;; Set the element of a V2DI/VD2F mode
986 (define_insn "vsx_set_<mode>"
987   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
988         (unspec:VSX_D [(match_operand:VSX_D 1 "vsx_register_operand" "wd,wa")
989                        (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")
990                        (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
991                       UNSPEC_VSX_SET))]
992   "VECTOR_MEM_VSX_P (<MODE>mode)"
994   if (INTVAL (operands[3]) == 0)
995     return \"xxpermdi %x0,%x1,%x2,1\";
996   else if (INTVAL (operands[3]) == 1)
997     return \"xxpermdi %x0,%x2,%x1,0\";
998   else
999     gcc_unreachable ();
1001   [(set_attr "type" "vecperm")])
1003 ;; Extract a DF/DI element from V2DF/V2DI
1004 (define_insn "vsx_extract_<mode>"
1005   [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,d,?wa")
1006         (vec_select:<VS_scalar> (match_operand:VSX_D 1 "vsx_register_operand" "wd,wd,wa")
1007                        (parallel
1008                         [(match_operand:QI 2 "u5bit_cint_operand" "i,i,i")])))]
1009   "VECTOR_MEM_VSX_P (<MODE>mode)"
1011   gcc_assert (UINTVAL (operands[2]) <= 1);
1012   operands[3] = GEN_INT (INTVAL (operands[2]) << 1);
1013   return \"xxpermdi %x0,%x1,%x1,%3\";
1015   [(set_attr "type" "vecperm")])
1017 ;; Optimize extracting element 0 from memory
1018 (define_insn "*vsx_extract_<mode>_zero"
1019   [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,d,?wa")
1020         (vec_select:<VS_scalar>
1021          (match_operand:VSX_D 1 "indexed_or_indirect_operand" "Z,Z,Z")
1022          (parallel [(const_int 0)])))]
1023   "VECTOR_MEM_VSX_P (<MODE>mode) && WORDS_BIG_ENDIAN"
1024   "lxsd%U1x %x0,%y1"
1025   [(set_attr "type" "fpload")
1026    (set_attr "length" "4")])  
1028 ;; General double word oriented permute, allow the other vector types for
1029 ;; optimizing the permute instruction.
1030 (define_insn "vsx_xxpermdi_<mode>"
1031   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=wd,?wa")
1032         (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "wd,wa")
1033                        (match_operand:VSX_L 2 "vsx_register_operand" "wd,wa")
1034                        (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
1035                       UNSPEC_VSX_XXPERMDI))]
1036   "VECTOR_MEM_VSX_P (<MODE>mode)"
1037   "xxpermdi %x0,%x1,%x2,%3"
1038   [(set_attr "type" "vecperm")])
1040 ;; Varient of xxpermdi that is emitted by the vec_interleave functions
1041 (define_insn "*vsx_xxpermdi2_<mode>"
1042   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd")
1043         (vec_concat:VSX_D
1044          (vec_select:<VS_scalar>
1045           (match_operand:VSX_D 1 "vsx_register_operand" "wd")
1046           (parallel
1047            [(match_operand:QI 2 "u5bit_cint_operand" "i")]))
1048          (vec_select:<VS_scalar>
1049           (match_operand:VSX_D 3 "vsx_register_operand" "wd")
1050           (parallel
1051            [(match_operand:QI 4 "u5bit_cint_operand" "i")]))))]
1052   "VECTOR_MEM_VSX_P (<MODE>mode)"
1054   gcc_assert ((UINTVAL (operands[2]) <= 1) && (UINTVAL (operands[4]) <= 1));
1055   operands[5] = GEN_INT (((INTVAL (operands[2]) & 1) << 1)
1056                          | (INTVAL (operands[4]) & 1));
1057   return \"xxpermdi %x0,%x1,%x3,%5\";
1059   [(set_attr "type" "vecperm")])
1061 ;; V2DF/V2DI splat
1062 (define_insn "vsx_splat_<mode>"
1063   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,wd,wd,?wa,?wa,?wa")
1064         (vec_duplicate:VSX_D
1065          (match_operand:<VS_scalar> 1 "input_operand" "ws,f,Z,wa,wa,Z")))]
1066   "VECTOR_MEM_VSX_P (<MODE>mode)"
1067   "@
1068    xxpermdi %x0,%x1,%x1,0
1069    xxpermdi %x0,%x1,%x1,0
1070    lxvdsx %x0,%y1
1071    xxpermdi %x0,%x1,%x1,0
1072    xxpermdi %x0,%x1,%x1,0
1073    lxvdsx %x0,%y1"
1074   [(set_attr "type" "vecperm,vecperm,vecload,vecperm,vecperm,vecload")])
1076 ;; V4SF/V4SI splat
1077 (define_insn "vsx_xxspltw_<mode>"
1078   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1079         (vec_duplicate:VSX_W
1080          (vec_select:<VS_scalar>
1081           (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1082           (parallel
1083            [(match_operand:QI 2 "u5bit_cint_operand" "i,i")]))))]
1084   "VECTOR_MEM_VSX_P (<MODE>mode)"
1085   "xxspltw %x0,%x1,%2"
1086   [(set_attr "type" "vecperm")])
1088 ;; V4SF/V4SI interleave
1089 (define_insn "vsx_xxmrghw_<mode>"
1090   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1091         (vec_merge:VSX_W
1092          (vec_select:VSX_W
1093           (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1094           (parallel [(const_int 0)
1095                      (const_int 2)
1096                      (const_int 1)
1097                      (const_int 3)]))
1098          (vec_select:VSX_W
1099           (match_operand:VSX_W 2 "vsx_register_operand" "wf,wa")
1100           (parallel [(const_int 2)
1101                      (const_int 0)
1102                      (const_int 3)
1103                      (const_int 1)]))
1104          (const_int 5)))]
1105   "VECTOR_MEM_VSX_P (<MODE>mode)"
1106   "xxmrghw %x0,%x1,%x2"
1107   [(set_attr "type" "vecperm")])
1109 (define_insn "vsx_xxmrglw_<mode>"
1110   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1111         (vec_merge:VSX_W
1112          (vec_select:VSX_W
1113           (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1114           (parallel [(const_int 2)
1115                      (const_int 0)
1116                      (const_int 3)
1117                      (const_int 1)]))
1118          (vec_select:VSX_W
1119           (match_operand:VSX_W 2 "vsx_register_operand" "wf,?wa")
1120           (parallel [(const_int 0)
1121                      (const_int 2)
1122                      (const_int 1)
1123                      (const_int 3)]))
1124          (const_int 5)))]
1125   "VECTOR_MEM_VSX_P (<MODE>mode)"
1126   "xxmrglw %x0,%x1,%x2"
1127   [(set_attr "type" "vecperm")])
1129 ;; Shift left double by word immediate
1130 (define_insn "vsx_xxsldwi_<mode>"
1131   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=wa")
1132         (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "wa")
1133                        (match_operand:VSX_L 2 "vsx_register_operand" "wa")
1134                        (match_operand:QI 3 "u5bit_cint_operand" "i")]
1135                       UNSPEC_VSX_SLDWI))]
1136   "VECTOR_MEM_VSX_P (<MODE>mode)"
1137   "xxsldwi %x0,%x1,%x2,%3"
1138   [(set_attr "type" "vecperm")])