OSDN Git Service

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