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 ;; Like VSX_L, but don't support TImode for doing logical instructions in
41 (define_mode_iterator VSX_L2 [V16QI V8HI V4SI V2DI V4SF V2DF])
43 ;; Iterator for memory move. Handle TImode specially to allow
44 ;; it to use gprs as well as vsx registers.
45 (define_mode_iterator VSX_M [V16QI V8HI V4SI V2DI V4SF V2DF])
47 ;; Map into the appropriate load/store name based on the type
48 (define_mode_attr VSm [(V16QI "vw4")
57 ;; Map into the appropriate suffix based on the type
58 (define_mode_attr VSs [(V16QI "sp")
68 ;; Map the register class used
69 (define_mode_attr VSr [(V16QI "v")
79 ;; Map the register class used for float<->int conversions
80 (define_mode_attr VSr2 [(V2DF "wd")
84 (define_mode_attr VSr3 [(V2DF "wa")
88 ;; Map the register class for sp<->dp float conversions, destination
89 (define_mode_attr VSr4 [(SF "ws")
94 ;; Map the register class for sp<->dp float conversions, destination
95 (define_mode_attr VSr5 [(SF "ws")
100 ;; Same size integer type for floating point data
101 (define_mode_attr VSi [(V4SF "v4si")
105 (define_mode_attr VSI [(V4SF "V4SI")
109 ;; Word size for same size conversion
110 (define_mode_attr VSc [(V4SF "w")
114 ;; Map into either s or v, depending on whether this is a scalar or vector
116 (define_mode_attr VSv [(V16QI "v")
124 ;; Appropriate type for add ops (and other simple FP ops)
125 (define_mode_attr VStype_simple [(V2DF "vecdouble")
129 (define_mode_attr VSfptype_simple [(V2DF "fp_addsub_d")
133 ;; Appropriate type for multiply ops
134 (define_mode_attr VStype_mul [(V2DF "vecdouble")
138 (define_mode_attr VSfptype_mul [(V2DF "fp_mul_d")
142 ;; Appropriate type for divide ops.
143 (define_mode_attr VStype_div [(V2DF "vecdiv")
147 (define_mode_attr VSfptype_div [(V2DF "fp_div_d")
151 ;; Appropriate type for sqrt ops. For now, just lump the vector sqrt with
153 (define_mode_attr VStype_sqrt [(V2DF "dsqrt")
157 (define_mode_attr VSfptype_sqrt [(V2DF "fp_sqrt_d")
161 ;; Iterator and modes for sp<->dp conversions
162 ;; Because scalar SF values are represented internally as double, use the
163 ;; V4SF type to represent this than SF.
164 (define_mode_iterator VSX_SPDP [DF V4SF V2DF])
166 (define_mode_attr VS_spdp_res [(DF "V4SF")
170 (define_mode_attr VS_spdp_insn [(DF "xscvdpsp")
174 (define_mode_attr VS_spdp_type [(DF "fp")
178 ;; Map the scalar mode for a vector type
179 (define_mode_attr VS_scalar [(V2DF "DF")
186 ;; Map to a double-sized vector mode
187 (define_mode_attr VS_double [(V4SI "V8SI")
192 ;; Constants for creating unspecs
193 (define_c_enum "unspec"
215 (define_insn "*vsx_mov<mode>"
216 [(set (match_operand:VSX_M 0 "nonimmediate_operand" "=Z,<VSr>,<VSr>,?Z,?wa,?wa,wQ,?&r,??Y,??r,??r,<VSr>,?wa,*r,v,wZ, v")
217 (match_operand:VSX_M 1 "input_operand" "<VSr>,Z,<VSr>,wa,Z,wa,r,wQ,r,Y,r,j,j,j,W,v,wZ"))]
218 "VECTOR_MEM_VSX_P (<MODE>mode)
219 && (register_operand (operands[0], <MODE>mode)
220 || register_operand (operands[1], <MODE>mode))"
222 return rs6000_output_move_128bit (operands);
224 [(set_attr "type" "vecstore,vecload,vecsimple,vecstore,vecload,vecsimple,load,store,store,load, *,vecsimple,vecsimple,*, *,vecstore,vecload")
225 (set_attr "length" "4,4,4,4,4,4,12,12,12,12,16,4,4,*,16,4,4")])
227 ;; Unlike other VSX moves, allow the GPRs even for reloading, since a normal
228 ;; use of TImode is for unions. However for plain data movement, slightly
229 ;; favor the vector loads
230 (define_insn "*vsx_movti_64bit"
231 [(set (match_operand:TI 0 "nonimmediate_operand" "=Z,wa,wa,wa,v,v,wZ,wQ,&r,Y,r,r,?r")
232 (match_operand:TI 1 "input_operand" "wa,Z,wa,O,W,wZ,v,r,wQ,r,Y,r,n"))]
233 "TARGET_POWERPC64 && VECTOR_MEM_VSX_P (TImode)
234 && (register_operand (operands[0], TImode)
235 || register_operand (operands[1], TImode))"
237 return rs6000_output_move_128bit (operands);
239 [(set_attr "type" "vecstore,vecload,vecsimple,vecsimple,vecsimple,vecstore,vecload,store,load,store,load,*,*")
240 (set_attr "length" "4,4,4,4,16,4,4,8,8,8,8,8,8")])
242 (define_insn "*vsx_movti_32bit"
243 [(set (match_operand:TI 0 "nonimmediate_operand" "=Z,wa,wa,wa,v, v,wZ,Q,Y,????r,????r,????r,r")
244 (match_operand:TI 1 "input_operand" "wa, Z,wa, O,W,wZ, v,r,r, Q, Y, r,n"))]
245 "! TARGET_POWERPC64 && VECTOR_MEM_VSX_P (TImode)
246 && (register_operand (operands[0], TImode)
247 || register_operand (operands[1], TImode))"
249 switch (which_alternative)
252 return "stxvd2x %x1,%y0";
255 return "lxvd2x %x0,%y1";
258 return "xxlor %x0,%x1,%x1";
261 return "xxlxor %x0,%x0,%x0";
264 return output_vec_const_move (operands);
267 return "stvx %1,%y0";
274 return \"stswi %1,%P0,16\";
280 /* If the address is not used in the output, we can use lsi. Otherwise,
281 fall through to generating four loads. */
283 && ! reg_overlap_mentioned_p (operands[0], operands[1]))
284 return \"lswi %0,%P1,16\";
285 /* ... fall through ... */
295 [(set_attr "type" "vecstore,vecload,vecsimple,vecsimple,vecsimple,vecstore,vecload,store_ux,store_ux,load_ux,load_ux, *, *")
296 (set_attr "length" " 4, 4, 4, 4, 8, 4, 4, 16, 16, 16, 16,16,16")
297 (set (attr "cell_micro") (if_then_else (match_test "TARGET_STRING")
298 (const_string "always")
299 (const_string "conditional")))])
301 ;; Explicit load/store expanders for the builtin functions
302 (define_expand "vsx_load_<mode>"
303 [(set (match_operand:VSX_M 0 "vsx_register_operand" "")
304 (match_operand:VSX_M 1 "memory_operand" ""))]
305 "VECTOR_MEM_VSX_P (<MODE>mode)"
308 (define_expand "vsx_store_<mode>"
309 [(set (match_operand:VSX_M 0 "memory_operand" "")
310 (match_operand:VSX_M 1 "vsx_register_operand" ""))]
311 "VECTOR_MEM_VSX_P (<MODE>mode)"
315 ;; VSX scalar and vector floating point arithmetic instructions
316 (define_insn "*vsx_add<mode>3"
317 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
318 (plus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
319 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
320 "VECTOR_UNIT_VSX_P (<MODE>mode)"
321 "x<VSv>add<VSs> %x0,%x1,%x2"
322 [(set_attr "type" "<VStype_simple>")
323 (set_attr "fp_type" "<VSfptype_simple>")])
325 (define_insn "*vsx_sub<mode>3"
326 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
327 (minus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
328 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
329 "VECTOR_UNIT_VSX_P (<MODE>mode)"
330 "x<VSv>sub<VSs> %x0,%x1,%x2"
331 [(set_attr "type" "<VStype_simple>")
332 (set_attr "fp_type" "<VSfptype_simple>")])
334 (define_insn "*vsx_mul<mode>3"
335 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
336 (mult:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
337 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
338 "VECTOR_UNIT_VSX_P (<MODE>mode)"
339 "x<VSv>mul<VSs> %x0,%x1,%x2"
340 [(set_attr "type" "<VStype_mul>")
341 (set_attr "fp_type" "<VSfptype_mul>")])
343 (define_insn "*vsx_div<mode>3"
344 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
345 (div:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
346 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
347 "VECTOR_UNIT_VSX_P (<MODE>mode)"
348 "x<VSv>div<VSs> %x0,%x1,%x2"
349 [(set_attr "type" "<VStype_div>")
350 (set_attr "fp_type" "<VSfptype_div>")])
352 ;; *tdiv* instruction returning the FG flag
353 (define_expand "vsx_tdiv<mode>3_fg"
355 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
356 (match_operand:VSX_B 2 "vsx_register_operand" "")]
358 (set (match_operand:SI 0 "gpc_reg_operand" "")
361 "VECTOR_UNIT_VSX_P (<MODE>mode)"
363 operands[3] = gen_reg_rtx (CCFPmode);
366 ;; *tdiv* instruction returning the FE flag
367 (define_expand "vsx_tdiv<mode>3_fe"
369 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
370 (match_operand:VSX_B 2 "vsx_register_operand" "")]
372 (set (match_operand:SI 0 "gpc_reg_operand" "")
375 "VECTOR_UNIT_VSX_P (<MODE>mode)"
377 operands[3] = gen_reg_rtx (CCFPmode);
380 (define_insn "*vsx_tdiv<mode>3_internal"
381 [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
382 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
383 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")]
385 "VECTOR_UNIT_VSX_P (<MODE>mode)"
386 "x<VSv>tdiv<VSs> %0,%x1,%x2"
387 [(set_attr "type" "<VStype_simple>")
388 (set_attr "fp_type" "<VSfptype_simple>")])
390 (define_insn "vsx_fre<mode>2"
391 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
392 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
394 "VECTOR_UNIT_VSX_P (<MODE>mode)"
395 "x<VSv>re<VSs> %x0,%x1"
396 [(set_attr "type" "<VStype_simple>")
397 (set_attr "fp_type" "<VSfptype_simple>")])
399 (define_insn "*vsx_neg<mode>2"
400 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
401 (neg:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
402 "VECTOR_UNIT_VSX_P (<MODE>mode)"
403 "x<VSv>neg<VSs> %x0,%x1"
404 [(set_attr "type" "<VStype_simple>")
405 (set_attr "fp_type" "<VSfptype_simple>")])
407 (define_insn "*vsx_abs<mode>2"
408 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
409 (abs:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
410 "VECTOR_UNIT_VSX_P (<MODE>mode)"
411 "x<VSv>abs<VSs> %x0,%x1"
412 [(set_attr "type" "<VStype_simple>")
413 (set_attr "fp_type" "<VSfptype_simple>")])
415 (define_insn "vsx_nabs<mode>2"
416 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
419 (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa"))))]
420 "VECTOR_UNIT_VSX_P (<MODE>mode)"
421 "x<VSv>nabs<VSs> %x0,%x1"
422 [(set_attr "type" "<VStype_simple>")
423 (set_attr "fp_type" "<VSfptype_simple>")])
425 (define_insn "vsx_smax<mode>3"
426 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
427 (smax:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
428 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
429 "VECTOR_UNIT_VSX_P (<MODE>mode)"
430 "x<VSv>max<VSs> %x0,%x1,%x2"
431 [(set_attr "type" "<VStype_simple>")
432 (set_attr "fp_type" "<VSfptype_simple>")])
434 (define_insn "*vsx_smin<mode>3"
435 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
436 (smin:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
437 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
438 "VECTOR_UNIT_VSX_P (<MODE>mode)"
439 "x<VSv>min<VSs> %x0,%x1,%x2"
440 [(set_attr "type" "<VStype_simple>")
441 (set_attr "fp_type" "<VSfptype_simple>")])
443 ;; Special VSX version of smin/smax for single precision floating point. Since
444 ;; both numbers are rounded to single precision, we can just use the DP version
445 ;; of the instruction.
447 (define_insn "*vsx_smaxsf3"
448 [(set (match_operand:SF 0 "vsx_register_operand" "=f")
449 (smax:SF (match_operand:SF 1 "vsx_register_operand" "f")
450 (match_operand:SF 2 "vsx_register_operand" "f")))]
451 "VECTOR_UNIT_VSX_P (DFmode)"
452 "xsmaxdp %x0,%x1,%x2"
453 [(set_attr "type" "fp")
454 (set_attr "fp_type" "fp_addsub_d")])
456 (define_insn "*vsx_sminsf3"
457 [(set (match_operand:SF 0 "vsx_register_operand" "=f")
458 (smin:SF (match_operand:SF 1 "vsx_register_operand" "f")
459 (match_operand:SF 2 "vsx_register_operand" "f")))]
460 "VECTOR_UNIT_VSX_P (DFmode)"
461 "xsmindp %x0,%x1,%x2"
462 [(set_attr "type" "fp")
463 (set_attr "fp_type" "fp_addsub_d")])
465 (define_insn "*vsx_sqrt<mode>2"
466 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
467 (sqrt:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
468 "VECTOR_UNIT_VSX_P (<MODE>mode)"
469 "x<VSv>sqrt<VSs> %x0,%x1"
470 [(set_attr "type" "<VStype_sqrt>")
471 (set_attr "fp_type" "<VSfptype_sqrt>")])
473 (define_insn "*vsx_rsqrte<mode>2"
474 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
475 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
477 "VECTOR_UNIT_VSX_P (<MODE>mode)"
478 "x<VSv>rsqrte<VSs> %x0,%x1"
479 [(set_attr "type" "<VStype_simple>")
480 (set_attr "fp_type" "<VSfptype_simple>")])
482 ;; *tsqrt* returning the fg flag
483 (define_expand "vsx_tsqrt<mode>2_fg"
485 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
487 (set (match_operand:SI 0 "gpc_reg_operand" "")
490 "VECTOR_UNIT_VSX_P (<MODE>mode)"
492 operands[3] = gen_reg_rtx (CCFPmode);
495 ;; *tsqrt* returning the fe flag
496 (define_expand "vsx_tsqrt<mode>2_fe"
498 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
500 (set (match_operand:SI 0 "gpc_reg_operand" "")
503 "VECTOR_UNIT_VSX_P (<MODE>mode)"
505 operands[3] = gen_reg_rtx (CCFPmode);
508 (define_insn "*vsx_tsqrt<mode>2_internal"
509 [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
510 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
512 "VECTOR_UNIT_VSX_P (<MODE>mode)"
513 "x<VSv>tsqrt<VSs> %0,%x1"
514 [(set_attr "type" "<VStype_simple>")
515 (set_attr "fp_type" "<VSfptype_simple>")])
517 ;; Fused vector multiply/add instructions Support the classical DF versions of
518 ;; fma, which allows the target to be a separate register from the 3 inputs.
519 ;; Under VSX, the target must be either the addend or the first multiply.
520 ;; Where we can, also do the same for the Altivec V4SF fmas.
522 (define_insn "*vsx_fmadf4"
523 [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
525 (match_operand:DF 1 "vsx_register_operand" "%ws,ws,wa,wa,d")
526 (match_operand:DF 2 "vsx_register_operand" "ws,0,wa,0,d")
527 (match_operand:DF 3 "vsx_register_operand" "0,ws,0,wa,d")))]
528 "VECTOR_UNIT_VSX_P (DFmode)"
530 xsmaddadp %x0,%x1,%x2
531 xsmaddmdp %x0,%x1,%x3
532 xsmaddadp %x0,%x1,%x2
533 xsmaddmdp %x0,%x1,%x3
535 [(set_attr "type" "fp")
536 (set_attr "fp_type" "fp_maddsub_d")])
538 (define_insn "*vsx_fmav4sf4"
539 [(set (match_operand:V4SF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,v")
541 (match_operand:V4SF 1 "vsx_register_operand" "%ws,ws,wa,wa,v")
542 (match_operand:V4SF 2 "vsx_register_operand" "ws,0,wa,0,v")
543 (match_operand:V4SF 3 "vsx_register_operand" "0,ws,0,wa,v")))]
544 "VECTOR_UNIT_VSX_P (V4SFmode)"
546 xvmaddasp %x0,%x1,%x2
547 xvmaddmsp %x0,%x1,%x3
548 xvmaddasp %x0,%x1,%x2
549 xvmaddmsp %x0,%x1,%x3
551 [(set_attr "type" "vecfloat")])
553 (define_insn "*vsx_fmav2df4"
554 [(set (match_operand:V2DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa")
556 (match_operand:V2DF 1 "vsx_register_operand" "%ws,ws,wa,wa")
557 (match_operand:V2DF 2 "vsx_register_operand" "ws,0,wa,0")
558 (match_operand:V2DF 3 "vsx_register_operand" "0,ws,0,wa")))]
559 "VECTOR_UNIT_VSX_P (V2DFmode)"
561 xvmaddadp %x0,%x1,%x2
562 xvmaddmdp %x0,%x1,%x3
563 xvmaddadp %x0,%x1,%x2
564 xvmaddmdp %x0,%x1,%x3"
565 [(set_attr "type" "vecdouble")])
567 (define_insn "*vsx_fmsdf4"
568 [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
570 (match_operand:DF 1 "vsx_register_operand" "%ws,ws,wa,wa,d")
571 (match_operand:DF 2 "vsx_register_operand" "ws,0,wa,0,d")
573 (match_operand:DF 3 "vsx_register_operand" "0,ws,0,wa,d"))))]
574 "VECTOR_UNIT_VSX_P (DFmode)"
576 xsmsubadp %x0,%x1,%x2
577 xsmsubmdp %x0,%x1,%x3
578 xsmsubadp %x0,%x1,%x2
579 xsmsubmdp %x0,%x1,%x3
581 [(set_attr "type" "fp")
582 (set_attr "fp_type" "fp_maddsub_d")])
584 (define_insn "*vsx_fms<mode>4"
585 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
587 (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
588 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0,wa,0")
590 (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
591 "VECTOR_UNIT_VSX_P (<MODE>mode)"
593 x<VSv>msuba<VSs> %x0,%x1,%x2
594 x<VSv>msubm<VSs> %x0,%x1,%x3
595 x<VSv>msuba<VSs> %x0,%x1,%x2
596 x<VSv>msubm<VSs> %x0,%x1,%x3"
597 [(set_attr "type" "<VStype_mul>")])
599 (define_insn "*vsx_nfmadf4"
600 [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
603 (match_operand:DF 1 "vsx_register_operand" "ws,ws,wa,wa,d")
604 (match_operand:DF 2 "vsx_register_operand" "ws,0,wa,0,d")
605 (match_operand:DF 3 "vsx_register_operand" "0,ws,0,wa,d"))))]
606 "VECTOR_UNIT_VSX_P (DFmode)"
608 xsnmaddadp %x0,%x1,%x2
609 xsnmaddmdp %x0,%x1,%x3
610 xsnmaddadp %x0,%x1,%x2
611 xsnmaddmdp %x0,%x1,%x3
613 [(set_attr "type" "fp")
614 (set_attr "fp_type" "fp_maddsub_d")])
616 (define_insn "*vsx_nfma<mode>4"
617 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
620 (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSr>,wa,wa")
621 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0,wa,0")
622 (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
623 "VECTOR_UNIT_VSX_P (<MODE>mode)"
625 x<VSv>nmadda<VSs> %x0,%x1,%x2
626 x<VSv>nmaddm<VSs> %x0,%x1,%x3
627 x<VSv>nmadda<VSs> %x0,%x1,%x2
628 x<VSv>nmaddm<VSs> %x0,%x1,%x3"
629 [(set_attr "type" "<VStype_mul>")
630 (set_attr "fp_type" "<VSfptype_mul>")])
632 (define_insn "*vsx_nfmsdf4"
633 [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
636 (match_operand:DF 1 "vsx_register_operand" "%ws,ws,wa,wa,d")
637 (match_operand:DF 2 "vsx_register_operand" "ws,0,wa,0,d")
639 (match_operand:DF 3 "vsx_register_operand" "0,ws,0,wa,d")))))]
640 "VECTOR_UNIT_VSX_P (DFmode)"
642 xsnmsubadp %x0,%x1,%x2
643 xsnmsubmdp %x0,%x1,%x3
644 xsnmsubadp %x0,%x1,%x2
645 xsnmsubmdp %x0,%x1,%x3
647 [(set_attr "type" "fp")
648 (set_attr "fp_type" "fp_maddsub_d")])
650 (define_insn "*vsx_nfmsv4sf4"
651 [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf,wf,?wa,?wa,v")
654 (match_operand:V4SF 1 "vsx_register_operand" "%wf,wf,wa,wa,v")
655 (match_operand:V4SF 2 "vsx_register_operand" "wf,0,wa,0,v")
657 (match_operand:V4SF 3 "vsx_register_operand" "0,wf,0,wa,v")))))]
658 "VECTOR_UNIT_VSX_P (V4SFmode)"
660 xvnmsubasp %x0,%x1,%x2
661 xvnmsubmsp %x0,%x1,%x3
662 xvnmsubasp %x0,%x1,%x2
663 xvnmsubmsp %x0,%x1,%x3
664 vnmsubfp %0,%1,%2,%3"
665 [(set_attr "type" "vecfloat")])
667 (define_insn "*vsx_nfmsv2df4"
668 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd,?wa,?wa")
671 (match_operand:V2DF 1 "vsx_register_operand" "%wd,wd,wa,wa")
672 (match_operand:V2DF 2 "vsx_register_operand" "wd,0,wa,0")
674 (match_operand:V2DF 3 "vsx_register_operand" "0,wd,0,wa")))))]
675 "VECTOR_UNIT_VSX_P (V2DFmode)"
677 xvnmsubadp %x0,%x1,%x2
678 xvnmsubmdp %x0,%x1,%x3
679 xvnmsubadp %x0,%x1,%x2
680 xvnmsubmdp %x0,%x1,%x3"
681 [(set_attr "type" "vecdouble")])
683 ;; Vector conditional expressions (no scalar version for these instructions)
684 (define_insn "vsx_eq<mode>"
685 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
686 (eq:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
687 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
688 "VECTOR_UNIT_VSX_P (<MODE>mode)"
689 "xvcmpeq<VSs> %x0,%x1,%x2"
690 [(set_attr "type" "<VStype_simple>")
691 (set_attr "fp_type" "<VSfptype_simple>")])
693 (define_insn "vsx_gt<mode>"
694 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
695 (gt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
696 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
697 "VECTOR_UNIT_VSX_P (<MODE>mode)"
698 "xvcmpgt<VSs> %x0,%x1,%x2"
699 [(set_attr "type" "<VStype_simple>")
700 (set_attr "fp_type" "<VSfptype_simple>")])
702 (define_insn "*vsx_ge<mode>"
703 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
704 (ge:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
705 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
706 "VECTOR_UNIT_VSX_P (<MODE>mode)"
707 "xvcmpge<VSs> %x0,%x1,%x2"
708 [(set_attr "type" "<VStype_simple>")
709 (set_attr "fp_type" "<VSfptype_simple>")])
711 ;; Floating point scalar compare
712 (define_insn "*vsx_cmpdf_internal1"
713 [(set (match_operand:CCFP 0 "cc_reg_operand" "=y,?y")
714 (compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "ws,wa")
715 (match_operand:DF 2 "gpc_reg_operand" "ws,wa")))]
716 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
717 && VECTOR_UNIT_VSX_P (DFmode)"
718 "xscmpudp %0,%x1,%x2"
719 [(set_attr "type" "fpcompare")])
721 ;; Compare vectors producing a vector result and a predicate, setting CR6 to
722 ;; indicate a combined status
723 (define_insn "*vsx_eq_<mode>_p"
726 [(eq:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
727 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
729 (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
730 (eq:VSX_F (match_dup 1)
732 "VECTOR_UNIT_VSX_P (<MODE>mode)"
733 "xvcmpeq<VSs>. %x0,%x1,%x2"
734 [(set_attr "type" "<VStype_simple>")])
736 (define_insn "*vsx_gt_<mode>_p"
739 [(gt:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
740 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
742 (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
743 (gt:VSX_F (match_dup 1)
745 "VECTOR_UNIT_VSX_P (<MODE>mode)"
746 "xvcmpgt<VSs>. %x0,%x1,%x2"
747 [(set_attr "type" "<VStype_simple>")])
749 (define_insn "*vsx_ge_<mode>_p"
752 [(ge:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
753 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
755 (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
756 (ge:VSX_F (match_dup 1)
758 "VECTOR_UNIT_VSX_P (<MODE>mode)"
759 "xvcmpge<VSs>. %x0,%x1,%x2"
760 [(set_attr "type" "<VStype_simple>")])
763 (define_insn "*vsx_xxsel<mode>"
764 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
766 (ne:CC (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
767 (match_operand:VSX_L 4 "zero_constant" ""))
768 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
769 (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
770 "VECTOR_MEM_VSX_P (<MODE>mode)"
771 "xxsel %x0,%x3,%x2,%x1"
772 [(set_attr "type" "vecperm")])
774 (define_insn "*vsx_xxsel<mode>_uns"
775 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
777 (ne:CCUNS (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
778 (match_operand:VSX_L 4 "zero_constant" ""))
779 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
780 (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
781 "VECTOR_MEM_VSX_P (<MODE>mode)"
782 "xxsel %x0,%x3,%x2,%x1"
783 [(set_attr "type" "vecperm")])
786 (define_insn "vsx_copysign<mode>3"
787 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
789 [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
790 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")]
792 "VECTOR_UNIT_VSX_P (<MODE>mode)"
793 "x<VSv>cpsgn<VSs> %x0,%x2,%x1"
794 [(set_attr "type" "<VStype_simple>")
795 (set_attr "fp_type" "<VSfptype_simple>")])
797 ;; For the conversions, limit the register class for the integer value to be
798 ;; the fprs because we don't want to add the altivec registers to movdi/movsi.
799 ;; For the unsigned tests, there isn't a generic double -> unsigned conversion
800 ;; in rs6000.md so don't test VECTOR_UNIT_VSX_P, just test against VSX.
801 ;; Don't use vsx_register_operand here, use gpc_reg_operand to match rs6000.md.
802 (define_insn "vsx_float<VSi><mode>2"
803 [(set (match_operand:VSX_B 0 "gpc_reg_operand" "=<VSr>,?wa")
804 (float:VSX_B (match_operand:<VSI> 1 "gpc_reg_operand" "<VSr2>,<VSr3>")))]
805 "VECTOR_UNIT_VSX_P (<MODE>mode)"
806 "x<VSv>cvsx<VSc><VSs> %x0,%x1"
807 [(set_attr "type" "<VStype_simple>")
808 (set_attr "fp_type" "<VSfptype_simple>")])
810 (define_insn "vsx_floatuns<VSi><mode>2"
811 [(set (match_operand:VSX_B 0 "gpc_reg_operand" "=<VSr>,?wa")
812 (unsigned_float:VSX_B (match_operand:<VSI> 1 "gpc_reg_operand" "<VSr2>,<VSr3>")))]
813 "VECTOR_UNIT_VSX_P (<MODE>mode)"
814 "x<VSv>cvux<VSc><VSs> %x0,%x1"
815 [(set_attr "type" "<VStype_simple>")
816 (set_attr "fp_type" "<VSfptype_simple>")])
818 (define_insn "vsx_fix_trunc<mode><VSi>2"
819 [(set (match_operand:<VSI> 0 "gpc_reg_operand" "=<VSr2>,?<VSr3>")
820 (fix:<VSI> (match_operand:VSX_B 1 "gpc_reg_operand" "<VSr>,wa")))]
821 "VECTOR_UNIT_VSX_P (<MODE>mode)"
822 "x<VSv>cv<VSs>sx<VSc>s %x0,%x1"
823 [(set_attr "type" "<VStype_simple>")
824 (set_attr "fp_type" "<VSfptype_simple>")])
826 (define_insn "vsx_fixuns_trunc<mode><VSi>2"
827 [(set (match_operand:<VSI> 0 "gpc_reg_operand" "=<VSr2>,?<VSr3>")
828 (unsigned_fix:<VSI> (match_operand:VSX_B 1 "gpc_reg_operand" "<VSr>,wa")))]
829 "VECTOR_UNIT_VSX_P (<MODE>mode)"
830 "x<VSv>cv<VSs>ux<VSc>s %x0,%x1"
831 [(set_attr "type" "<VStype_simple>")
832 (set_attr "fp_type" "<VSfptype_simple>")])
834 ;; Math rounding functions
835 (define_insn "vsx_x<VSv>r<VSs>i"
836 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
837 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
838 UNSPEC_VSX_ROUND_I))]
839 "VECTOR_UNIT_VSX_P (<MODE>mode)"
840 "x<VSv>r<VSs>i %x0,%x1"
841 [(set_attr "type" "<VStype_simple>")
842 (set_attr "fp_type" "<VSfptype_simple>")])
844 (define_insn "vsx_x<VSv>r<VSs>ic"
845 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
846 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
847 UNSPEC_VSX_ROUND_IC))]
848 "VECTOR_UNIT_VSX_P (<MODE>mode)"
849 "x<VSv>r<VSs>ic %x0,%x1"
850 [(set_attr "type" "<VStype_simple>")
851 (set_attr "fp_type" "<VSfptype_simple>")])
853 (define_insn "vsx_btrunc<mode>2"
854 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
855 (fix:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
856 "VECTOR_UNIT_VSX_P (<MODE>mode)"
857 "x<VSv>r<VSs>iz %x0,%x1"
858 [(set_attr "type" "<VStype_simple>")
859 (set_attr "fp_type" "<VSfptype_simple>")])
861 (define_insn "*vsx_b2trunc<mode>2"
862 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
863 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
865 "VECTOR_UNIT_VSX_P (<MODE>mode)"
866 "x<VSv>r<VSs>iz %x0,%x1"
867 [(set_attr "type" "<VStype_simple>")
868 (set_attr "fp_type" "<VSfptype_simple>")])
870 (define_insn "vsx_floor<mode>2"
871 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
872 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
874 "VECTOR_UNIT_VSX_P (<MODE>mode)"
875 "x<VSv>r<VSs>im %x0,%x1"
876 [(set_attr "type" "<VStype_simple>")
877 (set_attr "fp_type" "<VSfptype_simple>")])
879 (define_insn "vsx_ceil<mode>2"
880 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
881 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
883 "VECTOR_UNIT_VSX_P (<MODE>mode)"
884 "x<VSv>r<VSs>ip %x0,%x1"
885 [(set_attr "type" "<VStype_simple>")
886 (set_attr "fp_type" "<VSfptype_simple>")])
889 ;; VSX convert to/from double vector
891 ;; Convert between single and double precision
892 ;; Don't use xscvspdp and xscvdpsp for scalar conversions, since the normal
893 ;; scalar single precision instructions internally use the double format.
894 ;; Prefer the altivec registers, since we likely will need to do a vperm
895 (define_insn "vsx_<VS_spdp_insn>"
896 [(set (match_operand:<VS_spdp_res> 0 "vsx_register_operand" "=<VSr4>,?wa")
897 (unspec:<VS_spdp_res> [(match_operand:VSX_SPDP 1 "vsx_register_operand" "<VSr5>,wa")]
899 "VECTOR_UNIT_VSX_P (<MODE>mode)"
900 "<VS_spdp_insn> %x0,%x1"
901 [(set_attr "type" "<VS_spdp_type>")])
903 ;; xscvspdp, represent the scalar SF type as V4SF
904 (define_insn "vsx_xscvspdp"
905 [(set (match_operand:DF 0 "vsx_register_operand" "=ws,?wa")
906 (unspec:DF [(match_operand:V4SF 1 "vsx_register_operand" "wa,wa")]
908 "VECTOR_UNIT_VSX_P (V4SFmode)"
910 [(set_attr "type" "fp")])
912 ;; xscvdpsp used for splat'ing a scalar to V4SF, knowing that the internal SF
913 ;; format of scalars is actually DF.
914 (define_insn "vsx_xscvdpsp_scalar"
915 [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
916 (unspec:V4SF [(match_operand:SF 1 "vsx_register_operand" "f")]
918 "VECTOR_UNIT_VSX_P (V4SFmode)"
920 [(set_attr "type" "fp")])
922 ;; Same as vsx_xscvspdp, but use SF as the type
923 (define_insn "vsx_xscvspdp_scalar2"
924 [(set (match_operand:SF 0 "vsx_register_operand" "=f")
925 (unspec:SF [(match_operand:V4SF 1 "vsx_register_operand" "wa")]
927 "VECTOR_UNIT_VSX_P (V4SFmode)"
929 [(set_attr "type" "fp")])
931 ;; ISA 2.07 xscvdpspn/xscvspdpn that does not raise an error on signalling NaNs
932 (define_insn "vsx_xscvdpspn"
933 [(set (match_operand:V4SF 0 "vsx_register_operand" "=ws,?wa")
934 (unspec:V4SF [(match_operand:DF 1 "vsx_register_operand" "wd,wa")]
935 UNSPEC_VSX_CVDPSPN))]
938 [(set_attr "type" "fp")])
940 (define_insn "vsx_xscvspdpn"
941 [(set (match_operand:DF 0 "vsx_register_operand" "=ws,?wa")
942 (unspec:DF [(match_operand:V4SF 1 "vsx_register_operand" "wa,wa")]
943 UNSPEC_VSX_CVSPDPN))]
946 [(set_attr "type" "fp")])
948 (define_insn "vsx_xscvdpspn_scalar"
949 [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
950 (unspec:V4SF [(match_operand:SF 1 "vsx_register_operand" "f")]
951 UNSPEC_VSX_CVDPSPN))]
954 [(set_attr "type" "fp")])
956 ;; Used by direct move to move a SFmode value from GPR to VSX register
957 (define_insn "vsx_xscvspdpn_directmove"
958 [(set (match_operand:SF 0 "vsx_register_operand" "=wa")
959 (unspec:SF [(match_operand:SF 1 "vsx_register_operand" "wa")]
960 UNSPEC_VSX_CVSPDPN))]
963 [(set_attr "type" "fp")])
965 ;; Convert from 64-bit to 32-bit types
966 ;; Note, favor the Altivec registers since the usual use of these instructions
967 ;; is in vector converts and we need to use the Altivec vperm instruction.
969 (define_insn "vsx_xvcvdpsxws"
970 [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
971 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
972 UNSPEC_VSX_CVDPSXWS))]
973 "VECTOR_UNIT_VSX_P (V2DFmode)"
975 [(set_attr "type" "vecdouble")])
977 (define_insn "vsx_xvcvdpuxws"
978 [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
979 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
980 UNSPEC_VSX_CVDPUXWS))]
981 "VECTOR_UNIT_VSX_P (V2DFmode)"
983 [(set_attr "type" "vecdouble")])
985 (define_insn "vsx_xvcvsxdsp"
986 [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
987 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
988 UNSPEC_VSX_CVSXDSP))]
989 "VECTOR_UNIT_VSX_P (V2DFmode)"
991 [(set_attr "type" "vecfloat")])
993 (define_insn "vsx_xvcvuxdsp"
994 [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
995 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
996 UNSPEC_VSX_CVUXDSP))]
997 "VECTOR_UNIT_VSX_P (V2DFmode)"
999 [(set_attr "type" "vecdouble")])
1001 ;; Convert from 32-bit to 64-bit types
1002 (define_insn "vsx_xvcvsxwdp"
1003 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1004 (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
1005 UNSPEC_VSX_CVSXWDP))]
1006 "VECTOR_UNIT_VSX_P (V2DFmode)"
1008 [(set_attr "type" "vecdouble")])
1010 (define_insn "vsx_xvcvuxwdp"
1011 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1012 (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
1013 UNSPEC_VSX_CVUXWDP))]
1014 "VECTOR_UNIT_VSX_P (V2DFmode)"
1016 [(set_attr "type" "vecdouble")])
1018 (define_insn "vsx_xvcvspsxds"
1019 [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
1020 (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
1021 UNSPEC_VSX_CVSPSXDS))]
1022 "VECTOR_UNIT_VSX_P (V2DFmode)"
1023 "xvcvspsxds %x0,%x1"
1024 [(set_attr "type" "vecdouble")])
1026 (define_insn "vsx_xvcvspuxds"
1027 [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
1028 (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
1029 UNSPEC_VSX_CVSPUXDS))]
1030 "VECTOR_UNIT_VSX_P (V2DFmode)"
1031 "xvcvspuxds %x0,%x1"
1032 [(set_attr "type" "vecdouble")])
1034 ;; Only optimize (float (fix x)) -> frz if we are in fast-math mode, since
1035 ;; since the xsrdpiz instruction does not truncate the value if the floating
1036 ;; point value is < LONG_MIN or > LONG_MAX.
1037 (define_insn "*vsx_float_fix_<mode>2"
1038 [(set (match_operand:VSX_DF 0 "vsx_register_operand" "=<VSr>,?wa")
1041 (match_operand:VSX_DF 1 "vsx_register_operand" "<VSr>,?wa"))))]
1042 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
1043 && VECTOR_UNIT_VSX_P (<MODE>mode) && flag_unsafe_math_optimizations
1044 && !flag_trapping_math && TARGET_FRIZ"
1045 "x<VSv>r<VSs>iz %x0,%x1"
1046 [(set_attr "type" "<VStype_simple>")
1047 (set_attr "fp_type" "<VSfptype_simple>")])
1050 ;; Logical operations. Do not support TImode logical instructions on 32-bit at
1051 ;; present, because the compiler will see that we have a TImode and when it
1052 ;; wanted DImode, and convert the DImode to TImode, store it on the stack, and
1053 ;; load it in a VSX register or generate extra logical instructions in GPR
1056 ;; When we are splitting the operations to GPRs, we use three alternatives, two
1057 ;; where the first/second inputs and output are in the same register, and the
1058 ;; third where the output specifies an early clobber so that we don't have to
1059 ;; worry about overlapping registers.
1061 (define_insn "*vsx_and<mode>3_32bit"
1062 [(set (match_operand:VSX_L2 0 "vlogical_operand" "=wa")
1063 (and:VSX_L2 (match_operand:VSX_L2 1 "vlogical_operand" "%wa")
1064 (match_operand:VSX_L2 2 "vlogical_operand" "wa")))
1065 (clobber (match_scratch:CC 3 "X"))]
1066 "!TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)"
1067 "xxland %x0,%x1,%x2"
1068 [(set_attr "type" "vecsimple")
1069 (set_attr "length" "4")])
1071 (define_insn_and_split "*vsx_and<mode>3_64bit"
1072 [(set (match_operand:VSX_L 0 "vlogical_operand" "=wa,?r,?r,&?r")
1074 (match_operand:VSX_L 1 "vlogical_operand" "%wa,0,r,r")
1075 (match_operand:VSX_L 2 "vlogical_operand" "wa,r,0,r")))
1076 (clobber (match_scratch:CC 3 "X,X,X,X"))]
1077 "TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)"
1083 "reload_completed && TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)
1084 && int_reg_operand (operands[0], <MODE>mode)"
1085 [(parallel [(set (match_dup 4) (and:DI (match_dup 5) (match_dup 6)))
1086 (clobber (match_dup 3))])
1087 (parallel [(set (match_dup 7) (and:DI (match_dup 8) (match_dup 9)))
1088 (clobber (match_dup 3))])]
1090 operands[4] = simplify_subreg (DImode, operands[0], <MODE>mode, 0);
1091 operands[5] = simplify_subreg (DImode, operands[1], <MODE>mode, 0);
1092 operands[6] = simplify_subreg (DImode, operands[2], <MODE>mode, 0);
1093 operands[7] = simplify_subreg (DImode, operands[0], <MODE>mode, 8);
1094 operands[8] = simplify_subreg (DImode, operands[1], <MODE>mode, 8);
1095 operands[9] = simplify_subreg (DImode, operands[2], <MODE>mode, 8);
1097 [(set_attr "type" "vecsimple,two,two,two")
1098 (set_attr "length" "4,8,8,8")])
1100 (define_insn "*vsx_ior<mode>3_32bit"
1101 [(set (match_operand:VSX_L2 0 "vlogical_operand" "=wa")
1102 (ior:VSX_L2 (match_operand:VSX_L2 1 "vlogical_operand" "%wa")
1103 (match_operand:VSX_L2 2 "vlogical_operand" "wa")))]
1104 "!TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)"
1106 [(set_attr "type" "vecsimple")
1107 (set_attr "length" "4")])
1109 (define_insn_and_split "*vsx_ior<mode>3_64bit"
1110 [(set (match_operand:VSX_L 0 "vlogical_operand" "=wa,?r,?r,&?r,?r,&?r")
1112 (match_operand:VSX_L 1 "vlogical_operand" "%wa,0,r,r,0,r")
1113 (match_operand:VSX_L 2 "vsx_reg_or_cint_operand" "wa,r,0,r,n,n")))]
1114 "TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)"
1122 "reload_completed && TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)
1123 && int_reg_operand (operands[0], <MODE>mode)"
1126 operands[3] = simplify_subreg (DImode, operands[0], <MODE>mode, 0);
1127 operands[4] = simplify_subreg (DImode, operands[1], <MODE>mode, 0);
1128 operands[5] = simplify_subreg (DImode, operands[2], <MODE>mode, 0);
1129 operands[6] = simplify_subreg (DImode, operands[0], <MODE>mode, 8);
1130 operands[7] = simplify_subreg (DImode, operands[1], <MODE>mode, 8);
1131 operands[8] = simplify_subreg (DImode, operands[2], <MODE>mode, 8);
1133 if (operands[5] == constm1_rtx)
1134 emit_move_insn (operands[3], constm1_rtx);
1136 else if (operands[5] == const0_rtx)
1138 if (!rtx_equal_p (operands[3], operands[4]))
1139 emit_move_insn (operands[3], operands[4]);
1142 emit_insn (gen_iordi3 (operands[3], operands[4], operands[5]));
1144 if (operands[8] == constm1_rtx)
1145 emit_move_insn (operands[8], constm1_rtx);
1147 else if (operands[8] == const0_rtx)
1149 if (!rtx_equal_p (operands[6], operands[7]))
1150 emit_move_insn (operands[6], operands[7]);
1153 emit_insn (gen_iordi3 (operands[6], operands[7], operands[8]));
1156 [(set_attr "type" "vecsimple,two,two,two,three,three")
1157 (set_attr "length" "4,8,8,8,16,16")])
1159 (define_insn "*vsx_xor<mode>3_32bit"
1160 [(set (match_operand:VSX_L2 0 "vlogical_operand" "=wa")
1161 (xor:VSX_L2 (match_operand:VSX_L2 1 "vlogical_operand" "%wa")
1162 (match_operand:VSX_L2 2 "vlogical_operand" "wa")))]
1163 "VECTOR_MEM_VSX_P (<MODE>mode) && !TARGET_POWERPC64"
1164 "xxlxor %x0,%x1,%x2"
1165 [(set_attr "type" "vecsimple")
1166 (set_attr "length" "4")])
1168 (define_insn_and_split "*vsx_xor<mode>3_64bit"
1169 [(set (match_operand:VSX_L 0 "vlogical_operand" "=wa,?r,?r,&?r,?r,&?r")
1171 (match_operand:VSX_L 1 "vlogical_operand" "%wa,0,r,r,0,r")
1172 (match_operand:VSX_L 2 "vsx_reg_or_cint_operand" "wa,r,0,r,n,n")))]
1173 "TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)"
1181 "reload_completed && TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)
1182 && int_reg_operand (operands[0], <MODE>mode)"
1183 [(set (match_dup 3) (xor:DI (match_dup 4) (match_dup 5)))
1184 (set (match_dup 6) (xor:DI (match_dup 7) (match_dup 8)))]
1186 operands[3] = simplify_subreg (DImode, operands[0], <MODE>mode, 0);
1187 operands[4] = simplify_subreg (DImode, operands[1], <MODE>mode, 0);
1188 operands[5] = simplify_subreg (DImode, operands[2], <MODE>mode, 0);
1189 operands[6] = simplify_subreg (DImode, operands[0], <MODE>mode, 8);
1190 operands[7] = simplify_subreg (DImode, operands[1], <MODE>mode, 8);
1191 operands[8] = simplify_subreg (DImode, operands[2], <MODE>mode, 8);
1193 [(set_attr "type" "vecsimple,two,two,two,three,three")
1194 (set_attr "length" "4,8,8,8,16,16")])
1196 (define_insn "*vsx_one_cmpl<mode>2_32bit"
1197 [(set (match_operand:VSX_L2 0 "vlogical_operand" "=wa")
1198 (not:VSX_L2 (match_operand:VSX_L2 1 "vlogical_operand" "wa")))]
1199 "!TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)"
1200 "xxlnor %x0,%x1,%x1"
1201 [(set_attr "type" "vecsimple")
1202 (set_attr "length" "4")])
1204 (define_insn_and_split "*vsx_one_cmpl<mode>2_64bit"
1205 [(set (match_operand:VSX_L 0 "vlogical_operand" "=wa,?r,&?r")
1206 (not:VSX_L (match_operand:VSX_L 1 "vlogical_operand" "wa,0,r")))]
1207 "TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)"
1212 "reload_completed && TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)
1213 && int_reg_operand (operands[0], <MODE>mode)"
1214 [(set (match_dup 2) (not:DI (match_dup 3)))
1215 (set (match_dup 4) (not:DI (match_dup 5)))]
1217 operands[2] = simplify_subreg (DImode, operands[0], <MODE>mode, 0);
1218 operands[3] = simplify_subreg (DImode, operands[1], <MODE>mode, 0);
1219 operands[4] = simplify_subreg (DImode, operands[0], <MODE>mode, 8);
1220 operands[5] = simplify_subreg (DImode, operands[1], <MODE>mode, 8);
1222 [(set_attr "type" "vecsimple,two,two")
1223 (set_attr "length" "4,8,8")])
1225 (define_insn "*vsx_nor<mode>3_32bit"
1226 [(set (match_operand:VSX_L2 0 "vlogical_operand" "=wa")
1228 (not:VSX_L2 (match_operand:VSX_L 1 "vlogical_operand" "%wa"))
1229 (not:VSX_L2 (match_operand:VSX_L 2 "vlogical_operand" "wa"))))]
1230 "!TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)"
1231 "xxlnor %x0,%x1,%x2"
1232 [(set_attr "type" "vecsimple")
1233 (set_attr "length" "4")])
1235 (define_insn_and_split "*vsx_nor<mode>3_64bit"
1236 [(set (match_operand:VSX_L 0 "vlogical_operand" "=wa,?r,?r,&?r")
1238 (not:VSX_L (match_operand:VSX_L 1 "vlogical_operand" "%wa,0,r,r"))
1239 (not:VSX_L (match_operand:VSX_L 2 "vlogical_operand" "wa,r,0,r"))))]
1240 "TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)"
1246 "reload_completed && TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)
1247 && int_reg_operand (operands[0], <MODE>mode)"
1248 [(set (match_dup 3) (and:DI (not:DI (match_dup 4)) (not:DI (match_dup 5))))
1249 (set (match_dup 6) (and:DI (not:DI (match_dup 7)) (not:DI (match_dup 8))))]
1251 operands[3] = simplify_subreg (DImode, operands[0], <MODE>mode, 0);
1252 operands[4] = simplify_subreg (DImode, operands[1], <MODE>mode, 0);
1253 operands[5] = simplify_subreg (DImode, operands[2], <MODE>mode, 0);
1254 operands[6] = simplify_subreg (DImode, operands[0], <MODE>mode, 8);
1255 operands[7] = simplify_subreg (DImode, operands[1], <MODE>mode, 8);
1256 operands[8] = simplify_subreg (DImode, operands[2], <MODE>mode, 8);
1258 [(set_attr "type" "vecsimple,two,two,two")
1259 (set_attr "length" "4,8,8,8")])
1261 (define_insn "*vsx_andc<mode>3_32bit"
1262 [(set (match_operand:VSX_L2 0 "vlogical_operand" "=wa")
1265 (match_operand:VSX_L2 2 "vlogical_operand" "wa"))
1266 (match_operand:VSX_L2 1 "vlogical_operand" "wa")))]
1267 "!TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)"
1268 "xxlandc %x0,%x1,%x2"
1269 [(set_attr "type" "vecsimple")
1270 (set_attr "length" "4")])
1272 (define_insn_and_split "*vsx_andc<mode>3_64bit"
1273 [(set (match_operand:VSX_L 0 "vlogical_operand" "=wa,?r,?r,?r")
1276 (match_operand:VSX_L 2 "vlogical_operand" "wa,0,r,r"))
1277 (match_operand:VSX_L 1 "vlogical_operand" "wa,r,0,r")))]
1278 "TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)"
1284 "reload_completed && TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)
1285 && int_reg_operand (operands[0], <MODE>mode)"
1286 [(set (match_dup 3) (and:DI (not:DI (match_dup 4)) (match_dup 5)))
1287 (set (match_dup 6) (and:DI (not:DI (match_dup 7)) (match_dup 8)))]
1289 operands[3] = simplify_subreg (DImode, operands[0], <MODE>mode, 0);
1290 operands[4] = simplify_subreg (DImode, operands[1], <MODE>mode, 0);
1291 operands[5] = simplify_subreg (DImode, operands[2], <MODE>mode, 0);
1292 operands[6] = simplify_subreg (DImode, operands[0], <MODE>mode, 8);
1293 operands[7] = simplify_subreg (DImode, operands[1], <MODE>mode, 8);
1294 operands[8] = simplify_subreg (DImode, operands[2], <MODE>mode, 8);
1296 [(set_attr "type" "vecsimple,two,two,two")
1297 (set_attr "length" "4,8,8,8")])
1299 ;; Power8 vector logical instructions.
1300 (define_insn "*vsx_eqv<mode>3_32bit"
1301 [(set (match_operand:VSX_L2 0 "vlogical_operand" "=wa")
1303 (xor:VSX_L2 (match_operand:VSX_L2 1 "vlogical_operand" "wa")
1304 (match_operand:VSX_L2 2 "vlogical_operand" "wa"))))]
1305 "!TARGET_POWERPC64 && TARGET_P8_VECTOR && VECTOR_MEM_VSX_P (<MODE>mode)"
1306 "xxleqv %x0,%x1,%x2"
1307 [(set_attr "type" "vecsimple")
1308 (set_attr "length" "4")])
1310 (define_insn_and_split "*vsx_eqv<mode>3_64bit"
1311 [(set (match_operand:VSX_L 0 "vlogical_operand" "=wa,?r,?r,?r")
1313 (xor:VSX_L (match_operand:VSX_L 1 "vlogical_operand" "wa,0,r,r")
1314 (match_operand:VSX_L 2 "vlogical_operand" "wa,r,0,r"))))]
1315 "TARGET_POWERPC64 && TARGET_P8_VECTOR && VECTOR_MEM_VSX_P (<MODE>mode)"
1321 "reload_completed && TARGET_POWERPC64 && TARGET_P8_VECTOR
1322 && VECTOR_MEM_VSX_P (<MODE>mode)
1323 && int_reg_operand (operands[0], <MODE>mode)"
1324 [(set (match_dup 3) (not:DI (xor:DI (match_dup 4) (match_dup 5))))
1325 (set (match_dup 6) (not:DI (xor:DI (match_dup 7) (match_dup 8))))]
1327 operands[3] = simplify_subreg (DImode, operands[0], <MODE>mode, 0);
1328 operands[4] = simplify_subreg (DImode, operands[1], <MODE>mode, 0);
1329 operands[5] = simplify_subreg (DImode, operands[2], <MODE>mode, 0);
1330 operands[6] = simplify_subreg (DImode, operands[0], <MODE>mode, 8);
1331 operands[7] = simplify_subreg (DImode, operands[1], <MODE>mode, 8);
1332 operands[8] = simplify_subreg (DImode, operands[2], <MODE>mode, 8);
1334 [(set_attr "type" "vecsimple,two,two,two")
1335 (set_attr "length" "4,8,8,8")])
1337 ;; Rewrite nand into canonical form
1338 (define_insn "*vsx_nand<mode>3_32bit"
1339 [(set (match_operand:VSX_L2 0 "vlogical_operand" "=wa")
1341 (not:VSX_L2 (match_operand:VSX_L2 1 "vlogical_operand" "wa"))
1342 (not:VSX_L2 (match_operand:VSX_L2 2 "vlogical_operand" "wa"))))]
1343 "!TARGET_POWERPC64 && TARGET_P8_VECTOR && VECTOR_MEM_VSX_P (<MODE>mode)"
1344 "xxlnand %x0,%x1,%x2"
1345 [(set_attr "type" "vecsimple")
1346 (set_attr "length" "4")])
1348 (define_insn_and_split "*vsx_nand<mode>3_64bit"
1349 [(set (match_operand:VSX_L 0 "register_operand" "=wa,?r,?r,?r")
1351 (not:VSX_L (match_operand:VSX_L 1 "register_operand" "wa,0,r,r"))
1352 (not:VSX_L (match_operand:VSX_L 2 "register_operand" "wa,r,0,r"))))]
1353 "TARGET_POWERPC64 && TARGET_P8_VECTOR && VECTOR_MEM_VSX_P (<MODE>mode)"
1359 "reload_completed && TARGET_POWERPC64 && TARGET_P8_VECTOR
1360 && VECTOR_MEM_VSX_P (<MODE>mode)
1361 && int_reg_operand (operands[0], <MODE>mode)"
1362 [(set (match_dup 3) (ior:DI (not:DI (match_dup 4)) (not:DI (match_dup 5))))
1363 (set (match_dup 6) (ior:DI (not:DI (match_dup 7)) (not:DI (match_dup 8))))]
1365 operands[3] = simplify_subreg (DImode, operands[0], <MODE>mode, 0);
1366 operands[4] = simplify_subreg (DImode, operands[1], <MODE>mode, 0);
1367 operands[5] = simplify_subreg (DImode, operands[2], <MODE>mode, 0);
1368 operands[6] = simplify_subreg (DImode, operands[0], <MODE>mode, 8);
1369 operands[7] = simplify_subreg (DImode, operands[1], <MODE>mode, 8);
1370 operands[8] = simplify_subreg (DImode, operands[2], <MODE>mode, 8);
1372 [(set_attr "type" "vecsimple,two,two,two")
1373 (set_attr "length" "4,8,8,8")])
1375 ;; Rewrite or complement into canonical form, by reversing the arguments
1376 (define_insn "*vsx_orc<mode>3_32bit"
1377 [(set (match_operand:VSX_L2 0 "vlogical_operand" "=wa")
1379 (not:VSX_L2 (match_operand:VSX_L2 1 "vlogical_operand" "wa"))
1380 (match_operand:VSX_L2 2 "vlogical_operand" "wa")))]
1381 "!TARGET_POWERPC64 && TARGET_P8_VECTOR && VECTOR_MEM_VSX_P (<MODE>mode)"
1382 "xxlorc %x0,%x2,%x1"
1383 [(set_attr "type" "vecsimple")
1384 (set_attr "length" "4")])
1386 (define_insn_and_split "*vsx_orc<mode>3_64bit"
1387 [(set (match_operand:VSX_L 0 "vlogical_operand" "=wa,?r,?r,?r")
1389 (not:VSX_L (match_operand:VSX_L 1 "vlogical_operand" "wa,0,r,r"))
1390 (match_operand:VSX_L 2 "vlogical_operand" "wa,r,0,r")))]
1391 "TARGET_POWERPC64 && TARGET_P8_VECTOR && VECTOR_MEM_VSX_P (<MODE>mode)"
1397 "reload_completed && TARGET_POWERPC64 && TARGET_P8_VECTOR
1398 && VECTOR_MEM_VSX_P (<MODE>mode)
1399 && int_reg_operand (operands[0], <MODE>mode)"
1400 [(set (match_dup 3) (ior:DI (not:DI (match_dup 4)) (match_dup 5)))
1401 (set (match_dup 6) (ior:DI (not:DI (match_dup 7)) (match_dup 8)))]
1403 operands[3] = simplify_subreg (DImode, operands[0], <MODE>mode, 0);
1404 operands[4] = simplify_subreg (DImode, operands[1], <MODE>mode, 0);
1405 operands[5] = simplify_subreg (DImode, operands[2], <MODE>mode, 0);
1406 operands[6] = simplify_subreg (DImode, operands[0], <MODE>mode, 8);
1407 operands[7] = simplify_subreg (DImode, operands[1], <MODE>mode, 8);
1408 operands[8] = simplify_subreg (DImode, operands[2], <MODE>mode, 8);
1410 [(set_attr "type" "vecsimple,two,two,two")
1411 (set_attr "length" "4,8,8,8")])
1414 ;; Permute operations
1416 ;; Build a V2DF/V2DI vector from two scalars
1417 (define_insn "vsx_concat_<mode>"
1418 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=<VSr>,?wa")
1420 (match_operand:<VS_scalar> 1 "vsx_register_operand" "ws,wa")
1421 (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")))]
1422 "VECTOR_MEM_VSX_P (<MODE>mode)"
1423 "xxpermdi %x0,%x1,%x2,0"
1424 [(set_attr "type" "vecperm")])
1426 ;; Special purpose concat using xxpermdi to glue two single precision values
1427 ;; together, relying on the fact that internally scalar floats are represented
1428 ;; as doubles. This is used to initialize a V4SF vector with 4 floats
1429 (define_insn "vsx_concat_v2sf"
1430 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1432 [(match_operand:SF 1 "vsx_register_operand" "f,f")
1433 (match_operand:SF 2 "vsx_register_operand" "f,f")]
1434 UNSPEC_VSX_CONCAT))]
1435 "VECTOR_MEM_VSX_P (V2DFmode)"
1436 "xxpermdi %x0,%x1,%x2,0"
1437 [(set_attr "type" "vecperm")])
1439 ;; Set the element of a V2DI/VD2F mode
1440 (define_insn "vsx_set_<mode>"
1441 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
1442 (unspec:VSX_D [(match_operand:VSX_D 1 "vsx_register_operand" "wd,wa")
1443 (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")
1444 (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
1446 "VECTOR_MEM_VSX_P (<MODE>mode)"
1448 if (INTVAL (operands[3]) == 0)
1449 return \"xxpermdi %x0,%x2,%x1,1\";
1450 else if (INTVAL (operands[3]) == 1)
1451 return \"xxpermdi %x0,%x1,%x2,0\";
1455 [(set_attr "type" "vecperm")])
1457 ;; Extract a DF/DI element from V2DF/V2DI
1458 (define_insn "vsx_extract_<mode>"
1459 [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,d,?wa")
1460 (vec_select:<VS_scalar> (match_operand:VSX_D 1 "vsx_register_operand" "wd,wd,wa")
1462 [(match_operand:QI 2 "u5bit_cint_operand" "i,i,i")])))]
1463 "VECTOR_MEM_VSX_P (<MODE>mode)"
1465 gcc_assert (UINTVAL (operands[2]) <= 1);
1466 operands[3] = GEN_INT (INTVAL (operands[2]) << 1);
1467 return \"xxpermdi %x0,%x1,%x1,%3\";
1469 [(set_attr "type" "vecperm")])
1471 ;; Optimize extracting element 0 from memory
1472 (define_insn "*vsx_extract_<mode>_zero"
1473 [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,d,?wa")
1474 (vec_select:<VS_scalar>
1475 (match_operand:VSX_D 1 "indexed_or_indirect_operand" "Z,Z,Z")
1476 (parallel [(const_int 0)])))]
1477 "VECTOR_MEM_VSX_P (<MODE>mode) && WORDS_BIG_ENDIAN"
1481 (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
1482 (const_string "fpload_ux")
1483 (const_string "fpload")))
1484 (set_attr "length" "4")])
1486 ;; Extract a SF element from V4SF
1487 (define_insn_and_split "vsx_extract_v4sf"
1488 [(set (match_operand:SF 0 "vsx_register_operand" "=f,f")
1490 (match_operand:V4SF 1 "vsx_register_operand" "wa,wa")
1491 (parallel [(match_operand:QI 2 "u5bit_cint_operand" "O,i")])))
1492 (clobber (match_scratch:V4SF 3 "=X,0"))]
1493 "VECTOR_UNIT_VSX_P (V4SFmode)"
1501 rtx op0 = operands[0];
1502 rtx op1 = operands[1];
1503 rtx op2 = operands[2];
1504 rtx op3 = operands[3];
1506 HOST_WIDE_INT ele = INTVAL (op2);
1512 if (GET_CODE (op3) == SCRATCH)
1513 op3 = gen_reg_rtx (V4SFmode);
1514 emit_insn (gen_vsx_xxsldwi_v4sf (op3, op1, op1, op2));
1517 emit_insn (gen_vsx_xscvspdp_scalar2 (op0, tmp));
1520 [(set_attr "length" "4,8")
1521 (set_attr "type" "fp")])
1523 ;; Expand the builtin form of xxpermdi to canonical rtl.
1524 (define_expand "vsx_xxpermdi_<mode>"
1525 [(match_operand:VSX_L 0 "vsx_register_operand" "")
1526 (match_operand:VSX_L 1 "vsx_register_operand" "")
1527 (match_operand:VSX_L 2 "vsx_register_operand" "")
1528 (match_operand:QI 3 "u5bit_cint_operand" "")]
1529 "VECTOR_MEM_VSX_P (<MODE>mode)"
1531 rtx target = operands[0];
1532 rtx op0 = operands[1];
1533 rtx op1 = operands[2];
1534 int mask = INTVAL (operands[3]);
1535 rtx perm0 = GEN_INT ((mask >> 1) & 1);
1536 rtx perm1 = GEN_INT ((mask & 1) + 2);
1537 rtx (*gen) (rtx, rtx, rtx, rtx, rtx);
1539 if (<MODE>mode == V2DFmode)
1540 gen = gen_vsx_xxpermdi2_v2df_1;
1543 gen = gen_vsx_xxpermdi2_v2di_1;
1544 if (<MODE>mode != V2DImode)
1546 target = gen_lowpart (V2DImode, target);
1547 op0 = gen_lowpart (V2DImode, op0);
1548 op1 = gen_lowpart (V2DImode, op1);
1551 emit_insn (gen (target, op0, op1, perm0, perm1));
1555 (define_insn "vsx_xxpermdi2_<mode>_1"
1556 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd")
1558 (vec_concat:<VS_double>
1559 (match_operand:VSX_D 1 "vsx_register_operand" "wd")
1560 (match_operand:VSX_D 2 "vsx_register_operand" "wd"))
1561 (parallel [(match_operand 3 "const_0_to_1_operand" "")
1562 (match_operand 4 "const_2_to_3_operand" "")])))]
1563 "VECTOR_MEM_VSX_P (<MODE>mode)"
1565 int mask = (INTVAL (operands[3]) << 1) | (INTVAL (operands[4]) - 2);
1566 operands[3] = GEN_INT (mask);
1567 return "xxpermdi %x0,%x1,%x2,%3";
1569 [(set_attr "type" "vecperm")])
1571 (define_expand "vec_perm_const<mode>"
1572 [(match_operand:VSX_D 0 "vsx_register_operand" "")
1573 (match_operand:VSX_D 1 "vsx_register_operand" "")
1574 (match_operand:VSX_D 2 "vsx_register_operand" "")
1575 (match_operand:V2DI 3 "" "")]
1576 "VECTOR_MEM_VSX_P (<MODE>mode)"
1578 if (rs6000_expand_vec_perm_const (operands))
1584 ;; Expanders for builtins
1585 (define_expand "vsx_mergel_<mode>"
1586 [(set (match_operand:VSX_D 0 "vsx_register_operand" "")
1588 (vec_concat:<VS_double>
1589 (match_operand:VSX_D 1 "vsx_register_operand" "")
1590 (match_operand:VSX_D 2 "vsx_register_operand" ""))
1591 (parallel [(const_int 1) (const_int 3)])))]
1592 "VECTOR_MEM_VSX_P (<MODE>mode)"
1595 (define_expand "vsx_mergeh_<mode>"
1596 [(set (match_operand:VSX_D 0 "vsx_register_operand" "")
1598 (vec_concat:<VS_double>
1599 (match_operand:VSX_D 1 "vsx_register_operand" "")
1600 (match_operand:VSX_D 2 "vsx_register_operand" ""))
1601 (parallel [(const_int 0) (const_int 2)])))]
1602 "VECTOR_MEM_VSX_P (<MODE>mode)"
1606 (define_insn "vsx_splat_<mode>"
1607 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,wd,wd,?wa,?wa,?wa")
1608 (vec_duplicate:VSX_D
1609 (match_operand:<VS_scalar> 1 "splat_input_operand" "ws,f,Z,wa,wa,Z")))]
1610 "VECTOR_MEM_VSX_P (<MODE>mode)"
1612 xxpermdi %x0,%x1,%x1,0
1613 xxpermdi %x0,%x1,%x1,0
1615 xxpermdi %x0,%x1,%x1,0
1616 xxpermdi %x0,%x1,%x1,0
1618 [(set_attr "type" "vecperm,vecperm,vecload,vecperm,vecperm,vecload")])
1621 (define_insn "vsx_xxspltw_<mode>"
1622 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1623 (vec_duplicate:VSX_W
1624 (vec_select:<VS_scalar>
1625 (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1627 [(match_operand:QI 2 "u5bit_cint_operand" "i,i")]))))]
1628 "VECTOR_MEM_VSX_P (<MODE>mode)"
1629 "xxspltw %x0,%x1,%2"
1630 [(set_attr "type" "vecperm")])
1632 ;; V4SF/V4SI interleave
1633 (define_insn "vsx_xxmrghw_<mode>"
1634 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1636 (vec_concat:<VS_double>
1637 (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1638 (match_operand:VSX_W 2 "vsx_register_operand" "wf,wa"))
1639 (parallel [(const_int 0) (const_int 4)
1640 (const_int 1) (const_int 5)])))]
1641 "VECTOR_MEM_VSX_P (<MODE>mode)"
1642 "xxmrghw %x0,%x1,%x2"
1643 [(set_attr "type" "vecperm")])
1645 (define_insn "vsx_xxmrglw_<mode>"
1646 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1648 (vec_concat:<VS_double>
1649 (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1650 (match_operand:VSX_W 2 "vsx_register_operand" "wf,?wa"))
1651 (parallel [(const_int 2) (const_int 6)
1652 (const_int 3) (const_int 7)])))]
1653 "VECTOR_MEM_VSX_P (<MODE>mode)"
1654 "xxmrglw %x0,%x1,%x2"
1655 [(set_attr "type" "vecperm")])
1657 ;; Shift left double by word immediate
1658 (define_insn "vsx_xxsldwi_<mode>"
1659 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=wa")
1660 (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "wa")
1661 (match_operand:VSX_L 2 "vsx_register_operand" "wa")
1662 (match_operand:QI 3 "u5bit_cint_operand" "i")]
1664 "VECTOR_MEM_VSX_P (<MODE>mode)"
1665 "xxsldwi %x0,%x1,%x2,%3"
1666 [(set_attr "type" "vecperm")])
1669 ;; Vector reduction insns and splitters
1671 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v2df"
1672 [(set (match_operand:V2DF 0 "vfloat_operand" "=&wd,&?wa,wd,?wa")
1676 (match_operand:V2DF 1 "vfloat_operand" "wd,wa,wd,wa")
1677 (parallel [(const_int 1)]))
1680 (parallel [(const_int 0)])))
1682 (clobber (match_scratch:V2DF 2 "=0,0,&wd,&wa"))]
1683 "VECTOR_UNIT_VSX_P (V2DFmode)"
1689 rtx tmp = (GET_CODE (operands[2]) == SCRATCH)
1690 ? gen_reg_rtx (V2DFmode)
1692 emit_insn (gen_vsx_xxsldwi_v2df (tmp, operands[1], operands[1], const2_rtx));
1693 emit_insn (gen_<VEC_reduc_rtx>v2df3 (operands[0], tmp, operands[1]));
1696 [(set_attr "length" "8")
1697 (set_attr "type" "veccomplex")])
1699 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v4sf"
1700 [(set (match_operand:V4SF 0 "vfloat_operand" "=wf,?wa")
1702 (unspec:V4SF [(const_int 0)] UNSPEC_REDUC)
1703 (match_operand:V4SF 1 "vfloat_operand" "wf,wa")))
1704 (clobber (match_scratch:V4SF 2 "=&wf,&wa"))
1705 (clobber (match_scratch:V4SF 3 "=&wf,&wa"))]
1706 "VECTOR_UNIT_VSX_P (V4SFmode)"
1712 rtx op0 = operands[0];
1713 rtx op1 = operands[1];
1714 rtx tmp2, tmp3, tmp4;
1716 if (can_create_pseudo_p ())
1718 tmp2 = gen_reg_rtx (V4SFmode);
1719 tmp3 = gen_reg_rtx (V4SFmode);
1720 tmp4 = gen_reg_rtx (V4SFmode);
1729 emit_insn (gen_vsx_xxsldwi_v4sf (tmp2, op1, op1, const2_rtx));
1730 emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp3, tmp2, op1));
1731 emit_insn (gen_vsx_xxsldwi_v4sf (tmp4, tmp3, tmp3, GEN_INT (3)));
1732 emit_insn (gen_<VEC_reduc_rtx>v4sf3 (op0, tmp4, tmp3));
1735 [(set_attr "length" "16")
1736 (set_attr "type" "veccomplex")])
1738 ;; Combiner patterns with the vector reduction patterns that knows we can get
1739 ;; to the top element of the V2DF array without doing an extract.
1741 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v2df_scalar"
1742 [(set (match_operand:DF 0 "vfloat_operand" "=&ws,&?wa,ws,?wa")
1747 (match_operand:V2DF 1 "vfloat_operand" "wd,wa,wd,wa")
1748 (parallel [(const_int 1)]))
1751 (parallel [(const_int 0)])))
1753 (parallel [(const_int 1)])))
1754 (clobber (match_scratch:DF 2 "=0,0,&wd,&wa"))]
1755 "VECTOR_UNIT_VSX_P (V2DFmode)"
1761 rtx hi = gen_highpart (DFmode, operands[1]);
1762 rtx lo = (GET_CODE (operands[2]) == SCRATCH)
1763 ? gen_reg_rtx (DFmode)
1766 emit_insn (gen_vsx_extract_v2df (lo, operands[1], const1_rtx));
1767 emit_insn (gen_<VEC_reduc_rtx>df3 (operands[0], hi, lo));
1770 [(set_attr "length" "8")
1771 (set_attr "type" "veccomplex")])
1773 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v4sf_scalar"
1774 [(set (match_operand:SF 0 "vfloat_operand" "=f,?f")
1777 (unspec:V4SF [(const_int 0)] UNSPEC_REDUC)
1778 (match_operand:V4SF 1 "vfloat_operand" "wf,wa"))
1779 (parallel [(const_int 3)])))
1780 (clobber (match_scratch:V4SF 2 "=&wf,&wa"))
1781 (clobber (match_scratch:V4SF 3 "=&wf,&wa"))
1782 (clobber (match_scratch:V4SF 4 "=0,0"))]
1783 "VECTOR_UNIT_VSX_P (V4SFmode)"
1789 rtx op0 = operands[0];
1790 rtx op1 = operands[1];
1791 rtx tmp2, tmp3, tmp4, tmp5;
1793 if (can_create_pseudo_p ())
1795 tmp2 = gen_reg_rtx (V4SFmode);
1796 tmp3 = gen_reg_rtx (V4SFmode);
1797 tmp4 = gen_reg_rtx (V4SFmode);
1798 tmp5 = gen_reg_rtx (V4SFmode);
1808 emit_insn (gen_vsx_xxsldwi_v4sf (tmp2, op1, op1, const2_rtx));
1809 emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp3, tmp2, op1));
1810 emit_insn (gen_vsx_xxsldwi_v4sf (tmp4, tmp3, tmp3, GEN_INT (3)));
1811 emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp5, tmp4, tmp3));
1812 emit_insn (gen_vsx_xscvspdp_scalar2 (op0, tmp5));
1815 [(set_attr "length" "20")
1816 (set_attr "type" "veccomplex")])