2 ;; Copyright (C) 2009, 2010, 2011
3 ;; Free Software Foundation, Inc.
4 ;; Contributed by Michael Meissner <meissner@linux.vnet.ibm.com>
6 ;; This file is part of GCC.
8 ;; GCC is free software; you can redistribute it and/or modify it
9 ;; under the terms of the GNU General Public License as published
10 ;; by the Free Software Foundation; either version 3, or (at your
11 ;; option) any later version.
13 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
14 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 ;; License for more details.
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with GCC; see the file COPYING3. If not see
20 ;; <http://www.gnu.org/licenses/>.
22 ;; Iterator for both scalar and vector floating point types supported by VSX
23 (define_mode_iterator VSX_B [DF V4SF V2DF])
25 ;; Iterator for the 2 64-bit vector types
26 (define_mode_iterator VSX_D [V2DF V2DI])
28 ;; Iterator for the 2 32-bit vector types
29 (define_mode_iterator VSX_W [V4SF V4SI])
31 ;; Iterator for the DF types
32 (define_mode_iterator VSX_DF [V2DF DF])
34 ;; Iterator for vector floating point types supported by VSX
35 (define_mode_iterator VSX_F [V4SF V2DF])
37 ;; Iterator for logical types supported by VSX
38 (define_mode_iterator VSX_L [V16QI V8HI V4SI V2DI V4SF V2DF TI])
40 ;; Iterator for memory move. Handle TImode specially to allow
41 ;; it to use gprs as well as vsx registers.
42 (define_mode_iterator VSX_M [V16QI V8HI V4SI V2DI V4SF V2DF])
44 ;; Map into the appropriate load/store name based on the type
45 (define_mode_attr VSm [(V16QI "vw4")
54 ;; Map into the appropriate suffix based on the type
55 (define_mode_attr VSs [(V16QI "sp")
65 ;; Map the register class used
66 (define_mode_attr VSr [(V16QI "v")
76 ;; Map the register class used for float<->int conversions
77 (define_mode_attr VSr2 [(V2DF "wd")
81 (define_mode_attr VSr3 [(V2DF "wa")
85 ;; Map the register class for sp<->dp float conversions, destination
86 (define_mode_attr VSr4 [(SF "ws")
91 ;; Map the register class for sp<->dp float conversions, destination
92 (define_mode_attr VSr5 [(SF "ws")
97 ;; Same size integer type for floating point data
98 (define_mode_attr VSi [(V4SF "v4si")
102 (define_mode_attr VSI [(V4SF "V4SI")
106 ;; Word size for same size conversion
107 (define_mode_attr VSc [(V4SF "w")
111 ;; Map into either s or v, depending on whether this is a scalar or vector
113 (define_mode_attr VSv [(V16QI "v")
122 ;; Appropriate type for add ops (and other simple FP ops)
123 (define_mode_attr VStype_simple [(V2DF "vecdouble")
127 (define_mode_attr VSfptype_simple [(V2DF "fp_addsub_d")
131 ;; Appropriate type for multiply ops
132 (define_mode_attr VStype_mul [(V2DF "vecdouble")
136 (define_mode_attr VSfptype_mul [(V2DF "fp_mul_d")
140 ;; Appropriate type for divide ops.
141 (define_mode_attr VStype_div [(V2DF "vecdiv")
145 (define_mode_attr VSfptype_div [(V2DF "fp_div_d")
149 ;; Appropriate type for sqrt ops. For now, just lump the vector sqrt with
151 (define_mode_attr VStype_sqrt [(V2DF "dsqrt")
155 (define_mode_attr VSfptype_sqrt [(V2DF "fp_sqrt_d")
159 ;; Iterator and modes for sp<->dp conversions
160 ;; Because scalar SF values are represented internally as double, use the
161 ;; V4SF type to represent this than SF.
162 (define_mode_iterator VSX_SPDP [DF V4SF V2DF])
164 (define_mode_attr VS_spdp_res [(DF "V4SF")
168 (define_mode_attr VS_spdp_insn [(DF "xscvdpsp")
172 (define_mode_attr VS_spdp_type [(DF "fp")
176 ;; Map the scalar mode for a vector type
177 (define_mode_attr VS_scalar [(V2DF "DF")
184 ;; Constants for creating unspecs
185 (define_c_enum "unspec"
206 (define_insn "*vsx_mov<mode>"
207 [(set (match_operand:VSX_M 0 "nonimmediate_operand" "=Z,<VSr>,<VSr>,?Z,?wa,?wa,*o,*r,*r,<VSr>,?wa,v,wZ,v")
208 (match_operand:VSX_M 1 "input_operand" "<VSr>,Z,<VSr>,wa,Z,wa,r,o,r,j,j,W,v,wZ"))]
209 "VECTOR_MEM_VSX_P (<MODE>mode)
210 && (register_operand (operands[0], <MODE>mode)
211 || register_operand (operands[1], <MODE>mode))"
213 switch (which_alternative)
217 gcc_assert (MEM_P (operands[0])
218 && GET_CODE (XEXP (operands[0], 0)) != PRE_INC
219 && GET_CODE (XEXP (operands[0], 0)) != PRE_DEC
220 && GET_CODE (XEXP (operands[0], 0)) != PRE_MODIFY);
221 return "stx<VSm>x %x1,%y0";
225 gcc_assert (MEM_P (operands[1])
226 && GET_CODE (XEXP (operands[1], 0)) != PRE_INC
227 && GET_CODE (XEXP (operands[1], 0)) != PRE_DEC
228 && GET_CODE (XEXP (operands[1], 0)) != PRE_MODIFY);
229 return "lx<VSm>x %x0,%y1";
233 return "xxlor %x0,%x1,%x1";
242 return "xxlxor %x0,%x0,%x0";
245 return output_vec_const_move (operands);
248 gcc_assert (MEM_P (operands[0])
249 && GET_CODE (XEXP (operands[0], 0)) != PRE_INC
250 && GET_CODE (XEXP (operands[0], 0)) != PRE_DEC
251 && GET_CODE (XEXP (operands[0], 0)) != PRE_MODIFY);
252 return "stvx %1,%y0";
255 gcc_assert (MEM_P (operands[0])
256 && GET_CODE (XEXP (operands[0], 0)) != PRE_INC
257 && GET_CODE (XEXP (operands[0], 0)) != PRE_DEC
258 && GET_CODE (XEXP (operands[0], 0)) != PRE_MODIFY);
265 [(set_attr "type" "vecstore,vecload,vecsimple,vecstore,vecload,vecsimple,*,*,*,vecsimple,vecsimple,*,vecstore,vecload")])
267 ;; Unlike other VSX moves, allow the GPRs, since a normal use of TImode is for
268 ;; unions. However for plain data movement, slightly favor the vector loads
269 (define_insn "*vsx_movti"
270 [(set (match_operand:TI 0 "nonimmediate_operand" "=Z,wa,wa,?o,?r,?r,wa,v,v,wZ")
271 (match_operand:TI 1 "input_operand" "wa,Z,wa,r,o,r,j,W,wZ,v"))]
272 "VECTOR_MEM_VSX_P (TImode)
273 && (register_operand (operands[0], TImode)
274 || register_operand (operands[1], TImode))"
276 switch (which_alternative)
279 return "stxvd2x %x1,%y0";
282 return "lxvd2x %x0,%y1";
285 return "xxlor %x0,%x1,%x1";
293 return "xxlxor %x0,%x0,%x0";
296 return output_vec_const_move (operands);
299 return "stvx %1,%y0";
308 [(set_attr "type" "vecstore,vecload,vecsimple,*,*,*,vecsimple,*,vecstore,vecload")])
310 ;; Explicit load/store expanders for the builtin functions
311 (define_expand "vsx_load_<mode>"
312 [(set (match_operand:VSX_M 0 "vsx_register_operand" "")
313 (match_operand:VSX_M 1 "memory_operand" ""))]
314 "VECTOR_MEM_VSX_P (<MODE>mode)"
317 (define_expand "vsx_store_<mode>"
318 [(set (match_operand:VEC_M 0 "memory_operand" "")
319 (match_operand:VEC_M 1 "vsx_register_operand" ""))]
320 "VECTOR_MEM_VSX_P (<MODE>mode)"
324 ;; VSX scalar and vector floating point arithmetic instructions
325 (define_insn "*vsx_add<mode>3"
326 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
327 (plus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
328 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
329 "VECTOR_UNIT_VSX_P (<MODE>mode)"
330 "x<VSv>add<VSs> %x0,%x1,%x2"
331 [(set_attr "type" "<VStype_simple>")
332 (set_attr "fp_type" "<VSfptype_simple>")])
334 (define_insn "*vsx_sub<mode>3"
335 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
336 (minus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
337 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
338 "VECTOR_UNIT_VSX_P (<MODE>mode)"
339 "x<VSv>sub<VSs> %x0,%x1,%x2"
340 [(set_attr "type" "<VStype_simple>")
341 (set_attr "fp_type" "<VSfptype_simple>")])
343 (define_insn "*vsx_mul<mode>3"
344 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
345 (mult:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
346 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
347 "VECTOR_UNIT_VSX_P (<MODE>mode)"
348 "x<VSv>mul<VSs> %x0,%x1,%x2"
349 [(set_attr "type" "<VStype_mul>")
350 (set_attr "fp_type" "<VSfptype_mul>")])
352 (define_insn "*vsx_div<mode>3"
353 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
354 (div:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
355 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
356 "VECTOR_UNIT_VSX_P (<MODE>mode)"
357 "x<VSv>div<VSs> %x0,%x1,%x2"
358 [(set_attr "type" "<VStype_div>")
359 (set_attr "fp_type" "<VSfptype_div>")])
361 ;; *tdiv* instruction returning the FG flag
362 (define_expand "vsx_tdiv<mode>3_fg"
364 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
365 (match_operand:VSX_B 2 "vsx_register_operand" "")]
367 (set (match_operand:SI 0 "gpc_reg_operand" "")
370 "VECTOR_UNIT_VSX_P (<MODE>mode)"
372 operands[3] = gen_reg_rtx (CCFPmode);
375 ;; *tdiv* instruction returning the FE flag
376 (define_expand "vsx_tdiv<mode>3_fe"
378 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
379 (match_operand:VSX_B 2 "vsx_register_operand" "")]
381 (set (match_operand:SI 0 "gpc_reg_operand" "")
384 "VECTOR_UNIT_VSX_P (<MODE>mode)"
386 operands[3] = gen_reg_rtx (CCFPmode);
389 (define_insn "*vsx_tdiv<mode>3_internal"
390 [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
391 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
392 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")]
394 "VECTOR_UNIT_VSX_P (<MODE>mode)"
395 "x<VSv>tdiv<VSs> %0,%x1,%x2"
396 [(set_attr "type" "<VStype_simple>")
397 (set_attr "fp_type" "<VSfptype_simple>")])
399 (define_insn "vsx_fre<mode>2"
400 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
401 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
403 "VECTOR_UNIT_VSX_P (<MODE>mode)"
404 "x<VSv>re<VSs> %x0,%x1"
405 [(set_attr "type" "<VStype_simple>")
406 (set_attr "fp_type" "<VSfptype_simple>")])
408 (define_insn "*vsx_neg<mode>2"
409 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
410 (neg:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
411 "VECTOR_UNIT_VSX_P (<MODE>mode)"
412 "x<VSv>neg<VSs> %x0,%x1"
413 [(set_attr "type" "<VStype_simple>")
414 (set_attr "fp_type" "<VSfptype_simple>")])
416 (define_insn "*vsx_abs<mode>2"
417 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
418 (abs:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
419 "VECTOR_UNIT_VSX_P (<MODE>mode)"
420 "x<VSv>abs<VSs> %x0,%x1"
421 [(set_attr "type" "<VStype_simple>")
422 (set_attr "fp_type" "<VSfptype_simple>")])
424 (define_insn "vsx_nabs<mode>2"
425 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
428 (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa"))))]
429 "VECTOR_UNIT_VSX_P (<MODE>mode)"
430 "x<VSv>nabs<VSs> %x0,%x1"
431 [(set_attr "type" "<VStype_simple>")
432 (set_attr "fp_type" "<VSfptype_simple>")])
434 (define_insn "vsx_smax<mode>3"
435 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
436 (smax:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
437 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
438 "VECTOR_UNIT_VSX_P (<MODE>mode)"
439 "x<VSv>max<VSs> %x0,%x1,%x2"
440 [(set_attr "type" "<VStype_simple>")
441 (set_attr "fp_type" "<VSfptype_simple>")])
443 (define_insn "*vsx_smin<mode>3"
444 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
445 (smin:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
446 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
447 "VECTOR_UNIT_VSX_P (<MODE>mode)"
448 "x<VSv>min<VSs> %x0,%x1,%x2"
449 [(set_attr "type" "<VStype_simple>")
450 (set_attr "fp_type" "<VSfptype_simple>")])
452 ;; Special VSX version of smin/smax for single precision floating point. Since
453 ;; both numbers are rounded to single precision, we can just use the DP version
454 ;; of the instruction.
456 (define_insn "*vsx_smaxsf3"
457 [(set (match_operand:SF 0 "vsx_register_operand" "=f")
458 (smax:SF (match_operand:SF 1 "vsx_register_operand" "f")
459 (match_operand:SF 2 "vsx_register_operand" "f")))]
460 "VECTOR_UNIT_VSX_P (DFmode)"
461 "xsmaxdp %x0,%x1,%x2"
462 [(set_attr "type" "fp")
463 (set_attr "fp_type" "fp_addsub_d")])
465 (define_insn "*vsx_sminsf3"
466 [(set (match_operand:SF 0 "vsx_register_operand" "=f")
467 (smin:SF (match_operand:SF 1 "vsx_register_operand" "f")
468 (match_operand:SF 2 "vsx_register_operand" "f")))]
469 "VECTOR_UNIT_VSX_P (DFmode)"
470 "xsmindp %x0,%x1,%x2"
471 [(set_attr "type" "fp")
472 (set_attr "fp_type" "fp_addsub_d")])
474 (define_insn "*vsx_sqrt<mode>2"
475 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
476 (sqrt:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
477 "VECTOR_UNIT_VSX_P (<MODE>mode)"
478 "x<VSv>sqrt<VSs> %x0,%x1"
479 [(set_attr "type" "<VStype_sqrt>")
480 (set_attr "fp_type" "<VSfptype_sqrt>")])
482 (define_insn "*vsx_rsqrte<mode>2"
483 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
484 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
486 "VECTOR_UNIT_VSX_P (<MODE>mode)"
487 "x<VSv>rsqrte<VSs> %x0,%x1"
488 [(set_attr "type" "<VStype_simple>")
489 (set_attr "fp_type" "<VSfptype_simple>")])
491 ;; *tsqrt* returning the fg flag
492 (define_expand "vsx_tsqrt<mode>2_fg"
494 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
496 (set (match_operand:SI 0 "gpc_reg_operand" "")
499 "VECTOR_UNIT_VSX_P (<MODE>mode)"
501 operands[3] = gen_reg_rtx (CCFPmode);
504 ;; *tsqrt* returning the fe flag
505 (define_expand "vsx_tsqrt<mode>2_fe"
507 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
509 (set (match_operand:SI 0 "gpc_reg_operand" "")
512 "VECTOR_UNIT_VSX_P (<MODE>mode)"
514 operands[3] = gen_reg_rtx (CCFPmode);
517 (define_insn "*vsx_tsqrt<mode>2_internal"
518 [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
519 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
521 "VECTOR_UNIT_VSX_P (<MODE>mode)"
522 "x<VSv>tsqrt<VSs> %0,%x1"
523 [(set_attr "type" "<VStype_simple>")
524 (set_attr "fp_type" "<VSfptype_simple>")])
526 ;; Fused vector multiply/add instructions Support the classical DF versions of
527 ;; fma, which allows the target to be a separate register from the 3 inputs.
528 ;; Under VSX, the target must be either the addend or the first multiply.
529 ;; Where we can, also do the same for the Altivec V4SF fmas.
531 (define_insn "*vsx_fmadf4"
532 [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
534 (match_operand:DF 1 "vsx_register_operand" "%ws,ws,wa,wa,d")
535 (match_operand:DF 2 "vsx_register_operand" "ws,0,wa,0,d")
536 (match_operand:DF 3 "vsx_register_operand" "0,ws,0,wa,d")))]
537 "VECTOR_UNIT_VSX_P (DFmode)"
539 xsmaddadp %x0,%x1,%x2
540 xsmaddmdp %x0,%x1,%x3
541 xsmaddadp %x0,%x1,%x2
542 xsmaddmdp %x0,%x1,%x3
543 {fma|fmadd} %0,%1,%2,%3"
544 [(set_attr "type" "fp")
545 (set_attr "fp_type" "fp_maddsub_d")])
547 (define_insn "*vsx_fmav4sf4"
548 [(set (match_operand:V4SF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,v")
550 (match_operand:V4SF 1 "vsx_register_operand" "%ws,ws,wa,wa,v")
551 (match_operand:V4SF 2 "vsx_register_operand" "ws,0,wa,0,v")
552 (match_operand:V4SF 3 "vsx_register_operand" "0,ws,0,wa,v")))]
553 "VECTOR_UNIT_VSX_P (V4SFmode)"
555 xvmaddasp %x0,%x1,%x2
556 xvmaddmsp %x0,%x1,%x3
557 xvmaddasp %x0,%x1,%x2
558 xvmaddmsp %x0,%x1,%x3
560 [(set_attr "type" "vecfloat")])
562 (define_insn "*vsx_fmav2df4"
563 [(set (match_operand:V2DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa")
565 (match_operand:V2DF 1 "vsx_register_operand" "%ws,ws,wa,wa")
566 (match_operand:V2DF 2 "vsx_register_operand" "ws,0,wa,0")
567 (match_operand:V2DF 3 "vsx_register_operand" "0,ws,0,wa")))]
568 "VECTOR_UNIT_VSX_P (V2DFmode)"
570 xvmaddadp %x0,%x1,%x2
571 xvmaddmdp %x0,%x1,%x3
572 xvmaddadp %x0,%x1,%x2
573 xvmaddmdp %x0,%x1,%x3"
574 [(set_attr "type" "vecdouble")])
576 (define_insn "*vsx_fmsdf4"
577 [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
579 (match_operand:DF 1 "vsx_register_operand" "%ws,ws,wa,wa,d")
580 (match_operand:DF 2 "vsx_register_operand" "ws,0,wa,0,d")
582 (match_operand:DF 3 "vsx_register_operand" "0,ws,0,wa,d"))))]
583 "VECTOR_UNIT_VSX_P (DFmode)"
585 xsmsubadp %x0,%x1,%x2
586 xsmsubmdp %x0,%x1,%x3
587 xsmsubadp %x0,%x1,%x2
588 xsmsubmdp %x0,%x1,%x3
589 {fms|fmsub} %0,%1,%2,%3"
590 [(set_attr "type" "fp")
591 (set_attr "fp_type" "fp_maddsub_d")])
593 (define_insn "*vsx_fms<mode>4"
594 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
596 (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
597 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0,wa,0")
599 (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
600 "VECTOR_UNIT_VSX_P (<MODE>mode)"
602 x<VSv>msuba<VSs> %x0,%x1,%x2
603 x<VSv>msubm<VSs> %x0,%x1,%x3
604 x<VSv>msuba<VSs> %x0,%x1,%x2
605 x<VSv>msubm<VSs> %x0,%x1,%x3"
606 [(set_attr "type" "<VStype_mul>")])
608 (define_insn "*vsx_nfmadf4"
609 [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
612 (match_operand:DF 1 "vsx_register_operand" "ws,ws,wa,wa,d")
613 (match_operand:DF 2 "vsx_register_operand" "ws,0,wa,0,d")
614 (match_operand:DF 3 "vsx_register_operand" "0,ws,0,wa,d"))))]
615 "VECTOR_UNIT_VSX_P (DFmode)"
617 xsnmaddadp %x0,%x1,%x2
618 xsnmaddmdp %x0,%x1,%x3
619 xsnmaddadp %x0,%x1,%x2
620 xsnmaddmdp %x0,%x1,%x3
621 {fnma|fnmadd} %0,%1,%2,%3"
622 [(set_attr "type" "fp")
623 (set_attr "fp_type" "fp_maddsub_d")])
625 (define_insn "*vsx_nfma<mode>4"
626 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
629 (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSr>,wa,wa")
630 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0,wa,0")
631 (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
632 "VECTOR_UNIT_VSX_P (<MODE>mode)"
634 x<VSv>nmadda<VSs> %x0,%x1,%x2
635 x<VSv>nmaddm<VSs> %x0,%x1,%x3
636 x<VSv>nmadda<VSs> %x0,%x1,%x2
637 x<VSv>nmaddm<VSs> %x0,%x1,%x3"
638 [(set_attr "type" "<VStype_mul>")
639 (set_attr "fp_type" "<VSfptype_mul>")])
641 (define_insn "*vsx_nfmsdf4"
642 [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
645 (match_operand:DF 1 "vsx_register_operand" "%ws,ws,wa,wa,d")
646 (match_operand:DF 2 "vsx_register_operand" "ws,0,wa,0,d")
648 (match_operand:DF 3 "vsx_register_operand" "0,ws,0,wa,d")))))]
649 "VECTOR_UNIT_VSX_P (DFmode)"
651 xsnmsubadp %x0,%x1,%x2
652 xsnmsubmdp %x0,%x1,%x3
653 xsnmsubadp %x0,%x1,%x2
654 xsnmsubmdp %x0,%x1,%x3
655 {fnms|fnmsub} %0,%1,%2,%3"
656 [(set_attr "type" "fp")
657 (set_attr "fp_type" "fp_maddsub_d")])
659 (define_insn "*vsx_nfmsv4sf4"
660 [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf,wf,?wa,?wa,v")
663 (match_operand:V4SF 1 "vsx_register_operand" "%wf,wf,wa,wa,v")
664 (match_operand:V4SF 2 "vsx_register_operand" "wf,0,wa,0,v")
666 (match_operand:V4SF 3 "vsx_register_operand" "0,wf,0,wa,v")))))]
667 "VECTOR_UNIT_VSX_P (V4SFmode)"
669 xvnmsubasp %x0,%x1,%x2
670 xvnmsubmsp %x0,%x1,%x3
671 xvnmsubasp %x0,%x1,%x2
672 xvnmsubmsp %x0,%x1,%x3
673 vnmsubfp %0,%1,%2,%3"
674 [(set_attr "type" "vecfloat")])
676 (define_insn "*vsx_nfmsv2df4"
677 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd,?wa,?wa")
680 (match_operand:V2DF 1 "vsx_register_operand" "%wd,wd,wa,wa")
681 (match_operand:V2DF 2 "vsx_register_operand" "wd,0,wa,0")
683 (match_operand:V2DF 3 "vsx_register_operand" "0,wd,0,wa")))))]
684 "VECTOR_UNIT_VSX_P (V2DFmode)"
686 xvnmsubadp %x0,%x1,%x2
687 xvnmsubmdp %x0,%x1,%x3
688 xvnmsubadp %x0,%x1,%x2
689 xvnmsubmdp %x0,%x1,%x3"
690 [(set_attr "type" "vecdouble")])
692 ;; Vector conditional expressions (no scalar version for these instructions)
693 (define_insn "vsx_eq<mode>"
694 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
695 (eq:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
696 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
697 "VECTOR_UNIT_VSX_P (<MODE>mode)"
698 "xvcmpeq<VSs> %x0,%x1,%x2"
699 [(set_attr "type" "<VStype_simple>")
700 (set_attr "fp_type" "<VSfptype_simple>")])
702 (define_insn "vsx_gt<mode>"
703 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
704 (gt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
705 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
706 "VECTOR_UNIT_VSX_P (<MODE>mode)"
707 "xvcmpgt<VSs> %x0,%x1,%x2"
708 [(set_attr "type" "<VStype_simple>")
709 (set_attr "fp_type" "<VSfptype_simple>")])
711 (define_insn "*vsx_ge<mode>"
712 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
713 (ge:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
714 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
715 "VECTOR_UNIT_VSX_P (<MODE>mode)"
716 "xvcmpge<VSs> %x0,%x1,%x2"
717 [(set_attr "type" "<VStype_simple>")
718 (set_attr "fp_type" "<VSfptype_simple>")])
720 ;; Floating point scalar compare
721 (define_insn "*vsx_cmpdf_internal1"
722 [(set (match_operand:CCFP 0 "cc_reg_operand" "=y,?y")
723 (compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "ws,wa")
724 (match_operand:DF 2 "gpc_reg_operand" "ws,wa")))]
725 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
726 && VECTOR_UNIT_VSX_P (DFmode)"
727 "xscmpudp %0,%x1,%x2"
728 [(set_attr "type" "fpcompare")])
730 ;; Compare vectors producing a vector result and a predicate, setting CR6 to
731 ;; indicate a combined status
732 (define_insn "*vsx_eq_<mode>_p"
735 [(eq:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
736 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
738 (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
739 (eq:VSX_F (match_dup 1)
741 "VECTOR_UNIT_VSX_P (<MODE>mode)"
742 "xvcmpeq<VSs>. %x0,%x1,%x2"
743 [(set_attr "type" "<VStype_simple>")])
745 (define_insn "*vsx_gt_<mode>_p"
748 [(gt:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
749 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
751 (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
752 (gt:VSX_F (match_dup 1)
754 "VECTOR_UNIT_VSX_P (<MODE>mode)"
755 "xvcmpgt<VSs>. %x0,%x1,%x2"
756 [(set_attr "type" "<VStype_simple>")])
758 (define_insn "*vsx_ge_<mode>_p"
761 [(ge:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
762 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
764 (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
765 (ge:VSX_F (match_dup 1)
767 "VECTOR_UNIT_VSX_P (<MODE>mode)"
768 "xvcmpge<VSs>. %x0,%x1,%x2"
769 [(set_attr "type" "<VStype_simple>")])
772 (define_insn "*vsx_xxsel<mode>"
773 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
775 (ne:CC (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
776 (match_operand:VSX_L 4 "zero_constant" ""))
777 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
778 (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
779 "VECTOR_MEM_VSX_P (<MODE>mode)"
780 "xxsel %x0,%x3,%x2,%x1"
781 [(set_attr "type" "vecperm")])
783 (define_insn "*vsx_xxsel<mode>_uns"
784 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
786 (ne:CCUNS (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
787 (match_operand:VSX_L 4 "zero_constant" ""))
788 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
789 (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
790 "VECTOR_MEM_VSX_P (<MODE>mode)"
791 "xxsel %x0,%x3,%x2,%x1"
792 [(set_attr "type" "vecperm")])
795 (define_insn "vsx_copysign<mode>3"
796 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
798 [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
799 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")]
801 "VECTOR_UNIT_VSX_P (<MODE>mode)"
802 "x<VSv>cpsgn<VSs> %x0,%x2,%x1"
803 [(set_attr "type" "<VStype_simple>")
804 (set_attr "fp_type" "<VSfptype_simple>")])
806 ;; For the conversions, limit the register class for the integer value to be
807 ;; the fprs because we don't want to add the altivec registers to movdi/movsi.
808 ;; For the unsigned tests, there isn't a generic double -> unsigned conversion
809 ;; in rs6000.md so don't test VECTOR_UNIT_VSX_P, just test against VSX.
810 ;; Don't use vsx_register_operand here, use gpc_reg_operand to match rs6000.md.
811 (define_insn "vsx_float<VSi><mode>2"
812 [(set (match_operand:VSX_B 0 "gpc_reg_operand" "=<VSr>,?wa")
813 (float:VSX_B (match_operand:<VSI> 1 "gpc_reg_operand" "<VSr2>,<VSr3>")))]
814 "VECTOR_UNIT_VSX_P (<MODE>mode)"
815 "x<VSv>cvsx<VSc><VSs> %x0,%x1"
816 [(set_attr "type" "<VStype_simple>")
817 (set_attr "fp_type" "<VSfptype_simple>")])
819 (define_insn "vsx_floatuns<VSi><mode>2"
820 [(set (match_operand:VSX_B 0 "gpc_reg_operand" "=<VSr>,?wa")
821 (unsigned_float:VSX_B (match_operand:<VSI> 1 "gpc_reg_operand" "<VSr2>,<VSr3>")))]
822 "VECTOR_UNIT_VSX_P (<MODE>mode)"
823 "x<VSv>cvux<VSc><VSs> %x0,%x1"
824 [(set_attr "type" "<VStype_simple>")
825 (set_attr "fp_type" "<VSfptype_simple>")])
827 (define_insn "vsx_fix_trunc<mode><VSi>2"
828 [(set (match_operand:<VSI> 0 "gpc_reg_operand" "=<VSr2>,?<VSr3>")
829 (fix:<VSI> (match_operand:VSX_B 1 "gpc_reg_operand" "<VSr>,wa")))]
830 "VECTOR_UNIT_VSX_P (<MODE>mode)"
831 "x<VSv>cv<VSs>sx<VSc>s %x0,%x1"
832 [(set_attr "type" "<VStype_simple>")
833 (set_attr "fp_type" "<VSfptype_simple>")])
835 (define_insn "vsx_fixuns_trunc<mode><VSi>2"
836 [(set (match_operand:<VSI> 0 "gpc_reg_operand" "=<VSr2>,?<VSr3>")
837 (unsigned_fix:<VSI> (match_operand:VSX_B 1 "gpc_reg_operand" "<VSr>,wa")))]
838 "VECTOR_UNIT_VSX_P (<MODE>mode)"
839 "x<VSv>cv<VSs>ux<VSc>s %x0,%x1"
840 [(set_attr "type" "<VStype_simple>")
841 (set_attr "fp_type" "<VSfptype_simple>")])
843 ;; Math rounding functions
844 (define_insn "vsx_x<VSv>r<VSs>i"
845 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
846 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
847 UNSPEC_VSX_ROUND_I))]
848 "VECTOR_UNIT_VSX_P (<MODE>mode)"
849 "x<VSv>r<VSs>i %x0,%x1"
850 [(set_attr "type" "<VStype_simple>")
851 (set_attr "fp_type" "<VSfptype_simple>")])
853 (define_insn "vsx_x<VSv>r<VSs>ic"
854 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
855 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
856 UNSPEC_VSX_ROUND_IC))]
857 "VECTOR_UNIT_VSX_P (<MODE>mode)"
858 "x<VSv>r<VSs>ic %x0,%x1"
859 [(set_attr "type" "<VStype_simple>")
860 (set_attr "fp_type" "<VSfptype_simple>")])
862 (define_insn "vsx_btrunc<mode>2"
863 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
864 (fix:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
865 "VECTOR_UNIT_VSX_P (<MODE>mode)"
866 "x<VSv>r<VSs>iz %x0,%x1"
867 [(set_attr "type" "<VStype_simple>")
868 (set_attr "fp_type" "<VSfptype_simple>")])
870 (define_insn "*vsx_b2trunc<mode>2"
871 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
872 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
874 "VECTOR_UNIT_VSX_P (<MODE>mode)"
875 "x<VSv>r<VSs>iz %x0,%x1"
876 [(set_attr "type" "<VStype_simple>")
877 (set_attr "fp_type" "<VSfptype_simple>")])
879 (define_insn "vsx_floor<mode>2"
880 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
881 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
883 "VECTOR_UNIT_VSX_P (<MODE>mode)"
884 "x<VSv>r<VSs>im %x0,%x1"
885 [(set_attr "type" "<VStype_simple>")
886 (set_attr "fp_type" "<VSfptype_simple>")])
888 (define_insn "vsx_ceil<mode>2"
889 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
890 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
892 "VECTOR_UNIT_VSX_P (<MODE>mode)"
893 "x<VSv>r<VSs>ip %x0,%x1"
894 [(set_attr "type" "<VStype_simple>")
895 (set_attr "fp_type" "<VSfptype_simple>")])
898 ;; VSX convert to/from double vector
900 ;; Convert between single and double precision
901 ;; Don't use xscvspdp and xscvdpsp for scalar conversions, since the normal
902 ;; scalar single precision instructions internally use the double format.
903 ;; Prefer the altivec registers, since we likely will need to do a vperm
904 (define_insn "vsx_<VS_spdp_insn>"
905 [(set (match_operand:<VS_spdp_res> 0 "vsx_register_operand" "=<VSr4>,?wa")
906 (unspec:<VS_spdp_res> [(match_operand:VSX_SPDP 1 "vsx_register_operand" "<VSr5>,wa")]
908 "VECTOR_UNIT_VSX_P (<MODE>mode)"
909 "<VS_spdp_insn> %x0,%x1"
910 [(set_attr "type" "<VS_spdp_type>")])
912 ;; xscvspdp, represent the scalar SF type as V4SF
913 (define_insn "vsx_xscvspdp"
914 [(set (match_operand:DF 0 "vsx_register_operand" "=ws,?wa")
915 (unspec:DF [(match_operand:V4SF 1 "vsx_register_operand" "wa,wa")]
917 "VECTOR_UNIT_VSX_P (DFmode)"
919 [(set_attr "type" "fp")])
921 ;; xscvdpsp used for splat'ing a scalar to V4SF, knowing that the internal SF
922 ;; format of scalars is actually DF.
923 (define_insn "vsx_xscvdpsp_scalar"
924 [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
925 (unspec:V4SF [(match_operand:SF 1 "vsx_register_operand" "f")]
927 "VECTOR_UNIT_VSX_P (DFmode)"
929 [(set_attr "type" "fp")])
931 ;; Same as vsx_xscvspdp, but use SF as the type
932 (define_insn "vsx_xscvspdp_scalar2"
933 [(set (match_operand:SF 0 "vsx_register_operand" "=f")
934 (unspec:SF [(match_operand:V4SF 1 "vsx_register_operand" "wa")]
936 "VECTOR_UNIT_VSX_P (DFmode)"
938 [(set_attr "type" "fp")])
940 ;; Convert from 64-bit to 32-bit types
941 ;; Note, favor the Altivec registers since the usual use of these instructions
942 ;; is in vector converts and we need to use the Altivec vperm instruction.
944 (define_insn "vsx_xvcvdpsxws"
945 [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
946 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
947 UNSPEC_VSX_CVDPSXWS))]
948 "VECTOR_UNIT_VSX_P (V2DFmode)"
950 [(set_attr "type" "vecdouble")])
952 (define_insn "vsx_xvcvdpuxws"
953 [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
954 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
955 UNSPEC_VSX_CVDPUXWS))]
956 "VECTOR_UNIT_VSX_P (V2DFmode)"
958 [(set_attr "type" "vecdouble")])
960 (define_insn "vsx_xvcvsxdsp"
961 [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
962 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
963 UNSPEC_VSX_CVSXDSP))]
964 "VECTOR_UNIT_VSX_P (V2DFmode)"
966 [(set_attr "type" "vecfloat")])
968 (define_insn "vsx_xvcvuxdsp"
969 [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
970 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
971 UNSPEC_VSX_CVUXDSP))]
972 "VECTOR_UNIT_VSX_P (V2DFmode)"
974 [(set_attr "type" "vecdouble")])
976 ;; Convert from 32-bit to 64-bit types
977 (define_insn "vsx_xvcvsxwdp"
978 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
979 (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
980 UNSPEC_VSX_CVSXWDP))]
981 "VECTOR_UNIT_VSX_P (V2DFmode)"
983 [(set_attr "type" "vecdouble")])
985 (define_insn "vsx_xvcvuxwdp"
986 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
987 (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
988 UNSPEC_VSX_CVUXWDP))]
989 "VECTOR_UNIT_VSX_P (V2DFmode)"
991 [(set_attr "type" "vecdouble")])
993 (define_insn "vsx_xvcvspsxds"
994 [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
995 (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
996 UNSPEC_VSX_CVSPSXDS))]
997 "VECTOR_UNIT_VSX_P (V2DFmode)"
999 [(set_attr "type" "vecdouble")])
1001 (define_insn "vsx_xvcvspuxds"
1002 [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
1003 (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
1004 UNSPEC_VSX_CVSPUXDS))]
1005 "VECTOR_UNIT_VSX_P (V2DFmode)"
1006 "xvcvspuxds %x0,%x1"
1007 [(set_attr "type" "vecdouble")])
1009 ;; Only optimize (float (fix x)) -> frz if we are in fast-math mode, since
1010 ;; since the xsrdpiz instruction does not truncate the value if the floating
1011 ;; point value is < LONG_MIN or > LONG_MAX.
1012 (define_insn "*vsx_float_fix_<mode>2"
1013 [(set (match_operand:VSX_DF 0 "vsx_register_operand" "=<VSr>,?wa")
1016 (match_operand:VSX_DF 1 "vsx_register_operand" "<VSr>,?wa"))))]
1017 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
1018 && VECTOR_UNIT_VSX_P (<MODE>mode) && flag_unsafe_math_optimizations
1019 && !flag_trapping_math && TARGET_FRIZ"
1020 "x<VSv>r<VSs>iz %x0,%x1"
1021 [(set_attr "type" "<VStype_simple>")
1022 (set_attr "fp_type" "<VSfptype_simple>")])
1025 ;; Logical and permute operations
1026 (define_insn "*vsx_and<mode>3"
1027 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1029 (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
1030 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
1031 "VECTOR_MEM_VSX_P (<MODE>mode)"
1032 "xxland %x0,%x1,%x2"
1033 [(set_attr "type" "vecsimple")])
1035 (define_insn "*vsx_ior<mode>3"
1036 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1037 (ior:VSX_L (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
1038 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
1039 "VECTOR_MEM_VSX_P (<MODE>mode)"
1041 [(set_attr "type" "vecsimple")])
1043 (define_insn "*vsx_xor<mode>3"
1044 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1046 (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
1047 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
1048 "VECTOR_MEM_VSX_P (<MODE>mode)"
1049 "xxlxor %x0,%x1,%x2"
1050 [(set_attr "type" "vecsimple")])
1052 (define_insn "*vsx_one_cmpl<mode>2"
1053 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1055 (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")))]
1056 "VECTOR_MEM_VSX_P (<MODE>mode)"
1057 "xxlnor %x0,%x1,%x1"
1058 [(set_attr "type" "vecsimple")])
1060 (define_insn "*vsx_nor<mode>3"
1061 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1064 (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
1065 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa"))))]
1066 "VECTOR_MEM_VSX_P (<MODE>mode)"
1067 "xxlnor %x0,%x1,%x2"
1068 [(set_attr "type" "vecsimple")])
1070 (define_insn "*vsx_andc<mode>3"
1071 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1074 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa"))
1075 (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")))]
1076 "VECTOR_MEM_VSX_P (<MODE>mode)"
1077 "xxlandc %x0,%x1,%x2"
1078 [(set_attr "type" "vecsimple")])
1081 ;; Permute operations
1083 ;; Build a V2DF/V2DI vector from two scalars
1084 (define_insn "vsx_concat_<mode>"
1085 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
1087 [(match_operand:<VS_scalar> 1 "vsx_register_operand" "ws,wa")
1088 (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")]
1089 UNSPEC_VSX_CONCAT))]
1090 "VECTOR_MEM_VSX_P (<MODE>mode)"
1091 "xxpermdi %x0,%x1,%x2,0"
1092 [(set_attr "type" "vecperm")])
1094 ;; Special purpose concat using xxpermdi to glue two single precision values
1095 ;; together, relying on the fact that internally scalar floats are represented
1096 ;; as doubles. This is used to initialize a V4SF vector with 4 floats
1097 (define_insn "vsx_concat_v2sf"
1098 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1100 [(match_operand:SF 1 "vsx_register_operand" "f,f")
1101 (match_operand:SF 2 "vsx_register_operand" "f,f")]
1102 UNSPEC_VSX_CONCAT))]
1103 "VECTOR_MEM_VSX_P (V2DFmode)"
1104 "xxpermdi %x0,%x1,%x2,0"
1105 [(set_attr "type" "vecperm")])
1107 ;; Set the element of a V2DI/VD2F mode
1108 (define_insn "vsx_set_<mode>"
1109 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
1110 (unspec:VSX_D [(match_operand:VSX_D 1 "vsx_register_operand" "wd,wa")
1111 (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")
1112 (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
1114 "VECTOR_MEM_VSX_P (<MODE>mode)"
1116 if (INTVAL (operands[3]) == 0)
1117 return \"xxpermdi %x0,%x1,%x2,1\";
1118 else if (INTVAL (operands[3]) == 1)
1119 return \"xxpermdi %x0,%x2,%x1,0\";
1123 [(set_attr "type" "vecperm")])
1125 ;; Extract a DF/DI element from V2DF/V2DI
1126 (define_insn "vsx_extract_<mode>"
1127 [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,d,?wa")
1128 (vec_select:<VS_scalar> (match_operand:VSX_D 1 "vsx_register_operand" "wd,wd,wa")
1130 [(match_operand:QI 2 "u5bit_cint_operand" "i,i,i")])))]
1131 "VECTOR_MEM_VSX_P (<MODE>mode)"
1133 gcc_assert (UINTVAL (operands[2]) <= 1);
1134 operands[3] = GEN_INT (INTVAL (operands[2]) << 1);
1135 return \"xxpermdi %x0,%x1,%x1,%3\";
1137 [(set_attr "type" "vecperm")])
1139 ;; Optimize extracting element 0 from memory
1140 (define_insn "*vsx_extract_<mode>_zero"
1141 [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,d,?wa")
1142 (vec_select:<VS_scalar>
1143 (match_operand:VSX_D 1 "indexed_or_indirect_operand" "Z,Z,Z")
1144 (parallel [(const_int 0)])))]
1145 "VECTOR_MEM_VSX_P (<MODE>mode) && WORDS_BIG_ENDIAN"
1147 [(set_attr "type" "fpload")
1148 (set_attr "length" "4")])
1150 ;; Extract a SF element from V4SF
1151 (define_insn_and_split "vsx_extract_v4sf"
1152 [(set (match_operand:SF 0 "vsx_register_operand" "=f,f")
1154 (match_operand:V4SF 1 "vsx_register_operand" "wa,wa")
1155 (parallel [(match_operand:QI 2 "u5bit_cint_operand" "O,i")])))
1156 (clobber (match_scratch:V4SF 3 "=X,0"))]
1157 "VECTOR_UNIT_VSX_P (V4SFmode)"
1165 rtx op0 = operands[0];
1166 rtx op1 = operands[1];
1167 rtx op2 = operands[2];
1168 rtx op3 = operands[3];
1170 HOST_WIDE_INT ele = INTVAL (op2);
1176 if (GET_CODE (op3) == SCRATCH)
1177 op3 = gen_reg_rtx (V4SFmode);
1178 emit_insn (gen_vsx_xxsldwi_v4sf (op3, op1, op1, op2));
1181 emit_insn (gen_vsx_xscvspdp_scalar2 (op0, tmp));
1184 [(set_attr "length" "4,8")
1185 (set_attr "type" "fp")])
1187 ;; General double word oriented permute, allow the other vector types for
1188 ;; optimizing the permute instruction.
1189 (define_insn "vsx_xxpermdi_<mode>"
1190 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=wd,?wa")
1191 (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "wd,wa")
1192 (match_operand:VSX_L 2 "vsx_register_operand" "wd,wa")
1193 (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
1194 UNSPEC_VSX_XXPERMDI))]
1195 "VECTOR_MEM_VSX_P (<MODE>mode)"
1196 "xxpermdi %x0,%x1,%x2,%3"
1197 [(set_attr "type" "vecperm")])
1199 ;; Varient of xxpermdi that is emitted by the vec_interleave functions
1200 (define_insn "*vsx_xxpermdi2_<mode>"
1201 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd")
1203 (vec_select:<VS_scalar>
1204 (match_operand:VSX_D 1 "vsx_register_operand" "wd")
1206 [(match_operand:QI 2 "u5bit_cint_operand" "i")]))
1207 (vec_select:<VS_scalar>
1208 (match_operand:VSX_D 3 "vsx_register_operand" "wd")
1210 [(match_operand:QI 4 "u5bit_cint_operand" "i")]))))]
1211 "VECTOR_MEM_VSX_P (<MODE>mode)"
1213 gcc_assert ((UINTVAL (operands[2]) <= 1) && (UINTVAL (operands[4]) <= 1));
1214 operands[5] = GEN_INT (((INTVAL (operands[2]) & 1) << 1)
1215 | (INTVAL (operands[4]) & 1));
1216 return \"xxpermdi %x0,%x1,%x3,%5\";
1218 [(set_attr "type" "vecperm")])
1221 (define_insn "vsx_splat_<mode>"
1222 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,wd,wd,?wa,?wa,?wa")
1223 (vec_duplicate:VSX_D
1224 (match_operand:<VS_scalar> 1 "splat_input_operand" "ws,f,Z,wa,wa,Z")))]
1225 "VECTOR_MEM_VSX_P (<MODE>mode)"
1227 xxpermdi %x0,%x1,%x1,0
1228 xxpermdi %x0,%x1,%x1,0
1230 xxpermdi %x0,%x1,%x1,0
1231 xxpermdi %x0,%x1,%x1,0
1233 [(set_attr "type" "vecperm,vecperm,vecload,vecperm,vecperm,vecload")])
1236 (define_insn "vsx_xxspltw_<mode>"
1237 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1238 (vec_duplicate:VSX_W
1239 (vec_select:<VS_scalar>
1240 (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1242 [(match_operand:QI 2 "u5bit_cint_operand" "i,i")]))))]
1243 "VECTOR_MEM_VSX_P (<MODE>mode)"
1244 "xxspltw %x0,%x1,%2"
1245 [(set_attr "type" "vecperm")])
1247 ;; V4SF/V4SI interleave
1248 (define_insn "vsx_xxmrghw_<mode>"
1249 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1252 (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1253 (parallel [(const_int 0)
1258 (match_operand:VSX_W 2 "vsx_register_operand" "wf,wa")
1259 (parallel [(const_int 2)
1264 "VECTOR_MEM_VSX_P (<MODE>mode)"
1265 "xxmrghw %x0,%x1,%x2"
1266 [(set_attr "type" "vecperm")])
1268 (define_insn "vsx_xxmrglw_<mode>"
1269 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1272 (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1273 (parallel [(const_int 2)
1278 (match_operand:VSX_W 2 "vsx_register_operand" "wf,?wa")
1279 (parallel [(const_int 0)
1284 "VECTOR_MEM_VSX_P (<MODE>mode)"
1285 "xxmrglw %x0,%x1,%x2"
1286 [(set_attr "type" "vecperm")])
1288 ;; Shift left double by word immediate
1289 (define_insn "vsx_xxsldwi_<mode>"
1290 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=wa")
1291 (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "wa")
1292 (match_operand:VSX_L 2 "vsx_register_operand" "wa")
1293 (match_operand:QI 3 "u5bit_cint_operand" "i")]
1295 "VECTOR_MEM_VSX_P (<MODE>mode)"
1296 "xxsldwi %x0,%x1,%x2,%3"
1297 [(set_attr "type" "vecperm")])
1300 ;; Vector reduction insns and splitters
1302 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v2df"
1303 [(set (match_operand:V2DF 0 "vfloat_operand" "=&wd,&?wa,wd,?wa")
1307 (match_operand:V2DF 1 "vfloat_operand" "wd,wa,wd,wa")
1308 (parallel [(const_int 1)]))
1311 (parallel [(const_int 0)])))
1313 (clobber (match_scratch:V2DF 2 "=0,0,&wd,&wa"))]
1314 "VECTOR_UNIT_VSX_P (V2DFmode)"
1320 rtx tmp = (GET_CODE (operands[2]) == SCRATCH)
1321 ? gen_reg_rtx (V2DFmode)
1323 emit_insn (gen_vsx_xxsldwi_v2df (tmp, operands[1], operands[1], const2_rtx));
1324 emit_insn (gen_<VEC_reduc_rtx>v2df3 (operands[0], tmp, operands[1]));
1327 [(set_attr "length" "8")
1328 (set_attr "type" "veccomplex")])
1330 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v4sf"
1331 [(set (match_operand:V4SF 0 "vfloat_operand" "=wf,?wa")
1333 (unspec:V4SF [(const_int 0)] UNSPEC_REDUC)
1334 (match_operand:V4SF 1 "vfloat_operand" "wf,wa")))
1335 (clobber (match_scratch:V4SF 2 "=&wf,&wa"))
1336 (clobber (match_scratch:V4SF 3 "=&wf,&wa"))]
1337 "VECTOR_UNIT_VSX_P (V4SFmode)"
1343 rtx op0 = operands[0];
1344 rtx op1 = operands[1];
1345 rtx tmp2, tmp3, tmp4;
1347 if (can_create_pseudo_p ())
1349 tmp2 = gen_reg_rtx (V4SFmode);
1350 tmp3 = gen_reg_rtx (V4SFmode);
1351 tmp4 = gen_reg_rtx (V4SFmode);
1360 emit_insn (gen_vsx_xxsldwi_v4sf (tmp2, op1, op1, const2_rtx));
1361 emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp3, tmp2, op1));
1362 emit_insn (gen_vsx_xxsldwi_v4sf (tmp4, tmp3, tmp3, GEN_INT (3)));
1363 emit_insn (gen_<VEC_reduc_rtx>v4sf3 (op0, tmp4, tmp3));
1366 [(set_attr "length" "16")
1367 (set_attr "type" "veccomplex")])
1369 ;; Combiner patterns with the vector reduction patterns that knows we can get
1370 ;; to the top element of the V2DF array without doing an extract.
1372 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v2df_scalar"
1373 [(set (match_operand:DF 0 "vfloat_operand" "=&ws,&?wa,ws,?wa")
1378 (match_operand:V2DF 1 "vfloat_operand" "wd,wa,wd,wa")
1379 (parallel [(const_int 1)]))
1382 (parallel [(const_int 0)])))
1384 (parallel [(const_int 1)])))
1385 (clobber (match_scratch:DF 2 "=0,0,&wd,&wa"))]
1386 "VECTOR_UNIT_VSX_P (V2DFmode)"
1392 rtx hi = gen_highpart (DFmode, operands[1]);
1393 rtx lo = (GET_CODE (operands[2]) == SCRATCH)
1394 ? gen_reg_rtx (DFmode)
1397 emit_insn (gen_vsx_extract_v2df (lo, operands[1], const1_rtx));
1398 emit_insn (gen_<VEC_reduc_rtx>df3 (operands[0], hi, lo));
1401 [(set_attr "length" "8")
1402 (set_attr "type" "veccomplex")])
1404 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v4sf_scalar"
1405 [(set (match_operand:SF 0 "vfloat_operand" "=f,?f")
1408 (unspec:V4SF [(const_int 0)] UNSPEC_REDUC)
1409 (match_operand:V4SF 1 "vfloat_operand" "wf,wa"))
1410 (parallel [(const_int 3)])))
1411 (clobber (match_scratch:V4SF 2 "=&wf,&wa"))
1412 (clobber (match_scratch:V4SF 3 "=&wf,&wa"))
1413 (clobber (match_scratch:V4SF 4 "=0,0"))]
1414 "VECTOR_UNIT_VSX_P (V4SFmode)"
1420 rtx op0 = operands[0];
1421 rtx op1 = operands[1];
1422 rtx tmp2, tmp3, tmp4, tmp5;
1424 if (can_create_pseudo_p ())
1426 tmp2 = gen_reg_rtx (V4SFmode);
1427 tmp3 = gen_reg_rtx (V4SFmode);
1428 tmp4 = gen_reg_rtx (V4SFmode);
1429 tmp5 = gen_reg_rtx (V4SFmode);
1439 emit_insn (gen_vsx_xxsldwi_v4sf (tmp2, op1, op1, const2_rtx));
1440 emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp3, tmp2, op1));
1441 emit_insn (gen_vsx_xxsldwi_v4sf (tmp4, tmp3, tmp3, GEN_INT (3)));
1442 emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp5, tmp4, tmp3));
1443 emit_insn (gen_vsx_xscvspdp_scalar2 (op0, tmp5));
1446 [(set_attr "length" "20")
1447 (set_attr "type" "veccomplex")])