2 ;; Copyright (C) 2009-2016 Free Software Foundation, Inc.
3 ;; Contributed by Michael Meissner <meissner@linux.vnet.ibm.com>
5 ;; This file is part of GCC.
7 ;; GCC is free software; you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published
9 ;; by the Free Software Foundation; either version 3, or (at your
10 ;; option) any later version.
12 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
13 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 ;; License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3. If not see
19 ;; <http://www.gnu.org/licenses/>.
21 ;; Iterator for both scalar and vector floating point types supported by VSX
22 (define_mode_iterator VSX_B [DF V4SF V2DF])
24 ;; Iterator for the 2 64-bit vector types
25 (define_mode_iterator VSX_D [V2DF V2DI])
27 ;; Iterator for the 2 64-bit vector types + 128-bit types that are loaded with
28 ;; lxvd2x to properly handle swapping words on little endian
29 (define_mode_iterator VSX_LE [V2DF V2DI V1TI])
31 ;; Mode iterator to handle swapping words on little endian for the 128-bit
32 ;; types that goes in a single vector register.
33 (define_mode_iterator VSX_LE_128 [(KF "FLOAT128_VECTOR_P (KFmode)")
34 (TF "FLOAT128_VECTOR_P (TFmode)")
35 (TI "TARGET_VSX_TIMODE")])
37 ;; Iterator for the 2 32-bit vector types
38 (define_mode_iterator VSX_W [V4SF V4SI])
40 ;; Iterator for the DF types
41 (define_mode_iterator VSX_DF [V2DF DF])
43 ;; Iterator for vector floating point types supported by VSX
44 (define_mode_iterator VSX_F [V4SF V2DF])
46 ;; Iterator for logical types supported by VSX
47 (define_mode_iterator VSX_L [V16QI
55 (KF "FLOAT128_VECTOR_P (KFmode)")
56 (TF "FLOAT128_VECTOR_P (TFmode)")])
58 ;; Iterator for memory moves.
59 (define_mode_iterator VSX_M [V16QI
66 (KF "FLOAT128_VECTOR_P (KFmode)")
67 (TF "FLOAT128_VECTOR_P (TFmode)")
68 (TI "TARGET_VSX_TIMODE")])
70 ;; Map into the appropriate load/store name based on the type
71 (define_mode_attr VSm [(V16QI "vw4")
83 ;; Map into the appropriate suffix based on the type
84 (define_mode_attr VSs [(V16QI "sp")
97 ;; Map the register class used
98 (define_mode_attr VSr [(V16QI "v")
112 ;; Map the register class used for float<->int conversions (floating point side)
113 ;; VSr2 is the preferred register class, VSr3 is any register class that will
115 (define_mode_attr VSr2 [(V2DF "wd")
121 (define_mode_attr VSr3 [(V2DF "wa")
127 ;; Map the register class for sp<->dp float conversions, destination
128 (define_mode_attr VSr4 [(SF "ws")
133 ;; Map the register class for sp<->dp float conversions, source
134 (define_mode_attr VSr5 [(SF "ws")
139 ;; The VSX register class that a type can occupy, even if it is not the
140 ;; preferred register class (VSr is the preferred register class that will get
142 (define_mode_attr VSa [(V16QI "wa")
156 ;; Same size integer type for floating point data
157 (define_mode_attr VSi [(V4SF "v4si")
161 (define_mode_attr VSI [(V4SF "V4SI")
165 ;; Word size for same size conversion
166 (define_mode_attr VSc [(V4SF "w")
170 ;; Map into either s or v, depending on whether this is a scalar or vector
172 (define_mode_attr VSv [(V16QI "v")
182 ;; Appropriate type for add ops (and other simple FP ops)
183 (define_mode_attr VStype_simple [(V2DF "vecdouble")
187 (define_mode_attr VSfptype_simple [(V2DF "fp_addsub_d")
191 ;; Appropriate type for multiply ops
192 (define_mode_attr VStype_mul [(V2DF "vecdouble")
196 (define_mode_attr VSfptype_mul [(V2DF "fp_mul_d")
200 ;; Appropriate type for divide ops.
201 (define_mode_attr VStype_div [(V2DF "vecdiv")
205 (define_mode_attr VSfptype_div [(V2DF "fp_div_d")
209 ;; Appropriate type for sqrt ops. For now, just lump the vector sqrt with
211 (define_mode_attr VStype_sqrt [(V2DF "dsqrt")
215 (define_mode_attr VSfptype_sqrt [(V2DF "fp_sqrt_d")
219 ;; Iterator and modes for sp<->dp conversions
220 ;; Because scalar SF values are represented internally as double, use the
221 ;; V4SF type to represent this than SF.
222 (define_mode_iterator VSX_SPDP [DF V4SF V2DF])
224 (define_mode_attr VS_spdp_res [(DF "V4SF")
228 (define_mode_attr VS_spdp_insn [(DF "xscvdpsp")
232 (define_mode_attr VS_spdp_type [(DF "fp")
236 ;; Map the scalar mode for a vector type
237 (define_mode_attr VS_scalar [(V1TI "TI")
245 ;; Map to a double-sized vector mode
246 (define_mode_attr VS_double [(V4SI "V8SI")
252 ;; Map register class for 64-bit element in 128-bit vector for direct moves
254 (define_mode_attr VS_64dm [(V2DF "wk")
257 ;; Map register class for 64-bit element in 128-bit vector for normal register
259 (define_mode_attr VS_64reg [(V2DF "ws")
262 ;; Iterators for loading constants with xxspltib
263 (define_mode_iterator VSINT_84 [V4SI V2DI DI])
264 (define_mode_iterator VSINT_842 [V8HI V4SI V2DI])
266 ;; Iterator for ISA 3.0 vector extract/insert of integer vectors
267 (define_mode_iterator VSX_EXTRACT_I [V16QI V8HI V4SI])
269 ;; Mode attribute to give the correct predicate for ISA 3.0 vector extract and
270 ;; insert to validate the operand number.
271 (define_mode_attr VSX_EXTRACT_PREDICATE [(V16QI "const_0_to_15_operand")
272 (V8HI "const_0_to_7_operand")
273 (V4SI "const_0_to_3_operand")])
275 ;; Mode attribute to give the constraint for vector extract and insert
277 (define_mode_attr VSX_EX [(V16QI "v")
281 ;; Constants for creating unspecs
282 (define_c_enum "unspec"
308 UNSPEC_VSX_XVCVDPSXDS
309 UNSPEC_VSX_XVCVDPUXDS
310 UNSPEC_VSX_SIGN_EXTEND
316 ;; The patterns for LE permuted loads and stores come before the general
317 ;; VSX moves so they match first.
318 (define_insn_and_split "*vsx_le_perm_load_<mode>"
319 [(set (match_operand:VSX_LE 0 "vsx_register_operand" "=<VSa>")
320 (match_operand:VSX_LE 1 "memory_operand" "Z"))]
321 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
323 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
327 (parallel [(const_int 1) (const_int 0)])))
331 (parallel [(const_int 1) (const_int 0)])))]
334 operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
338 [(set_attr "type" "vecload")
339 (set_attr "length" "8")])
341 (define_insn_and_split "*vsx_le_perm_load_<mode>"
342 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=<VSa>")
343 (match_operand:VSX_W 1 "memory_operand" "Z"))]
344 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
346 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
350 (parallel [(const_int 2) (const_int 3)
351 (const_int 0) (const_int 1)])))
355 (parallel [(const_int 2) (const_int 3)
356 (const_int 0) (const_int 1)])))]
359 operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
363 [(set_attr "type" "vecload")
364 (set_attr "length" "8")])
366 (define_insn_and_split "*vsx_le_perm_load_v8hi"
367 [(set (match_operand:V8HI 0 "vsx_register_operand" "=wa")
368 (match_operand:V8HI 1 "memory_operand" "Z"))]
369 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
371 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
375 (parallel [(const_int 4) (const_int 5)
376 (const_int 6) (const_int 7)
377 (const_int 0) (const_int 1)
378 (const_int 2) (const_int 3)])))
382 (parallel [(const_int 4) (const_int 5)
383 (const_int 6) (const_int 7)
384 (const_int 0) (const_int 1)
385 (const_int 2) (const_int 3)])))]
388 operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
392 [(set_attr "type" "vecload")
393 (set_attr "length" "8")])
395 (define_insn_and_split "*vsx_le_perm_load_v16qi"
396 [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
397 (match_operand:V16QI 1 "memory_operand" "Z"))]
398 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
400 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
404 (parallel [(const_int 8) (const_int 9)
405 (const_int 10) (const_int 11)
406 (const_int 12) (const_int 13)
407 (const_int 14) (const_int 15)
408 (const_int 0) (const_int 1)
409 (const_int 2) (const_int 3)
410 (const_int 4) (const_int 5)
411 (const_int 6) (const_int 7)])))
415 (parallel [(const_int 8) (const_int 9)
416 (const_int 10) (const_int 11)
417 (const_int 12) (const_int 13)
418 (const_int 14) (const_int 15)
419 (const_int 0) (const_int 1)
420 (const_int 2) (const_int 3)
421 (const_int 4) (const_int 5)
422 (const_int 6) (const_int 7)])))]
425 operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
429 [(set_attr "type" "vecload")
430 (set_attr "length" "8")])
432 (define_insn "*vsx_le_perm_store_<mode>"
433 [(set (match_operand:VSX_LE 0 "memory_operand" "=Z")
434 (match_operand:VSX_LE 1 "vsx_register_operand" "+<VSa>"))]
435 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
437 [(set_attr "type" "vecstore")
438 (set_attr "length" "12")])
441 [(set (match_operand:VSX_LE 0 "memory_operand" "")
442 (match_operand:VSX_LE 1 "vsx_register_operand" ""))]
443 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && !reload_completed"
447 (parallel [(const_int 1) (const_int 0)])))
451 (parallel [(const_int 1) (const_int 0)])))]
453 operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[1])
457 ;; The post-reload split requires that we re-permute the source
458 ;; register in case it is still live.
460 [(set (match_operand:VSX_LE 0 "memory_operand" "")
461 (match_operand:VSX_LE 1 "vsx_register_operand" ""))]
462 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && reload_completed"
466 (parallel [(const_int 1) (const_int 0)])))
470 (parallel [(const_int 1) (const_int 0)])))
474 (parallel [(const_int 1) (const_int 0)])))]
477 (define_insn "*vsx_le_perm_store_<mode>"
478 [(set (match_operand:VSX_W 0 "memory_operand" "=Z")
479 (match_operand:VSX_W 1 "vsx_register_operand" "+<VSa>"))]
480 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
482 [(set_attr "type" "vecstore")
483 (set_attr "length" "12")])
486 [(set (match_operand:VSX_W 0 "memory_operand" "")
487 (match_operand:VSX_W 1 "vsx_register_operand" ""))]
488 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && !reload_completed"
492 (parallel [(const_int 2) (const_int 3)
493 (const_int 0) (const_int 1)])))
497 (parallel [(const_int 2) (const_int 3)
498 (const_int 0) (const_int 1)])))]
500 operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[1])
504 ;; The post-reload split requires that we re-permute the source
505 ;; register in case it is still live.
507 [(set (match_operand:VSX_W 0 "memory_operand" "")
508 (match_operand:VSX_W 1 "vsx_register_operand" ""))]
509 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && reload_completed"
513 (parallel [(const_int 2) (const_int 3)
514 (const_int 0) (const_int 1)])))
518 (parallel [(const_int 2) (const_int 3)
519 (const_int 0) (const_int 1)])))
523 (parallel [(const_int 2) (const_int 3)
524 (const_int 0) (const_int 1)])))]
527 (define_insn "*vsx_le_perm_store_v8hi"
528 [(set (match_operand:V8HI 0 "memory_operand" "=Z")
529 (match_operand:V8HI 1 "vsx_register_operand" "+wa"))]
530 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
532 [(set_attr "type" "vecstore")
533 (set_attr "length" "12")])
536 [(set (match_operand:V8HI 0 "memory_operand" "")
537 (match_operand:V8HI 1 "vsx_register_operand" ""))]
538 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && !reload_completed"
542 (parallel [(const_int 4) (const_int 5)
543 (const_int 6) (const_int 7)
544 (const_int 0) (const_int 1)
545 (const_int 2) (const_int 3)])))
549 (parallel [(const_int 4) (const_int 5)
550 (const_int 6) (const_int 7)
551 (const_int 0) (const_int 1)
552 (const_int 2) (const_int 3)])))]
554 operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[1])
558 ;; The post-reload split requires that we re-permute the source
559 ;; register in case it is still live.
561 [(set (match_operand:V8HI 0 "memory_operand" "")
562 (match_operand:V8HI 1 "vsx_register_operand" ""))]
563 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && reload_completed"
567 (parallel [(const_int 4) (const_int 5)
568 (const_int 6) (const_int 7)
569 (const_int 0) (const_int 1)
570 (const_int 2) (const_int 3)])))
574 (parallel [(const_int 4) (const_int 5)
575 (const_int 6) (const_int 7)
576 (const_int 0) (const_int 1)
577 (const_int 2) (const_int 3)])))
581 (parallel [(const_int 4) (const_int 5)
582 (const_int 6) (const_int 7)
583 (const_int 0) (const_int 1)
584 (const_int 2) (const_int 3)])))]
587 (define_insn "*vsx_le_perm_store_v16qi"
588 [(set (match_operand:V16QI 0 "memory_operand" "=Z")
589 (match_operand:V16QI 1 "vsx_register_operand" "+wa"))]
590 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
592 [(set_attr "type" "vecstore")
593 (set_attr "length" "12")])
596 [(set (match_operand:V16QI 0 "memory_operand" "")
597 (match_operand:V16QI 1 "vsx_register_operand" ""))]
598 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && !reload_completed"
602 (parallel [(const_int 8) (const_int 9)
603 (const_int 10) (const_int 11)
604 (const_int 12) (const_int 13)
605 (const_int 14) (const_int 15)
606 (const_int 0) (const_int 1)
607 (const_int 2) (const_int 3)
608 (const_int 4) (const_int 5)
609 (const_int 6) (const_int 7)])))
613 (parallel [(const_int 8) (const_int 9)
614 (const_int 10) (const_int 11)
615 (const_int 12) (const_int 13)
616 (const_int 14) (const_int 15)
617 (const_int 0) (const_int 1)
618 (const_int 2) (const_int 3)
619 (const_int 4) (const_int 5)
620 (const_int 6) (const_int 7)])))]
622 operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[1])
626 ;; The post-reload split requires that we re-permute the source
627 ;; register in case it is still live.
629 [(set (match_operand:V16QI 0 "memory_operand" "")
630 (match_operand:V16QI 1 "vsx_register_operand" ""))]
631 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && reload_completed"
635 (parallel [(const_int 8) (const_int 9)
636 (const_int 10) (const_int 11)
637 (const_int 12) (const_int 13)
638 (const_int 14) (const_int 15)
639 (const_int 0) (const_int 1)
640 (const_int 2) (const_int 3)
641 (const_int 4) (const_int 5)
642 (const_int 6) (const_int 7)])))
646 (parallel [(const_int 8) (const_int 9)
647 (const_int 10) (const_int 11)
648 (const_int 12) (const_int 13)
649 (const_int 14) (const_int 15)
650 (const_int 0) (const_int 1)
651 (const_int 2) (const_int 3)
652 (const_int 4) (const_int 5)
653 (const_int 6) (const_int 7)])))
657 (parallel [(const_int 8) (const_int 9)
658 (const_int 10) (const_int 11)
659 (const_int 12) (const_int 13)
660 (const_int 14) (const_int 15)
661 (const_int 0) (const_int 1)
662 (const_int 2) (const_int 3)
663 (const_int 4) (const_int 5)
664 (const_int 6) (const_int 7)])))]
667 ;; Little endian word swapping for 128-bit types that are either scalars or the
668 ;; special V1TI container class, which it is not appropriate to use vec_select
670 (define_insn "*vsx_le_permute_<mode>"
671 [(set (match_operand:VSX_LE_128 0 "nonimmediate_operand" "=<VSa>,<VSa>,Z")
673 (match_operand:VSX_LE_128 1 "input_operand" "<VSa>,Z,<VSa>")
675 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
677 xxpermdi %x0,%x1,%x1,2
680 [(set_attr "length" "4")
681 (set_attr "type" "vecperm,vecload,vecstore")])
683 (define_insn_and_split "*vsx_le_undo_permute_<mode>"
684 [(set (match_operand:VSX_LE_128 0 "vsx_register_operand" "=<VSa>,<VSa>")
687 (match_operand:VSX_LE_128 1 "vsx_register_operand" "0,<VSa>")
690 "!BYTES_BIG_ENDIAN && TARGET_VSX"
695 [(set (match_dup 0) (match_dup 1))]
697 if (reload_completed && REGNO (operands[0]) == REGNO (operands[1]))
699 emit_note (NOTE_INSN_DELETED);
703 [(set_attr "length" "0,4")
704 (set_attr "type" "veclogical")])
706 (define_insn_and_split "*vsx_le_perm_load_<mode>"
707 [(set (match_operand:VSX_LE_128 0 "vsx_register_operand" "=<VSa>")
708 (match_operand:VSX_LE_128 1 "memory_operand" "Z"))]
709 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
711 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
713 (rotate:VSX_LE_128 (match_dup 1)
716 (rotate:VSX_LE_128 (match_dup 2)
720 operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
724 [(set_attr "type" "vecload")
725 (set_attr "length" "8")])
727 (define_insn "*vsx_le_perm_store_<mode>"
728 [(set (match_operand:VSX_LE_128 0 "memory_operand" "=Z")
729 (match_operand:VSX_LE_128 1 "vsx_register_operand" "+<VSa>"))]
730 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
732 [(set_attr "type" "vecstore")
733 (set_attr "length" "12")])
736 [(set (match_operand:VSX_LE_128 0 "memory_operand" "")
737 (match_operand:VSX_LE_128 1 "vsx_register_operand" ""))]
738 "!BYTES_BIG_ENDIAN && TARGET_VSX && !reload_completed && !TARGET_P9_VECTOR"
740 (rotate:VSX_LE_128 (match_dup 1)
743 (rotate:VSX_LE_128 (match_dup 2)
746 operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
750 ;; Peephole to catch memory to memory transfers for TImode if TImode landed in
751 ;; VSX registers on a little endian system. The vector types and IEEE 128-bit
752 ;; floating point are handled by the more generic swap elimination pass.
754 [(set (match_operand:TI 0 "vsx_register_operand" "")
755 (rotate:TI (match_operand:TI 1 "vsx_register_operand" "")
757 (set (match_operand:TI 2 "vsx_register_operand" "")
758 (rotate:TI (match_dup 0)
760 "!BYTES_BIG_ENDIAN && TARGET_VSX && TARGET_VSX_TIMODE && !TARGET_P9_VECTOR
761 && (rtx_equal_p (operands[0], operands[2])
762 || peep2_reg_dead_p (2, operands[0]))"
763 [(set (match_dup 2) (match_dup 1))])
765 ;; The post-reload split requires that we re-permute the source
766 ;; register in case it is still live.
768 [(set (match_operand:VSX_LE_128 0 "memory_operand" "")
769 (match_operand:VSX_LE_128 1 "vsx_register_operand" ""))]
770 "!BYTES_BIG_ENDIAN && TARGET_VSX && reload_completed && !TARGET_P9_VECTOR"
772 (rotate:VSX_LE_128 (match_dup 1)
775 (rotate:VSX_LE_128 (match_dup 1)
778 (rotate:VSX_LE_128 (match_dup 1)
782 ;; Vector constants that can be generated with XXSPLTIB that was added in ISA
783 ;; 3.0. Both (const_vector [..]) and (vec_duplicate ...) forms are recognized.
784 (define_insn "xxspltib_v16qi"
785 [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
786 (vec_duplicate:V16QI (match_operand:SI 1 "s8bit_cint_operand" "n")))]
789 operands[2] = GEN_INT (INTVAL (operands[1]) & 0xff);
790 return "xxspltib %x0,%2";
792 [(set_attr "type" "vecperm")])
794 (define_insn "xxspltib_<mode>_nosplit"
795 [(set (match_operand:VSINT_842 0 "vsx_register_operand" "=wa,wa")
796 (match_operand:VSINT_842 1 "xxspltib_constant_nosplit" "jwM,wE"))]
799 rtx op1 = operands[1];
803 if (!xxspltib_constant_p (op1, <MODE>mode, &num_insns, &value)
807 operands[2] = GEN_INT (value & 0xff);
808 return "xxspltib %x0,%2";
810 [(set_attr "type" "vecperm")])
812 (define_insn_and_split "*xxspltib_<mode>_split"
813 [(set (match_operand:VSINT_842 0 "altivec_register_operand" "=v")
814 (match_operand:VSINT_842 1 "xxspltib_constant_split" "wS"))]
822 rtx op0 = operands[0];
823 rtx op1 = operands[1];
824 rtx tmp = ((can_create_pseudo_p ())
825 ? gen_reg_rtx (V16QImode)
826 : gen_lowpart (V16QImode, op0));
828 if (!xxspltib_constant_p (op1, <MODE>mode, &num_insns, &value)
832 emit_insn (gen_xxspltib_v16qi (tmp, GEN_INT (value)));
834 if (<MODE>mode == V2DImode)
835 emit_insn (gen_vsx_sign_extend_qi_v2di (op0, tmp));
837 else if (<MODE>mode == V4SImode)
838 emit_insn (gen_vsx_sign_extend_qi_v4si (op0, tmp));
840 else if (<MODE>mode == V8HImode)
841 emit_insn (gen_altivec_vupkhsb (op0, tmp));
848 [(set_attr "type" "vecperm")
849 (set_attr "length" "8")])
852 ;; Prefer using vector registers over GPRs. Prefer using ISA 3.0's XXSPLTISB
853 ;; or Altivec VSPLITW 0/-1 over XXLXOR/XXLORC to set a register to all 0's or
854 ;; all 1's, since the machine does not have to wait for the previous
855 ;; instruction using the register being set (such as a store waiting on a slow
856 ;; instruction). But generate XXLXOR/XXLORC if it will avoid a register move.
858 ;; VSX store VSX load VSX move VSX->GPR GPR->VSX LQ (GPR)
859 ;; STQ (GPR) GPR load GPR store GPR move XXSPLTIB VSPLTISW
860 ;; VSX 0/-1 GPR 0/-1 VMX const GPR const LVX (VMX) STVX (VMX)
861 (define_insn "*vsx_mov<mode>_64bit"
862 [(set (match_operand:VSX_M 0 "nonimmediate_operand"
863 "=ZwO, <VSa>, <VSa>, r, we, ?wQ,
864 ?&r, ??r, ??Y, ??r, wo, v,
865 ?<VSa>, *r, v, ??r, wZ, v")
867 (match_operand:VSX_M 1 "input_operand"
868 "<VSa>, ZwO, <VSa>, we, r, r,
869 wQ, Y, r, r, wE, jwM,
870 ?jwM, jwM, W, W, v, wZ"))]
872 "TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)
873 && (register_operand (operands[0], <MODE>mode)
874 || register_operand (operands[1], <MODE>mode))"
876 return rs6000_output_move_128bit (operands);
879 "vecstore, vecload, vecsimple, mffgpr, mftgpr, load,
880 store, load, store, *, vecsimple, vecsimple,
881 vecsimple, *, *, *, vecstore, vecload")
886 4, 8, 20, 20, 4, 4")])
888 ;; VSX store VSX load VSX move GPR load GPR store GPR move
889 ;; XXSPLTIB VSPLTISW VSX 0/-1 GPR 0/-1 VMX const GPR const
890 ;; LVX (VMX) STVX (VMX)
891 (define_insn "*vsx_mov<mode>_32bit"
892 [(set (match_operand:VSX_M 0 "nonimmediate_operand"
893 "=ZwO, <VSa>, <VSa>, ??r, ??Y, ??r,
894 wo, v, ?<VSa>, *r, v, ??r,
897 (match_operand:VSX_M 1 "input_operand"
898 "<VSa>, ZwO, <VSa>, Y, r, r,
899 wE, jwM, ?jwM, jwM, W, W,
902 "!TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)
903 && (register_operand (operands[0], <MODE>mode)
904 || register_operand (operands[1], <MODE>mode))"
906 return rs6000_output_move_128bit (operands);
909 "vecstore, vecload, vecsimple, load, store, *,
910 vecsimple, vecsimple, vecsimple, *, *, *,
914 "4, 4, 4, 16, 16, 16,
918 ;; Explicit load/store expanders for the builtin functions
919 (define_expand "vsx_load_<mode>"
920 [(set (match_operand:VSX_M 0 "vsx_register_operand" "")
921 (match_operand:VSX_M 1 "memory_operand" ""))]
922 "VECTOR_MEM_VSX_P (<MODE>mode)"
925 (define_expand "vsx_store_<mode>"
926 [(set (match_operand:VSX_M 0 "memory_operand" "")
927 (match_operand:VSX_M 1 "vsx_register_operand" ""))]
928 "VECTOR_MEM_VSX_P (<MODE>mode)"
931 ;; Explicit load/store expanders for the builtin functions for lxvd2x, etc.,
932 ;; when you really want their element-reversing behavior.
933 (define_insn "vsx_ld_elemrev_v2di"
934 [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
936 (match_operand:V2DI 1 "memory_operand" "Z")
937 (parallel [(const_int 1) (const_int 0)])))]
938 "VECTOR_MEM_VSX_P (V2DImode) && !BYTES_BIG_ENDIAN"
940 [(set_attr "type" "vecload")])
942 (define_insn "vsx_ld_elemrev_v2df"
943 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wa")
945 (match_operand:V2DF 1 "memory_operand" "Z")
946 (parallel [(const_int 1) (const_int 0)])))]
947 "VECTOR_MEM_VSX_P (V2DFmode) && !BYTES_BIG_ENDIAN"
949 [(set_attr "type" "vecload")])
951 (define_insn "vsx_ld_elemrev_v4si"
952 [(set (match_operand:V4SI 0 "vsx_register_operand" "=wa")
954 (match_operand:V4SI 1 "memory_operand" "Z")
955 (parallel [(const_int 3) (const_int 2)
956 (const_int 1) (const_int 0)])))]
957 "VECTOR_MEM_VSX_P (V4SImode) && !BYTES_BIG_ENDIAN"
959 [(set_attr "type" "vecload")])
961 (define_insn "vsx_ld_elemrev_v4sf"
962 [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
964 (match_operand:V4SF 1 "memory_operand" "Z")
965 (parallel [(const_int 3) (const_int 2)
966 (const_int 1) (const_int 0)])))]
967 "VECTOR_MEM_VSX_P (V4SFmode) && !BYTES_BIG_ENDIAN"
969 [(set_attr "type" "vecload")])
971 (define_insn "vsx_ld_elemrev_v8hi"
972 [(set (match_operand:V8HI 0 "vsx_register_operand" "=wa")
974 (match_operand:V8HI 1 "memory_operand" "Z")
975 (parallel [(const_int 7) (const_int 6)
976 (const_int 5) (const_int 4)
977 (const_int 3) (const_int 2)
978 (const_int 1) (const_int 0)])))]
979 "VECTOR_MEM_VSX_P (V8HImode) && !BYTES_BIG_ENDIAN && TARGET_P9_VECTOR"
981 [(set_attr "type" "vecload")])
983 (define_insn "vsx_ld_elemrev_v16qi"
984 [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
986 (match_operand:V16QI 1 "memory_operand" "Z")
987 (parallel [(const_int 15) (const_int 14)
988 (const_int 13) (const_int 12)
989 (const_int 11) (const_int 10)
990 (const_int 9) (const_int 8)
991 (const_int 7) (const_int 6)
992 (const_int 5) (const_int 4)
993 (const_int 3) (const_int 2)
994 (const_int 1) (const_int 0)])))]
995 "VECTOR_MEM_VSX_P (V16QImode) && !BYTES_BIG_ENDIAN && TARGET_P9_VECTOR"
997 [(set_attr "type" "vecload")])
999 (define_insn "vsx_st_elemrev_v2df"
1000 [(set (match_operand:V2DF 0 "memory_operand" "=Z")
1002 (match_operand:V2DF 1 "vsx_register_operand" "wa")
1003 (parallel [(const_int 1) (const_int 0)])))]
1004 "VECTOR_MEM_VSX_P (V2DFmode) && !BYTES_BIG_ENDIAN"
1006 [(set_attr "type" "vecstore")])
1008 (define_insn "vsx_st_elemrev_v2di"
1009 [(set (match_operand:V2DI 0 "memory_operand" "=Z")
1011 (match_operand:V2DI 1 "vsx_register_operand" "wa")
1012 (parallel [(const_int 1) (const_int 0)])))]
1013 "VECTOR_MEM_VSX_P (V2DImode) && !BYTES_BIG_ENDIAN"
1015 [(set_attr "type" "vecstore")])
1017 (define_insn "vsx_st_elemrev_v4sf"
1018 [(set (match_operand:V4SF 0 "memory_operand" "=Z")
1020 (match_operand:V4SF 1 "vsx_register_operand" "wa")
1021 (parallel [(const_int 3) (const_int 2)
1022 (const_int 1) (const_int 0)])))]
1023 "VECTOR_MEM_VSX_P (V4SFmode) && !BYTES_BIG_ENDIAN"
1025 [(set_attr "type" "vecstore")])
1027 (define_insn "vsx_st_elemrev_v4si"
1028 [(set (match_operand:V4SI 0 "memory_operand" "=Z")
1030 (match_operand:V4SI 1 "vsx_register_operand" "wa")
1031 (parallel [(const_int 3) (const_int 2)
1032 (const_int 1) (const_int 0)])))]
1033 "VECTOR_MEM_VSX_P (V4SImode) && !BYTES_BIG_ENDIAN"
1035 [(set_attr "type" "vecstore")])
1037 (define_insn "vsx_st_elemrev_v8hi"
1038 [(set (match_operand:V8HI 0 "memory_operand" "=Z")
1040 (match_operand:V8HI 1 "vsx_register_operand" "wa")
1041 (parallel [(const_int 7) (const_int 6)
1042 (const_int 5) (const_int 4)
1043 (const_int 3) (const_int 2)
1044 (const_int 1) (const_int 0)])))]
1045 "VECTOR_MEM_VSX_P (V8HImode) && !BYTES_BIG_ENDIAN && TARGET_P9_VECTOR"
1047 [(set_attr "type" "vecstore")])
1049 (define_insn "vsx_st_elemrev_v16qi"
1050 [(set (match_operand:V16QI 0 "memory_operand" "=Z")
1052 (match_operand:V16QI 1 "vsx_register_operand" "wa")
1053 (parallel [(const_int 15) (const_int 14)
1054 (const_int 13) (const_int 12)
1055 (const_int 11) (const_int 10)
1056 (const_int 9) (const_int 8)
1057 (const_int 7) (const_int 6)
1058 (const_int 5) (const_int 4)
1059 (const_int 3) (const_int 2)
1060 (const_int 1) (const_int 0)])))]
1061 "VECTOR_MEM_VSX_P (V16QImode) && !BYTES_BIG_ENDIAN && TARGET_P9_VECTOR"
1063 [(set_attr "type" "vecstore")])
1066 ;; VSX vector floating point arithmetic instructions. The VSX scalar
1067 ;; instructions are now combined with the insn for the traditional floating
1069 (define_insn "*vsx_add<mode>3"
1070 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1071 (plus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1072 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1073 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1074 "xvadd<VSs> %x0,%x1,%x2"
1075 [(set_attr "type" "<VStype_simple>")
1076 (set_attr "fp_type" "<VSfptype_simple>")])
1078 (define_insn "*vsx_sub<mode>3"
1079 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1080 (minus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1081 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1082 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1083 "xvsub<VSs> %x0,%x1,%x2"
1084 [(set_attr "type" "<VStype_simple>")
1085 (set_attr "fp_type" "<VSfptype_simple>")])
1087 (define_insn "*vsx_mul<mode>3"
1088 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1089 (mult:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1090 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1091 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1092 "xvmul<VSs> %x0,%x1,%x2"
1093 [(set_attr "type" "<VStype_simple>")
1094 (set_attr "fp_type" "<VSfptype_mul>")])
1096 ; Emulate vector with scalar for vec_mul in V2DImode
1097 (define_insn_and_split "vsx_mul_v2di"
1098 [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
1099 (unspec:V2DI [(match_operand:V2DI 1 "vsx_register_operand" "wa")
1100 (match_operand:V2DI 2 "vsx_register_operand" "wa")]
1102 "VECTOR_MEM_VSX_P (V2DImode)"
1104 "VECTOR_MEM_VSX_P (V2DImode) && !reload_completed && !reload_in_progress"
1108 rtx op0 = operands[0];
1109 rtx op1 = operands[1];
1110 rtx op2 = operands[2];
1111 rtx op3 = gen_reg_rtx (DImode);
1112 rtx op4 = gen_reg_rtx (DImode);
1113 rtx op5 = gen_reg_rtx (DImode);
1114 emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (0)));
1115 emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (0)));
1116 emit_insn (gen_muldi3 (op5, op3, op4));
1117 emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (1)));
1118 emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (1)));
1119 emit_insn (gen_muldi3 (op3, op3, op4));
1120 emit_insn (gen_vsx_concat_v2di (op0, op5, op3));
1123 [(set_attr "type" "mul")])
1125 (define_insn "*vsx_div<mode>3"
1126 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1127 (div:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1128 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1129 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1130 "xvdiv<VSs> %x0,%x1,%x2"
1131 [(set_attr "type" "<VStype_div>")
1132 (set_attr "fp_type" "<VSfptype_div>")])
1134 ; Emulate vector with scalar for vec_div in V2DImode
1135 (define_insn_and_split "vsx_div_v2di"
1136 [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
1137 (unspec:V2DI [(match_operand:V2DI 1 "vsx_register_operand" "wa")
1138 (match_operand:V2DI 2 "vsx_register_operand" "wa")]
1140 "VECTOR_MEM_VSX_P (V2DImode)"
1142 "VECTOR_MEM_VSX_P (V2DImode) && !reload_completed && !reload_in_progress"
1146 rtx op0 = operands[0];
1147 rtx op1 = operands[1];
1148 rtx op2 = operands[2];
1149 rtx op3 = gen_reg_rtx (DImode);
1150 rtx op4 = gen_reg_rtx (DImode);
1151 rtx op5 = gen_reg_rtx (DImode);
1152 emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (0)));
1153 emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (0)));
1154 emit_insn (gen_divdi3 (op5, op3, op4));
1155 emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (1)));
1156 emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (1)));
1157 emit_insn (gen_divdi3 (op3, op3, op4));
1158 emit_insn (gen_vsx_concat_v2di (op0, op5, op3));
1161 [(set_attr "type" "div")])
1163 (define_insn_and_split "vsx_udiv_v2di"
1164 [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
1165 (unspec:V2DI [(match_operand:V2DI 1 "vsx_register_operand" "wa")
1166 (match_operand:V2DI 2 "vsx_register_operand" "wa")]
1168 "VECTOR_MEM_VSX_P (V2DImode)"
1170 "VECTOR_MEM_VSX_P (V2DImode) && !reload_completed && !reload_in_progress"
1174 rtx op0 = operands[0];
1175 rtx op1 = operands[1];
1176 rtx op2 = operands[2];
1177 rtx op3 = gen_reg_rtx (DImode);
1178 rtx op4 = gen_reg_rtx (DImode);
1179 rtx op5 = gen_reg_rtx (DImode);
1180 emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (0)));
1181 emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (0)));
1182 emit_insn (gen_udivdi3 (op5, op3, op4));
1183 emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (1)));
1184 emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (1)));
1185 emit_insn (gen_udivdi3 (op3, op3, op4));
1186 emit_insn (gen_vsx_concat_v2di (op0, op5, op3));
1189 [(set_attr "type" "div")])
1191 ;; *tdiv* instruction returning the FG flag
1192 (define_expand "vsx_tdiv<mode>3_fg"
1194 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
1195 (match_operand:VSX_B 2 "vsx_register_operand" "")]
1197 (set (match_operand:SI 0 "gpc_reg_operand" "")
1198 (gt:SI (match_dup 3)
1200 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1202 operands[3] = gen_reg_rtx (CCFPmode);
1205 ;; *tdiv* instruction returning the FE flag
1206 (define_expand "vsx_tdiv<mode>3_fe"
1208 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
1209 (match_operand:VSX_B 2 "vsx_register_operand" "")]
1211 (set (match_operand:SI 0 "gpc_reg_operand" "")
1212 (eq:SI (match_dup 3)
1214 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1216 operands[3] = gen_reg_rtx (CCFPmode);
1219 (define_insn "*vsx_tdiv<mode>3_internal"
1220 [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
1221 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSa>")
1222 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,<VSa>")]
1224 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1225 "x<VSv>tdiv<VSs> %0,%x1,%x2"
1226 [(set_attr "type" "<VStype_simple>")
1227 (set_attr "fp_type" "<VSfptype_simple>")])
1229 (define_insn "vsx_fre<mode>2"
1230 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1231 (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")]
1233 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1235 [(set_attr "type" "<VStype_simple>")
1236 (set_attr "fp_type" "<VSfptype_simple>")])
1238 (define_insn "*vsx_neg<mode>2"
1239 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1240 (neg:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")))]
1241 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1242 "xvneg<VSs> %x0,%x1"
1243 [(set_attr "type" "<VStype_simple>")
1244 (set_attr "fp_type" "<VSfptype_simple>")])
1246 (define_insn "*vsx_abs<mode>2"
1247 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1248 (abs:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")))]
1249 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1250 "xvabs<VSs> %x0,%x1"
1251 [(set_attr "type" "<VStype_simple>")
1252 (set_attr "fp_type" "<VSfptype_simple>")])
1254 (define_insn "vsx_nabs<mode>2"
1255 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1258 (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>"))))]
1259 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1260 "xvnabs<VSs> %x0,%x1"
1261 [(set_attr "type" "<VStype_simple>")
1262 (set_attr "fp_type" "<VSfptype_simple>")])
1264 (define_insn "vsx_smax<mode>3"
1265 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1266 (smax:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1267 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1268 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1269 "xvmax<VSs> %x0,%x1,%x2"
1270 [(set_attr "type" "<VStype_simple>")
1271 (set_attr "fp_type" "<VSfptype_simple>")])
1273 (define_insn "*vsx_smin<mode>3"
1274 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1275 (smin:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1276 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1277 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1278 "xvmin<VSs> %x0,%x1,%x2"
1279 [(set_attr "type" "<VStype_simple>")
1280 (set_attr "fp_type" "<VSfptype_simple>")])
1282 (define_insn "*vsx_sqrt<mode>2"
1283 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1284 (sqrt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")))]
1285 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1286 "xvsqrt<VSs> %x0,%x1"
1287 [(set_attr "type" "<VStype_sqrt>")
1288 (set_attr "fp_type" "<VSfptype_sqrt>")])
1290 (define_insn "*vsx_rsqrte<mode>2"
1291 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1292 (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")]
1294 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1295 "xvrsqrte<VSs> %x0,%x1"
1296 [(set_attr "type" "<VStype_simple>")
1297 (set_attr "fp_type" "<VSfptype_simple>")])
1299 ;; *tsqrt* returning the fg flag
1300 (define_expand "vsx_tsqrt<mode>2_fg"
1302 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
1304 (set (match_operand:SI 0 "gpc_reg_operand" "")
1305 (gt:SI (match_dup 3)
1307 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1309 operands[3] = gen_reg_rtx (CCFPmode);
1312 ;; *tsqrt* returning the fe flag
1313 (define_expand "vsx_tsqrt<mode>2_fe"
1315 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
1317 (set (match_operand:SI 0 "gpc_reg_operand" "")
1318 (eq:SI (match_dup 3)
1320 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1322 operands[3] = gen_reg_rtx (CCFPmode);
1325 (define_insn "*vsx_tsqrt<mode>2_internal"
1326 [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
1327 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSa>")]
1329 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1330 "x<VSv>tsqrt<VSs> %0,%x1"
1331 [(set_attr "type" "<VStype_simple>")
1332 (set_attr "fp_type" "<VSfptype_simple>")])
1334 ;; Fused vector multiply/add instructions. Support the classical Altivec
1335 ;; versions of fma, which allows the target to be a separate register from the
1336 ;; 3 inputs. Under VSX, the target must be either the addend or the first
1339 (define_insn "*vsx_fmav4sf4"
1340 [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf,wf,?wa,?wa,v")
1342 (match_operand:V4SF 1 "vsx_register_operand" "%wf,wf,wa,wa,v")
1343 (match_operand:V4SF 2 "vsx_register_operand" "wf,0,wa,0,v")
1344 (match_operand:V4SF 3 "vsx_register_operand" "0,wf,0,wa,v")))]
1345 "VECTOR_UNIT_VSX_P (V4SFmode)"
1347 xvmaddasp %x0,%x1,%x2
1348 xvmaddmsp %x0,%x1,%x3
1349 xvmaddasp %x0,%x1,%x2
1350 xvmaddmsp %x0,%x1,%x3
1351 vmaddfp %0,%1,%2,%3"
1352 [(set_attr "type" "vecfloat")])
1354 (define_insn "*vsx_fmav2df4"
1355 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd,?wa,?wa")
1357 (match_operand:V2DF 1 "vsx_register_operand" "%wd,wd,wa,wa")
1358 (match_operand:V2DF 2 "vsx_register_operand" "wd,0,wa,0")
1359 (match_operand:V2DF 3 "vsx_register_operand" "0,wd,0,wa")))]
1360 "VECTOR_UNIT_VSX_P (V2DFmode)"
1362 xvmaddadp %x0,%x1,%x2
1363 xvmaddmdp %x0,%x1,%x3
1364 xvmaddadp %x0,%x1,%x2
1365 xvmaddmdp %x0,%x1,%x3"
1366 [(set_attr "type" "vecdouble")])
1368 (define_insn "*vsx_fms<mode>4"
1369 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>,?<VSa>,?<VSa>")
1371 (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>,<VSa>,<VSa>")
1372 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0,<VSa>,0")
1374 (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>,0,<VSa>"))))]
1375 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1377 xvmsuba<VSs> %x0,%x1,%x2
1378 xvmsubm<VSs> %x0,%x1,%x3
1379 xvmsuba<VSs> %x0,%x1,%x2
1380 xvmsubm<VSs> %x0,%x1,%x3"
1381 [(set_attr "type" "<VStype_mul>")])
1383 (define_insn "*vsx_nfma<mode>4"
1384 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>,?<VSa>,?<VSa>")
1387 (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSr>,<VSa>,<VSa>")
1388 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0,<VSa>,0")
1389 (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>,0,<VSa>"))))]
1390 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1392 xvnmadda<VSs> %x0,%x1,%x2
1393 xvnmaddm<VSs> %x0,%x1,%x3
1394 xvnmadda<VSs> %x0,%x1,%x2
1395 xvnmaddm<VSs> %x0,%x1,%x3"
1396 [(set_attr "type" "<VStype_mul>")
1397 (set_attr "fp_type" "<VSfptype_mul>")])
1399 (define_insn "*vsx_nfmsv4sf4"
1400 [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf,wf,?wa,?wa,v")
1403 (match_operand:V4SF 1 "vsx_register_operand" "%wf,wf,wa,wa,v")
1404 (match_operand:V4SF 2 "vsx_register_operand" "wf,0,wa,0,v")
1406 (match_operand:V4SF 3 "vsx_register_operand" "0,wf,0,wa,v")))))]
1407 "VECTOR_UNIT_VSX_P (V4SFmode)"
1409 xvnmsubasp %x0,%x1,%x2
1410 xvnmsubmsp %x0,%x1,%x3
1411 xvnmsubasp %x0,%x1,%x2
1412 xvnmsubmsp %x0,%x1,%x3
1413 vnmsubfp %0,%1,%2,%3"
1414 [(set_attr "type" "vecfloat")])
1416 (define_insn "*vsx_nfmsv2df4"
1417 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd,?wa,?wa")
1420 (match_operand:V2DF 1 "vsx_register_operand" "%wd,wd,wa,wa")
1421 (match_operand:V2DF 2 "vsx_register_operand" "wd,0,wa,0")
1423 (match_operand:V2DF 3 "vsx_register_operand" "0,wd,0,wa")))))]
1424 "VECTOR_UNIT_VSX_P (V2DFmode)"
1426 xvnmsubadp %x0,%x1,%x2
1427 xvnmsubmdp %x0,%x1,%x3
1428 xvnmsubadp %x0,%x1,%x2
1429 xvnmsubmdp %x0,%x1,%x3"
1430 [(set_attr "type" "vecdouble")])
1432 ;; Vector conditional expressions (no scalar version for these instructions)
1433 (define_insn "vsx_eq<mode>"
1434 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1435 (eq:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1436 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1437 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1438 "xvcmpeq<VSs> %x0,%x1,%x2"
1439 [(set_attr "type" "<VStype_simple>")
1440 (set_attr "fp_type" "<VSfptype_simple>")])
1442 (define_insn "vsx_gt<mode>"
1443 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1444 (gt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1445 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1446 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1447 "xvcmpgt<VSs> %x0,%x1,%x2"
1448 [(set_attr "type" "<VStype_simple>")
1449 (set_attr "fp_type" "<VSfptype_simple>")])
1451 (define_insn "*vsx_ge<mode>"
1452 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1453 (ge:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1454 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1455 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1456 "xvcmpge<VSs> %x0,%x1,%x2"
1457 [(set_attr "type" "<VStype_simple>")
1458 (set_attr "fp_type" "<VSfptype_simple>")])
1460 ;; Compare vectors producing a vector result and a predicate, setting CR6 to
1461 ;; indicate a combined status
1462 (define_insn "*vsx_eq_<mode>_p"
1465 [(eq:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?<VSa>")
1466 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?<VSa>"))]
1468 (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1469 (eq:VSX_F (match_dup 1)
1471 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1472 "xvcmpeq<VSs>. %x0,%x1,%x2"
1473 [(set_attr "type" "<VStype_simple>")])
1475 (define_insn "*vsx_gt_<mode>_p"
1478 [(gt:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?<VSa>")
1479 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?<VSa>"))]
1481 (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1482 (gt:VSX_F (match_dup 1)
1484 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1485 "xvcmpgt<VSs>. %x0,%x1,%x2"
1486 [(set_attr "type" "<VStype_simple>")])
1488 (define_insn "*vsx_ge_<mode>_p"
1491 [(ge:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?<VSa>")
1492 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?<VSa>"))]
1494 (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1495 (ge:VSX_F (match_dup 1)
1497 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1498 "xvcmpge<VSs>. %x0,%x1,%x2"
1499 [(set_attr "type" "<VStype_simple>")])
1502 (define_insn "*vsx_xxsel<mode>"
1503 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1505 (ne:CC (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,<VSa>")
1506 (match_operand:VSX_L 4 "zero_constant" ""))
1507 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,<VSa>")
1508 (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,<VSa>")))]
1509 "VECTOR_MEM_VSX_P (<MODE>mode)"
1510 "xxsel %x0,%x3,%x2,%x1"
1511 [(set_attr "type" "vecmove")])
1513 (define_insn "*vsx_xxsel<mode>_uns"
1514 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1516 (ne:CCUNS (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,<VSa>")
1517 (match_operand:VSX_L 4 "zero_constant" ""))
1518 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,<VSa>")
1519 (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,<VSa>")))]
1520 "VECTOR_MEM_VSX_P (<MODE>mode)"
1521 "xxsel %x0,%x3,%x2,%x1"
1522 [(set_attr "type" "vecmove")])
1525 (define_insn "vsx_copysign<mode>3"
1526 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1528 [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1529 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")]
1531 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1532 "xvcpsgn<VSs> %x0,%x2,%x1"
1533 [(set_attr "type" "<VStype_simple>")
1534 (set_attr "fp_type" "<VSfptype_simple>")])
1536 ;; For the conversions, limit the register class for the integer value to be
1537 ;; the fprs because we don't want to add the altivec registers to movdi/movsi.
1538 ;; For the unsigned tests, there isn't a generic double -> unsigned conversion
1539 ;; in rs6000.md so don't test VECTOR_UNIT_VSX_P, just test against VSX.
1540 ;; Don't use vsx_register_operand here, use gpc_reg_operand to match rs6000.md
1541 ;; in allowing virtual registers.
1542 (define_insn "vsx_float<VSi><mode>2"
1543 [(set (match_operand:VSX_F 0 "gpc_reg_operand" "=<VSr>,?<VSa>")
1544 (float:VSX_F (match_operand:<VSI> 1 "gpc_reg_operand" "<VSr2>,<VSr3>")))]
1545 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1546 "xvcvsx<VSc><VSs> %x0,%x1"
1547 [(set_attr "type" "<VStype_simple>")
1548 (set_attr "fp_type" "<VSfptype_simple>")])
1550 (define_insn "vsx_floatuns<VSi><mode>2"
1551 [(set (match_operand:VSX_F 0 "gpc_reg_operand" "=<VSr>,?<VSa>")
1552 (unsigned_float:VSX_F (match_operand:<VSI> 1 "gpc_reg_operand" "<VSr2>,<VSr3>")))]
1553 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1554 "xvcvux<VSc><VSs> %x0,%x1"
1555 [(set_attr "type" "<VStype_simple>")
1556 (set_attr "fp_type" "<VSfptype_simple>")])
1558 (define_insn "vsx_fix_trunc<mode><VSi>2"
1559 [(set (match_operand:<VSI> 0 "gpc_reg_operand" "=<VSr2>,?<VSr3>")
1560 (fix:<VSI> (match_operand:VSX_F 1 "gpc_reg_operand" "<VSr>,<VSa>")))]
1561 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1562 "x<VSv>cv<VSs>sx<VSc>s %x0,%x1"
1563 [(set_attr "type" "<VStype_simple>")
1564 (set_attr "fp_type" "<VSfptype_simple>")])
1566 (define_insn "vsx_fixuns_trunc<mode><VSi>2"
1567 [(set (match_operand:<VSI> 0 "gpc_reg_operand" "=<VSr2>,?<VSr3>")
1568 (unsigned_fix:<VSI> (match_operand:VSX_F 1 "gpc_reg_operand" "<VSr>,<VSa>")))]
1569 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1570 "x<VSv>cv<VSs>ux<VSc>s %x0,%x1"
1571 [(set_attr "type" "<VStype_simple>")
1572 (set_attr "fp_type" "<VSfptype_simple>")])
1574 ;; Math rounding functions
1575 (define_insn "vsx_x<VSv>r<VSs>i"
1576 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1577 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSa>")]
1578 UNSPEC_VSX_ROUND_I))]
1579 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1580 "x<VSv>r<VSs>i %x0,%x1"
1581 [(set_attr "type" "<VStype_simple>")
1582 (set_attr "fp_type" "<VSfptype_simple>")])
1584 (define_insn "vsx_x<VSv>r<VSs>ic"
1585 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1586 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSa>")]
1587 UNSPEC_VSX_ROUND_IC))]
1588 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1589 "x<VSv>r<VSs>ic %x0,%x1"
1590 [(set_attr "type" "<VStype_simple>")
1591 (set_attr "fp_type" "<VSfptype_simple>")])
1593 (define_insn "vsx_btrunc<mode>2"
1594 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1595 (fix:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")))]
1596 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1597 "xvr<VSs>iz %x0,%x1"
1598 [(set_attr "type" "<VStype_simple>")
1599 (set_attr "fp_type" "<VSfptype_simple>")])
1601 (define_insn "*vsx_b2trunc<mode>2"
1602 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1603 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSa>")]
1605 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1606 "x<VSv>r<VSs>iz %x0,%x1"
1607 [(set_attr "type" "<VStype_simple>")
1608 (set_attr "fp_type" "<VSfptype_simple>")])
1610 (define_insn "vsx_floor<mode>2"
1611 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1612 (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")]
1614 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1615 "xvr<VSs>im %x0,%x1"
1616 [(set_attr "type" "<VStype_simple>")
1617 (set_attr "fp_type" "<VSfptype_simple>")])
1619 (define_insn "vsx_ceil<mode>2"
1620 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1621 (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")]
1623 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1624 "xvr<VSs>ip %x0,%x1"
1625 [(set_attr "type" "<VStype_simple>")
1626 (set_attr "fp_type" "<VSfptype_simple>")])
1629 ;; VSX convert to/from double vector
1631 ;; Convert between single and double precision
1632 ;; Don't use xscvspdp and xscvdpsp for scalar conversions, since the normal
1633 ;; scalar single precision instructions internally use the double format.
1634 ;; Prefer the altivec registers, since we likely will need to do a vperm
1635 (define_insn "vsx_<VS_spdp_insn>"
1636 [(set (match_operand:<VS_spdp_res> 0 "vsx_register_operand" "=<VSr4>,?<VSa>")
1637 (unspec:<VS_spdp_res> [(match_operand:VSX_SPDP 1 "vsx_register_operand" "<VSr5>,<VSa>")]
1638 UNSPEC_VSX_CVSPDP))]
1639 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1640 "<VS_spdp_insn> %x0,%x1"
1641 [(set_attr "type" "<VS_spdp_type>")])
1643 ;; xscvspdp, represent the scalar SF type as V4SF
1644 (define_insn "vsx_xscvspdp"
1645 [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
1646 (unspec:DF [(match_operand:V4SF 1 "vsx_register_operand" "wa")]
1647 UNSPEC_VSX_CVSPDP))]
1648 "VECTOR_UNIT_VSX_P (V4SFmode)"
1650 [(set_attr "type" "fp")])
1652 ;; xscvdpsp used for splat'ing a scalar to V4SF, knowing that the internal SF
1653 ;; format of scalars is actually DF.
1654 (define_insn "vsx_xscvdpsp_scalar"
1655 [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
1656 (unspec:V4SF [(match_operand:SF 1 "vsx_register_operand" "f")]
1657 UNSPEC_VSX_CVSPDP))]
1658 "VECTOR_UNIT_VSX_P (V4SFmode)"
1660 [(set_attr "type" "fp")])
1662 ;; Same as vsx_xscvspdp, but use SF as the type
1663 (define_insn "vsx_xscvspdp_scalar2"
1664 [(set (match_operand:SF 0 "vsx_register_operand" "=f")
1665 (unspec:SF [(match_operand:V4SF 1 "vsx_register_operand" "wa")]
1666 UNSPEC_VSX_CVSPDP))]
1667 "VECTOR_UNIT_VSX_P (V4SFmode)"
1669 [(set_attr "type" "fp")])
1671 ;; ISA 2.07 xscvdpspn/xscvspdpn that does not raise an error on signalling NaNs
1672 (define_insn "vsx_xscvdpspn"
1673 [(set (match_operand:V4SF 0 "vsx_register_operand" "=ww,?ww")
1674 (unspec:V4SF [(match_operand:DF 1 "vsx_register_operand" "wd,wa")]
1675 UNSPEC_VSX_CVDPSPN))]
1678 [(set_attr "type" "fp")])
1680 (define_insn "vsx_xscvspdpn"
1681 [(set (match_operand:DF 0 "vsx_register_operand" "=ws,?ws")
1682 (unspec:DF [(match_operand:V4SF 1 "vsx_register_operand" "wf,wa")]
1683 UNSPEC_VSX_CVSPDPN))]
1686 [(set_attr "type" "fp")])
1688 (define_insn "vsx_xscvdpspn_scalar"
1689 [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf,?wa")
1690 (unspec:V4SF [(match_operand:SF 1 "vsx_register_operand" "ww,ww")]
1691 UNSPEC_VSX_CVDPSPN))]
1694 [(set_attr "type" "fp")])
1696 ;; Used by direct move to move a SFmode value from GPR to VSX register
1697 (define_insn "vsx_xscvspdpn_directmove"
1698 [(set (match_operand:SF 0 "vsx_register_operand" "=wa")
1699 (unspec:SF [(match_operand:SF 1 "vsx_register_operand" "wa")]
1700 UNSPEC_VSX_CVSPDPN))]
1703 [(set_attr "type" "fp")])
1705 ;; Convert and scale (used by vec_ctf, vec_cts, vec_ctu for double/long long)
1707 (define_expand "vsx_xvcvsxddp_scale"
1708 [(match_operand:V2DF 0 "vsx_register_operand" "")
1709 (match_operand:V2DI 1 "vsx_register_operand" "")
1710 (match_operand:QI 2 "immediate_operand" "")]
1711 "VECTOR_UNIT_VSX_P (V2DFmode)"
1713 rtx op0 = operands[0];
1714 rtx op1 = operands[1];
1715 int scale = INTVAL(operands[2]);
1716 emit_insn (gen_vsx_xvcvsxddp (op0, op1));
1718 rs6000_scale_v2df (op0, op0, -scale);
1722 (define_insn "vsx_xvcvsxddp"
1723 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wa")
1724 (unspec:V2DF [(match_operand:V2DI 1 "vsx_register_operand" "wa")]
1725 UNSPEC_VSX_XVCVSXDDP))]
1726 "VECTOR_UNIT_VSX_P (V2DFmode)"
1728 [(set_attr "type" "vecdouble")])
1730 (define_expand "vsx_xvcvuxddp_scale"
1731 [(match_operand:V2DF 0 "vsx_register_operand" "")
1732 (match_operand:V2DI 1 "vsx_register_operand" "")
1733 (match_operand:QI 2 "immediate_operand" "")]
1734 "VECTOR_UNIT_VSX_P (V2DFmode)"
1736 rtx op0 = operands[0];
1737 rtx op1 = operands[1];
1738 int scale = INTVAL(operands[2]);
1739 emit_insn (gen_vsx_xvcvuxddp (op0, op1));
1741 rs6000_scale_v2df (op0, op0, -scale);
1745 (define_insn "vsx_xvcvuxddp"
1746 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wa")
1747 (unspec:V2DF [(match_operand:V2DI 1 "vsx_register_operand" "wa")]
1748 UNSPEC_VSX_XVCVUXDDP))]
1749 "VECTOR_UNIT_VSX_P (V2DFmode)"
1751 [(set_attr "type" "vecdouble")])
1753 (define_expand "vsx_xvcvdpsxds_scale"
1754 [(match_operand:V2DI 0 "vsx_register_operand" "")
1755 (match_operand:V2DF 1 "vsx_register_operand" "")
1756 (match_operand:QI 2 "immediate_operand" "")]
1757 "VECTOR_UNIT_VSX_P (V2DFmode)"
1759 rtx op0 = operands[0];
1760 rtx op1 = operands[1];
1762 int scale = INTVAL (operands[2]);
1767 tmp = gen_reg_rtx (V2DFmode);
1768 rs6000_scale_v2df (tmp, op1, scale);
1770 emit_insn (gen_vsx_xvcvdpsxds (op0, tmp));
1774 (define_insn "vsx_xvcvdpsxds"
1775 [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
1776 (unspec:V2DI [(match_operand:V2DF 1 "vsx_register_operand" "wa")]
1777 UNSPEC_VSX_XVCVDPSXDS))]
1778 "VECTOR_UNIT_VSX_P (V2DFmode)"
1779 "xvcvdpsxds %x0,%x1"
1780 [(set_attr "type" "vecdouble")])
1782 (define_expand "vsx_xvcvdpuxds_scale"
1783 [(match_operand:V2DI 0 "vsx_register_operand" "")
1784 (match_operand:V2DF 1 "vsx_register_operand" "")
1785 (match_operand:QI 2 "immediate_operand" "")]
1786 "VECTOR_UNIT_VSX_P (V2DFmode)"
1788 rtx op0 = operands[0];
1789 rtx op1 = operands[1];
1791 int scale = INTVAL (operands[2]);
1796 tmp = gen_reg_rtx (V2DFmode);
1797 rs6000_scale_v2df (tmp, op1, scale);
1799 emit_insn (gen_vsx_xvcvdpuxds (op0, tmp));
1803 (define_insn "vsx_xvcvdpuxds"
1804 [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
1805 (unspec:V2DI [(match_operand:V2DF 1 "vsx_register_operand" "wa")]
1806 UNSPEC_VSX_XVCVDPUXDS))]
1807 "VECTOR_UNIT_VSX_P (V2DFmode)"
1808 "xvcvdpuxds %x0,%x1"
1809 [(set_attr "type" "vecdouble")])
1811 ;; Convert from 64-bit to 32-bit types
1812 ;; Note, favor the Altivec registers since the usual use of these instructions
1813 ;; is in vector converts and we need to use the Altivec vperm instruction.
1815 (define_insn "vsx_xvcvdpsxws"
1816 [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
1817 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
1818 UNSPEC_VSX_CVDPSXWS))]
1819 "VECTOR_UNIT_VSX_P (V2DFmode)"
1820 "xvcvdpsxws %x0,%x1"
1821 [(set_attr "type" "vecdouble")])
1823 (define_insn "vsx_xvcvdpuxws"
1824 [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
1825 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
1826 UNSPEC_VSX_CVDPUXWS))]
1827 "VECTOR_UNIT_VSX_P (V2DFmode)"
1828 "xvcvdpuxws %x0,%x1"
1829 [(set_attr "type" "vecdouble")])
1831 (define_insn "vsx_xvcvsxdsp"
1832 [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
1833 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
1834 UNSPEC_VSX_CVSXDSP))]
1835 "VECTOR_UNIT_VSX_P (V2DFmode)"
1837 [(set_attr "type" "vecfloat")])
1839 (define_insn "vsx_xvcvuxdsp"
1840 [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
1841 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
1842 UNSPEC_VSX_CVUXDSP))]
1843 "VECTOR_UNIT_VSX_P (V2DFmode)"
1845 [(set_attr "type" "vecdouble")])
1847 ;; Convert from 32-bit to 64-bit types
1848 (define_insn "vsx_xvcvsxwdp"
1849 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1850 (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
1851 UNSPEC_VSX_CVSXWDP))]
1852 "VECTOR_UNIT_VSX_P (V2DFmode)"
1854 [(set_attr "type" "vecdouble")])
1856 (define_insn "vsx_xvcvuxwdp"
1857 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1858 (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
1859 UNSPEC_VSX_CVUXWDP))]
1860 "VECTOR_UNIT_VSX_P (V2DFmode)"
1862 [(set_attr "type" "vecdouble")])
1864 (define_insn "vsx_xvcvspsxds"
1865 [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
1866 (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
1867 UNSPEC_VSX_CVSPSXDS))]
1868 "VECTOR_UNIT_VSX_P (V2DFmode)"
1869 "xvcvspsxds %x0,%x1"
1870 [(set_attr "type" "vecdouble")])
1872 (define_insn "vsx_xvcvspuxds"
1873 [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
1874 (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
1875 UNSPEC_VSX_CVSPUXDS))]
1876 "VECTOR_UNIT_VSX_P (V2DFmode)"
1877 "xvcvspuxds %x0,%x1"
1878 [(set_attr "type" "vecdouble")])
1880 ;; Only optimize (float (fix x)) -> frz if we are in fast-math mode, since
1881 ;; since the xvrdpiz instruction does not truncate the value if the floating
1882 ;; point value is < LONG_MIN or > LONG_MAX.
1883 (define_insn "*vsx_float_fix_v2df2"
1884 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1887 (match_operand:V2DF 1 "vsx_register_operand" "wd,?wa"))))]
1888 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
1889 && VECTOR_UNIT_VSX_P (V2DFmode) && flag_unsafe_math_optimizations
1890 && !flag_trapping_math && TARGET_FRIZ"
1892 [(set_attr "type" "vecdouble")
1893 (set_attr "fp_type" "fp_addsub_d")])
1896 ;; Permute operations
1898 ;; Build a V2DF/V2DI vector from two scalars
1899 (define_insn "vsx_concat_<mode>"
1900 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1902 (match_operand:<VS_scalar> 1 "vsx_register_operand" "<VS_64reg>,<VSa>")
1903 (match_operand:<VS_scalar> 2 "vsx_register_operand" "<VS_64reg>,<VSa>")))]
1904 "VECTOR_MEM_VSX_P (<MODE>mode)"
1906 if (BYTES_BIG_ENDIAN)
1907 return "xxpermdi %x0,%x1,%x2,0";
1909 return "xxpermdi %x0,%x2,%x1,0";
1911 [(set_attr "type" "vecperm")])
1913 ;; Special purpose concat using xxpermdi to glue two single precision values
1914 ;; together, relying on the fact that internally scalar floats are represented
1915 ;; as doubles. This is used to initialize a V4SF vector with 4 floats
1916 (define_insn "vsx_concat_v2sf"
1917 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1919 [(match_operand:SF 1 "vsx_register_operand" "f,f")
1920 (match_operand:SF 2 "vsx_register_operand" "f,f")]
1921 UNSPEC_VSX_CONCAT))]
1922 "VECTOR_MEM_VSX_P (V2DFmode)"
1924 if (BYTES_BIG_ENDIAN)
1925 return "xxpermdi %x0,%x1,%x2,0";
1927 return "xxpermdi %x0,%x2,%x1,0";
1929 [(set_attr "type" "vecperm")])
1931 ;; xxpermdi for little endian loads and stores. We need several of
1932 ;; these since the form of the PARALLEL differs by mode.
1933 (define_insn "*vsx_xxpermdi2_le_<mode>"
1934 [(set (match_operand:VSX_LE 0 "vsx_register_operand" "=<VSa>")
1936 (match_operand:VSX_LE 1 "vsx_register_operand" "<VSa>")
1937 (parallel [(const_int 1) (const_int 0)])))]
1938 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode)"
1939 "xxpermdi %x0,%x1,%x1,2"
1940 [(set_attr "type" "vecperm")])
1942 (define_insn "*vsx_xxpermdi4_le_<mode>"
1943 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=<VSa>")
1945 (match_operand:VSX_W 1 "vsx_register_operand" "<VSa>")
1946 (parallel [(const_int 2) (const_int 3)
1947 (const_int 0) (const_int 1)])))]
1948 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode)"
1949 "xxpermdi %x0,%x1,%x1,2"
1950 [(set_attr "type" "vecperm")])
1952 (define_insn "*vsx_xxpermdi8_le_V8HI"
1953 [(set (match_operand:V8HI 0 "vsx_register_operand" "=wa")
1955 (match_operand:V8HI 1 "vsx_register_operand" "wa")
1956 (parallel [(const_int 4) (const_int 5)
1957 (const_int 6) (const_int 7)
1958 (const_int 0) (const_int 1)
1959 (const_int 2) (const_int 3)])))]
1960 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V8HImode)"
1961 "xxpermdi %x0,%x1,%x1,2"
1962 [(set_attr "type" "vecperm")])
1964 (define_insn "*vsx_xxpermdi16_le_V16QI"
1965 [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
1967 (match_operand:V16QI 1 "vsx_register_operand" "wa")
1968 (parallel [(const_int 8) (const_int 9)
1969 (const_int 10) (const_int 11)
1970 (const_int 12) (const_int 13)
1971 (const_int 14) (const_int 15)
1972 (const_int 0) (const_int 1)
1973 (const_int 2) (const_int 3)
1974 (const_int 4) (const_int 5)
1975 (const_int 6) (const_int 7)])))]
1976 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V16QImode)"
1977 "xxpermdi %x0,%x1,%x1,2"
1978 [(set_attr "type" "vecperm")])
1980 ;; lxvd2x for little endian loads. We need several of
1981 ;; these since the form of the PARALLEL differs by mode.
1982 (define_insn "*vsx_lxvd2x2_le_<mode>"
1983 [(set (match_operand:VSX_LE 0 "vsx_register_operand" "=<VSa>")
1985 (match_operand:VSX_LE 1 "memory_operand" "Z")
1986 (parallel [(const_int 1) (const_int 0)])))]
1987 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode) && !TARGET_P9_VECTOR"
1989 [(set_attr "type" "vecload")])
1991 (define_insn "*vsx_lxvd2x4_le_<mode>"
1992 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=<VSa>")
1994 (match_operand:VSX_W 1 "memory_operand" "Z")
1995 (parallel [(const_int 2) (const_int 3)
1996 (const_int 0) (const_int 1)])))]
1997 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode) && !TARGET_P9_VECTOR"
1999 [(set_attr "type" "vecload")])
2001 (define_insn "*vsx_lxvd2x8_le_V8HI"
2002 [(set (match_operand:V8HI 0 "vsx_register_operand" "=wa")
2004 (match_operand:V8HI 1 "memory_operand" "Z")
2005 (parallel [(const_int 4) (const_int 5)
2006 (const_int 6) (const_int 7)
2007 (const_int 0) (const_int 1)
2008 (const_int 2) (const_int 3)])))]
2009 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V8HImode) && !TARGET_P9_VECTOR"
2011 [(set_attr "type" "vecload")])
2013 (define_insn "*vsx_lxvd2x16_le_V16QI"
2014 [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
2016 (match_operand:V16QI 1 "memory_operand" "Z")
2017 (parallel [(const_int 8) (const_int 9)
2018 (const_int 10) (const_int 11)
2019 (const_int 12) (const_int 13)
2020 (const_int 14) (const_int 15)
2021 (const_int 0) (const_int 1)
2022 (const_int 2) (const_int 3)
2023 (const_int 4) (const_int 5)
2024 (const_int 6) (const_int 7)])))]
2025 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V16QImode) && !TARGET_P9_VECTOR"
2027 [(set_attr "type" "vecload")])
2029 ;; stxvd2x for little endian stores. We need several of
2030 ;; these since the form of the PARALLEL differs by mode.
2031 (define_insn "*vsx_stxvd2x2_le_<mode>"
2032 [(set (match_operand:VSX_LE 0 "memory_operand" "=Z")
2034 (match_operand:VSX_LE 1 "vsx_register_operand" "<VSa>")
2035 (parallel [(const_int 1) (const_int 0)])))]
2036 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode) && !TARGET_P9_VECTOR"
2038 [(set_attr "type" "vecstore")])
2040 (define_insn "*vsx_stxvd2x4_le_<mode>"
2041 [(set (match_operand:VSX_W 0 "memory_operand" "=Z")
2043 (match_operand:VSX_W 1 "vsx_register_operand" "<VSa>")
2044 (parallel [(const_int 2) (const_int 3)
2045 (const_int 0) (const_int 1)])))]
2046 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode) && !TARGET_P9_VECTOR"
2048 [(set_attr "type" "vecstore")])
2050 (define_insn "*vsx_stxvd2x8_le_V8HI"
2051 [(set (match_operand:V8HI 0 "memory_operand" "=Z")
2053 (match_operand:V8HI 1 "vsx_register_operand" "wa")
2054 (parallel [(const_int 4) (const_int 5)
2055 (const_int 6) (const_int 7)
2056 (const_int 0) (const_int 1)
2057 (const_int 2) (const_int 3)])))]
2058 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V8HImode) && !TARGET_P9_VECTOR"
2060 [(set_attr "type" "vecstore")])
2062 (define_insn "*vsx_stxvd2x16_le_V16QI"
2063 [(set (match_operand:V16QI 0 "memory_operand" "=Z")
2065 (match_operand:V16QI 1 "vsx_register_operand" "wa")
2066 (parallel [(const_int 8) (const_int 9)
2067 (const_int 10) (const_int 11)
2068 (const_int 12) (const_int 13)
2069 (const_int 14) (const_int 15)
2070 (const_int 0) (const_int 1)
2071 (const_int 2) (const_int 3)
2072 (const_int 4) (const_int 5)
2073 (const_int 6) (const_int 7)])))]
2074 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V16QImode) && !TARGET_P9_VECTOR"
2076 [(set_attr "type" "vecstore")])
2078 ;; Convert a TImode value into V1TImode
2079 (define_expand "vsx_set_v1ti"
2080 [(match_operand:V1TI 0 "nonimmediate_operand" "")
2081 (match_operand:V1TI 1 "nonimmediate_operand" "")
2082 (match_operand:TI 2 "input_operand" "")
2083 (match_operand:QI 3 "u5bit_cint_operand" "")]
2084 "VECTOR_MEM_VSX_P (V1TImode)"
2086 if (operands[3] != const0_rtx)
2089 emit_move_insn (operands[0], gen_lowpart (V1TImode, operands[1]));
2093 ;; Set the element of a V2DI/VD2F mode
2094 (define_insn "vsx_set_<mode>"
2095 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?<VSa>")
2097 [(match_operand:VSX_D 1 "vsx_register_operand" "wd,<VSa>")
2098 (match_operand:<VS_scalar> 2 "vsx_register_operand" "<VS_64reg>,<VSa>")
2099 (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
2101 "VECTOR_MEM_VSX_P (<MODE>mode)"
2103 int idx_first = BYTES_BIG_ENDIAN ? 0 : 1;
2104 if (INTVAL (operands[3]) == idx_first)
2105 return \"xxpermdi %x0,%x2,%x1,1\";
2106 else if (INTVAL (operands[3]) == 1 - idx_first)
2107 return \"xxpermdi %x0,%x1,%x2,0\";
2111 [(set_attr "type" "vecperm")])
2113 ;; Extract a DF/DI element from V2DF/V2DI
2114 ;; Optimize cases were we can do a simple or direct move.
2115 ;; Or see if we can avoid doing the move at all
2117 ;; There are some unresolved problems with reload that show up if an Altivec
2118 ;; register was picked. Limit the scalar value to FPRs for now.
2120 (define_insn "vsx_extract_<mode>"
2121 [(set (match_operand:<VS_scalar> 0 "gpc_reg_operand"
2124 (vec_select:<VS_scalar>
2125 (match_operand:VSX_D 1 "gpc_reg_operand"
2126 "<VSa>, <VSa>, <VSa>, <VSa>")
2129 [(match_operand:QI 2 "const_0_to_1_operand"
2130 "wD, wD, wL, n")])))]
2131 "VECTOR_MEM_VSX_P (<MODE>mode)"
2133 int element = INTVAL (operands[2]);
2134 int op0_regno = REGNO (operands[0]);
2135 int op1_regno = REGNO (operands[1]);
2138 gcc_assert (IN_RANGE (element, 0, 1));
2139 gcc_assert (VSX_REGNO_P (op1_regno));
2141 if (element == VECTOR_ELEMENT_SCALAR_64BIT)
2143 if (op0_regno == op1_regno)
2144 return ASM_COMMENT_START " vec_extract to same register";
2146 else if (INT_REGNO_P (op0_regno) && TARGET_DIRECT_MOVE
2147 && TARGET_POWERPC64)
2148 return "mfvsrd %0,%x1";
2150 else if (FP_REGNO_P (op0_regno) && FP_REGNO_P (op1_regno))
2153 else if (VSX_REGNO_P (op0_regno))
2154 return "xxlor %x0,%x1,%x1";
2160 else if (element == VECTOR_ELEMENT_MFVSRLD_64BIT && INT_REGNO_P (op0_regno)
2161 && TARGET_P9_VECTOR && TARGET_POWERPC64 && TARGET_DIRECT_MOVE)
2162 return "mfvsrdl %0,%x1";
2164 else if (VSX_REGNO_P (op0_regno))
2166 fldDM = element << 1;
2167 if (!BYTES_BIG_ENDIAN)
2169 operands[3] = GEN_INT (fldDM);
2170 return "xxpermdi %x0,%x1,%x1,%3";
2176 [(set_attr "type" "veclogical,mftgpr,mftgpr,vecperm")])
2178 ;; Optimize extracting a single scalar element from memory if the scalar is in
2179 ;; the correct location to use a single load.
2180 (define_insn "*vsx_extract_<mode>_load"
2181 [(set (match_operand:<VS_scalar> 0 "register_operand" "=d,wv,wr")
2182 (vec_select:<VS_scalar>
2183 (match_operand:VSX_D 1 "memory_operand" "m,Z,m")
2184 (parallel [(const_int 0)])))]
2185 "VECTOR_MEM_VSX_P (<MODE>mode)"
2190 [(set_attr "type" "fpload,fpload,load")
2191 (set_attr "length" "4")])
2193 ;; Optimize storing a single scalar element that is the right location to
2195 (define_insn "*vsx_extract_<mode>_store"
2196 [(set (match_operand:<VS_scalar> 0 "memory_operand" "=m,Z,?Z")
2197 (vec_select:<VS_scalar>
2198 (match_operand:VSX_D 1 "register_operand" "d,wd,<VSa>")
2199 (parallel [(match_operand:QI 2 "vsx_scalar_64bit" "wD,wD,wD")])))]
2200 "VECTOR_MEM_VSX_P (<MODE>mode)"
2205 [(set_attr "type" "fpstore")
2206 (set_attr "length" "4")])
2208 ;; Extract a SF element from V4SF
2209 (define_insn_and_split "vsx_extract_v4sf"
2210 [(set (match_operand:SF 0 "vsx_register_operand" "=f,f")
2212 (match_operand:V4SF 1 "vsx_register_operand" "wa,wa")
2213 (parallel [(match_operand:QI 2 "u5bit_cint_operand" "O,i")])))
2214 (clobber (match_scratch:V4SF 3 "=X,0"))]
2215 "VECTOR_UNIT_VSX_P (V4SFmode)"
2223 rtx op0 = operands[0];
2224 rtx op1 = operands[1];
2225 rtx op2 = operands[2];
2226 rtx op3 = operands[3];
2228 HOST_WIDE_INT ele = BYTES_BIG_ENDIAN ? INTVAL (op2) : 3 - INTVAL (op2);
2234 if (GET_CODE (op3) == SCRATCH)
2235 op3 = gen_reg_rtx (V4SFmode);
2236 emit_insn (gen_vsx_xxsldwi_v4sf (op3, op1, op1, GEN_INT (ele)));
2239 emit_insn (gen_vsx_xscvspdp_scalar2 (op0, tmp));
2242 [(set_attr "length" "4,8")
2243 (set_attr "type" "fp")])
2245 ;; Expand the builtin form of xxpermdi to canonical rtl.
2246 (define_expand "vsx_xxpermdi_<mode>"
2247 [(match_operand:VSX_L 0 "vsx_register_operand" "")
2248 (match_operand:VSX_L 1 "vsx_register_operand" "")
2249 (match_operand:VSX_L 2 "vsx_register_operand" "")
2250 (match_operand:QI 3 "u5bit_cint_operand" "")]
2251 "VECTOR_MEM_VSX_P (<MODE>mode)"
2253 rtx target = operands[0];
2254 rtx op0 = operands[1];
2255 rtx op1 = operands[2];
2256 int mask = INTVAL (operands[3]);
2257 rtx perm0 = GEN_INT ((mask >> 1) & 1);
2258 rtx perm1 = GEN_INT ((mask & 1) + 2);
2259 rtx (*gen) (rtx, rtx, rtx, rtx, rtx);
2261 if (<MODE>mode == V2DFmode)
2262 gen = gen_vsx_xxpermdi2_v2df_1;
2265 gen = gen_vsx_xxpermdi2_v2di_1;
2266 if (<MODE>mode != V2DImode)
2268 target = gen_lowpart (V2DImode, target);
2269 op0 = gen_lowpart (V2DImode, op0);
2270 op1 = gen_lowpart (V2DImode, op1);
2273 /* In little endian mode, vsx_xxpermdi2_<mode>_1 will perform a
2274 transformation we don't want; it is necessary for
2275 rs6000_expand_vec_perm_const_1 but not for this use. So we
2276 prepare for that by reversing the transformation here. */
2277 if (BYTES_BIG_ENDIAN)
2278 emit_insn (gen (target, op0, op1, perm0, perm1));
2281 rtx p0 = GEN_INT (3 - INTVAL (perm1));
2282 rtx p1 = GEN_INT (3 - INTVAL (perm0));
2283 emit_insn (gen (target, op1, op0, p0, p1));
2288 (define_insn "vsx_xxpermdi2_<mode>_1"
2289 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd")
2291 (vec_concat:<VS_double>
2292 (match_operand:VSX_D 1 "vsx_register_operand" "wd")
2293 (match_operand:VSX_D 2 "vsx_register_operand" "wd"))
2294 (parallel [(match_operand 3 "const_0_to_1_operand" "")
2295 (match_operand 4 "const_2_to_3_operand" "")])))]
2296 "VECTOR_MEM_VSX_P (<MODE>mode)"
2300 /* For little endian, swap operands and invert/swap selectors
2301 to get the correct xxpermdi. The operand swap sets up the
2302 inputs as a little endian array. The selectors are swapped
2303 because they are defined to use big endian ordering. The
2304 selectors are inverted to get the correct doublewords for
2305 little endian ordering. */
2306 if (BYTES_BIG_ENDIAN)
2308 op3 = INTVAL (operands[3]);
2309 op4 = INTVAL (operands[4]);
2313 op3 = 3 - INTVAL (operands[4]);
2314 op4 = 3 - INTVAL (operands[3]);
2317 mask = (op3 << 1) | (op4 - 2);
2318 operands[3] = GEN_INT (mask);
2320 if (BYTES_BIG_ENDIAN)
2321 return "xxpermdi %x0,%x1,%x2,%3";
2323 return "xxpermdi %x0,%x2,%x1,%3";
2325 [(set_attr "type" "vecperm")])
2327 (define_expand "vec_perm_const<mode>"
2328 [(match_operand:VSX_D 0 "vsx_register_operand" "")
2329 (match_operand:VSX_D 1 "vsx_register_operand" "")
2330 (match_operand:VSX_D 2 "vsx_register_operand" "")
2331 (match_operand:V2DI 3 "" "")]
2332 "VECTOR_MEM_VSX_P (<MODE>mode)"
2334 if (rs6000_expand_vec_perm_const (operands))
2340 ;; Extraction of a single element in a small integer vector. None of the small
2341 ;; types are currently allowed in a vector register, so we extract to a DImode
2342 ;; and either do a direct move or store.
2343 (define_insn_and_split "vsx_extract_<mode>"
2344 [(set (match_operand:<VS_scalar> 0 "nonimmediate_operand" "=r,Z")
2345 (vec_select:<VS_scalar>
2346 (match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "<VSX_EX>,<VSX_EX>")
2347 (parallel [(match_operand:QI 2 "<VSX_EXTRACT_PREDICATE>" "n,n")])))
2348 (clobber (match_scratch:DI 3 "=<VSX_EX>,<VSX_EX>"))]
2349 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB"
2351 "&& (reload_completed || MEM_P (operands[0]))"
2354 rtx dest = operands[0];
2355 rtx src = operands[1];
2356 rtx element = operands[2];
2357 rtx di_tmp = operands[3];
2359 if (GET_CODE (di_tmp) == SCRATCH)
2360 di_tmp = gen_reg_rtx (DImode);
2362 emit_insn (gen_vsx_extract_<mode>_di (di_tmp, src, element));
2365 emit_move_insn (gen_rtx_REG (DImode, REGNO (dest)), di_tmp);
2366 else if (SUBREG_P (dest))
2367 emit_move_insn (gen_rtx_REG (DImode, subreg_regno (dest)), di_tmp);
2368 else if (MEM_P (operands[0]))
2370 if (can_create_pseudo_p ())
2371 dest = rs6000_address_for_fpconvert (dest);
2373 if (<MODE>mode == V16QImode)
2374 emit_insn (gen_p9_stxsibx (dest, di_tmp));
2375 else if (<MODE>mode == V8HImode)
2376 emit_insn (gen_p9_stxsihx (dest, di_tmp));
2377 else if (<MODE>mode == V4SImode)
2378 emit_insn (gen_stfiwx (dest, di_tmp));
2387 [(set_attr "type" "vecsimple,fpstore")])
2389 (define_insn "vsx_extract_<mode>_di"
2390 [(set (match_operand:DI 0 "gpc_reg_operand" "=<VSX_EX>")
2392 (vec_select:<VS_scalar>
2393 (match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "<VSX_EX>")
2394 (parallel [(match_operand:QI 2 "<VSX_EXTRACT_PREDICATE>" "n")]))))]
2395 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB"
2397 int element = INTVAL (operands[2]);
2398 int unit_size = GET_MODE_UNIT_SIZE (<MODE>mode);
2399 int offset = ((VECTOR_ELT_ORDER_BIG)
2400 ? unit_size * element
2401 : unit_size * (GET_MODE_NUNITS (<MODE>mode) - 1 - element));
2403 operands[2] = GEN_INT (offset);
2405 return "xxextractuw %x0,%x1,%2";
2407 return "vextractu<wd> %0,%1,%2";
2409 [(set_attr "type" "vecsimple")])
2412 ;; Expanders for builtins
2413 (define_expand "vsx_mergel_<mode>"
2414 [(use (match_operand:VSX_D 0 "vsx_register_operand" ""))
2415 (use (match_operand:VSX_D 1 "vsx_register_operand" ""))
2416 (use (match_operand:VSX_D 2 "vsx_register_operand" ""))]
2417 "VECTOR_MEM_VSX_P (<MODE>mode)"
2422 /* Special handling for LE with -maltivec=be. */
2423 if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
2425 v = gen_rtvec (2, GEN_INT (0), GEN_INT (2));
2426 x = gen_rtx_VEC_CONCAT (<VS_double>mode, operands[2], operands[1]);
2430 v = gen_rtvec (2, GEN_INT (1), GEN_INT (3));
2431 x = gen_rtx_VEC_CONCAT (<VS_double>mode, operands[1], operands[2]);
2434 x = gen_rtx_VEC_SELECT (<MODE>mode, x, gen_rtx_PARALLEL (VOIDmode, v));
2435 emit_insn (gen_rtx_SET (operands[0], x));
2439 (define_expand "vsx_mergeh_<mode>"
2440 [(use (match_operand:VSX_D 0 "vsx_register_operand" ""))
2441 (use (match_operand:VSX_D 1 "vsx_register_operand" ""))
2442 (use (match_operand:VSX_D 2 "vsx_register_operand" ""))]
2443 "VECTOR_MEM_VSX_P (<MODE>mode)"
2448 /* Special handling for LE with -maltivec=be. */
2449 if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
2451 v = gen_rtvec (2, GEN_INT (1), GEN_INT (3));
2452 x = gen_rtx_VEC_CONCAT (<VS_double>mode, operands[2], operands[1]);
2456 v = gen_rtvec (2, GEN_INT (0), GEN_INT (2));
2457 x = gen_rtx_VEC_CONCAT (<VS_double>mode, operands[1], operands[2]);
2460 x = gen_rtx_VEC_SELECT (<MODE>mode, x, gen_rtx_PARALLEL (VOIDmode, v));
2461 emit_insn (gen_rtx_SET (operands[0], x));
2466 (define_insn "vsx_splat_<mode>"
2467 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=<VSa>,<VSa>,we")
2468 (vec_duplicate:VSX_D
2469 (match_operand:<VS_scalar> 1 "splat_input_operand" "<VS_64reg>,Z,b")))]
2470 "VECTOR_MEM_VSX_P (<MODE>mode)"
2472 xxpermdi %x0,%x1,%x1,0
2475 [(set_attr "type" "vecperm,vecload,mftgpr")])
2477 ;; V4SI splat (ISA 3.0)
2478 ;; When SI's are allowed in VSX registers, add XXSPLTW support
2479 (define_expand "vsx_splat_<mode>"
2480 [(set (match_operand:VSX_W 0 "vsx_register_operand" "")
2481 (vec_duplicate:VSX_W
2482 (match_operand:<VS_scalar> 1 "splat_input_operand" "")))]
2485 if (MEM_P (operands[1]))
2486 operands[1] = rs6000_address_for_fpconvert (operands[1]);
2487 else if (!REG_P (operands[1]))
2488 operands[1] = force_reg (<VS_scalar>mode, operands[1]);
2491 (define_insn "*vsx_splat_v4si_internal"
2492 [(set (match_operand:V4SI 0 "vsx_register_operand" "=wa,wa")
2494 (match_operand:SI 1 "splat_input_operand" "r,Z")))]
2499 [(set_attr "type" "mftgpr,vecload")])
2501 ;; V4SF splat (ISA 3.0)
2502 (define_insn_and_split "*vsx_splat_v4sf_internal"
2503 [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa,wa,wa")
2505 (match_operand:SF 1 "splat_input_operand" "Z,wy,r")))]
2511 "&& reload_completed && vsx_register_operand (operands[1], SFmode)"
2513 (unspec:V4SF [(match_dup 1)] UNSPEC_VSX_CVDPSPN))
2515 (unspec:V4SF [(match_dup 0)
2516 (const_int 0)] UNSPEC_VSX_XXSPLTW))]
2518 [(set_attr "type" "vecload,vecperm,mftgpr")
2519 (set_attr "length" "4,8,4")])
2521 ;; V4SF/V4SI splat from a vector element
2522 (define_insn "vsx_xxspltw_<mode>"
2523 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?<VSa>")
2524 (vec_duplicate:VSX_W
2525 (vec_select:<VS_scalar>
2526 (match_operand:VSX_W 1 "vsx_register_operand" "wf,<VSa>")
2528 [(match_operand:QI 2 "u5bit_cint_operand" "i,i")]))))]
2529 "VECTOR_MEM_VSX_P (<MODE>mode)"
2531 if (!BYTES_BIG_ENDIAN)
2532 operands[2] = GEN_INT (3 - INTVAL (operands[2]));
2534 return "xxspltw %x0,%x1,%2";
2536 [(set_attr "type" "vecperm")])
2538 (define_insn "vsx_xxspltw_<mode>_direct"
2539 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?<VSa>")
2540 (unspec:VSX_W [(match_operand:VSX_W 1 "vsx_register_operand" "wf,<VSa>")
2541 (match_operand:QI 2 "u5bit_cint_operand" "i,i")]
2542 UNSPEC_VSX_XXSPLTW))]
2543 "VECTOR_MEM_VSX_P (<MODE>mode)"
2544 "xxspltw %x0,%x1,%2"
2545 [(set_attr "type" "vecperm")])
2547 ;; V2DF/V2DI splat for use by vec_splat builtin
2548 (define_insn "vsx_xxspltd_<mode>"
2549 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wa")
2550 (unspec:VSX_D [(match_operand:VSX_D 1 "vsx_register_operand" "wa")
2551 (match_operand:QI 2 "u5bit_cint_operand" "i")]
2552 UNSPEC_VSX_XXSPLTD))]
2553 "VECTOR_MEM_VSX_P (<MODE>mode)"
2555 if ((VECTOR_ELT_ORDER_BIG && INTVAL (operands[2]) == 0)
2556 || (!VECTOR_ELT_ORDER_BIG && INTVAL (operands[2]) == 1))
2557 return "xxpermdi %x0,%x1,%x1,0";
2559 return "xxpermdi %x0,%x1,%x1,3";
2561 [(set_attr "type" "vecperm")])
2563 ;; V4SF/V4SI interleave
2564 (define_insn "vsx_xxmrghw_<mode>"
2565 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?<VSa>")
2567 (vec_concat:<VS_double>
2568 (match_operand:VSX_W 1 "vsx_register_operand" "wf,<VSa>")
2569 (match_operand:VSX_W 2 "vsx_register_operand" "wf,<VSa>"))
2570 (parallel [(const_int 0) (const_int 4)
2571 (const_int 1) (const_int 5)])))]
2572 "VECTOR_MEM_VSX_P (<MODE>mode)"
2574 if (BYTES_BIG_ENDIAN)
2575 return "xxmrghw %x0,%x1,%x2";
2577 return "xxmrglw %x0,%x2,%x1";
2579 [(set_attr "type" "vecperm")])
2581 (define_insn "vsx_xxmrglw_<mode>"
2582 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?<VSa>")
2584 (vec_concat:<VS_double>
2585 (match_operand:VSX_W 1 "vsx_register_operand" "wf,<VSa>")
2586 (match_operand:VSX_W 2 "vsx_register_operand" "wf,?<VSa>"))
2587 (parallel [(const_int 2) (const_int 6)
2588 (const_int 3) (const_int 7)])))]
2589 "VECTOR_MEM_VSX_P (<MODE>mode)"
2591 if (BYTES_BIG_ENDIAN)
2592 return "xxmrglw %x0,%x1,%x2";
2594 return "xxmrghw %x0,%x2,%x1";
2596 [(set_attr "type" "vecperm")])
2598 ;; Shift left double by word immediate
2599 (define_insn "vsx_xxsldwi_<mode>"
2600 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSa>")
2601 (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "<VSa>")
2602 (match_operand:VSX_L 2 "vsx_register_operand" "<VSa>")
2603 (match_operand:QI 3 "u5bit_cint_operand" "i")]
2605 "VECTOR_MEM_VSX_P (<MODE>mode)"
2606 "xxsldwi %x0,%x1,%x2,%3"
2607 [(set_attr "type" "vecperm")])
2610 ;; Vector reduction insns and splitters
2612 (define_insn_and_split "vsx_reduc_<VEC_reduc_name>_v2df"
2613 [(set (match_operand:V2DF 0 "vfloat_operand" "=&wd,&?wa,wd,?wa")
2617 (match_operand:V2DF 1 "vfloat_operand" "wd,wa,wd,wa")
2618 (parallel [(const_int 1)]))
2621 (parallel [(const_int 0)])))
2623 (clobber (match_scratch:V2DF 2 "=0,0,&wd,&wa"))]
2624 "VECTOR_UNIT_VSX_P (V2DFmode)"
2630 rtx tmp = (GET_CODE (operands[2]) == SCRATCH)
2631 ? gen_reg_rtx (V2DFmode)
2633 emit_insn (gen_vsx_xxsldwi_v2df (tmp, operands[1], operands[1], const2_rtx));
2634 emit_insn (gen_<VEC_reduc_rtx>v2df3 (operands[0], tmp, operands[1]));
2637 [(set_attr "length" "8")
2638 (set_attr "type" "veccomplex")])
2640 (define_insn_and_split "vsx_reduc_<VEC_reduc_name>_v4sf"
2641 [(set (match_operand:V4SF 0 "vfloat_operand" "=wf,?wa")
2643 (unspec:V4SF [(const_int 0)] UNSPEC_REDUC)
2644 (match_operand:V4SF 1 "vfloat_operand" "wf,wa")))
2645 (clobber (match_scratch:V4SF 2 "=&wf,&wa"))
2646 (clobber (match_scratch:V4SF 3 "=&wf,&wa"))]
2647 "VECTOR_UNIT_VSX_P (V4SFmode)"
2653 rtx op0 = operands[0];
2654 rtx op1 = operands[1];
2655 rtx tmp2, tmp3, tmp4;
2657 if (can_create_pseudo_p ())
2659 tmp2 = gen_reg_rtx (V4SFmode);
2660 tmp3 = gen_reg_rtx (V4SFmode);
2661 tmp4 = gen_reg_rtx (V4SFmode);
2670 emit_insn (gen_vsx_xxsldwi_v4sf (tmp2, op1, op1, const2_rtx));
2671 emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp3, tmp2, op1));
2672 emit_insn (gen_vsx_xxsldwi_v4sf (tmp4, tmp3, tmp3, GEN_INT (3)));
2673 emit_insn (gen_<VEC_reduc_rtx>v4sf3 (op0, tmp4, tmp3));
2676 [(set_attr "length" "16")
2677 (set_attr "type" "veccomplex")])
2679 ;; Combiner patterns with the vector reduction patterns that knows we can get
2680 ;; to the top element of the V2DF array without doing an extract.
2682 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v2df_scalar"
2683 [(set (match_operand:DF 0 "vfloat_operand" "=&ws,&?ws,ws,?ws")
2688 (match_operand:V2DF 1 "vfloat_operand" "wd,wa,wd,wa")
2689 (parallel [(const_int 1)]))
2692 (parallel [(const_int 0)])))
2694 (parallel [(const_int 1)])))
2695 (clobber (match_scratch:DF 2 "=0,0,&wd,&wa"))]
2696 "VECTOR_UNIT_VSX_P (V2DFmode)"
2702 rtx hi = gen_highpart (DFmode, operands[1]);
2703 rtx lo = (GET_CODE (operands[2]) == SCRATCH)
2704 ? gen_reg_rtx (DFmode)
2707 emit_insn (gen_vsx_extract_v2df (lo, operands[1], const1_rtx));
2708 emit_insn (gen_<VEC_reduc_rtx>df3 (operands[0], hi, lo));
2711 [(set_attr "length" "8")
2712 (set_attr "type" "veccomplex")])
2714 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v4sf_scalar"
2715 [(set (match_operand:SF 0 "vfloat_operand" "=f,?f")
2718 (unspec:V4SF [(const_int 0)] UNSPEC_REDUC)
2719 (match_operand:V4SF 1 "vfloat_operand" "wf,wa"))
2720 (parallel [(const_int 3)])))
2721 (clobber (match_scratch:V4SF 2 "=&wf,&wa"))
2722 (clobber (match_scratch:V4SF 3 "=&wf,&wa"))
2723 (clobber (match_scratch:V4SF 4 "=0,0"))]
2724 "VECTOR_UNIT_VSX_P (V4SFmode)"
2730 rtx op0 = operands[0];
2731 rtx op1 = operands[1];
2732 rtx tmp2, tmp3, tmp4, tmp5;
2734 if (can_create_pseudo_p ())
2736 tmp2 = gen_reg_rtx (V4SFmode);
2737 tmp3 = gen_reg_rtx (V4SFmode);
2738 tmp4 = gen_reg_rtx (V4SFmode);
2739 tmp5 = gen_reg_rtx (V4SFmode);
2749 emit_insn (gen_vsx_xxsldwi_v4sf (tmp2, op1, op1, const2_rtx));
2750 emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp3, tmp2, op1));
2751 emit_insn (gen_vsx_xxsldwi_v4sf (tmp4, tmp3, tmp3, GEN_INT (3)));
2752 emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp5, tmp4, tmp3));
2753 emit_insn (gen_vsx_xscvspdp_scalar2 (op0, tmp5));
2756 [(set_attr "length" "20")
2757 (set_attr "type" "veccomplex")])
2760 ;; Power8 Vector fusion. The fused ops must be physically adjacent.
2762 [(set (match_operand:P 0 "base_reg_operand" "")
2763 (match_operand:P 1 "short_cint_operand" ""))
2764 (set (match_operand:VSX_M 2 "vsx_register_operand" "")
2765 (mem:VSX_M (plus:P (match_dup 0)
2766 (match_operand:P 3 "int_reg_operand" ""))))]
2767 "TARGET_VSX && TARGET_P8_FUSION && !TARGET_P9_VECTOR"
2768 "li %0,%1\t\t\t# vector load fusion\;lx<VSX_M:VSm>x %x2,%0,%3"
2769 [(set_attr "length" "8")
2770 (set_attr "type" "vecload")])
2773 [(set (match_operand:P 0 "base_reg_operand" "")
2774 (match_operand:P 1 "short_cint_operand" ""))
2775 (set (match_operand:VSX_M 2 "vsx_register_operand" "")
2776 (mem:VSX_M (plus:P (match_operand:P 3 "int_reg_operand" "")
2778 "TARGET_VSX && TARGET_P8_FUSION && !TARGET_P9_VECTOR"
2779 "li %0,%1\t\t\t# vector load fusion\;lx<VSX_M:VSm>x %x2,%0,%3"
2780 [(set_attr "length" "8")
2781 (set_attr "type" "vecload")])
2784 ;; ISA 3.0 vector extend sign support
2786 (define_insn "vsx_sign_extend_qi_<mode>"
2787 [(set (match_operand:VSINT_84 0 "vsx_register_operand" "=v")
2789 [(match_operand:V16QI 1 "vsx_register_operand" "v")]
2790 UNSPEC_VSX_SIGN_EXTEND))]
2793 [(set_attr "type" "vecexts")])
2795 (define_insn "vsx_sign_extend_hi_<mode>"
2796 [(set (match_operand:VSINT_84 0 "vsx_register_operand" "=v")
2798 [(match_operand:V8HI 1 "vsx_register_operand" "v")]
2799 UNSPEC_VSX_SIGN_EXTEND))]
2802 [(set_attr "type" "vecexts")])
2804 (define_insn "*vsx_sign_extend_si_v2di"
2805 [(set (match_operand:V2DI 0 "vsx_register_operand" "=v")
2806 (unspec:V2DI [(match_operand:V4SI 1 "vsx_register_operand" "v")]
2807 UNSPEC_VSX_SIGN_EXTEND))]
2810 [(set_attr "type" "vecexts")])
2813 ;; ISA 3.0 memory operations
2814 (define_insn "p9_lxsi<wd>zx"
2815 [(set (match_operand:DI 0 "vsx_register_operand" "=wi")
2816 (unspec:DI [(zero_extend:DI
2817 (match_operand:QHI 1 "indexed_or_indirect_operand" "Z"))]
2820 "lxsi<wd>zx %x0,%y1"
2821 [(set_attr "type" "fpload")])
2823 (define_insn "p9_stxsi<wd>x"
2824 [(set (match_operand:QHI 0 "reg_or_indexed_operand" "=r,Z")
2825 (unspec:QHI [(match_operand:DI 1 "vsx_register_operand" "wi,wi")]
2831 [(set_attr "type" "mffgpr,fpstore")])