Fix PR target/47580
[official-gcc.git] / gcc / config / rs6000 / vsx.md
blob5b3040cc2f63a314c70ac3c54821002f49918173
1 ;; VSX patterns.
2 ;; Copyright (C) 2009, 2010, 2011
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 ;; Don't use vsx_register_operand here, use gpc_reg_operand to match rs6000.md.
699 (define_insn "vsx_float<VSi><mode>2"
700   [(set (match_operand:VSX_B 0 "gpc_reg_operand" "=<VSr>,?wa")
701         (float:VSX_B (match_operand:<VSI> 1 "gpc_reg_operand" "<VSr2>,<VSr3>")))]
702   "VECTOR_UNIT_VSX_P (<MODE>mode)"
703   "x<VSv>cvsx<VSc><VSs> %x0,%x1"
704   [(set_attr "type" "<VStype_simple>")
705    (set_attr "fp_type" "<VSfptype_simple>")])
707 (define_insn "vsx_floatuns<VSi><mode>2"
708   [(set (match_operand:VSX_B 0 "gpc_reg_operand" "=<VSr>,?wa")
709         (unsigned_float:VSX_B (match_operand:<VSI> 1 "gpc_reg_operand" "<VSr2>,<VSr3>")))]
710   "VECTOR_UNIT_VSX_P (<MODE>mode)"
711   "x<VSv>cvux<VSc><VSs> %x0,%x1"
712   [(set_attr "type" "<VStype_simple>")
713    (set_attr "fp_type" "<VSfptype_simple>")])
715 (define_insn "vsx_fix_trunc<mode><VSi>2"
716   [(set (match_operand:<VSI> 0 "gpc_reg_operand" "=<VSr2>,?<VSr3>")
717         (fix:<VSI> (match_operand:VSX_B 1 "gpc_reg_operand" "<VSr>,wa")))]
718   "VECTOR_UNIT_VSX_P (<MODE>mode)"
719   "x<VSv>cv<VSs>sx<VSc>s %x0,%x1"
720   [(set_attr "type" "<VStype_simple>")
721    (set_attr "fp_type" "<VSfptype_simple>")])
723 (define_insn "vsx_fixuns_trunc<mode><VSi>2"
724   [(set (match_operand:<VSI> 0 "gpc_reg_operand" "=<VSr2>,?<VSr3>")
725         (unsigned_fix:<VSI> (match_operand:VSX_B 1 "gpc_reg_operand" "<VSr>,wa")))]
726   "VECTOR_UNIT_VSX_P (<MODE>mode)"
727   "x<VSv>cv<VSs>ux<VSc>s %x0,%x1"
728   [(set_attr "type" "<VStype_simple>")
729    (set_attr "fp_type" "<VSfptype_simple>")])
731 ;; Math rounding functions
732 (define_insn "vsx_x<VSv>r<VSs>i"
733   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
734         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
735                       UNSPEC_VSX_ROUND_I))]
736   "VECTOR_UNIT_VSX_P (<MODE>mode)"
737   "x<VSv>r<VSs>i %x0,%x1"
738   [(set_attr "type" "<VStype_simple>")
739    (set_attr "fp_type" "<VSfptype_simple>")])
741 (define_insn "vsx_x<VSv>r<VSs>ic"
742   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
743         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
744                       UNSPEC_VSX_ROUND_IC))]
745   "VECTOR_UNIT_VSX_P (<MODE>mode)"
746   "x<VSv>r<VSs>ic %x0,%x1"
747   [(set_attr "type" "<VStype_simple>")
748    (set_attr "fp_type" "<VSfptype_simple>")])
750 (define_insn "vsx_btrunc<mode>2"
751   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
752         (fix:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
753   "VECTOR_UNIT_VSX_P (<MODE>mode)"
754   "x<VSv>r<VSs>iz %x0,%x1"
755   [(set_attr "type" "<VStype_simple>")
756    (set_attr "fp_type" "<VSfptype_simple>")])
758 (define_insn "*vsx_b2trunc<mode>2"
759   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
760         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
761                       UNSPEC_FRIZ))]
762   "VECTOR_UNIT_VSX_P (<MODE>mode)"
763   "x<VSv>r<VSs>iz %x0,%x1"
764   [(set_attr "type" "<VStype_simple>")
765    (set_attr "fp_type" "<VSfptype_simple>")])
767 (define_insn "vsx_floor<mode>2"
768   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
769         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
770                       UNSPEC_FRIM))]
771   "VECTOR_UNIT_VSX_P (<MODE>mode)"
772   "x<VSv>r<VSs>im %x0,%x1"
773   [(set_attr "type" "<VStype_simple>")
774    (set_attr "fp_type" "<VSfptype_simple>")])
776 (define_insn "vsx_ceil<mode>2"
777   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
778         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
779                       UNSPEC_FRIP))]
780   "VECTOR_UNIT_VSX_P (<MODE>mode)"
781   "x<VSv>r<VSs>ip %x0,%x1"
782   [(set_attr "type" "<VStype_simple>")
783    (set_attr "fp_type" "<VSfptype_simple>")])
786 ;; VSX convert to/from double vector
788 ;; Convert between single and double precision
789 ;; Don't use xscvspdp and xscvdpsp for scalar conversions, since the normal
790 ;; scalar single precision instructions internally use the double format.
791 ;; Prefer the altivec registers, since we likely will need to do a vperm
792 (define_insn "vsx_<VS_spdp_insn>"
793   [(set (match_operand:<VS_spdp_res> 0 "vsx_register_operand" "=<VSr4>,?wa")
794         (unspec:<VS_spdp_res> [(match_operand:VSX_SPDP 1 "vsx_register_operand" "<VSr5>,wa")]
795                               UNSPEC_VSX_CVSPDP))]
796   "VECTOR_UNIT_VSX_P (<MODE>mode)"
797   "<VS_spdp_insn> %x0,%x1"
798   [(set_attr "type" "<VS_spdp_type>")])
800 ;; xscvspdp, represent the scalar SF type as V4SF
801 (define_insn "vsx_xscvspdp"
802   [(set (match_operand:DF 0 "vsx_register_operand" "=ws,?wa")
803         (unspec:DF [(match_operand:V4SF 1 "vsx_register_operand" "wa,wa")]
804                    UNSPEC_VSX_CVSPDP))]
805   "VECTOR_UNIT_VSX_P (DFmode)"
806   "xscvspdp %x0,%x1"
807   [(set_attr "type" "fp")])
809 ;; xscvdpsp used for splat'ing a scalar to V4SF, knowing that the internal SF
810 ;; format of scalars is actually DF.
811 (define_insn "vsx_xscvdpsp_scalar"
812   [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
813         (unspec:V4SF [(match_operand:SF 1 "vsx_register_operand" "f")]
814                      UNSPEC_VSX_CVSPDP))]
815   "VECTOR_UNIT_VSX_P (DFmode)"
816   "xscvdpsp %x0,%x1"
817   [(set_attr "type" "fp")])
819 ;; Convert from 64-bit to 32-bit types
820 ;; Note, favor the Altivec registers since the usual use of these instructions
821 ;; is in vector converts and we need to use the Altivec vperm instruction.
823 (define_insn "vsx_xvcvdpsxws"
824   [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
825         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
826                      UNSPEC_VSX_CVDPSXWS))]
827   "VECTOR_UNIT_VSX_P (V2DFmode)"
828   "xvcvdpsxws %x0,%x1"
829   [(set_attr "type" "vecfloat")])
831 (define_insn "vsx_xvcvdpuxws"
832   [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
833         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
834                      UNSPEC_VSX_CVDPUXWS))]
835   "VECTOR_UNIT_VSX_P (V2DFmode)"
836   "xvcvdpuxws %x0,%x1"
837   [(set_attr "type" "vecfloat")])
839 (define_insn "vsx_xvcvsxdsp"
840   [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
841         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
842                      UNSPEC_VSX_CVSXDSP))]
843   "VECTOR_UNIT_VSX_P (V2DFmode)"
844   "xvcvsxdsp %x0,%x1"
845   [(set_attr "type" "vecfloat")])
847 (define_insn "vsx_xvcvuxdsp"
848   [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
849         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
850                      UNSPEC_VSX_CVUXDSP))]
851   "VECTOR_UNIT_VSX_P (V2DFmode)"
852   "xvcvuxwdp %x0,%x1"
853   [(set_attr "type" "vecfloat")])
855 ;; Convert from 32-bit to 64-bit types
856 (define_insn "vsx_xvcvsxwdp"
857   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
858         (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
859                      UNSPEC_VSX_CVSXWDP))]
860   "VECTOR_UNIT_VSX_P (V2DFmode)"
861   "xvcvsxwdp %x0,%x1"
862   [(set_attr "type" "vecfloat")])
864 (define_insn "vsx_xvcvuxwdp"
865   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
866         (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
867                      UNSPEC_VSX_CVUXWDP))]
868   "VECTOR_UNIT_VSX_P (V2DFmode)"
869   "xvcvuxwdp %x0,%x1"
870   [(set_attr "type" "vecfloat")])
872 (define_insn "vsx_xvcvspsxds"
873   [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
874         (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
875                      UNSPEC_VSX_CVSPSXDS))]
876   "VECTOR_UNIT_VSX_P (V2DFmode)"
877   "xvcvspsxds %x0,%x1"
878   [(set_attr "type" "vecfloat")])
880 (define_insn "vsx_xvcvspuxds"
881   [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
882         (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
883                      UNSPEC_VSX_CVSPUXDS))]
884   "VECTOR_UNIT_VSX_P (V2DFmode)"
885   "xvcvspuxds %x0,%x1"
886   [(set_attr "type" "vecfloat")])
888 ;; Only optimize (float (fix x)) -> frz if we are in fast-math mode, since
889 ;; since the xsrdpiz instruction does not truncate the value if the floating
890 ;; point value is < LONG_MIN or > LONG_MAX.
891 (define_insn "*vsx_float_fix_<mode>2"
892   [(set (match_operand:VSX_DF 0 "vsx_register_operand" "=<VSr>,?wa")
893         (float:VSX_DF
894          (fix:<VSI>
895           (match_operand:VSX_DF 1 "vsx_register_operand" "<VSr>,?wa"))))]
896   "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
897    && VECTOR_UNIT_VSX_P (<MODE>mode) && flag_unsafe_math_optimizations
898    && !flag_trapping_math && TARGET_FRIZ"
899   "x<VSv>r<VSs>iz %x0,%x1"
900   [(set_attr "type" "<VStype_simple>")
901    (set_attr "fp_type" "<VSfptype_simple>")])
904 ;; Logical and permute operations
905 (define_insn "*vsx_and<mode>3"
906   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
907         (and:VSX_L
908          (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
909          (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
910   "VECTOR_MEM_VSX_P (<MODE>mode)"
911   "xxland %x0,%x1,%x2"
912   [(set_attr "type" "vecsimple")])
914 (define_insn "*vsx_ior<mode>3"
915   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
916         (ior:VSX_L (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
917                    (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
918   "VECTOR_MEM_VSX_P (<MODE>mode)"
919   "xxlor %x0,%x1,%x2"
920   [(set_attr "type" "vecsimple")])
922 (define_insn "*vsx_xor<mode>3"
923   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
924         (xor:VSX_L
925          (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
926          (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
927   "VECTOR_MEM_VSX_P (<MODE>mode)"
928   "xxlxor %x0,%x1,%x2"
929   [(set_attr "type" "vecsimple")])
931 (define_insn "*vsx_one_cmpl<mode>2"
932   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
933         (not:VSX_L
934          (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")))]
935   "VECTOR_MEM_VSX_P (<MODE>mode)"
936   "xxlnor %x0,%x1,%x1"
937   [(set_attr "type" "vecsimple")])
938   
939 (define_insn "*vsx_nor<mode>3"
940   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
941         (not:VSX_L
942          (ior:VSX_L
943           (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
944           (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa"))))]
945   "VECTOR_MEM_VSX_P (<MODE>mode)"
946   "xxlnor %x0,%x1,%x2"
947   [(set_attr "type" "vecsimple")])
949 (define_insn "*vsx_andc<mode>3"
950   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
951         (and:VSX_L
952          (not:VSX_L
953           (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa"))
954          (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")))]
955   "VECTOR_MEM_VSX_P (<MODE>mode)"
956   "xxlandc %x0,%x1,%x2"
957   [(set_attr "type" "vecsimple")])
960 ;; Permute operations
962 ;; Build a V2DF/V2DI vector from two scalars
963 (define_insn "vsx_concat_<mode>"
964   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
965         (unspec:VSX_D
966          [(match_operand:<VS_scalar> 1 "vsx_register_operand" "ws,wa")
967           (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")]
968          UNSPEC_VSX_CONCAT))]
969   "VECTOR_MEM_VSX_P (<MODE>mode)"
970   "xxpermdi %x0,%x1,%x2,0"
971   [(set_attr "type" "vecperm")])
973 ;; Special purpose concat using xxpermdi to glue two single precision values
974 ;; together, relying on the fact that internally scalar floats are represented
975 ;; as doubles.  This is used to initialize a V4SF vector with 4 floats
976 (define_insn "vsx_concat_v2sf"
977   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
978         (unspec:V2DF
979          [(match_operand:SF 1 "vsx_register_operand" "f,f")
980           (match_operand:SF 2 "vsx_register_operand" "f,f")]
981          UNSPEC_VSX_CONCAT))]
982   "VECTOR_MEM_VSX_P (V2DFmode)"
983   "xxpermdi %x0,%x1,%x2,0"
984   [(set_attr "type" "vecperm")])
986 ;; Set the element of a V2DI/VD2F mode
987 (define_insn "vsx_set_<mode>"
988   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
989         (unspec:VSX_D [(match_operand:VSX_D 1 "vsx_register_operand" "wd,wa")
990                        (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")
991                        (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
992                       UNSPEC_VSX_SET))]
993   "VECTOR_MEM_VSX_P (<MODE>mode)"
995   if (INTVAL (operands[3]) == 0)
996     return \"xxpermdi %x0,%x1,%x2,1\";
997   else if (INTVAL (operands[3]) == 1)
998     return \"xxpermdi %x0,%x2,%x1,0\";
999   else
1000     gcc_unreachable ();
1002   [(set_attr "type" "vecperm")])
1004 ;; Extract a DF/DI element from V2DF/V2DI
1005 (define_insn "vsx_extract_<mode>"
1006   [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,d,?wa")
1007         (vec_select:<VS_scalar> (match_operand:VSX_D 1 "vsx_register_operand" "wd,wd,wa")
1008                        (parallel
1009                         [(match_operand:QI 2 "u5bit_cint_operand" "i,i,i")])))]
1010   "VECTOR_MEM_VSX_P (<MODE>mode)"
1012   gcc_assert (UINTVAL (operands[2]) <= 1);
1013   operands[3] = GEN_INT (INTVAL (operands[2]) << 1);
1014   return \"xxpermdi %x0,%x1,%x1,%3\";
1016   [(set_attr "type" "vecperm")])
1018 ;; Optimize extracting element 0 from memory
1019 (define_insn "*vsx_extract_<mode>_zero"
1020   [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,d,?wa")
1021         (vec_select:<VS_scalar>
1022          (match_operand:VSX_D 1 "indexed_or_indirect_operand" "Z,Z,Z")
1023          (parallel [(const_int 0)])))]
1024   "VECTOR_MEM_VSX_P (<MODE>mode) && WORDS_BIG_ENDIAN"
1025   "lxsd%U1x %x0,%y1"
1026   [(set_attr "type" "fpload")
1027    (set_attr "length" "4")])  
1029 ;; General double word oriented permute, allow the other vector types for
1030 ;; optimizing the permute instruction.
1031 (define_insn "vsx_xxpermdi_<mode>"
1032   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=wd,?wa")
1033         (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "wd,wa")
1034                        (match_operand:VSX_L 2 "vsx_register_operand" "wd,wa")
1035                        (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
1036                       UNSPEC_VSX_XXPERMDI))]
1037   "VECTOR_MEM_VSX_P (<MODE>mode)"
1038   "xxpermdi %x0,%x1,%x2,%3"
1039   [(set_attr "type" "vecperm")])
1041 ;; Varient of xxpermdi that is emitted by the vec_interleave functions
1042 (define_insn "*vsx_xxpermdi2_<mode>"
1043   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd")
1044         (vec_concat:VSX_D
1045          (vec_select:<VS_scalar>
1046           (match_operand:VSX_D 1 "vsx_register_operand" "wd")
1047           (parallel
1048            [(match_operand:QI 2 "u5bit_cint_operand" "i")]))
1049          (vec_select:<VS_scalar>
1050           (match_operand:VSX_D 3 "vsx_register_operand" "wd")
1051           (parallel
1052            [(match_operand:QI 4 "u5bit_cint_operand" "i")]))))]
1053   "VECTOR_MEM_VSX_P (<MODE>mode)"
1055   gcc_assert ((UINTVAL (operands[2]) <= 1) && (UINTVAL (operands[4]) <= 1));
1056   operands[5] = GEN_INT (((INTVAL (operands[2]) & 1) << 1)
1057                          | (INTVAL (operands[4]) & 1));
1058   return \"xxpermdi %x0,%x1,%x3,%5\";
1060   [(set_attr "type" "vecperm")])
1062 ;; V2DF/V2DI splat
1063 (define_insn "vsx_splat_<mode>"
1064   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,wd,wd,?wa,?wa,?wa")
1065         (vec_duplicate:VSX_D
1066          (match_operand:<VS_scalar> 1 "input_operand" "ws,f,Z,wa,wa,Z")))]
1067   "VECTOR_MEM_VSX_P (<MODE>mode)"
1068   "@
1069    xxpermdi %x0,%x1,%x1,0
1070    xxpermdi %x0,%x1,%x1,0
1071    lxvdsx %x0,%y1
1072    xxpermdi %x0,%x1,%x1,0
1073    xxpermdi %x0,%x1,%x1,0
1074    lxvdsx %x0,%y1"
1075   [(set_attr "type" "vecperm,vecperm,vecload,vecperm,vecperm,vecload")])
1077 ;; V4SF/V4SI splat
1078 (define_insn "vsx_xxspltw_<mode>"
1079   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1080         (vec_duplicate:VSX_W
1081          (vec_select:<VS_scalar>
1082           (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1083           (parallel
1084            [(match_operand:QI 2 "u5bit_cint_operand" "i,i")]))))]
1085   "VECTOR_MEM_VSX_P (<MODE>mode)"
1086   "xxspltw %x0,%x1,%2"
1087   [(set_attr "type" "vecperm")])
1089 ;; V4SF/V4SI interleave
1090 (define_insn "vsx_xxmrghw_<mode>"
1091   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1092         (vec_merge:VSX_W
1093          (vec_select:VSX_W
1094           (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1095           (parallel [(const_int 0)
1096                      (const_int 2)
1097                      (const_int 1)
1098                      (const_int 3)]))
1099          (vec_select:VSX_W
1100           (match_operand:VSX_W 2 "vsx_register_operand" "wf,wa")
1101           (parallel [(const_int 2)
1102                      (const_int 0)
1103                      (const_int 3)
1104                      (const_int 1)]))
1105          (const_int 5)))]
1106   "VECTOR_MEM_VSX_P (<MODE>mode)"
1107   "xxmrghw %x0,%x1,%x2"
1108   [(set_attr "type" "vecperm")])
1110 (define_insn "vsx_xxmrglw_<mode>"
1111   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1112         (vec_merge:VSX_W
1113          (vec_select:VSX_W
1114           (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1115           (parallel [(const_int 2)
1116                      (const_int 0)
1117                      (const_int 3)
1118                      (const_int 1)]))
1119          (vec_select:VSX_W
1120           (match_operand:VSX_W 2 "vsx_register_operand" "wf,?wa")
1121           (parallel [(const_int 0)
1122                      (const_int 2)
1123                      (const_int 1)
1124                      (const_int 3)]))
1125          (const_int 5)))]
1126   "VECTOR_MEM_VSX_P (<MODE>mode)"
1127   "xxmrglw %x0,%x1,%x2"
1128   [(set_attr "type" "vecperm")])
1130 ;; Shift left double by word immediate
1131 (define_insn "vsx_xxsldwi_<mode>"
1132   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=wa")
1133         (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "wa")
1134                        (match_operand:VSX_L 2 "vsx_register_operand" "wa")
1135                        (match_operand:QI 3 "u5bit_cint_operand" "i")]
1136                       UNSPEC_VSX_SLDWI))]
1137   "VECTOR_MEM_VSX_P (<MODE>mode)"
1138   "xxsldwi %x0,%x1,%x2,%3"
1139   [(set_attr "type" "vecperm")])