OSDN Git Service

PR target/45844
[pf3gnuchains/gcc-fork.git] / gcc / config / rs6000 / vsx.md
1 ;; VSX patterns.
2 ;; Copyright (C) 2009, 2010, 2011
3 ;; Free Software Foundation, Inc.
4 ;; Contributed by Michael Meissner <meissner@linux.vnet.ibm.com>
5
6 ;; This file is part of GCC.
7
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.
12
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.
17
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/>.
21
22 ;; Iterator for both scalar and vector floating point types supported by VSX
23 (define_mode_iterator VSX_B [DF V4SF V2DF])
24
25 ;; Iterator for the 2 64-bit vector types
26 (define_mode_iterator VSX_D [V2DF V2DI])
27
28 ;; Iterator for the 2 32-bit vector types
29 (define_mode_iterator VSX_W [V4SF V4SI])
30
31 ;; Iterator for the DF types
32 (define_mode_iterator VSX_DF [V2DF DF])
33
34 ;; Iterator for vector floating point types supported by VSX
35 (define_mode_iterator VSX_F [V4SF V2DF])
36
37 ;; Iterator for logical types supported by VSX
38 (define_mode_iterator VSX_L [V16QI V8HI V4SI V2DI V4SF V2DF TI])
39
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])
43
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")])
53
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")])
64
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")])
75
76 ;; Map the register class used for float<->int conversions
77 (define_mode_attr VSr2  [(V2DF  "wd")
78                          (V4SF  "wf")
79                          (DF    "ws")])
80
81 (define_mode_attr VSr3  [(V2DF  "wa")
82                          (V4SF  "wa")
83                          (DF    "ws")])
84
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")])
90
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")])
96
97 ;; Same size integer type for floating point data
98 (define_mode_attr VSi [(V4SF  "v4si")
99                        (V2DF  "v2di")
100                        (DF    "di")])
101
102 (define_mode_attr VSI [(V4SF  "V4SI")
103                        (V2DF  "V2DI")
104                        (DF    "DI")])
105
106 ;; Word size for same size conversion
107 (define_mode_attr VSc [(V4SF "w")
108                        (V2DF "d")
109                        (DF   "d")])
110
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")])
121
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")])
126
127 (define_mode_attr VSfptype_simple [(V2DF "fp_addsub_d")
128                                    (V4SF "fp_addsub_s")
129                                    (DF   "fp_addsub_d")])
130
131 ;; Appropriate type for multiply ops
132 (define_mode_attr VStype_mul    [(V2DF "vecfloat")
133                                  (V4SF "vecfloat")
134                                  (DF   "dmul")])
135
136 (define_mode_attr VSfptype_mul  [(V2DF "fp_mul_d")
137                                  (V4SF "fp_mul_s")
138                                  (DF   "fp_mul_d")])
139
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")])
145
146 (define_mode_attr VSfptype_div  [(V2DF "fp_div_d")
147                                  (V4SF "fp_div_s")
148                                  (DF   "fp_div_d")])
149
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")])
155
156 (define_mode_attr VSfptype_sqrt [(V2DF "fp_sqrt_d")
157                                  (V4SF "fp_sqrt_s")
158                                  (DF   "fp_sqrt_d")])
159
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])
164
165 (define_mode_attr VS_spdp_res [(DF      "V4SF")
166                                (V4SF    "V2DF")
167                                (V2DF    "V4SF")])
168
169 (define_mode_attr VS_spdp_insn [(DF     "xscvdpsp")
170                                 (V4SF   "xvcvspdp")
171                                 (V2DF   "xvcvdpsp")])
172
173 (define_mode_attr VS_spdp_type [(DF     "fp")
174                                 (V4SF   "vecfloat")
175                                 (V2DF   "vecfloat")])
176
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)])
205
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))"
213 {
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";
223
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";
231
232     case 2:
233     case 5:
234       return "xxlor %x0,%x1,%x1";
235
236     case 6:
237     case 7:
238     case 8:
239       return "#";
240
241     case 9:
242     case 10:
243       return "xxlxor %x0,%x0,%x0";
244
245     case 11:
246       return output_vec_const_move (operands);
247
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";
254
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";
261
262     default:
263       gcc_unreachable ();
264     }
265 }
266   [(set_attr "type" "vecstore,vecload,vecsimple,vecstore,vecload,vecsimple,*,*,*,vecsimple,vecsimple,*,vecstore,vecload")])
267
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))"
276 {
277   switch (which_alternative)
278     {
279     case 0:
280       return "stxvd2x %x1,%y0";
281
282     case 1:
283       return "lxvd2x %x0,%y1";
284
285     case 2:
286       return "xxlor %x0,%x1,%x1";
287
288     case 3:
289     case 4:
290     case 5:
291       return "#";
292
293     case 6:
294       return "xxlxor %x0,%x0,%x0";
295
296     case 7:
297       return output_vec_const_move (operands);
298
299     case 8:
300       return "stvx %1,%y0";
301
302     case 9:
303       return "lvx %0,%y1";
304
305     default:
306       gcc_unreachable ();
307     }
308 }
309   [(set_attr "type" "vecstore,vecload,vecsimple,*,*,*,vecsimple,*,vecstore,vecload")])
310
311 ;; Explicit  load/store expanders for the builtin functions
312 (define_expand "vsx_load_<mode>"
313   [(set (match_operand:VSX_M 0 "vsx_register_operand" "")
314         (match_operand:VSX_M 1 "memory_operand" ""))]
315   "VECTOR_MEM_VSX_P (<MODE>mode)"
316   "")
317
318 (define_expand "vsx_store_<mode>"
319   [(set (match_operand:VEC_M 0 "memory_operand" "")
320         (match_operand:VEC_M 1 "vsx_register_operand" ""))]
321   "VECTOR_MEM_VSX_P (<MODE>mode)"
322   "")
323
324 \f
325 ;; VSX scalar and vector floating point arithmetic instructions
326 (define_insn "*vsx_add<mode>3"
327   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
328         (plus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
329                     (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
330   "VECTOR_UNIT_VSX_P (<MODE>mode)"
331   "x<VSv>add<VSs> %x0,%x1,%x2"
332   [(set_attr "type" "<VStype_simple>")
333    (set_attr "fp_type" "<VSfptype_simple>")])
334
335 (define_insn "*vsx_sub<mode>3"
336   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
337         (minus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
338                      (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
339   "VECTOR_UNIT_VSX_P (<MODE>mode)"
340   "x<VSv>sub<VSs> %x0,%x1,%x2"
341   [(set_attr "type" "<VStype_simple>")
342    (set_attr "fp_type" "<VSfptype_simple>")])
343
344 (define_insn "*vsx_mul<mode>3"
345   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
346         (mult:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
347                     (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
348   "VECTOR_UNIT_VSX_P (<MODE>mode)"
349   "x<VSv>mul<VSs> %x0,%x1,%x2"
350   [(set_attr "type" "<VStype_mul>")
351    (set_attr "fp_type" "<VSfptype_mul>")])
352
353 (define_insn "*vsx_div<mode>3"
354   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
355         (div:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
356                    (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
357   "VECTOR_UNIT_VSX_P (<MODE>mode)"
358   "x<VSv>div<VSs> %x0,%x1,%x2"
359   [(set_attr "type" "<VStype_div>")
360    (set_attr "fp_type" "<VSfptype_div>")])
361
362 ;; *tdiv* instruction returning the FG flag
363 (define_expand "vsx_tdiv<mode>3_fg"
364   [(set (match_dup 3)
365         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
366                       (match_operand:VSX_B 2 "vsx_register_operand" "")]
367                      UNSPEC_VSX_TDIV))
368    (set (match_operand:SI 0 "gpc_reg_operand" "")
369         (gt:SI (match_dup 3)
370                (const_int 0)))]
371   "VECTOR_UNIT_VSX_P (<MODE>mode)"
372 {
373   operands[3] = gen_reg_rtx (CCFPmode);
374 })
375
376 ;; *tdiv* instruction returning the FE flag
377 (define_expand "vsx_tdiv<mode>3_fe"
378   [(set (match_dup 3)
379         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
380                       (match_operand:VSX_B 2 "vsx_register_operand" "")]
381                      UNSPEC_VSX_TDIV))
382    (set (match_operand:SI 0 "gpc_reg_operand" "")
383         (eq:SI (match_dup 3)
384                (const_int 0)))]
385   "VECTOR_UNIT_VSX_P (<MODE>mode)"
386 {
387   operands[3] = gen_reg_rtx (CCFPmode);
388 })
389
390 (define_insn "*vsx_tdiv<mode>3_internal"
391   [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
392         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
393                       (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")]
394                    UNSPEC_VSX_TDIV))]
395   "VECTOR_UNIT_VSX_P (<MODE>mode)"
396   "x<VSv>tdiv<VSs> %0,%x1,%x2"
397   [(set_attr "type" "<VStype_simple>")
398    (set_attr "fp_type" "<VSfptype_simple>")])
399
400 (define_insn "vsx_fre<mode>2"
401   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
402         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
403                       UNSPEC_FRES))]
404   "VECTOR_UNIT_VSX_P (<MODE>mode)"
405   "x<VSv>re<VSs> %x0,%x1"
406   [(set_attr "type" "<VStype_simple>")
407    (set_attr "fp_type" "<VSfptype_simple>")])
408
409 (define_insn "*vsx_neg<mode>2"
410   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
411         (neg:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
412   "VECTOR_UNIT_VSX_P (<MODE>mode)"
413   "x<VSv>neg<VSs> %x0,%x1"
414   [(set_attr "type" "<VStype_simple>")
415    (set_attr "fp_type" "<VSfptype_simple>")])
416
417 (define_insn "*vsx_abs<mode>2"
418   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
419         (abs:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
420   "VECTOR_UNIT_VSX_P (<MODE>mode)"
421   "x<VSv>abs<VSs> %x0,%x1"
422   [(set_attr "type" "<VStype_simple>")
423    (set_attr "fp_type" "<VSfptype_simple>")])
424
425 (define_insn "vsx_nabs<mode>2"
426   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
427         (neg:VSX_B
428          (abs:VSX_B
429           (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa"))))]
430   "VECTOR_UNIT_VSX_P (<MODE>mode)"
431   "x<VSv>nabs<VSs> %x0,%x1"
432   [(set_attr "type" "<VStype_simple>")
433    (set_attr "fp_type" "<VSfptype_simple>")])
434
435 (define_insn "vsx_smax<mode>3"
436   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
437         (smax:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
438                     (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
439   "VECTOR_UNIT_VSX_P (<MODE>mode)"
440   "x<VSv>max<VSs> %x0,%x1,%x2"
441   [(set_attr "type" "<VStype_simple>")
442    (set_attr "fp_type" "<VSfptype_simple>")])
443
444 (define_insn "*vsx_smin<mode>3"
445   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
446         (smin:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
447                     (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
448   "VECTOR_UNIT_VSX_P (<MODE>mode)"
449   "x<VSv>min<VSs> %x0,%x1,%x2"
450   [(set_attr "type" "<VStype_simple>")
451    (set_attr "fp_type" "<VSfptype_simple>")])
452
453 ;; Special VSX version of smin/smax for single precision floating point.  Since
454 ;; both numbers are rounded to single precision, we can just use the DP version
455 ;; of the instruction.
456
457 (define_insn "*vsx_smaxsf3"
458   [(set (match_operand:SF 0 "vsx_register_operand" "=f")
459         (smax:SF (match_operand:SF 1 "vsx_register_operand" "f")
460                  (match_operand:SF 2 "vsx_register_operand" "f")))]
461   "VECTOR_UNIT_VSX_P (DFmode)"
462   "xsmaxdp %x0,%x1,%x2"
463   [(set_attr "type" "fp")
464    (set_attr "fp_type" "fp_addsub_d")])
465
466 (define_insn "*vsx_sminsf3"
467   [(set (match_operand:SF 0 "vsx_register_operand" "=f")
468         (smin:SF (match_operand:SF 1 "vsx_register_operand" "f")
469                  (match_operand:SF 2 "vsx_register_operand" "f")))]
470   "VECTOR_UNIT_VSX_P (DFmode)"
471   "xsmindp %x0,%x1,%x2"
472   [(set_attr "type" "fp")
473    (set_attr "fp_type" "fp_addsub_d")])
474
475 (define_insn "*vsx_sqrt<mode>2"
476   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
477         (sqrt:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
478   "VECTOR_UNIT_VSX_P (<MODE>mode)"
479   "x<VSv>sqrt<VSs> %x0,%x1"
480   [(set_attr "type" "<VStype_sqrt>")
481    (set_attr "fp_type" "<VSfptype_sqrt>")])
482
483 (define_insn "*vsx_rsqrte<mode>2"
484   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
485         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
486                       UNSPEC_RSQRT))]
487   "VECTOR_UNIT_VSX_P (<MODE>mode)"
488   "x<VSv>rsqrte<VSs> %x0,%x1"
489   [(set_attr "type" "<VStype_simple>")
490    (set_attr "fp_type" "<VSfptype_simple>")])
491
492 ;; *tsqrt* returning the fg flag
493 (define_expand "vsx_tsqrt<mode>2_fg"
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         (gt:SI (match_dup 3)
499                (const_int 0)))]
500   "VECTOR_UNIT_VSX_P (<MODE>mode)"
501 {
502   operands[3] = gen_reg_rtx (CCFPmode);
503 })
504
505 ;; *tsqrt* returning the fe flag
506 (define_expand "vsx_tsqrt<mode>2_fe"
507   [(set (match_dup 3)
508         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
509                      UNSPEC_VSX_TSQRT))
510    (set (match_operand:SI 0 "gpc_reg_operand" "")
511         (eq:SI (match_dup 3)
512                (const_int 0)))]
513   "VECTOR_UNIT_VSX_P (<MODE>mode)"
514 {
515   operands[3] = gen_reg_rtx (CCFPmode);
516 })
517
518 (define_insn "*vsx_tsqrt<mode>2_internal"
519   [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
520         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
521                      UNSPEC_VSX_TSQRT))]
522   "VECTOR_UNIT_VSX_P (<MODE>mode)"
523   "x<VSv>tsqrt<VSs> %0,%x1"
524   [(set_attr "type" "<VStype_simple>")
525    (set_attr "fp_type" "<VSfptype_simple>")])
526
527 ;; Fused vector multiply/add instructions
528
529 (define_insn "*vsx_fma<mode>4"
530   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
531         (fma:VSX_B
532           (match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
533           (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
534           (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")))]
535   "VECTOR_UNIT_VSX_P (<MODE>mode)"
536   "@
537    x<VSv>madda<VSs> %x0,%x1,%x2
538    x<VSv>maddm<VSs> %x0,%x1,%x3
539    x<VSv>madda<VSs> %x0,%x1,%x2
540    x<VSv>maddm<VSs> %x0,%x1,%x3"
541   [(set_attr "type" "<VStype_mul>")
542    (set_attr "fp_type" "<VSfptype_mul>")])
543
544 (define_insn "*vsx_fms<mode>4"
545   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
546         (fma:VSX_B
547           (match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
548           (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
549           (neg:VSX_B
550             (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
551   "VECTOR_UNIT_VSX_P (<MODE>mode)"
552   "@
553    x<VSv>msuba<VSs> %x0,%x1,%x2
554    x<VSv>msubm<VSs> %x0,%x1,%x3
555    x<VSv>msuba<VSs> %x0,%x1,%x2
556    x<VSv>msubm<VSs> %x0,%x1,%x3"
557   [(set_attr "type" "<VStype_mul>")
558    (set_attr "fp_type" "<VSfptype_mul>")])
559
560 (define_insn "*vsx_nfma<mode>4"
561   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
562         (neg:VSX_B
563          (fma:VSX_B
564           (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSr>,wa,wa")
565           (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
566           (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
567   "VECTOR_UNIT_VSX_P (<MODE>mode)"
568   "@
569    x<VSv>nmadda<VSs> %x0,%x1,%x2
570    x<VSv>nmaddm<VSs> %x0,%x1,%x3
571    x<VSv>nmadda<VSs> %x0,%x1,%x2
572    x<VSv>nmaddm<VSs> %x0,%x1,%x3"
573   [(set_attr "type" "<VStype_mul>")
574    (set_attr "fp_type" "<VSfptype_mul>")])
575
576 (define_insn "*vsx_nfms<mode>4"
577   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
578         (neg:VSX_B
579          (fma:VSX_B
580            (match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
581            (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
582            (neg:VSX_B
583              (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")))))]
584   "VECTOR_UNIT_VSX_P (<MODE>mode)"
585   "@
586    x<VSv>nmsuba<VSs> %x0,%x1,%x2
587    x<VSv>nmsubm<VSs> %x0,%x1,%x3
588    x<VSv>nmsuba<VSs> %x0,%x1,%x2
589    x<VSv>nmsubm<VSs> %x0,%x1,%x3"
590   [(set_attr "type" "<VStype_mul>")
591    (set_attr "fp_type" "<VSfptype_mul>")])
592
593 ;; Vector conditional expressions (no scalar version for these instructions)
594 (define_insn "vsx_eq<mode>"
595   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
596         (eq:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
597                   (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
598   "VECTOR_UNIT_VSX_P (<MODE>mode)"
599   "xvcmpeq<VSs> %x0,%x1,%x2"
600   [(set_attr "type" "<VStype_simple>")
601    (set_attr "fp_type" "<VSfptype_simple>")])
602
603 (define_insn "vsx_gt<mode>"
604   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
605         (gt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
606                   (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
607   "VECTOR_UNIT_VSX_P (<MODE>mode)"
608   "xvcmpgt<VSs> %x0,%x1,%x2"
609   [(set_attr "type" "<VStype_simple>")
610    (set_attr "fp_type" "<VSfptype_simple>")])
611
612 (define_insn "*vsx_ge<mode>"
613   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
614         (ge:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
615                   (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
616   "VECTOR_UNIT_VSX_P (<MODE>mode)"
617   "xvcmpge<VSs> %x0,%x1,%x2"
618   [(set_attr "type" "<VStype_simple>")
619    (set_attr "fp_type" "<VSfptype_simple>")])
620
621 ;; Floating point scalar compare
622 (define_insn "*vsx_cmpdf_internal1"
623   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y,?y")
624         (compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "ws,wa")
625                       (match_operand:DF 2 "gpc_reg_operand" "ws,wa")))]
626   "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
627    && VECTOR_UNIT_VSX_P (DFmode)"
628   "xscmpudp %0,%x1,%x2"
629   [(set_attr "type" "fpcompare")])
630
631 ;; Compare vectors producing a vector result and a predicate, setting CR6 to
632 ;; indicate a combined status
633 (define_insn "*vsx_eq_<mode>_p"
634   [(set (reg:CC 74)
635         (unspec:CC
636          [(eq: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         (eq:VSX_F (match_dup 1)
641                   (match_dup 2)))]
642   "VECTOR_UNIT_VSX_P (<MODE>mode)"
643   "xvcmpeq<VSs>. %x0,%x1,%x2"
644   [(set_attr "type" "veccmp")])
645
646 (define_insn "*vsx_gt_<mode>_p"
647   [(set (reg:CC 74)
648         (unspec:CC
649          [(gt: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         (gt:VSX_F (match_dup 1)
654                   (match_dup 2)))]
655   "VECTOR_UNIT_VSX_P (<MODE>mode)"
656   "xvcmpgt<VSs>. %x0,%x1,%x2"
657   [(set_attr "type" "veccmp")])
658
659 (define_insn "*vsx_ge_<mode>_p"
660   [(set (reg:CC 74)
661         (unspec:CC
662          [(ge:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
663                  (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
664          UNSPEC_PREDICATE))
665    (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
666         (ge:VSX_F (match_dup 1)
667                   (match_dup 2)))]
668   "VECTOR_UNIT_VSX_P (<MODE>mode)"
669   "xvcmpge<VSs>. %x0,%x1,%x2"
670   [(set_attr "type" "veccmp")])
671
672 ;; Vector select
673 (define_insn "*vsx_xxsel<mode>"
674   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
675         (if_then_else:VSX_L
676          (ne:CC (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
677                 (const_int 0))
678          (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
679          (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
680   "VECTOR_MEM_VSX_P (<MODE>mode)"
681   "xxsel %x0,%x3,%x2,%x1"
682   [(set_attr "type" "vecperm")])
683
684 (define_insn "*vsx_xxsel<mode>_uns"
685   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
686         (if_then_else:VSX_L
687          (ne:CCUNS (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
688                    (const_int 0))
689          (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
690          (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
691   "VECTOR_MEM_VSX_P (<MODE>mode)"
692   "xxsel %x0,%x3,%x2,%x1"
693   [(set_attr "type" "vecperm")])
694
695 ;; Copy sign
696 (define_insn "vsx_copysign<mode>3"
697   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
698         (unspec:VSX_B
699          [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
700           (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")]
701          UNSPEC_COPYSIGN))]
702   "VECTOR_UNIT_VSX_P (<MODE>mode)"
703   "x<VSv>cpsgn<VSs> %x0,%x2,%x1"
704   [(set_attr "type" "<VStype_simple>")
705    (set_attr "fp_type" "<VSfptype_simple>")])
706
707 ;; For the conversions, limit the register class for the integer value to be
708 ;; the fprs because we don't want to add the altivec registers to movdi/movsi.
709 ;; For the unsigned tests, there isn't a generic double -> unsigned conversion
710 ;; in rs6000.md so don't test VECTOR_UNIT_VSX_P, just test against VSX.
711 ;; Don't use vsx_register_operand here, use gpc_reg_operand to match rs6000.md.
712 (define_insn "vsx_float<VSi><mode>2"
713   [(set (match_operand:VSX_B 0 "gpc_reg_operand" "=<VSr>,?wa")
714         (float:VSX_B (match_operand:<VSI> 1 "gpc_reg_operand" "<VSr2>,<VSr3>")))]
715   "VECTOR_UNIT_VSX_P (<MODE>mode)"
716   "x<VSv>cvsx<VSc><VSs> %x0,%x1"
717   [(set_attr "type" "<VStype_simple>")
718    (set_attr "fp_type" "<VSfptype_simple>")])
719
720 (define_insn "vsx_floatuns<VSi><mode>2"
721   [(set (match_operand:VSX_B 0 "gpc_reg_operand" "=<VSr>,?wa")
722         (unsigned_float:VSX_B (match_operand:<VSI> 1 "gpc_reg_operand" "<VSr2>,<VSr3>")))]
723   "VECTOR_UNIT_VSX_P (<MODE>mode)"
724   "x<VSv>cvux<VSc><VSs> %x0,%x1"
725   [(set_attr "type" "<VStype_simple>")
726    (set_attr "fp_type" "<VSfptype_simple>")])
727
728 (define_insn "vsx_fix_trunc<mode><VSi>2"
729   [(set (match_operand:<VSI> 0 "gpc_reg_operand" "=<VSr2>,?<VSr3>")
730         (fix:<VSI> (match_operand:VSX_B 1 "gpc_reg_operand" "<VSr>,wa")))]
731   "VECTOR_UNIT_VSX_P (<MODE>mode)"
732   "x<VSv>cv<VSs>sx<VSc>s %x0,%x1"
733   [(set_attr "type" "<VStype_simple>")
734    (set_attr "fp_type" "<VSfptype_simple>")])
735
736 (define_insn "vsx_fixuns_trunc<mode><VSi>2"
737   [(set (match_operand:<VSI> 0 "gpc_reg_operand" "=<VSr2>,?<VSr3>")
738         (unsigned_fix:<VSI> (match_operand:VSX_B 1 "gpc_reg_operand" "<VSr>,wa")))]
739   "VECTOR_UNIT_VSX_P (<MODE>mode)"
740   "x<VSv>cv<VSs>ux<VSc>s %x0,%x1"
741   [(set_attr "type" "<VStype_simple>")
742    (set_attr "fp_type" "<VSfptype_simple>")])
743
744 ;; Math rounding functions
745 (define_insn "vsx_x<VSv>r<VSs>i"
746   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
747         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
748                       UNSPEC_VSX_ROUND_I))]
749   "VECTOR_UNIT_VSX_P (<MODE>mode)"
750   "x<VSv>r<VSs>i %x0,%x1"
751   [(set_attr "type" "<VStype_simple>")
752    (set_attr "fp_type" "<VSfptype_simple>")])
753
754 (define_insn "vsx_x<VSv>r<VSs>ic"
755   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
756         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
757                       UNSPEC_VSX_ROUND_IC))]
758   "VECTOR_UNIT_VSX_P (<MODE>mode)"
759   "x<VSv>r<VSs>ic %x0,%x1"
760   [(set_attr "type" "<VStype_simple>")
761    (set_attr "fp_type" "<VSfptype_simple>")])
762
763 (define_insn "vsx_btrunc<mode>2"
764   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
765         (fix:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
766   "VECTOR_UNIT_VSX_P (<MODE>mode)"
767   "x<VSv>r<VSs>iz %x0,%x1"
768   [(set_attr "type" "<VStype_simple>")
769    (set_attr "fp_type" "<VSfptype_simple>")])
770
771 (define_insn "*vsx_b2trunc<mode>2"
772   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
773         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
774                       UNSPEC_FRIZ))]
775   "VECTOR_UNIT_VSX_P (<MODE>mode)"
776   "x<VSv>r<VSs>iz %x0,%x1"
777   [(set_attr "type" "<VStype_simple>")
778    (set_attr "fp_type" "<VSfptype_simple>")])
779
780 (define_insn "vsx_floor<mode>2"
781   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
782         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
783                       UNSPEC_FRIM))]
784   "VECTOR_UNIT_VSX_P (<MODE>mode)"
785   "x<VSv>r<VSs>im %x0,%x1"
786   [(set_attr "type" "<VStype_simple>")
787    (set_attr "fp_type" "<VSfptype_simple>")])
788
789 (define_insn "vsx_ceil<mode>2"
790   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
791         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
792                       UNSPEC_FRIP))]
793   "VECTOR_UNIT_VSX_P (<MODE>mode)"
794   "x<VSv>r<VSs>ip %x0,%x1"
795   [(set_attr "type" "<VStype_simple>")
796    (set_attr "fp_type" "<VSfptype_simple>")])
797
798 \f
799 ;; VSX convert to/from double vector
800
801 ;; Convert between single and double precision
802 ;; Don't use xscvspdp and xscvdpsp for scalar conversions, since the normal
803 ;; scalar single precision instructions internally use the double format.
804 ;; Prefer the altivec registers, since we likely will need to do a vperm
805 (define_insn "vsx_<VS_spdp_insn>"
806   [(set (match_operand:<VS_spdp_res> 0 "vsx_register_operand" "=<VSr4>,?wa")
807         (unspec:<VS_spdp_res> [(match_operand:VSX_SPDP 1 "vsx_register_operand" "<VSr5>,wa")]
808                               UNSPEC_VSX_CVSPDP))]
809   "VECTOR_UNIT_VSX_P (<MODE>mode)"
810   "<VS_spdp_insn> %x0,%x1"
811   [(set_attr "type" "<VS_spdp_type>")])
812
813 ;; xscvspdp, represent the scalar SF type as V4SF
814 (define_insn "vsx_xscvspdp"
815   [(set (match_operand:DF 0 "vsx_register_operand" "=ws,?wa")
816         (unspec:DF [(match_operand:V4SF 1 "vsx_register_operand" "wa,wa")]
817                    UNSPEC_VSX_CVSPDP))]
818   "VECTOR_UNIT_VSX_P (DFmode)"
819   "xscvspdp %x0,%x1"
820   [(set_attr "type" "fp")])
821
822 ;; xscvdpsp used for splat'ing a scalar to V4SF, knowing that the internal SF
823 ;; format of scalars is actually DF.
824 (define_insn "vsx_xscvdpsp_scalar"
825   [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
826         (unspec:V4SF [(match_operand:SF 1 "vsx_register_operand" "f")]
827                      UNSPEC_VSX_CVSPDP))]
828   "VECTOR_UNIT_VSX_P (DFmode)"
829   "xscvdpsp %x0,%x1"
830   [(set_attr "type" "fp")])
831
832 ;; Convert from 64-bit to 32-bit types
833 ;; Note, favor the Altivec registers since the usual use of these instructions
834 ;; is in vector converts and we need to use the Altivec vperm instruction.
835
836 (define_insn "vsx_xvcvdpsxws"
837   [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
838         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
839                      UNSPEC_VSX_CVDPSXWS))]
840   "VECTOR_UNIT_VSX_P (V2DFmode)"
841   "xvcvdpsxws %x0,%x1"
842   [(set_attr "type" "vecfloat")])
843
844 (define_insn "vsx_xvcvdpuxws"
845   [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
846         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
847                      UNSPEC_VSX_CVDPUXWS))]
848   "VECTOR_UNIT_VSX_P (V2DFmode)"
849   "xvcvdpuxws %x0,%x1"
850   [(set_attr "type" "vecfloat")])
851
852 (define_insn "vsx_xvcvsxdsp"
853   [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
854         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
855                      UNSPEC_VSX_CVSXDSP))]
856   "VECTOR_UNIT_VSX_P (V2DFmode)"
857   "xvcvsxdsp %x0,%x1"
858   [(set_attr "type" "vecfloat")])
859
860 (define_insn "vsx_xvcvuxdsp"
861   [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
862         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
863                      UNSPEC_VSX_CVUXDSP))]
864   "VECTOR_UNIT_VSX_P (V2DFmode)"
865   "xvcvuxwdp %x0,%x1"
866   [(set_attr "type" "vecfloat")])
867
868 ;; Convert from 32-bit to 64-bit types
869 (define_insn "vsx_xvcvsxwdp"
870   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
871         (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
872                      UNSPEC_VSX_CVSXWDP))]
873   "VECTOR_UNIT_VSX_P (V2DFmode)"
874   "xvcvsxwdp %x0,%x1"
875   [(set_attr "type" "vecfloat")])
876
877 (define_insn "vsx_xvcvuxwdp"
878   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
879         (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
880                      UNSPEC_VSX_CVUXWDP))]
881   "VECTOR_UNIT_VSX_P (V2DFmode)"
882   "xvcvuxwdp %x0,%x1"
883   [(set_attr "type" "vecfloat")])
884
885 (define_insn "vsx_xvcvspsxds"
886   [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
887         (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
888                      UNSPEC_VSX_CVSPSXDS))]
889   "VECTOR_UNIT_VSX_P (V2DFmode)"
890   "xvcvspsxds %x0,%x1"
891   [(set_attr "type" "vecfloat")])
892
893 (define_insn "vsx_xvcvspuxds"
894   [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
895         (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
896                      UNSPEC_VSX_CVSPUXDS))]
897   "VECTOR_UNIT_VSX_P (V2DFmode)"
898   "xvcvspuxds %x0,%x1"
899   [(set_attr "type" "vecfloat")])
900
901 ;; Only optimize (float (fix x)) -> frz if we are in fast-math mode, since
902 ;; since the xsrdpiz instruction does not truncate the value if the floating
903 ;; point value is < LONG_MIN or > LONG_MAX.
904 (define_insn "*vsx_float_fix_<mode>2"
905   [(set (match_operand:VSX_DF 0 "vsx_register_operand" "=<VSr>,?wa")
906         (float:VSX_DF
907          (fix:<VSI>
908           (match_operand:VSX_DF 1 "vsx_register_operand" "<VSr>,?wa"))))]
909   "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
910    && VECTOR_UNIT_VSX_P (<MODE>mode) && flag_unsafe_math_optimizations
911    && !flag_trapping_math && TARGET_FRIZ"
912   "x<VSv>r<VSs>iz %x0,%x1"
913   [(set_attr "type" "<VStype_simple>")
914    (set_attr "fp_type" "<VSfptype_simple>")])
915
916 \f
917 ;; Logical and permute operations
918 (define_insn "*vsx_and<mode>3"
919   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
920         (and:VSX_L
921          (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
922          (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
923   "VECTOR_MEM_VSX_P (<MODE>mode)"
924   "xxland %x0,%x1,%x2"
925   [(set_attr "type" "vecsimple")])
926
927 (define_insn "*vsx_ior<mode>3"
928   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
929         (ior:VSX_L (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
930                    (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
931   "VECTOR_MEM_VSX_P (<MODE>mode)"
932   "xxlor %x0,%x1,%x2"
933   [(set_attr "type" "vecsimple")])
934
935 (define_insn "*vsx_xor<mode>3"
936   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
937         (xor:VSX_L
938          (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
939          (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
940   "VECTOR_MEM_VSX_P (<MODE>mode)"
941   "xxlxor %x0,%x1,%x2"
942   [(set_attr "type" "vecsimple")])
943
944 (define_insn "*vsx_one_cmpl<mode>2"
945   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
946         (not:VSX_L
947          (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")))]
948   "VECTOR_MEM_VSX_P (<MODE>mode)"
949   "xxlnor %x0,%x1,%x1"
950   [(set_attr "type" "vecsimple")])
951   
952 (define_insn "*vsx_nor<mode>3"
953   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
954         (not:VSX_L
955          (ior:VSX_L
956           (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
957           (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa"))))]
958   "VECTOR_MEM_VSX_P (<MODE>mode)"
959   "xxlnor %x0,%x1,%x2"
960   [(set_attr "type" "vecsimple")])
961
962 (define_insn "*vsx_andc<mode>3"
963   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
964         (and:VSX_L
965          (not:VSX_L
966           (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa"))
967          (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")))]
968   "VECTOR_MEM_VSX_P (<MODE>mode)"
969   "xxlandc %x0,%x1,%x2"
970   [(set_attr "type" "vecsimple")])
971
972 \f
973 ;; Permute operations
974
975 ;; Build a V2DF/V2DI vector from two scalars
976 (define_insn "vsx_concat_<mode>"
977   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
978         (unspec:VSX_D
979          [(match_operand:<VS_scalar> 1 "vsx_register_operand" "ws,wa")
980           (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")]
981          UNSPEC_VSX_CONCAT))]
982   "VECTOR_MEM_VSX_P (<MODE>mode)"
983   "xxpermdi %x0,%x1,%x2,0"
984   [(set_attr "type" "vecperm")])
985
986 ;; Special purpose concat using xxpermdi to glue two single precision values
987 ;; together, relying on the fact that internally scalar floats are represented
988 ;; as doubles.  This is used to initialize a V4SF vector with 4 floats
989 (define_insn "vsx_concat_v2sf"
990   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
991         (unspec:V2DF
992          [(match_operand:SF 1 "vsx_register_operand" "f,f")
993           (match_operand:SF 2 "vsx_register_operand" "f,f")]
994          UNSPEC_VSX_CONCAT))]
995   "VECTOR_MEM_VSX_P (V2DFmode)"
996   "xxpermdi %x0,%x1,%x2,0"
997   [(set_attr "type" "vecperm")])
998
999 ;; Set the element of a V2DI/VD2F mode
1000 (define_insn "vsx_set_<mode>"
1001   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
1002         (unspec:VSX_D [(match_operand:VSX_D 1 "vsx_register_operand" "wd,wa")
1003                        (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")
1004                        (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
1005                       UNSPEC_VSX_SET))]
1006   "VECTOR_MEM_VSX_P (<MODE>mode)"
1007 {
1008   if (INTVAL (operands[3]) == 0)
1009     return \"xxpermdi %x0,%x1,%x2,1\";
1010   else if (INTVAL (operands[3]) == 1)
1011     return \"xxpermdi %x0,%x2,%x1,0\";
1012   else
1013     gcc_unreachable ();
1014 }
1015   [(set_attr "type" "vecperm")])
1016
1017 ;; Extract a DF/DI element from V2DF/V2DI
1018 (define_insn "vsx_extract_<mode>"
1019   [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,d,?wa")
1020         (vec_select:<VS_scalar> (match_operand:VSX_D 1 "vsx_register_operand" "wd,wd,wa")
1021                        (parallel
1022                         [(match_operand:QI 2 "u5bit_cint_operand" "i,i,i")])))]
1023   "VECTOR_MEM_VSX_P (<MODE>mode)"
1024 {
1025   gcc_assert (UINTVAL (operands[2]) <= 1);
1026   operands[3] = GEN_INT (INTVAL (operands[2]) << 1);
1027   return \"xxpermdi %x0,%x1,%x1,%3\";
1028 }
1029   [(set_attr "type" "vecperm")])
1030
1031 ;; Optimize extracting element 0 from memory
1032 (define_insn "*vsx_extract_<mode>_zero"
1033   [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,d,?wa")
1034         (vec_select:<VS_scalar>
1035          (match_operand:VSX_D 1 "indexed_or_indirect_operand" "Z,Z,Z")
1036          (parallel [(const_int 0)])))]
1037   "VECTOR_MEM_VSX_P (<MODE>mode) && WORDS_BIG_ENDIAN"
1038   "lxsd%U1x %x0,%y1"
1039   [(set_attr "type" "fpload")
1040    (set_attr "length" "4")])  
1041
1042 ;; General double word oriented permute, allow the other vector types for
1043 ;; optimizing the permute instruction.
1044 (define_insn "vsx_xxpermdi_<mode>"
1045   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=wd,?wa")
1046         (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "wd,wa")
1047                        (match_operand:VSX_L 2 "vsx_register_operand" "wd,wa")
1048                        (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
1049                       UNSPEC_VSX_XXPERMDI))]
1050   "VECTOR_MEM_VSX_P (<MODE>mode)"
1051   "xxpermdi %x0,%x1,%x2,%3"
1052   [(set_attr "type" "vecperm")])
1053
1054 ;; Varient of xxpermdi that is emitted by the vec_interleave functions
1055 (define_insn "*vsx_xxpermdi2_<mode>"
1056   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd")
1057         (vec_concat:VSX_D
1058          (vec_select:<VS_scalar>
1059           (match_operand:VSX_D 1 "vsx_register_operand" "wd")
1060           (parallel
1061            [(match_operand:QI 2 "u5bit_cint_operand" "i")]))
1062          (vec_select:<VS_scalar>
1063           (match_operand:VSX_D 3 "vsx_register_operand" "wd")
1064           (parallel
1065            [(match_operand:QI 4 "u5bit_cint_operand" "i")]))))]
1066   "VECTOR_MEM_VSX_P (<MODE>mode)"
1067 {
1068   gcc_assert ((UINTVAL (operands[2]) <= 1) && (UINTVAL (operands[4]) <= 1));
1069   operands[5] = GEN_INT (((INTVAL (operands[2]) & 1) << 1)
1070                          | (INTVAL (operands[4]) & 1));
1071   return \"xxpermdi %x0,%x1,%x3,%5\";
1072 }
1073   [(set_attr "type" "vecperm")])
1074
1075 ;; V2DF/V2DI splat
1076 (define_insn "vsx_splat_<mode>"
1077   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,wd,wd,?wa,?wa,?wa")
1078         (vec_duplicate:VSX_D
1079          (match_operand:<VS_scalar> 1 "splat_input_operand" "ws,f,Z,wa,wa,Z")))]
1080   "VECTOR_MEM_VSX_P (<MODE>mode)"
1081   "@
1082    xxpermdi %x0,%x1,%x1,0
1083    xxpermdi %x0,%x1,%x1,0
1084    lxvdsx %x0,%y1
1085    xxpermdi %x0,%x1,%x1,0
1086    xxpermdi %x0,%x1,%x1,0
1087    lxvdsx %x0,%y1"
1088   [(set_attr "type" "vecperm,vecperm,vecload,vecperm,vecperm,vecload")])
1089
1090 ;; V4SF/V4SI splat
1091 (define_insn "vsx_xxspltw_<mode>"
1092   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1093         (vec_duplicate:VSX_W
1094          (vec_select:<VS_scalar>
1095           (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1096           (parallel
1097            [(match_operand:QI 2 "u5bit_cint_operand" "i,i")]))))]
1098   "VECTOR_MEM_VSX_P (<MODE>mode)"
1099   "xxspltw %x0,%x1,%2"
1100   [(set_attr "type" "vecperm")])
1101
1102 ;; V4SF/V4SI interleave
1103 (define_insn "vsx_xxmrghw_<mode>"
1104   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1105         (vec_merge:VSX_W
1106          (vec_select:VSX_W
1107           (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1108           (parallel [(const_int 0)
1109                      (const_int 2)
1110                      (const_int 1)
1111                      (const_int 3)]))
1112          (vec_select:VSX_W
1113           (match_operand:VSX_W 2 "vsx_register_operand" "wf,wa")
1114           (parallel [(const_int 2)
1115                      (const_int 0)
1116                      (const_int 3)
1117                      (const_int 1)]))
1118          (const_int 5)))]
1119   "VECTOR_MEM_VSX_P (<MODE>mode)"
1120   "xxmrghw %x0,%x1,%x2"
1121   [(set_attr "type" "vecperm")])
1122
1123 (define_insn "vsx_xxmrglw_<mode>"
1124   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1125         (vec_merge:VSX_W
1126          (vec_select:VSX_W
1127           (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1128           (parallel [(const_int 2)
1129                      (const_int 0)
1130                      (const_int 3)
1131                      (const_int 1)]))
1132          (vec_select:VSX_W
1133           (match_operand:VSX_W 2 "vsx_register_operand" "wf,?wa")
1134           (parallel [(const_int 0)
1135                      (const_int 2)
1136                      (const_int 1)
1137                      (const_int 3)]))
1138          (const_int 5)))]
1139   "VECTOR_MEM_VSX_P (<MODE>mode)"
1140   "xxmrglw %x0,%x1,%x2"
1141   [(set_attr "type" "vecperm")])
1142
1143 ;; Shift left double by word immediate
1144 (define_insn "vsx_xxsldwi_<mode>"
1145   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=wa")
1146         (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "wa")
1147                        (match_operand:VSX_L 2 "vsx_register_operand" "wa")
1148                        (match_operand:QI 3 "u5bit_cint_operand" "i")]
1149                       UNSPEC_VSX_SLDWI))]
1150   "VECTOR_MEM_VSX_P (<MODE>mode)"
1151   "xxsldwi %x0,%x1,%x2,%3"
1152   [(set_attr "type" "vecperm")])