OSDN Git Service

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