2 ;; Copyright (C) 2009-2013 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 32-bit vector types
28 (define_mode_iterator VSX_W [V4SF V4SI])
30 ;; Iterator for the DF types
31 (define_mode_iterator VSX_DF [V2DF DF])
33 ;; Iterator for vector floating point types supported by VSX
34 (define_mode_iterator VSX_F [V4SF V2DF])
36 ;; Iterator for logical types supported by VSX
37 (define_mode_iterator VSX_L [V16QI V8HI V4SI V2DI V4SF V2DF TI])
39 ;; Iterator for memory move. Handle TImode specially to allow
40 ;; it to use gprs as well as vsx registers.
41 (define_mode_iterator VSX_M [V16QI V8HI V4SI V2DI V4SF V2DF])
43 ;; Map into the appropriate load/store name based on the type
44 (define_mode_attr VSm [(V16QI "vw4")
53 ;; Map into the appropriate suffix based on the type
54 (define_mode_attr VSs [(V16QI "sp")
64 ;; Map the register class used
65 (define_mode_attr VSr [(V16QI "v")
75 ;; Map the register class used for float<->int conversions
76 (define_mode_attr VSr2 [(V2DF "wd")
80 (define_mode_attr VSr3 [(V2DF "wa")
84 ;; Map the register class for sp<->dp float conversions, destination
85 (define_mode_attr VSr4 [(SF "ws")
90 ;; Map the register class for sp<->dp float conversions, destination
91 (define_mode_attr VSr5 [(SF "ws")
96 ;; Same size integer type for floating point data
97 (define_mode_attr VSi [(V4SF "v4si")
101 (define_mode_attr VSI [(V4SF "V4SI")
105 ;; Word size for same size conversion
106 (define_mode_attr VSc [(V4SF "w")
110 ;; Map into either s or v, depending on whether this is a scalar or vector
112 (define_mode_attr VSv [(V16QI "v")
120 ;; Appropriate type for add ops (and other simple FP ops)
121 (define_mode_attr VStype_simple [(V2DF "vecdouble")
125 (define_mode_attr VSfptype_simple [(V2DF "fp_addsub_d")
129 ;; Appropriate type for multiply ops
130 (define_mode_attr VStype_mul [(V2DF "vecdouble")
134 (define_mode_attr VSfptype_mul [(V2DF "fp_mul_d")
138 ;; Appropriate type for divide ops.
139 (define_mode_attr VStype_div [(V2DF "vecdiv")
143 (define_mode_attr VSfptype_div [(V2DF "fp_div_d")
147 ;; Appropriate type for sqrt ops. For now, just lump the vector sqrt with
149 (define_mode_attr VStype_sqrt [(V2DF "dsqrt")
153 (define_mode_attr VSfptype_sqrt [(V2DF "fp_sqrt_d")
157 ;; Iterator and modes for sp<->dp conversions
158 ;; Because scalar SF values are represented internally as double, use the
159 ;; V4SF type to represent this than SF.
160 (define_mode_iterator VSX_SPDP [DF V4SF V2DF])
162 (define_mode_attr VS_spdp_res [(DF "V4SF")
166 (define_mode_attr VS_spdp_insn [(DF "xscvdpsp")
170 (define_mode_attr VS_spdp_type [(DF "fp")
174 ;; Map the scalar mode for a vector type
175 (define_mode_attr VS_scalar [(V2DF "DF")
182 ;; Map to a double-sized vector mode
183 (define_mode_attr VS_double [(V4SI "V8SI")
188 ;; Constants for creating unspecs
189 (define_c_enum "unspec"
209 (define_insn "*vsx_mov<mode>"
210 [(set (match_operand:VSX_M 0 "nonimmediate_operand" "=Z,<VSr>,<VSr>,?Z,?wa,?wa,*Y,*r,*r,<VSr>,?wa,v,wZ,v")
211 (match_operand:VSX_M 1 "input_operand" "<VSr>,Z,<VSr>,wa,Z,wa,r,Y,r,j,j,W,v,wZ"))]
212 "VECTOR_MEM_VSX_P (<MODE>mode)
213 && (register_operand (operands[0], <MODE>mode)
214 || register_operand (operands[1], <MODE>mode))"
216 switch (which_alternative)
220 gcc_assert (MEM_P (operands[0])
221 && GET_CODE (XEXP (operands[0], 0)) != PRE_INC
222 && GET_CODE (XEXP (operands[0], 0)) != PRE_DEC
223 && GET_CODE (XEXP (operands[0], 0)) != PRE_MODIFY);
224 return "stx<VSm>x %x1,%y0";
228 gcc_assert (MEM_P (operands[1])
229 && GET_CODE (XEXP (operands[1], 0)) != PRE_INC
230 && GET_CODE (XEXP (operands[1], 0)) != PRE_DEC
231 && GET_CODE (XEXP (operands[1], 0)) != PRE_MODIFY);
232 return "lx<VSm>x %x0,%y1";
236 return "xxlor %x0,%x1,%x1";
245 return "xxlxor %x0,%x0,%x0";
248 return output_vec_const_move (operands);
251 gcc_assert (MEM_P (operands[0])
252 && GET_CODE (XEXP (operands[0], 0)) != PRE_INC
253 && GET_CODE (XEXP (operands[0], 0)) != PRE_DEC
254 && GET_CODE (XEXP (operands[0], 0)) != PRE_MODIFY);
255 return "stvx %1,%y0";
258 gcc_assert (MEM_P (operands[0])
259 && GET_CODE (XEXP (operands[0], 0)) != PRE_INC
260 && GET_CODE (XEXP (operands[0], 0)) != PRE_DEC
261 && GET_CODE (XEXP (operands[0], 0)) != PRE_MODIFY);
268 [(set_attr "type" "vecstore,vecload,vecsimple,vecstore,vecload,vecsimple,*,*,*,vecsimple,vecsimple,*,vecstore,vecload")])
270 ;; Unlike other VSX moves, allow the GPRs even for reloading, since a normal
271 ;; use of TImode is for unions. However for plain data movement, slightly
272 ;; favor the vector loads
273 (define_insn "*vsx_movti_64bit"
274 [(set (match_operand:TI 0 "nonimmediate_operand" "=Z,wa,wa,wa,v, v,wZ,?Y,?r,?r")
275 (match_operand:TI 1 "input_operand" "wa, Z,wa, j,W,wZ, v, r, Y, r"))]
276 "TARGET_POWERPC64 && VECTOR_MEM_VSX_P (TImode)
277 && (register_operand (operands[0], TImode)
278 || register_operand (operands[1], TImode))"
280 switch (which_alternative)
283 return "stxvd2x %x1,%y0";
286 return "lxvd2x %x0,%y1";
289 return "xxlor %x0,%x1,%x1";
292 return "xxlxor %x0,%x0,%x0";
295 return output_vec_const_move (operands);
298 return "stvx %1,%y0";
312 [(set_attr "type" "vecstore,vecload,vecsimple,vecsimple,vecsimple,vecstore,vecload,*,*,*")
313 (set_attr "length" " 4, 4, 4, 4, 8, 4, 4,8,8,8")])
315 (define_insn "*vsx_movti_32bit"
316 [(set (match_operand:TI 0 "nonimmediate_operand" "=Z,wa,wa,wa,v, v,wZ,Q,Y,????r,????r,????r,r")
317 (match_operand:TI 1 "input_operand" "wa, Z,wa, j,W,wZ, v,r,r, Q, Y, r,n"))]
318 "! TARGET_POWERPC64 && VECTOR_MEM_VSX_P (TImode)
319 && (register_operand (operands[0], TImode)
320 || register_operand (operands[1], TImode))"
322 switch (which_alternative)
325 return "stxvd2x %x1,%y0";
328 return "lxvd2x %x0,%y1";
331 return "xxlor %x0,%x1,%x1";
334 return "xxlxor %x0,%x0,%x0";
337 return output_vec_const_move (operands);
340 return "stvx %1,%y0";
347 return \"stswi %1,%P0,16\";
353 /* If the address is not used in the output, we can use lsi. Otherwise,
354 fall through to generating four loads. */
356 && ! reg_overlap_mentioned_p (operands[0], operands[1]))
357 return \"lswi %0,%P1,16\";
358 /* ... fall through ... */
368 [(set_attr "type" "vecstore,vecload,vecsimple,vecsimple,vecsimple,vecstore,vecload,store_ux,store_ux,load_ux,load_ux, *, *")
369 (set_attr "length" " 4, 4, 4, 4, 8, 4, 4, 16, 16, 16, 16,16,16")
370 (set (attr "cell_micro") (if_then_else (match_test "TARGET_STRING")
371 (const_string "always")
372 (const_string "conditional")))])
374 ;; Explicit load/store expanders for the builtin functions
375 (define_expand "vsx_load_<mode>"
376 [(set (match_operand:VSX_M 0 "vsx_register_operand" "")
377 (match_operand:VSX_M 1 "memory_operand" ""))]
378 "VECTOR_MEM_VSX_P (<MODE>mode)"
381 (define_expand "vsx_store_<mode>"
382 [(set (match_operand:VSX_M 0 "memory_operand" "")
383 (match_operand:VSX_M 1 "vsx_register_operand" ""))]
384 "VECTOR_MEM_VSX_P (<MODE>mode)"
388 ;; VSX scalar and vector floating point arithmetic instructions
389 (define_insn "*vsx_add<mode>3"
390 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
391 (plus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
392 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
393 "VECTOR_UNIT_VSX_P (<MODE>mode)"
394 "x<VSv>add<VSs> %x0,%x1,%x2"
395 [(set_attr "type" "<VStype_simple>")
396 (set_attr "fp_type" "<VSfptype_simple>")])
398 (define_insn "*vsx_sub<mode>3"
399 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
400 (minus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
401 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
402 "VECTOR_UNIT_VSX_P (<MODE>mode)"
403 "x<VSv>sub<VSs> %x0,%x1,%x2"
404 [(set_attr "type" "<VStype_simple>")
405 (set_attr "fp_type" "<VSfptype_simple>")])
407 (define_insn "*vsx_mul<mode>3"
408 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
409 (mult:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
410 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
411 "VECTOR_UNIT_VSX_P (<MODE>mode)"
412 "x<VSv>mul<VSs> %x0,%x1,%x2"
413 [(set_attr "type" "<VStype_mul>")
414 (set_attr "fp_type" "<VSfptype_mul>")])
416 (define_insn "*vsx_div<mode>3"
417 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
418 (div:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
419 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
420 "VECTOR_UNIT_VSX_P (<MODE>mode)"
421 "x<VSv>div<VSs> %x0,%x1,%x2"
422 [(set_attr "type" "<VStype_div>")
423 (set_attr "fp_type" "<VSfptype_div>")])
425 ;; *tdiv* instruction returning the FG flag
426 (define_expand "vsx_tdiv<mode>3_fg"
428 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
429 (match_operand:VSX_B 2 "vsx_register_operand" "")]
431 (set (match_operand:SI 0 "gpc_reg_operand" "")
434 "VECTOR_UNIT_VSX_P (<MODE>mode)"
436 operands[3] = gen_reg_rtx (CCFPmode);
439 ;; *tdiv* instruction returning the FE flag
440 (define_expand "vsx_tdiv<mode>3_fe"
442 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
443 (match_operand:VSX_B 2 "vsx_register_operand" "")]
445 (set (match_operand:SI 0 "gpc_reg_operand" "")
448 "VECTOR_UNIT_VSX_P (<MODE>mode)"
450 operands[3] = gen_reg_rtx (CCFPmode);
453 (define_insn "*vsx_tdiv<mode>3_internal"
454 [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
455 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
456 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")]
458 "VECTOR_UNIT_VSX_P (<MODE>mode)"
459 "x<VSv>tdiv<VSs> %0,%x1,%x2"
460 [(set_attr "type" "<VStype_simple>")
461 (set_attr "fp_type" "<VSfptype_simple>")])
463 (define_insn "vsx_fre<mode>2"
464 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
465 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
467 "VECTOR_UNIT_VSX_P (<MODE>mode)"
468 "x<VSv>re<VSs> %x0,%x1"
469 [(set_attr "type" "<VStype_simple>")
470 (set_attr "fp_type" "<VSfptype_simple>")])
472 (define_insn "*vsx_neg<mode>2"
473 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
474 (neg:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
475 "VECTOR_UNIT_VSX_P (<MODE>mode)"
476 "x<VSv>neg<VSs> %x0,%x1"
477 [(set_attr "type" "<VStype_simple>")
478 (set_attr "fp_type" "<VSfptype_simple>")])
480 (define_insn "*vsx_abs<mode>2"
481 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
482 (abs:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
483 "VECTOR_UNIT_VSX_P (<MODE>mode)"
484 "x<VSv>abs<VSs> %x0,%x1"
485 [(set_attr "type" "<VStype_simple>")
486 (set_attr "fp_type" "<VSfptype_simple>")])
488 (define_insn "vsx_nabs<mode>2"
489 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
492 (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa"))))]
493 "VECTOR_UNIT_VSX_P (<MODE>mode)"
494 "x<VSv>nabs<VSs> %x0,%x1"
495 [(set_attr "type" "<VStype_simple>")
496 (set_attr "fp_type" "<VSfptype_simple>")])
498 (define_insn "vsx_smax<mode>3"
499 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
500 (smax:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
501 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
502 "VECTOR_UNIT_VSX_P (<MODE>mode)"
503 "x<VSv>max<VSs> %x0,%x1,%x2"
504 [(set_attr "type" "<VStype_simple>")
505 (set_attr "fp_type" "<VSfptype_simple>")])
507 (define_insn "*vsx_smin<mode>3"
508 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
509 (smin:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
510 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
511 "VECTOR_UNIT_VSX_P (<MODE>mode)"
512 "x<VSv>min<VSs> %x0,%x1,%x2"
513 [(set_attr "type" "<VStype_simple>")
514 (set_attr "fp_type" "<VSfptype_simple>")])
516 ;; Special VSX version of smin/smax for single precision floating point. Since
517 ;; both numbers are rounded to single precision, we can just use the DP version
518 ;; of the instruction.
520 (define_insn "*vsx_smaxsf3"
521 [(set (match_operand:SF 0 "vsx_register_operand" "=f")
522 (smax:SF (match_operand:SF 1 "vsx_register_operand" "f")
523 (match_operand:SF 2 "vsx_register_operand" "f")))]
524 "VECTOR_UNIT_VSX_P (DFmode)"
525 "xsmaxdp %x0,%x1,%x2"
526 [(set_attr "type" "fp")
527 (set_attr "fp_type" "fp_addsub_d")])
529 (define_insn "*vsx_sminsf3"
530 [(set (match_operand:SF 0 "vsx_register_operand" "=f")
531 (smin:SF (match_operand:SF 1 "vsx_register_operand" "f")
532 (match_operand:SF 2 "vsx_register_operand" "f")))]
533 "VECTOR_UNIT_VSX_P (DFmode)"
534 "xsmindp %x0,%x1,%x2"
535 [(set_attr "type" "fp")
536 (set_attr "fp_type" "fp_addsub_d")])
538 (define_insn "*vsx_sqrt<mode>2"
539 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
540 (sqrt:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
541 "VECTOR_UNIT_VSX_P (<MODE>mode)"
542 "x<VSv>sqrt<VSs> %x0,%x1"
543 [(set_attr "type" "<VStype_sqrt>")
544 (set_attr "fp_type" "<VSfptype_sqrt>")])
546 (define_insn "*vsx_rsqrte<mode>2"
547 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
548 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
550 "VECTOR_UNIT_VSX_P (<MODE>mode)"
551 "x<VSv>rsqrte<VSs> %x0,%x1"
552 [(set_attr "type" "<VStype_simple>")
553 (set_attr "fp_type" "<VSfptype_simple>")])
555 ;; *tsqrt* returning the fg flag
556 (define_expand "vsx_tsqrt<mode>2_fg"
558 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
560 (set (match_operand:SI 0 "gpc_reg_operand" "")
563 "VECTOR_UNIT_VSX_P (<MODE>mode)"
565 operands[3] = gen_reg_rtx (CCFPmode);
568 ;; *tsqrt* returning the fe flag
569 (define_expand "vsx_tsqrt<mode>2_fe"
571 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
573 (set (match_operand:SI 0 "gpc_reg_operand" "")
576 "VECTOR_UNIT_VSX_P (<MODE>mode)"
578 operands[3] = gen_reg_rtx (CCFPmode);
581 (define_insn "*vsx_tsqrt<mode>2_internal"
582 [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
583 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
585 "VECTOR_UNIT_VSX_P (<MODE>mode)"
586 "x<VSv>tsqrt<VSs> %0,%x1"
587 [(set_attr "type" "<VStype_simple>")
588 (set_attr "fp_type" "<VSfptype_simple>")])
590 ;; Fused vector multiply/add instructions Support the classical DF versions of
591 ;; fma, which allows the target to be a separate register from the 3 inputs.
592 ;; Under VSX, the target must be either the addend or the first multiply.
593 ;; Where we can, also do the same for the Altivec V4SF fmas.
595 (define_insn "*vsx_fmadf4"
596 [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
598 (match_operand:DF 1 "vsx_register_operand" "%ws,ws,wa,wa,d")
599 (match_operand:DF 2 "vsx_register_operand" "ws,0,wa,0,d")
600 (match_operand:DF 3 "vsx_register_operand" "0,ws,0,wa,d")))]
601 "VECTOR_UNIT_VSX_P (DFmode)"
603 xsmaddadp %x0,%x1,%x2
604 xsmaddmdp %x0,%x1,%x3
605 xsmaddadp %x0,%x1,%x2
606 xsmaddmdp %x0,%x1,%x3
608 [(set_attr "type" "fp")
609 (set_attr "fp_type" "fp_maddsub_d")])
611 (define_insn "*vsx_fmav4sf4"
612 [(set (match_operand:V4SF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,v")
614 (match_operand:V4SF 1 "vsx_register_operand" "%ws,ws,wa,wa,v")
615 (match_operand:V4SF 2 "vsx_register_operand" "ws,0,wa,0,v")
616 (match_operand:V4SF 3 "vsx_register_operand" "0,ws,0,wa,v")))]
617 "VECTOR_UNIT_VSX_P (V4SFmode)"
619 xvmaddasp %x0,%x1,%x2
620 xvmaddmsp %x0,%x1,%x3
621 xvmaddasp %x0,%x1,%x2
622 xvmaddmsp %x0,%x1,%x3
624 [(set_attr "type" "vecfloat")])
626 (define_insn "*vsx_fmav2df4"
627 [(set (match_operand:V2DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa")
629 (match_operand:V2DF 1 "vsx_register_operand" "%ws,ws,wa,wa")
630 (match_operand:V2DF 2 "vsx_register_operand" "ws,0,wa,0")
631 (match_operand:V2DF 3 "vsx_register_operand" "0,ws,0,wa")))]
632 "VECTOR_UNIT_VSX_P (V2DFmode)"
634 xvmaddadp %x0,%x1,%x2
635 xvmaddmdp %x0,%x1,%x3
636 xvmaddadp %x0,%x1,%x2
637 xvmaddmdp %x0,%x1,%x3"
638 [(set_attr "type" "vecdouble")])
640 (define_insn "*vsx_fmsdf4"
641 [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
643 (match_operand:DF 1 "vsx_register_operand" "%ws,ws,wa,wa,d")
644 (match_operand:DF 2 "vsx_register_operand" "ws,0,wa,0,d")
646 (match_operand:DF 3 "vsx_register_operand" "0,ws,0,wa,d"))))]
647 "VECTOR_UNIT_VSX_P (DFmode)"
649 xsmsubadp %x0,%x1,%x2
650 xsmsubmdp %x0,%x1,%x3
651 xsmsubadp %x0,%x1,%x2
652 xsmsubmdp %x0,%x1,%x3
654 [(set_attr "type" "fp")
655 (set_attr "fp_type" "fp_maddsub_d")])
657 (define_insn "*vsx_fms<mode>4"
658 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
660 (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
661 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0,wa,0")
663 (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
664 "VECTOR_UNIT_VSX_P (<MODE>mode)"
666 x<VSv>msuba<VSs> %x0,%x1,%x2
667 x<VSv>msubm<VSs> %x0,%x1,%x3
668 x<VSv>msuba<VSs> %x0,%x1,%x2
669 x<VSv>msubm<VSs> %x0,%x1,%x3"
670 [(set_attr "type" "<VStype_mul>")])
672 (define_insn "*vsx_nfmadf4"
673 [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
676 (match_operand:DF 1 "vsx_register_operand" "ws,ws,wa,wa,d")
677 (match_operand:DF 2 "vsx_register_operand" "ws,0,wa,0,d")
678 (match_operand:DF 3 "vsx_register_operand" "0,ws,0,wa,d"))))]
679 "VECTOR_UNIT_VSX_P (DFmode)"
681 xsnmaddadp %x0,%x1,%x2
682 xsnmaddmdp %x0,%x1,%x3
683 xsnmaddadp %x0,%x1,%x2
684 xsnmaddmdp %x0,%x1,%x3
686 [(set_attr "type" "fp")
687 (set_attr "fp_type" "fp_maddsub_d")])
689 (define_insn "*vsx_nfma<mode>4"
690 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
693 (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSr>,wa,wa")
694 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0,wa,0")
695 (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
696 "VECTOR_UNIT_VSX_P (<MODE>mode)"
698 x<VSv>nmadda<VSs> %x0,%x1,%x2
699 x<VSv>nmaddm<VSs> %x0,%x1,%x3
700 x<VSv>nmadda<VSs> %x0,%x1,%x2
701 x<VSv>nmaddm<VSs> %x0,%x1,%x3"
702 [(set_attr "type" "<VStype_mul>")
703 (set_attr "fp_type" "<VSfptype_mul>")])
705 (define_insn "*vsx_nfmsdf4"
706 [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
709 (match_operand:DF 1 "vsx_register_operand" "%ws,ws,wa,wa,d")
710 (match_operand:DF 2 "vsx_register_operand" "ws,0,wa,0,d")
712 (match_operand:DF 3 "vsx_register_operand" "0,ws,0,wa,d")))))]
713 "VECTOR_UNIT_VSX_P (DFmode)"
715 xsnmsubadp %x0,%x1,%x2
716 xsnmsubmdp %x0,%x1,%x3
717 xsnmsubadp %x0,%x1,%x2
718 xsnmsubmdp %x0,%x1,%x3
720 [(set_attr "type" "fp")
721 (set_attr "fp_type" "fp_maddsub_d")])
723 (define_insn "*vsx_nfmsv4sf4"
724 [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf,wf,?wa,?wa,v")
727 (match_operand:V4SF 1 "vsx_register_operand" "%wf,wf,wa,wa,v")
728 (match_operand:V4SF 2 "vsx_register_operand" "wf,0,wa,0,v")
730 (match_operand:V4SF 3 "vsx_register_operand" "0,wf,0,wa,v")))))]
731 "VECTOR_UNIT_VSX_P (V4SFmode)"
733 xvnmsubasp %x0,%x1,%x2
734 xvnmsubmsp %x0,%x1,%x3
735 xvnmsubasp %x0,%x1,%x2
736 xvnmsubmsp %x0,%x1,%x3
737 vnmsubfp %0,%1,%2,%3"
738 [(set_attr "type" "vecfloat")])
740 (define_insn "*vsx_nfmsv2df4"
741 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd,?wa,?wa")
744 (match_operand:V2DF 1 "vsx_register_operand" "%wd,wd,wa,wa")
745 (match_operand:V2DF 2 "vsx_register_operand" "wd,0,wa,0")
747 (match_operand:V2DF 3 "vsx_register_operand" "0,wd,0,wa")))))]
748 "VECTOR_UNIT_VSX_P (V2DFmode)"
750 xvnmsubadp %x0,%x1,%x2
751 xvnmsubmdp %x0,%x1,%x3
752 xvnmsubadp %x0,%x1,%x2
753 xvnmsubmdp %x0,%x1,%x3"
754 [(set_attr "type" "vecdouble")])
756 ;; Vector conditional expressions (no scalar version for these instructions)
757 (define_insn "vsx_eq<mode>"
758 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
759 (eq:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
760 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
761 "VECTOR_UNIT_VSX_P (<MODE>mode)"
762 "xvcmpeq<VSs> %x0,%x1,%x2"
763 [(set_attr "type" "<VStype_simple>")
764 (set_attr "fp_type" "<VSfptype_simple>")])
766 (define_insn "vsx_gt<mode>"
767 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
768 (gt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
769 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
770 "VECTOR_UNIT_VSX_P (<MODE>mode)"
771 "xvcmpgt<VSs> %x0,%x1,%x2"
772 [(set_attr "type" "<VStype_simple>")
773 (set_attr "fp_type" "<VSfptype_simple>")])
775 (define_insn "*vsx_ge<mode>"
776 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
777 (ge:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
778 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
779 "VECTOR_UNIT_VSX_P (<MODE>mode)"
780 "xvcmpge<VSs> %x0,%x1,%x2"
781 [(set_attr "type" "<VStype_simple>")
782 (set_attr "fp_type" "<VSfptype_simple>")])
784 ;; Floating point scalar compare
785 (define_insn "*vsx_cmpdf_internal1"
786 [(set (match_operand:CCFP 0 "cc_reg_operand" "=y,?y")
787 (compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "ws,wa")
788 (match_operand:DF 2 "gpc_reg_operand" "ws,wa")))]
789 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
790 && VECTOR_UNIT_VSX_P (DFmode)"
791 "xscmpudp %0,%x1,%x2"
792 [(set_attr "type" "fpcompare")])
794 ;; Compare vectors producing a vector result and a predicate, setting CR6 to
795 ;; indicate a combined status
796 (define_insn "*vsx_eq_<mode>_p"
799 [(eq:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
800 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
802 (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
803 (eq:VSX_F (match_dup 1)
805 "VECTOR_UNIT_VSX_P (<MODE>mode)"
806 "xvcmpeq<VSs>. %x0,%x1,%x2"
807 [(set_attr "type" "<VStype_simple>")])
809 (define_insn "*vsx_gt_<mode>_p"
812 [(gt:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
813 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
815 (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
816 (gt:VSX_F (match_dup 1)
818 "VECTOR_UNIT_VSX_P (<MODE>mode)"
819 "xvcmpgt<VSs>. %x0,%x1,%x2"
820 [(set_attr "type" "<VStype_simple>")])
822 (define_insn "*vsx_ge_<mode>_p"
825 [(ge:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
826 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
828 (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
829 (ge:VSX_F (match_dup 1)
831 "VECTOR_UNIT_VSX_P (<MODE>mode)"
832 "xvcmpge<VSs>. %x0,%x1,%x2"
833 [(set_attr "type" "<VStype_simple>")])
836 (define_insn "*vsx_xxsel<mode>"
837 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
839 (ne:CC (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
840 (match_operand:VSX_L 4 "zero_constant" ""))
841 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
842 (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
843 "VECTOR_MEM_VSX_P (<MODE>mode)"
844 "xxsel %x0,%x3,%x2,%x1"
845 [(set_attr "type" "vecperm")])
847 (define_insn "*vsx_xxsel<mode>_uns"
848 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
850 (ne:CCUNS (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
851 (match_operand:VSX_L 4 "zero_constant" ""))
852 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
853 (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
854 "VECTOR_MEM_VSX_P (<MODE>mode)"
855 "xxsel %x0,%x3,%x2,%x1"
856 [(set_attr "type" "vecperm")])
859 (define_insn "vsx_copysign<mode>3"
860 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
862 [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
863 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")]
865 "VECTOR_UNIT_VSX_P (<MODE>mode)"
866 "x<VSv>cpsgn<VSs> %x0,%x2,%x1"
867 [(set_attr "type" "<VStype_simple>")
868 (set_attr "fp_type" "<VSfptype_simple>")])
870 ;; For the conversions, limit the register class for the integer value to be
871 ;; the fprs because we don't want to add the altivec registers to movdi/movsi.
872 ;; For the unsigned tests, there isn't a generic double -> unsigned conversion
873 ;; in rs6000.md so don't test VECTOR_UNIT_VSX_P, just test against VSX.
874 ;; Don't use vsx_register_operand here, use gpc_reg_operand to match rs6000.md.
875 (define_insn "vsx_float<VSi><mode>2"
876 [(set (match_operand:VSX_B 0 "gpc_reg_operand" "=<VSr>,?wa")
877 (float:VSX_B (match_operand:<VSI> 1 "gpc_reg_operand" "<VSr2>,<VSr3>")))]
878 "VECTOR_UNIT_VSX_P (<MODE>mode)"
879 "x<VSv>cvsx<VSc><VSs> %x0,%x1"
880 [(set_attr "type" "<VStype_simple>")
881 (set_attr "fp_type" "<VSfptype_simple>")])
883 (define_insn "vsx_floatuns<VSi><mode>2"
884 [(set (match_operand:VSX_B 0 "gpc_reg_operand" "=<VSr>,?wa")
885 (unsigned_float:VSX_B (match_operand:<VSI> 1 "gpc_reg_operand" "<VSr2>,<VSr3>")))]
886 "VECTOR_UNIT_VSX_P (<MODE>mode)"
887 "x<VSv>cvux<VSc><VSs> %x0,%x1"
888 [(set_attr "type" "<VStype_simple>")
889 (set_attr "fp_type" "<VSfptype_simple>")])
891 (define_insn "vsx_fix_trunc<mode><VSi>2"
892 [(set (match_operand:<VSI> 0 "gpc_reg_operand" "=<VSr2>,?<VSr3>")
893 (fix:<VSI> (match_operand:VSX_B 1 "gpc_reg_operand" "<VSr>,wa")))]
894 "VECTOR_UNIT_VSX_P (<MODE>mode)"
895 "x<VSv>cv<VSs>sx<VSc>s %x0,%x1"
896 [(set_attr "type" "<VStype_simple>")
897 (set_attr "fp_type" "<VSfptype_simple>")])
899 (define_insn "vsx_fixuns_trunc<mode><VSi>2"
900 [(set (match_operand:<VSI> 0 "gpc_reg_operand" "=<VSr2>,?<VSr3>")
901 (unsigned_fix:<VSI> (match_operand:VSX_B 1 "gpc_reg_operand" "<VSr>,wa")))]
902 "VECTOR_UNIT_VSX_P (<MODE>mode)"
903 "x<VSv>cv<VSs>ux<VSc>s %x0,%x1"
904 [(set_attr "type" "<VStype_simple>")
905 (set_attr "fp_type" "<VSfptype_simple>")])
907 ;; Math rounding functions
908 (define_insn "vsx_x<VSv>r<VSs>i"
909 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
910 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
911 UNSPEC_VSX_ROUND_I))]
912 "VECTOR_UNIT_VSX_P (<MODE>mode)"
913 "x<VSv>r<VSs>i %x0,%x1"
914 [(set_attr "type" "<VStype_simple>")
915 (set_attr "fp_type" "<VSfptype_simple>")])
917 (define_insn "vsx_x<VSv>r<VSs>ic"
918 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
919 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
920 UNSPEC_VSX_ROUND_IC))]
921 "VECTOR_UNIT_VSX_P (<MODE>mode)"
922 "x<VSv>r<VSs>ic %x0,%x1"
923 [(set_attr "type" "<VStype_simple>")
924 (set_attr "fp_type" "<VSfptype_simple>")])
926 (define_insn "vsx_btrunc<mode>2"
927 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
928 (fix:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
929 "VECTOR_UNIT_VSX_P (<MODE>mode)"
930 "x<VSv>r<VSs>iz %x0,%x1"
931 [(set_attr "type" "<VStype_simple>")
932 (set_attr "fp_type" "<VSfptype_simple>")])
934 (define_insn "*vsx_b2trunc<mode>2"
935 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
936 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
938 "VECTOR_UNIT_VSX_P (<MODE>mode)"
939 "x<VSv>r<VSs>iz %x0,%x1"
940 [(set_attr "type" "<VStype_simple>")
941 (set_attr "fp_type" "<VSfptype_simple>")])
943 (define_insn "vsx_floor<mode>2"
944 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
945 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
947 "VECTOR_UNIT_VSX_P (<MODE>mode)"
948 "x<VSv>r<VSs>im %x0,%x1"
949 [(set_attr "type" "<VStype_simple>")
950 (set_attr "fp_type" "<VSfptype_simple>")])
952 (define_insn "vsx_ceil<mode>2"
953 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
954 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
956 "VECTOR_UNIT_VSX_P (<MODE>mode)"
957 "x<VSv>r<VSs>ip %x0,%x1"
958 [(set_attr "type" "<VStype_simple>")
959 (set_attr "fp_type" "<VSfptype_simple>")])
962 ;; VSX convert to/from double vector
964 ;; Convert between single and double precision
965 ;; Don't use xscvspdp and xscvdpsp for scalar conversions, since the normal
966 ;; scalar single precision instructions internally use the double format.
967 ;; Prefer the altivec registers, since we likely will need to do a vperm
968 (define_insn "vsx_<VS_spdp_insn>"
969 [(set (match_operand:<VS_spdp_res> 0 "vsx_register_operand" "=<VSr4>,?wa")
970 (unspec:<VS_spdp_res> [(match_operand:VSX_SPDP 1 "vsx_register_operand" "<VSr5>,wa")]
972 "VECTOR_UNIT_VSX_P (<MODE>mode)"
973 "<VS_spdp_insn> %x0,%x1"
974 [(set_attr "type" "<VS_spdp_type>")])
976 ;; xscvspdp, represent the scalar SF type as V4SF
977 (define_insn "vsx_xscvspdp"
978 [(set (match_operand:DF 0 "vsx_register_operand" "=ws,?wa")
979 (unspec:DF [(match_operand:V4SF 1 "vsx_register_operand" "wa,wa")]
981 "VECTOR_UNIT_VSX_P (V4SFmode)"
983 [(set_attr "type" "fp")])
985 ;; xscvdpsp used for splat'ing a scalar to V4SF, knowing that the internal SF
986 ;; format of scalars is actually DF.
987 (define_insn "vsx_xscvdpsp_scalar"
988 [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
989 (unspec:V4SF [(match_operand:SF 1 "vsx_register_operand" "f")]
991 "VECTOR_UNIT_VSX_P (V4SFmode)"
993 [(set_attr "type" "fp")])
995 ;; Same as vsx_xscvspdp, but use SF as the type
996 (define_insn "vsx_xscvspdp_scalar2"
997 [(set (match_operand:SF 0 "vsx_register_operand" "=f")
998 (unspec:SF [(match_operand:V4SF 1 "vsx_register_operand" "wa")]
1000 "VECTOR_UNIT_VSX_P (V4SFmode)"
1002 [(set_attr "type" "fp")])
1004 ;; Convert from 64-bit to 32-bit types
1005 ;; Note, favor the Altivec registers since the usual use of these instructions
1006 ;; is in vector converts and we need to use the Altivec vperm instruction.
1008 (define_insn "vsx_xvcvdpsxws"
1009 [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
1010 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
1011 UNSPEC_VSX_CVDPSXWS))]
1012 "VECTOR_UNIT_VSX_P (V2DFmode)"
1013 "xvcvdpsxws %x0,%x1"
1014 [(set_attr "type" "vecdouble")])
1016 (define_insn "vsx_xvcvdpuxws"
1017 [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
1018 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
1019 UNSPEC_VSX_CVDPUXWS))]
1020 "VECTOR_UNIT_VSX_P (V2DFmode)"
1021 "xvcvdpuxws %x0,%x1"
1022 [(set_attr "type" "vecdouble")])
1024 (define_insn "vsx_xvcvsxdsp"
1025 [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
1026 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
1027 UNSPEC_VSX_CVSXDSP))]
1028 "VECTOR_UNIT_VSX_P (V2DFmode)"
1030 [(set_attr "type" "vecfloat")])
1032 (define_insn "vsx_xvcvuxdsp"
1033 [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
1034 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
1035 UNSPEC_VSX_CVUXDSP))]
1036 "VECTOR_UNIT_VSX_P (V2DFmode)"
1038 [(set_attr "type" "vecdouble")])
1040 ;; Convert from 32-bit to 64-bit types
1041 (define_insn "vsx_xvcvsxwdp"
1042 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1043 (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
1044 UNSPEC_VSX_CVSXWDP))]
1045 "VECTOR_UNIT_VSX_P (V2DFmode)"
1047 [(set_attr "type" "vecdouble")])
1049 (define_insn "vsx_xvcvuxwdp"
1050 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1051 (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
1052 UNSPEC_VSX_CVUXWDP))]
1053 "VECTOR_UNIT_VSX_P (V2DFmode)"
1055 [(set_attr "type" "vecdouble")])
1057 (define_insn "vsx_xvcvspsxds"
1058 [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
1059 (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
1060 UNSPEC_VSX_CVSPSXDS))]
1061 "VECTOR_UNIT_VSX_P (V2DFmode)"
1062 "xvcvspsxds %x0,%x1"
1063 [(set_attr "type" "vecdouble")])
1065 (define_insn "vsx_xvcvspuxds"
1066 [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
1067 (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
1068 UNSPEC_VSX_CVSPUXDS))]
1069 "VECTOR_UNIT_VSX_P (V2DFmode)"
1070 "xvcvspuxds %x0,%x1"
1071 [(set_attr "type" "vecdouble")])
1073 ;; Only optimize (float (fix x)) -> frz if we are in fast-math mode, since
1074 ;; since the xsrdpiz instruction does not truncate the value if the floating
1075 ;; point value is < LONG_MIN or > LONG_MAX.
1076 (define_insn "*vsx_float_fix_<mode>2"
1077 [(set (match_operand:VSX_DF 0 "vsx_register_operand" "=<VSr>,?wa")
1080 (match_operand:VSX_DF 1 "vsx_register_operand" "<VSr>,?wa"))))]
1081 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
1082 && VECTOR_UNIT_VSX_P (<MODE>mode) && flag_unsafe_math_optimizations
1083 && !flag_trapping_math && TARGET_FRIZ"
1084 "x<VSv>r<VSs>iz %x0,%x1"
1085 [(set_attr "type" "<VStype_simple>")
1086 (set_attr "fp_type" "<VSfptype_simple>")])
1089 ;; Logical operations
1090 ;; Do not support TImode logical instructions on 32-bit at present, because the
1091 ;; compiler will see that we have a TImode and when it wanted DImode, and
1092 ;; convert the DImode to TImode, store it on the stack, and load it in a VSX
1094 (define_insn "*vsx_and<mode>3"
1095 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1097 (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
1098 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")))]
1099 "VECTOR_MEM_VSX_P (<MODE>mode)
1100 && (<MODE>mode != TImode || TARGET_POWERPC64)"
1101 "xxland %x0,%x1,%x2"
1102 [(set_attr "type" "vecsimple")])
1104 (define_insn "*vsx_ior<mode>3"
1105 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1106 (ior:VSX_L (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
1107 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")))]
1108 "VECTOR_MEM_VSX_P (<MODE>mode)
1109 && (<MODE>mode != TImode || TARGET_POWERPC64)"
1111 [(set_attr "type" "vecsimple")])
1113 (define_insn "*vsx_xor<mode>3"
1114 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1116 (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
1117 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")))]
1118 "VECTOR_MEM_VSX_P (<MODE>mode)
1119 && (<MODE>mode != TImode || TARGET_POWERPC64)"
1120 "xxlxor %x0,%x1,%x2"
1121 [(set_attr "type" "vecsimple")])
1123 (define_insn "*vsx_one_cmpl<mode>2"
1124 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1126 (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")))]
1127 "VECTOR_MEM_VSX_P (<MODE>mode)
1128 && (<MODE>mode != TImode || TARGET_POWERPC64)"
1129 "xxlnor %x0,%x1,%x1"
1130 [(set_attr "type" "vecsimple")])
1132 (define_insn "*vsx_nor<mode>3"
1133 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1136 (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
1137 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa"))))]
1138 "VECTOR_MEM_VSX_P (<MODE>mode)
1139 && (<MODE>mode != TImode || TARGET_POWERPC64)"
1140 "xxlnor %x0,%x1,%x2"
1141 [(set_attr "type" "vecsimple")])
1143 (define_insn "*vsx_andc<mode>3"
1144 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1147 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa"))
1148 (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")))]
1149 "VECTOR_MEM_VSX_P (<MODE>mode)
1150 && (<MODE>mode != TImode || TARGET_POWERPC64)"
1151 "xxlandc %x0,%x1,%x2"
1152 [(set_attr "type" "vecsimple")])
1155 ;; Permute operations
1157 ;; Build a V2DF/V2DI vector from two scalars
1158 (define_insn "vsx_concat_<mode>"
1159 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=<VSr>,?wa")
1161 (match_operand:<VS_scalar> 1 "vsx_register_operand" "ws,wa")
1162 (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")))]
1163 "VECTOR_MEM_VSX_P (<MODE>mode)"
1164 "xxpermdi %x0,%x1,%x2,0"
1165 [(set_attr "type" "vecperm")])
1167 ;; Special purpose concat using xxpermdi to glue two single precision values
1168 ;; together, relying on the fact that internally scalar floats are represented
1169 ;; as doubles. This is used to initialize a V4SF vector with 4 floats
1170 (define_insn "vsx_concat_v2sf"
1171 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1173 [(match_operand:SF 1 "vsx_register_operand" "f,f")
1174 (match_operand:SF 2 "vsx_register_operand" "f,f")]
1175 UNSPEC_VSX_CONCAT))]
1176 "VECTOR_MEM_VSX_P (V2DFmode)"
1177 "xxpermdi %x0,%x1,%x2,0"
1178 [(set_attr "type" "vecperm")])
1180 ;; Set the element of a V2DI/VD2F mode
1181 (define_insn "vsx_set_<mode>"
1182 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
1183 (unspec:VSX_D [(match_operand:VSX_D 1 "vsx_register_operand" "wd,wa")
1184 (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")
1185 (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
1187 "VECTOR_MEM_VSX_P (<MODE>mode)"
1189 if (INTVAL (operands[3]) == 0)
1190 return \"xxpermdi %x0,%x2,%x1,1\";
1191 else if (INTVAL (operands[3]) == 1)
1192 return \"xxpermdi %x0,%x1,%x2,0\";
1196 [(set_attr "type" "vecperm")])
1198 ;; Extract a DF/DI element from V2DF/V2DI
1199 (define_insn "vsx_extract_<mode>"
1200 [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,d,?wa")
1201 (vec_select:<VS_scalar> (match_operand:VSX_D 1 "vsx_register_operand" "wd,wd,wa")
1203 [(match_operand:QI 2 "u5bit_cint_operand" "i,i,i")])))]
1204 "VECTOR_MEM_VSX_P (<MODE>mode)"
1206 gcc_assert (UINTVAL (operands[2]) <= 1);
1207 operands[3] = GEN_INT (INTVAL (operands[2]) << 1);
1208 return \"xxpermdi %x0,%x1,%x1,%3\";
1210 [(set_attr "type" "vecperm")])
1212 ;; Optimize extracting element 0 from memory
1213 (define_insn "*vsx_extract_<mode>_zero"
1214 [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,d,?wa")
1215 (vec_select:<VS_scalar>
1216 (match_operand:VSX_D 1 "indexed_or_indirect_operand" "Z,Z,Z")
1217 (parallel [(const_int 0)])))]
1218 "VECTOR_MEM_VSX_P (<MODE>mode) && WORDS_BIG_ENDIAN"
1222 (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
1223 (const_string "fpload_ux")
1224 (const_string "fpload")))
1225 (set_attr "length" "4")])
1227 ;; Extract a SF element from V4SF
1228 (define_insn_and_split "vsx_extract_v4sf"
1229 [(set (match_operand:SF 0 "vsx_register_operand" "=f,f")
1231 (match_operand:V4SF 1 "vsx_register_operand" "wa,wa")
1232 (parallel [(match_operand:QI 2 "u5bit_cint_operand" "O,i")])))
1233 (clobber (match_scratch:V4SF 3 "=X,0"))]
1234 "VECTOR_UNIT_VSX_P (V4SFmode)"
1242 rtx op0 = operands[0];
1243 rtx op1 = operands[1];
1244 rtx op2 = operands[2];
1245 rtx op3 = operands[3];
1247 HOST_WIDE_INT ele = INTVAL (op2);
1253 if (GET_CODE (op3) == SCRATCH)
1254 op3 = gen_reg_rtx (V4SFmode);
1255 emit_insn (gen_vsx_xxsldwi_v4sf (op3, op1, op1, op2));
1258 emit_insn (gen_vsx_xscvspdp_scalar2 (op0, tmp));
1261 [(set_attr "length" "4,8")
1262 (set_attr "type" "fp")])
1264 ;; Expand the builtin form of xxpermdi to canonical rtl.
1265 (define_expand "vsx_xxpermdi_<mode>"
1266 [(match_operand:VSX_L 0 "vsx_register_operand" "")
1267 (match_operand:VSX_L 1 "vsx_register_operand" "")
1268 (match_operand:VSX_L 2 "vsx_register_operand" "")
1269 (match_operand:QI 3 "u5bit_cint_operand" "")]
1270 "VECTOR_MEM_VSX_P (<MODE>mode)"
1272 rtx target = operands[0];
1273 rtx op0 = operands[1];
1274 rtx op1 = operands[2];
1275 int mask = INTVAL (operands[3]);
1276 rtx perm0 = GEN_INT ((mask >> 1) & 1);
1277 rtx perm1 = GEN_INT ((mask & 1) + 2);
1278 rtx (*gen) (rtx, rtx, rtx, rtx, rtx);
1280 if (<MODE>mode == V2DFmode)
1281 gen = gen_vsx_xxpermdi2_v2df_1;
1284 gen = gen_vsx_xxpermdi2_v2di_1;
1285 if (<MODE>mode != V2DImode)
1287 target = gen_lowpart (V2DImode, target);
1288 op0 = gen_lowpart (V2DImode, op0);
1289 op1 = gen_lowpart (V2DImode, op1);
1292 emit_insn (gen (target, op0, op1, perm0, perm1));
1296 (define_insn "vsx_xxpermdi2_<mode>_1"
1297 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd")
1299 (vec_concat:<VS_double>
1300 (match_operand:VSX_D 1 "vsx_register_operand" "wd")
1301 (match_operand:VSX_D 2 "vsx_register_operand" "wd"))
1302 (parallel [(match_operand 3 "const_0_to_1_operand" "")
1303 (match_operand 4 "const_2_to_3_operand" "")])))]
1304 "VECTOR_MEM_VSX_P (<MODE>mode)"
1306 int mask = (INTVAL (operands[3]) << 1) | (INTVAL (operands[4]) - 2);
1307 operands[3] = GEN_INT (mask);
1308 return "xxpermdi %x0,%x1,%x2,%3";
1310 [(set_attr "type" "vecperm")])
1312 (define_expand "vec_perm_const<mode>"
1313 [(match_operand:VSX_D 0 "vsx_register_operand" "")
1314 (match_operand:VSX_D 1 "vsx_register_operand" "")
1315 (match_operand:VSX_D 2 "vsx_register_operand" "")
1316 (match_operand:V2DI 3 "" "")]
1317 "VECTOR_MEM_VSX_P (<MODE>mode)"
1319 if (rs6000_expand_vec_perm_const (operands))
1325 ;; Expanders for builtins
1326 (define_expand "vsx_mergel_<mode>"
1327 [(set (match_operand:VSX_D 0 "vsx_register_operand" "")
1329 (vec_concat:<VS_double>
1330 (match_operand:VSX_D 1 "vsx_register_operand" "")
1331 (match_operand:VSX_D 2 "vsx_register_operand" ""))
1332 (parallel [(const_int 1) (const_int 3)])))]
1333 "VECTOR_MEM_VSX_P (<MODE>mode)"
1336 (define_expand "vsx_mergeh_<mode>"
1337 [(set (match_operand:VSX_D 0 "vsx_register_operand" "")
1339 (vec_concat:<VS_double>
1340 (match_operand:VSX_D 1 "vsx_register_operand" "")
1341 (match_operand:VSX_D 2 "vsx_register_operand" ""))
1342 (parallel [(const_int 0) (const_int 2)])))]
1343 "VECTOR_MEM_VSX_P (<MODE>mode)"
1347 (define_insn "vsx_splat_<mode>"
1348 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,wd,wd,?wa,?wa,?wa")
1349 (vec_duplicate:VSX_D
1350 (match_operand:<VS_scalar> 1 "splat_input_operand" "ws,f,Z,wa,wa,Z")))]
1351 "VECTOR_MEM_VSX_P (<MODE>mode)"
1353 xxpermdi %x0,%x1,%x1,0
1354 xxpermdi %x0,%x1,%x1,0
1356 xxpermdi %x0,%x1,%x1,0
1357 xxpermdi %x0,%x1,%x1,0
1359 [(set_attr "type" "vecperm,vecperm,vecload,vecperm,vecperm,vecload")])
1362 (define_insn "vsx_xxspltw_<mode>"
1363 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1364 (vec_duplicate:VSX_W
1365 (vec_select:<VS_scalar>
1366 (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1368 [(match_operand:QI 2 "u5bit_cint_operand" "i,i")]))))]
1369 "VECTOR_MEM_VSX_P (<MODE>mode)"
1370 "xxspltw %x0,%x1,%2"
1371 [(set_attr "type" "vecperm")])
1373 ;; V4SF/V4SI interleave
1374 (define_insn "vsx_xxmrghw_<mode>"
1375 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1377 (vec_concat:<VS_double>
1378 (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1379 (match_operand:VSX_W 2 "vsx_register_operand" "wf,wa"))
1380 (parallel [(const_int 0) (const_int 4)
1381 (const_int 1) (const_int 5)])))]
1382 "VECTOR_MEM_VSX_P (<MODE>mode)"
1383 "xxmrghw %x0,%x1,%x2"
1384 [(set_attr "type" "vecperm")])
1386 (define_insn "vsx_xxmrglw_<mode>"
1387 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1389 (vec_concat:<VS_double>
1390 (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1391 (match_operand:VSX_W 2 "vsx_register_operand" "wf,?wa"))
1392 (parallel [(const_int 2) (const_int 6)
1393 (const_int 3) (const_int 7)])))]
1394 "VECTOR_MEM_VSX_P (<MODE>mode)"
1395 "xxmrglw %x0,%x1,%x2"
1396 [(set_attr "type" "vecperm")])
1398 ;; Shift left double by word immediate
1399 (define_insn "vsx_xxsldwi_<mode>"
1400 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=wa")
1401 (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "wa")
1402 (match_operand:VSX_L 2 "vsx_register_operand" "wa")
1403 (match_operand:QI 3 "u5bit_cint_operand" "i")]
1405 "VECTOR_MEM_VSX_P (<MODE>mode)"
1406 "xxsldwi %x0,%x1,%x2,%3"
1407 [(set_attr "type" "vecperm")])
1410 ;; Vector reduction insns and splitters
1412 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v2df"
1413 [(set (match_operand:V2DF 0 "vfloat_operand" "=&wd,&?wa,wd,?wa")
1417 (match_operand:V2DF 1 "vfloat_operand" "wd,wa,wd,wa")
1418 (parallel [(const_int 1)]))
1421 (parallel [(const_int 0)])))
1423 (clobber (match_scratch:V2DF 2 "=0,0,&wd,&wa"))]
1424 "VECTOR_UNIT_VSX_P (V2DFmode)"
1430 rtx tmp = (GET_CODE (operands[2]) == SCRATCH)
1431 ? gen_reg_rtx (V2DFmode)
1433 emit_insn (gen_vsx_xxsldwi_v2df (tmp, operands[1], operands[1], const2_rtx));
1434 emit_insn (gen_<VEC_reduc_rtx>v2df3 (operands[0], tmp, operands[1]));
1437 [(set_attr "length" "8")
1438 (set_attr "type" "veccomplex")])
1440 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v4sf"
1441 [(set (match_operand:V4SF 0 "vfloat_operand" "=wf,?wa")
1443 (unspec:V4SF [(const_int 0)] UNSPEC_REDUC)
1444 (match_operand:V4SF 1 "vfloat_operand" "wf,wa")))
1445 (clobber (match_scratch:V4SF 2 "=&wf,&wa"))
1446 (clobber (match_scratch:V4SF 3 "=&wf,&wa"))]
1447 "VECTOR_UNIT_VSX_P (V4SFmode)"
1453 rtx op0 = operands[0];
1454 rtx op1 = operands[1];
1455 rtx tmp2, tmp3, tmp4;
1457 if (can_create_pseudo_p ())
1459 tmp2 = gen_reg_rtx (V4SFmode);
1460 tmp3 = gen_reg_rtx (V4SFmode);
1461 tmp4 = gen_reg_rtx (V4SFmode);
1470 emit_insn (gen_vsx_xxsldwi_v4sf (tmp2, op1, op1, const2_rtx));
1471 emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp3, tmp2, op1));
1472 emit_insn (gen_vsx_xxsldwi_v4sf (tmp4, tmp3, tmp3, GEN_INT (3)));
1473 emit_insn (gen_<VEC_reduc_rtx>v4sf3 (op0, tmp4, tmp3));
1476 [(set_attr "length" "16")
1477 (set_attr "type" "veccomplex")])
1479 ;; Combiner patterns with the vector reduction patterns that knows we can get
1480 ;; to the top element of the V2DF array without doing an extract.
1482 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v2df_scalar"
1483 [(set (match_operand:DF 0 "vfloat_operand" "=&ws,&?wa,ws,?wa")
1488 (match_operand:V2DF 1 "vfloat_operand" "wd,wa,wd,wa")
1489 (parallel [(const_int 1)]))
1492 (parallel [(const_int 0)])))
1494 (parallel [(const_int 1)])))
1495 (clobber (match_scratch:DF 2 "=0,0,&wd,&wa"))]
1496 "VECTOR_UNIT_VSX_P (V2DFmode)"
1502 rtx hi = gen_highpart (DFmode, operands[1]);
1503 rtx lo = (GET_CODE (operands[2]) == SCRATCH)
1504 ? gen_reg_rtx (DFmode)
1507 emit_insn (gen_vsx_extract_v2df (lo, operands[1], const1_rtx));
1508 emit_insn (gen_<VEC_reduc_rtx>df3 (operands[0], hi, lo));
1511 [(set_attr "length" "8")
1512 (set_attr "type" "veccomplex")])
1514 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v4sf_scalar"
1515 [(set (match_operand:SF 0 "vfloat_operand" "=f,?f")
1518 (unspec:V4SF [(const_int 0)] UNSPEC_REDUC)
1519 (match_operand:V4SF 1 "vfloat_operand" "wf,wa"))
1520 (parallel [(const_int 3)])))
1521 (clobber (match_scratch:V4SF 2 "=&wf,&wa"))
1522 (clobber (match_scratch:V4SF 3 "=&wf,&wa"))
1523 (clobber (match_scratch:V4SF 4 "=0,0"))]
1524 "VECTOR_UNIT_VSX_P (V4SFmode)"
1530 rtx op0 = operands[0];
1531 rtx op1 = operands[1];
1532 rtx tmp2, tmp3, tmp4, tmp5;
1534 if (can_create_pseudo_p ())
1536 tmp2 = gen_reg_rtx (V4SFmode);
1537 tmp3 = gen_reg_rtx (V4SFmode);
1538 tmp4 = gen_reg_rtx (V4SFmode);
1539 tmp5 = gen_reg_rtx (V4SFmode);
1549 emit_insn (gen_vsx_xxsldwi_v4sf (tmp2, op1, op1, const2_rtx));
1550 emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp3, tmp2, op1));
1551 emit_insn (gen_vsx_xxsldwi_v4sf (tmp4, tmp3, tmp3, GEN_INT (3)));
1552 emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp5, tmp4, tmp3));
1553 emit_insn (gen_vsx_xscvspdp_scalar2 (op0, tmp5));
1556 [(set_attr "length" "20")
1557 (set_attr "type" "veccomplex")])