3 ;; Free Software Foundation, Inc.
4 ;; Contributed by Michael Meissner <meissner@linux.vnet.ibm.com>
6 ;; This file is part of GCC.
8 ;; GCC is free software; you can redistribute it and/or modify it
9 ;; under the terms of the GNU General Public License as published
10 ;; by the Free Software Foundation; either version 3, or (at your
11 ;; option) any later version.
13 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
14 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 ;; License for more details.
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with GCC; see the file COPYING3. If not see
20 ;; <http://www.gnu.org/licenses/>.
22 ;; Iterator for both scalar and vector floating point types supported by VSX
23 (define_mode_iterator VSX_B [DF V4SF V2DF])
25 ;; Iterator for the 2 64-bit vector types
26 (define_mode_iterator VSX_D [V2DF V2DI])
28 ;; Iterator for the 2 32-bit vector types
29 (define_mode_iterator VSX_W [V4SF V4SI])
31 ;; Iterator for vector floating point types supported by VSX
32 (define_mode_iterator VSX_F [V4SF V2DF])
34 ;; Iterator for logical types supported by VSX
35 (define_mode_iterator VSX_L [V16QI V8HI V4SI V2DI V4SF V2DF TI])
37 ;; Iterator for memory move. Handle TImode specially to allow
38 ;; it to use gprs as well as vsx registers.
39 (define_mode_iterator VSX_M [V16QI V8HI V4SI V2DI V4SF V2DF])
41 ;; Iterator for types for load/store with update
42 (define_mode_iterator VSX_U [V16QI V8HI V4SI V2DI V4SF V2DF TI DF])
44 ;; Map into the appropriate load/store name based on the type
45 (define_mode_attr VSm [(V16QI "vw4")
54 ;; Map into the appropriate suffix based on the type
55 (define_mode_attr VSs [(V16QI "sp")
65 ;; Map the register class used
66 (define_mode_attr VSr [(V16QI "v")
76 ;; Map the register class used for float<->int conversions
77 (define_mode_attr VSr2 [(V2DF "wd")
81 (define_mode_attr VSr3 [(V2DF "wa")
85 ;; Map the register class for sp<->dp float conversions, destination
86 (define_mode_attr VSr4 [(SF "ws")
91 ;; Map the register class for sp<->dp float conversions, destination
92 (define_mode_attr VSr5 [(SF "ws")
97 ;; Same size integer type for floating point data
98 (define_mode_attr VSi [(V4SF "v4si")
102 (define_mode_attr VSI [(V4SF "V4SI")
106 ;; Word size for same size conversion
107 (define_mode_attr VSc [(V4SF "w")
111 ;; Bitsize for DF load with update
112 (define_mode_attr VSbit [(SI "32")
115 ;; Map into either s or v, depending on whether this is a scalar or vector
117 (define_mode_attr VSv [(V16QI "v")
126 ;; Appropriate type for add ops (and other simple FP ops)
127 (define_mode_attr VStype_simple [(V2DF "vecfloat")
131 (define_mode_attr VSfptype_simple [(V2DF "fp_addsub_d")
135 ;; Appropriate type for multiply ops
136 (define_mode_attr VStype_mul [(V2DF "vecfloat")
140 (define_mode_attr VSfptype_mul [(V2DF "fp_mul_d")
144 ;; Appropriate type for divide ops. For now, just lump the vector divide with
145 ;; the scalar divides
146 (define_mode_attr VStype_div [(V2DF "ddiv")
150 (define_mode_attr VSfptype_div [(V2DF "fp_div_d")
154 ;; Appropriate type for sqrt ops. For now, just lump the vector sqrt with
156 (define_mode_attr VStype_sqrt [(V2DF "dsqrt")
160 (define_mode_attr VSfptype_sqrt [(V2DF "fp_sqrt_d")
164 ;; Iterator and modes for sp<->dp conversions
165 ;; Because scalar SF values are represented internally as double, use the
166 ;; V4SF type to represent this than SF.
167 (define_mode_iterator VSX_SPDP [DF V4SF V2DF])
169 (define_mode_attr VS_spdp_res [(DF "V4SF")
173 (define_mode_attr VS_spdp_insn [(DF "xscvdpsp")
177 (define_mode_attr VS_spdp_type [(DF "fp")
181 ;; Map the scalar mode for a vector type
182 (define_mode_attr VS_scalar [(V2DF "DF")
189 ;; Appropriate type for load + update
190 (define_mode_attr VStype_load_update [(V16QI "vecload")
199 ;; Appropriate type for store + update
200 (define_mode_attr VStype_store_update [(V16QI "vecstore")
209 ;; Constants for creating unspecs
211 [(UNSPEC_VSX_CONCAT 500)
212 (UNSPEC_VSX_CVDPSXWS 501)
213 (UNSPEC_VSX_CVDPUXWS 502)
214 (UNSPEC_VSX_CVSPDP 503)
215 (UNSPEC_VSX_CVSXWDP 504)
216 (UNSPEC_VSX_CVUXWDP 505)
217 (UNSPEC_VSX_CVSXDSP 506)
218 (UNSPEC_VSX_CVUXDSP 507)
219 (UNSPEC_VSX_CVSPSXDS 508)
220 (UNSPEC_VSX_CVSPUXDS 509)
221 (UNSPEC_VSX_MADD 510)
222 (UNSPEC_VSX_MSUB 511)
223 (UNSPEC_VSX_NMADD 512)
224 (UNSPEC_VSX_NMSUB 513)
225 (UNSPEC_VSX_RSQRTE 514)
226 (UNSPEC_VSX_TDIV 515)
227 (UNSPEC_VSX_TSQRT 516)
228 (UNSPEC_VSX_XXPERMDI 517)
230 (UNSPEC_VSX_ROUND_I 519)
231 (UNSPEC_VSX_ROUND_IC 520)
232 (UNSPEC_VSX_SLDWI 521)])
235 (define_insn "*vsx_mov<mode>"
236 [(set (match_operand:VSX_M 0 "nonimmediate_operand" "=Z,<VSr>,<VSr>,?Z,?wa,?wa,*o,*r,*r,<VSr>,?wa,v,wZ,v")
237 (match_operand:VSX_M 1 "input_operand" "<VSr>,Z,<VSr>,wa,Z,wa,r,o,r,j,j,W,v,wZ"))]
238 "VECTOR_MEM_VSX_P (<MODE>mode)
239 && (register_operand (operands[0], <MODE>mode)
240 || register_operand (operands[1], <MODE>mode))"
242 switch (which_alternative)
246 return "stx<VSm>%U0x %x1,%y0";
250 return "lx<VSm>%U0x %x0,%y1";
254 return "xxlor %x0,%x1,%x1";
263 return "xxlxor %x0,%x0,%x0";
266 return output_vec_const_move (operands);
269 return "stvx %1,%y0";
278 [(set_attr "type" "vecstore,vecload,vecsimple,vecstore,vecload,vecsimple,*,*,*,vecsimple,vecsimple,*,vecstore,vecload")])
280 ;; Unlike other VSX moves, allow the GPRs, since a normal use of TImode is for
281 ;; unions. However for plain data movement, slightly favor the vector loads
282 (define_insn "*vsx_movti"
283 [(set (match_operand:TI 0 "nonimmediate_operand" "=Z,wa,wa,?o,?r,?r,wa,v,v,wZ")
284 (match_operand:TI 1 "input_operand" "wa,Z,wa,r,o,r,j,W,wZ,v"))]
285 "VECTOR_MEM_VSX_P (TImode)
286 && (register_operand (operands[0], TImode)
287 || register_operand (operands[1], TImode))"
289 switch (which_alternative)
292 return "stxvd2%U0x %x1,%y0";
295 return "lxvd2%U0x %x0,%y1";
298 return "xxlor %x0,%x1,%x1";
306 return "xxlxor %x0,%x0,%x0";
309 return output_vec_const_move (operands);
312 return "stvx %1,%y0";
321 [(set_attr "type" "vecstore,vecload,vecsimple,*,*,*,vecsimple,*,vecstore,vecload")])
323 ;; Load/store with update
324 ;; Define insns that do load or store with update. Because VSX only has
325 ;; reg+reg addressing, pre-decrement or pre-increment is unlikely to be
328 ;; In all these cases, we use operands 0 and 1 for the register being
329 ;; incremented because those are the operands that local-alloc will
330 ;; tie and these are the pair most likely to be tieable (and the ones
331 ;; that will benefit the most).
333 (define_insn "*vsx_load<VSX_U:mode>_update_<P:mptrsize>"
334 [(set (match_operand:VSX_U 3 "vsx_register_operand" "=<VSr>,?wa")
335 (mem:VSX_U (plus:P (match_operand:P 1 "gpc_reg_operand" "0,0")
336 (match_operand:P 2 "gpc_reg_operand" "r,r"))))
337 (set (match_operand:P 0 "gpc_reg_operand" "=b,b")
338 (plus:P (match_dup 1)
340 "<P:tptrsize> && TARGET_UPDATE && VECTOR_MEM_VSX_P (<MODE>mode)"
341 "lx<VSm>ux %x3,%0,%2"
342 [(set_attr "type" "<VSX_U:VStype_load_update>")])
344 (define_insn "*vsx_store<mode>_update_<P:mptrsize>"
345 [(set (mem:VSX_U (plus:P (match_operand:P 1 "gpc_reg_operand" "0,0")
346 (match_operand:P 2 "gpc_reg_operand" "r,r")))
347 (match_operand:VSX_U 3 "gpc_reg_operand" "<VSr>,?wa"))
348 (set (match_operand:P 0 "gpc_reg_operand" "=b,b")
349 (plus:P (match_dup 1)
351 "<P:tptrsize> && TARGET_UPDATE && VECTOR_MEM_VSX_P (<MODE>mode)"
352 "stx<VSm>ux %x3,%0,%2"
353 [(set_attr "type" "<VSX_U:VStype_store_update>")])
355 ;; We may need to have a varient on the pattern for use in the prologue
356 ;; that doesn't depend on TARGET_UPDATE.
359 ;; VSX scalar and vector floating point arithmetic instructions
360 (define_insn "*vsx_add<mode>3"
361 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
362 (plus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
363 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
364 "VECTOR_UNIT_VSX_P (<MODE>mode)"
365 "x<VSv>add<VSs> %x0,%x1,%x2"
366 [(set_attr "type" "<VStype_simple>")
367 (set_attr "fp_type" "<VSfptype_simple>")])
369 (define_insn "*vsx_sub<mode>3"
370 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
371 (minus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
372 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
373 "VECTOR_UNIT_VSX_P (<MODE>mode)"
374 "x<VSv>sub<VSs> %x0,%x1,%x2"
375 [(set_attr "type" "<VStype_simple>")
376 (set_attr "fp_type" "<VSfptype_simple>")])
378 (define_insn "*vsx_mul<mode>3"
379 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
380 (mult:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
381 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
382 "VECTOR_UNIT_VSX_P (<MODE>mode)"
383 "x<VSv>mul<VSs> %x0,%x1,%x2"
384 [(set_attr "type" "<VStype_mul>")
385 (set_attr "fp_type" "<VSfptype_mul>")])
387 (define_insn "*vsx_div<mode>3"
388 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
389 (div:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
390 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
391 "VECTOR_UNIT_VSX_P (<MODE>mode)"
392 "x<VSv>div<VSs> %x0,%x1,%x2"
393 [(set_attr "type" "<VStype_div>")
394 (set_attr "fp_type" "<VSfptype_div>")])
396 ;; *tdiv* instruction returning the FG flag
397 (define_expand "vsx_tdiv<mode>3_fg"
399 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
400 (match_operand:VSX_B 2 "vsx_register_operand" "")]
402 (set (match_operand:SI 0 "gpc_reg_operand" "")
405 "VECTOR_UNIT_VSX_P (<MODE>mode)"
407 operands[3] = gen_reg_rtx (CCFPmode);
410 ;; *tdiv* instruction returning the FE flag
411 (define_expand "vsx_tdiv<mode>3_fe"
413 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
414 (match_operand:VSX_B 2 "vsx_register_operand" "")]
416 (set (match_operand:SI 0 "gpc_reg_operand" "")
419 "VECTOR_UNIT_VSX_P (<MODE>mode)"
421 operands[3] = gen_reg_rtx (CCFPmode);
424 (define_insn "*vsx_tdiv<mode>3_internal"
425 [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
426 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
427 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")]
429 "VECTOR_UNIT_VSX_P (<MODE>mode)"
430 "x<VSv>tdiv<VSs> %0,%x1,%x2"
431 [(set_attr "type" "<VStype_simple>")
432 (set_attr "fp_type" "<VSfptype_simple>")])
434 (define_insn "vsx_fre<mode>2"
435 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
436 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
438 "VECTOR_UNIT_VSX_P (<MODE>mode)"
439 "x<VSv>re<VSs> %x0,%x1"
440 [(set_attr "type" "<VStype_simple>")
441 (set_attr "fp_type" "<VSfptype_simple>")])
443 (define_insn "*vsx_neg<mode>2"
444 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
445 (neg:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
446 "VECTOR_UNIT_VSX_P (<MODE>mode)"
447 "x<VSv>neg<VSs> %x0,%x1"
448 [(set_attr "type" "<VStype_simple>")
449 (set_attr "fp_type" "<VSfptype_simple>")])
451 (define_insn "*vsx_abs<mode>2"
452 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
453 (abs:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
454 "VECTOR_UNIT_VSX_P (<MODE>mode)"
455 "x<VSv>abs<VSs> %x0,%x1"
456 [(set_attr "type" "<VStype_simple>")
457 (set_attr "fp_type" "<VSfptype_simple>")])
459 (define_insn "vsx_nabs<mode>2"
460 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
463 (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa"))))]
464 "VECTOR_UNIT_VSX_P (<MODE>mode)"
465 "x<VSv>nabs<VSs> %x0,%x1"
466 [(set_attr "type" "<VStype_simple>")
467 (set_attr "fp_type" "<VSfptype_simple>")])
469 (define_insn "vsx_smax<mode>3"
470 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
471 (smax:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
472 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
473 "VECTOR_UNIT_VSX_P (<MODE>mode)"
474 "x<VSv>max<VSs> %x0,%x1,%x2"
475 [(set_attr "type" "<VStype_simple>")
476 (set_attr "fp_type" "<VSfptype_simple>")])
478 (define_insn "*vsx_smin<mode>3"
479 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
480 (smin:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
481 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
482 "VECTOR_UNIT_VSX_P (<MODE>mode)"
483 "x<VSv>min<VSs> %x0,%x1,%x2"
484 [(set_attr "type" "<VStype_simple>")
485 (set_attr "fp_type" "<VSfptype_simple>")])
487 (define_insn "*vsx_sqrt<mode>2"
488 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
489 (sqrt:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
490 "VECTOR_UNIT_VSX_P (<MODE>mode)"
491 "x<VSv>sqrt<VSs> %x0,%x1"
492 [(set_attr "type" "<VStype_sqrt>")
493 (set_attr "fp_type" "<VSfptype_sqrt>")])
495 (define_insn "vsx_rsqrte<mode>2"
496 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
497 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
499 "VECTOR_UNIT_VSX_P (<MODE>mode)"
500 "x<VSv>rsqrte<VSs> %x0,%x1"
501 [(set_attr "type" "<VStype_simple>")
502 (set_attr "fp_type" "<VSfptype_simple>")])
504 ;; *tsqrt* returning the fg flag
505 (define_expand "vsx_tsqrt<mode>2_fg"
507 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
509 (set (match_operand:SI 0 "gpc_reg_operand" "")
512 "VECTOR_UNIT_VSX_P (<MODE>mode)"
514 operands[3] = gen_reg_rtx (CCFPmode);
517 ;; *tsqrt* returning the fe flag
518 (define_expand "vsx_tsqrt<mode>2_fe"
520 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
522 (set (match_operand:SI 0 "gpc_reg_operand" "")
525 "VECTOR_UNIT_VSX_P (<MODE>mode)"
527 operands[3] = gen_reg_rtx (CCFPmode);
530 (define_insn "*vsx_tsqrt<mode>2_internal"
531 [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
532 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
534 "VECTOR_UNIT_VSX_P (<MODE>mode)"
535 "x<VSv>tsqrt<VSs> %0,%x1"
536 [(set_attr "type" "<VStype_simple>")
537 (set_attr "fp_type" "<VSfptype_simple>")])
539 ;; Fused vector multiply/add instructions
541 ;; Note we have a pattern for the multiply/add operations that uses unspec and
542 ;; does not check -mfused-madd to allow users to use these ops when they know
543 ;; they want the fused multiply/add.
545 (define_expand "vsx_fmadd<mode>4"
546 [(set (match_operand:VSX_B 0 "vsx_register_operand" "")
549 (match_operand:VSX_B 1 "vsx_register_operand" "")
550 (match_operand:VSX_B 2 "vsx_register_operand" ""))
551 (match_operand:VSX_B 3 "vsx_register_operand" "")))]
552 "VECTOR_UNIT_VSX_P (<MODE>mode)"
554 if (!TARGET_FUSED_MADD)
556 emit_insn (gen_vsx_fmadd<mode>4_2 (operands[0], operands[1], operands[2],
562 (define_insn "*vsx_fmadd<mode>4_1"
563 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
566 (match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
567 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0"))
568 (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")))]
569 "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD"
571 x<VSv>madda<VSs> %x0,%x1,%x2
572 x<VSv>maddm<VSs> %x0,%x1,%x3
573 x<VSv>madda<VSs> %x0,%x1,%x2
574 x<VSv>maddm<VSs> %x0,%x1,%x3"
575 [(set_attr "type" "<VStype_mul>")
576 (set_attr "fp_type" "<VSfptype_mul>")])
578 (define_insn "vsx_fmadd<mode>4_2"
579 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
580 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
581 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
582 (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")]
584 "VECTOR_UNIT_VSX_P (<MODE>mode)"
586 x<VSv>madda<VSs> %x0,%x1,%x2
587 x<VSv>maddm<VSs> %x0,%x1,%x3
588 x<VSv>madda<VSs> %x0,%x1,%x2
589 x<VSv>maddm<VSs> %x0,%x1,%x3"
590 [(set_attr "type" "<VStype_mul>")
591 (set_attr "fp_type" "<VSfptype_mul>")])
593 (define_expand "vsx_fmsub<mode>4"
594 [(set (match_operand:VSX_B 0 "vsx_register_operand" "")
597 (match_operand:VSX_B 1 "vsx_register_operand" "")
598 (match_operand:VSX_B 2 "vsx_register_operand" ""))
599 (match_operand:VSX_B 3 "vsx_register_operand" "")))]
600 "VECTOR_UNIT_VSX_P (<MODE>mode)"
602 if (!TARGET_FUSED_MADD)
604 emit_insn (gen_vsx_fmsub<mode>4_2 (operands[0], operands[1], operands[2],
610 (define_insn "*vsx_fmsub<mode>4_1"
611 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
614 (match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
615 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0"))
616 (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")))]
617 "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD"
619 x<VSv>msuba<VSs> %x0,%x1,%x2
620 x<VSv>msubm<VSs> %x0,%x1,%x3
621 x<VSv>msuba<VSs> %x0,%x1,%x2
622 x<VSv>msubm<VSs> %x0,%x1,%x3"
623 [(set_attr "type" "<VStype_mul>")
624 (set_attr "fp_type" "<VSfptype_mul>")])
626 (define_insn "vsx_fmsub<mode>4_2"
627 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
628 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
629 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
630 (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")]
632 "VECTOR_UNIT_VSX_P (<MODE>mode)"
634 x<VSv>msuba<VSs> %x0,%x1,%x2
635 x<VSv>msubm<VSs> %x0,%x1,%x3
636 x<VSv>msuba<VSs> %x0,%x1,%x2
637 x<VSv>msubm<VSs> %x0,%x1,%x3"
638 [(set_attr "type" "<VStype_mul>")
639 (set_attr "fp_type" "<VSfptype_mul>")])
641 (define_expand "vsx_fnmadd<mode>4"
642 [(match_operand:VSX_B 0 "vsx_register_operand" "")
643 (match_operand:VSX_B 1 "vsx_register_operand" "")
644 (match_operand:VSX_B 2 "vsx_register_operand" "")
645 (match_operand:VSX_B 3 "vsx_register_operand" "")]
646 "VECTOR_UNIT_VSX_P (<MODE>mode)"
648 if (TARGET_FUSED_MADD && HONOR_SIGNED_ZEROS (DFmode))
650 emit_insn (gen_vsx_fnmadd<mode>4_1 (operands[0], operands[1],
651 operands[2], operands[3]));
654 else if (TARGET_FUSED_MADD && !HONOR_SIGNED_ZEROS (DFmode))
656 emit_insn (gen_vsx_fnmadd<mode>4_2 (operands[0], operands[1],
657 operands[2], operands[3]));
662 emit_insn (gen_vsx_fnmadd<mode>4_3 (operands[0], operands[1],
663 operands[2], operands[3]));
668 (define_insn "vsx_fnmadd<mode>4_1"
669 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
673 (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSr>,wa,wa")
674 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0"))
675 (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
676 "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD
677 && HONOR_SIGNED_ZEROS (DFmode)"
679 x<VSv>nmadda<VSs> %x0,%x1,%x2
680 x<VSv>nmaddm<VSs> %x0,%x1,%x3
681 x<VSv>nmadda<VSs> %x0,%x1,%x2
682 x<VSv>nmaddm<VSs> %x0,%x1,%x3"
683 [(set_attr "type" "<VStype_mul>")
684 (set_attr "fp_type" "<VSfptype_mul>")])
686 (define_insn "vsx_fnmadd<mode>4_2"
687 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
691 (match_operand:VSX_B 1 "gpc_reg_operand" "<VSr>,<VSr>,wa,wa"))
692 (match_operand:VSX_B 2 "gpc_reg_operand" "<VSr>,0,wa,0"))
693 (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")))]
694 "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD
695 && !HONOR_SIGNED_ZEROS (DFmode)"
697 x<VSv>nmadda<VSs> %x0,%x1,%x2
698 x<VSv>nmaddm<VSs> %x0,%x1,%x3
699 x<VSv>nmadda<VSs> %x0,%x1,%x2
700 x<VSv>nmaddm<VSs> %x0,%x1,%x3"
701 [(set_attr "type" "<VStype_mul>")
702 (set_attr "fp_type" "<VSfptype_mul>")])
704 (define_insn "vsx_fnmadd<mode>4_3"
705 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
706 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSr>,wa,wa")
707 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
708 (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")]
710 "VECTOR_UNIT_VSX_P (<MODE>mode)"
712 x<VSv>nmadda<VSs> %x0,%x1,%x2
713 x<VSv>nmaddm<VSs> %x0,%x1,%x3
714 x<VSv>nmadda<VSs> %x0,%x1,%x2
715 x<VSv>nmaddm<VSs> %x0,%x1,%x3"
716 [(set_attr "type" "<VStype_mul>")
717 (set_attr "fp_type" "<VSfptype_mul>")])
719 (define_expand "vsx_fnmsub<mode>4"
720 [(match_operand:VSX_B 0 "vsx_register_operand" "")
721 (match_operand:VSX_B 1 "vsx_register_operand" "")
722 (match_operand:VSX_B 2 "vsx_register_operand" "")
723 (match_operand:VSX_B 3 "vsx_register_operand" "")]
724 "VECTOR_UNIT_VSX_P (<MODE>mode)"
726 if (TARGET_FUSED_MADD && HONOR_SIGNED_ZEROS (DFmode))
728 emit_insn (gen_vsx_fnmsub<mode>4_1 (operands[0], operands[1],
729 operands[2], operands[3]));
732 else if (TARGET_FUSED_MADD && !HONOR_SIGNED_ZEROS (DFmode))
734 emit_insn (gen_vsx_fnmsub<mode>4_2 (operands[0], operands[1],
735 operands[2], operands[3]));
740 emit_insn (gen_vsx_fnmsub<mode>4_3 (operands[0], operands[1],
741 operands[2], operands[3]));
746 (define_insn "vsx_fnmsub<mode>4_1"
747 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
751 (match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
752 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0"))
753 (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
754 "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD
755 && HONOR_SIGNED_ZEROS (DFmode)"
757 x<VSv>nmsuba<VSs> %x0,%x1,%x2
758 x<VSv>nmsubm<VSs> %x0,%x1,%x3
759 x<VSv>nmsuba<VSs> %x0,%x1,%x2
760 x<VSv>nmsubm<VSs> %x0,%x1,%x3"
761 [(set_attr "type" "<VStype_mul>")
762 (set_attr "fp_type" "<VSfptype_mul>")])
764 (define_insn "vsx_fnmsub<mode>4_2"
765 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
767 (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")
769 (match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
770 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0"))))]
771 "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD
772 && !HONOR_SIGNED_ZEROS (DFmode)"
774 x<VSv>nmsuba<VSs> %x0,%x1,%x2
775 x<VSv>nmsubm<VSs> %x0,%x1,%x3
776 x<VSv>nmsuba<VSs> %x0,%x1,%x2
777 x<VSv>nmsubm<VSs> %x0,%x1,%x3"
778 [(set_attr "type" "<VStype_mul>")
779 (set_attr "fp_type" "<VSfptype_mul>")])
781 (define_insn "vsx_fnmsub<mode>4_3"
782 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
783 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
784 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
785 (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")]
787 "VECTOR_UNIT_VSX_P (<MODE>mode)"
789 x<VSv>nmsuba<VSs> %x0,%x1,%x2
790 x<VSv>nmsubm<VSs> %x0,%x1,%x3
791 x<VSv>nmsuba<VSs> %x0,%x1,%x2
792 x<VSv>nmsubm<VSs> %x0,%x1,%x3"
793 [(set_attr "type" "<VStype_mul>")
794 (set_attr "fp_type" "<VSfptype_mul>")])
796 ;; Vector conditional expressions (no scalar version for these instructions)
797 (define_insn "vsx_eq<mode>"
798 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
799 (eq:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
800 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
801 "VECTOR_UNIT_VSX_P (<MODE>mode)"
802 "xvcmpeq<VSs> %x0,%x1,%x2"
803 [(set_attr "type" "<VStype_simple>")
804 (set_attr "fp_type" "<VSfptype_simple>")])
806 (define_insn "vsx_gt<mode>"
807 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
808 (gt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
809 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
810 "VECTOR_UNIT_VSX_P (<MODE>mode)"
811 "xvcmpgt<VSs> %x0,%x1,%x2"
812 [(set_attr "type" "<VStype_simple>")
813 (set_attr "fp_type" "<VSfptype_simple>")])
815 (define_insn "*vsx_ge<mode>"
816 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
817 (ge:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
818 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
819 "VECTOR_UNIT_VSX_P (<MODE>mode)"
820 "xvcmpge<VSs> %x0,%x1,%x2"
821 [(set_attr "type" "<VStype_simple>")
822 (set_attr "fp_type" "<VSfptype_simple>")])
824 ;; Floating point scalar compare
825 (define_insn "*vsx_cmpdf_internal1"
826 [(set (match_operand:CCFP 0 "cc_reg_operand" "=y,?y")
827 (compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "ws,wa")
828 (match_operand:DF 2 "gpc_reg_operand" "ws,wa")))]
829 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
830 && VECTOR_UNIT_VSX_P (DFmode)"
831 "xscmpudp %0,%x1,%x2"
832 [(set_attr "type" "fpcompare")])
834 ;; Compare vectors producing a vector result and a predicate, setting CR6 to
835 ;; indicate a combined status
836 (define_insn "*vsx_eq_<mode>_p"
839 [(eq:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
840 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
842 (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
843 (eq:VSX_F (match_dup 1)
845 "VECTOR_UNIT_VSX_P (<MODE>mode)"
846 "xvcmpeq<VSs>. %x0,%x1,%x2"
847 [(set_attr "type" "veccmp")])
849 (define_insn "*vsx_gt_<mode>_p"
852 [(gt:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
853 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
855 (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
856 (gt:VSX_F (match_dup 1)
858 "VECTOR_UNIT_VSX_P (<MODE>mode)"
859 "xvcmpgt<VSs>. %x0,%x1,%x2"
860 [(set_attr "type" "veccmp")])
862 (define_insn "*vsx_ge_<mode>_p"
865 [(ge:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
866 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
868 (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
869 (ge:VSX_F (match_dup 1)
871 "VECTOR_UNIT_VSX_P (<MODE>mode)"
872 "xvcmpge<VSs>. %x0,%x1,%x2"
873 [(set_attr "type" "veccmp")])
876 (define_insn "*vsx_xxsel<mode>"
877 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
879 (ne:CC (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
881 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
882 (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
883 "VECTOR_MEM_VSX_P (<MODE>mode)"
884 "xxsel %x0,%x3,%x2,%x1"
885 [(set_attr "type" "vecperm")])
887 (define_insn "*vsx_xxsel<mode>_uns"
888 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
890 (ne:CCUNS (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
892 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
893 (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
894 "VECTOR_MEM_VSX_P (<MODE>mode)"
895 "xxsel %x0,%x3,%x2,%x1"
896 [(set_attr "type" "vecperm")])
899 (define_insn "vsx_copysign<mode>3"
900 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
902 (ge:VSX_B (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")
903 (match_operand:VSX_B 3 "zero_constant" "j,j"))
904 (abs:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa"))
905 (neg:VSX_B (abs:VSX_B (match_dup 1)))))]
906 "VECTOR_UNIT_VSX_P (<MODE>mode)"
907 "x<VSv>cpsgn<VSs> %x0,%x2,%x1"
908 [(set_attr "type" "<VStype_simple>")
909 (set_attr "fp_type" "<VSfptype_simple>")])
911 ;; For the conversions, limit the register class for the integer value to be
912 ;; the fprs because we don't want to add the altivec registers to movdi/movsi.
913 ;; For the unsigned tests, there isn't a generic double -> unsigned conversion
914 ;; in rs6000.md so don't test VECTOR_UNIT_VSX_P, just test against VSX.
915 (define_insn "vsx_float<VSi><mode>2"
916 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
917 (float:VSX_B (match_operand:<VSI> 1 "vsx_register_operand" "<VSr2>,<VSr3>")))]
918 "VECTOR_UNIT_VSX_P (<MODE>mode)"
919 "x<VSv>cvsx<VSc><VSs> %x0,%x1"
920 [(set_attr "type" "<VStype_simple>")
921 (set_attr "fp_type" "<VSfptype_simple>")])
923 (define_insn "vsx_floatuns<VSi><mode>2"
924 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
925 (unsigned_float:VSX_B (match_operand:<VSI> 1 "vsx_register_operand" "<VSr2>,<VSr3>")))]
926 "VECTOR_UNIT_VSX_P (<MODE>mode)"
927 "x<VSv>cvux<VSc><VSs> %x0,%x1"
928 [(set_attr "type" "<VStype_simple>")
929 (set_attr "fp_type" "<VSfptype_simple>")])
931 (define_insn "vsx_fix_trunc<mode><VSi>2"
932 [(set (match_operand:<VSI> 0 "vsx_register_operand" "=<VSr2>,?<VSr3>")
933 (fix:<VSI> (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
934 "VECTOR_UNIT_VSX_P (<MODE>mode)"
935 "x<VSv>cv<VSs>sx<VSc>s %x0,%x1"
936 [(set_attr "type" "<VStype_simple>")
937 (set_attr "fp_type" "<VSfptype_simple>")])
939 (define_insn "vsx_fixuns_trunc<mode><VSi>2"
940 [(set (match_operand:<VSI> 0 "vsx_register_operand" "=<VSr2>,?<VSr3>")
941 (unsigned_fix:<VSI> (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
942 "VECTOR_UNIT_VSX_P (<MODE>mode)"
943 "x<VSv>cv<VSs>ux<VSc>s %x0,%x1"
944 [(set_attr "type" "<VStype_simple>")
945 (set_attr "fp_type" "<VSfptype_simple>")])
947 ;; Math rounding functions
948 (define_insn "vsx_x<VSv>r<VSs>i"
949 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
950 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
951 UNSPEC_VSX_ROUND_I))]
952 "VECTOR_UNIT_VSX_P (<MODE>mode)"
953 "x<VSv>r<VSs>i %x0,%x1"
954 [(set_attr "type" "<VStype_simple>")
955 (set_attr "fp_type" "<VSfptype_simple>")])
957 (define_insn "vsx_x<VSv>r<VSs>ic"
958 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
959 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
960 UNSPEC_VSX_ROUND_IC))]
961 "VECTOR_UNIT_VSX_P (<MODE>mode)"
962 "x<VSv>r<VSs>ic %x0,%x1"
963 [(set_attr "type" "<VStype_simple>")
964 (set_attr "fp_type" "<VSfptype_simple>")])
966 (define_insn "vsx_btrunc<mode>2"
967 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
968 (fix:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
969 "VECTOR_UNIT_VSX_P (<MODE>mode)"
970 "x<VSv>r<VSs>iz %x0,%x1"
971 [(set_attr "type" "<VStype_simple>")
972 (set_attr "fp_type" "<VSfptype_simple>")])
974 (define_insn "*vsx_b2trunc<mode>2"
975 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
976 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
978 "VECTOR_UNIT_VSX_P (<MODE>mode)"
979 "x<VSv>r<VSs>iz %x0,%x1"
980 [(set_attr "type" "<VStype_simple>")
981 (set_attr "fp_type" "<VSfptype_simple>")])
983 (define_insn "vsx_floor<mode>2"
984 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
985 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
987 "VECTOR_UNIT_VSX_P (<MODE>mode)"
988 "x<VSv>r<VSs>im %x0,%x1"
989 [(set_attr "type" "<VStype_simple>")
990 (set_attr "fp_type" "<VSfptype_simple>")])
992 (define_insn "vsx_ceil<mode>2"
993 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
994 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
996 "VECTOR_UNIT_VSX_P (<MODE>mode)"
997 "x<VSv>r<VSs>ip %x0,%x1"
998 [(set_attr "type" "<VStype_simple>")
999 (set_attr "fp_type" "<VSfptype_simple>")])
1002 ;; VSX convert to/from double vector
1004 ;; Convert between single and double precision
1005 ;; Don't use xscvspdp and xscvdpsp for scalar conversions, since the normal
1006 ;; scalar single precision instructions internally use the double format.
1007 ;; Prefer the altivec registers, since we likely will need to do a vperm
1008 (define_insn "vsx_<VS_spdp_insn>"
1009 [(set (match_operand:<VS_spdp_res> 0 "vsx_register_operand" "=<VSr4>,?wa")
1010 (unspec:<VS_spdp_res> [(match_operand:VSX_SPDP 1 "vsx_register_operand" "<VSr5>,wa")]
1011 UNSPEC_VSX_CVSPDP))]
1012 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1013 "<VS_spdp_insn> %x0,%x1"
1014 [(set_attr "type" "<VS_spdp_type>")])
1016 ;; xscvspdp, represent the scalar SF type as V4SF
1017 (define_insn "vsx_xscvspdp"
1018 [(set (match_operand:DF 0 "vsx_register_operand" "=ws,?wa")
1019 (unspec:DF [(match_operand:V4SF 1 "vsx_register_operand" "wa,wa")]
1020 UNSPEC_VSX_CVSPDP))]
1021 "VECTOR_UNIT_VSX_P (DFmode)"
1023 [(set_attr "type" "fp")])
1025 ;; xscvdpsp used for splat'ing a scalar to V4SF, knowing that the internal SF
1026 ;; format of scalars is actually DF.
1027 (define_insn "vsx_xscvdpsp_scalar"
1028 [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
1029 (unspec:V4SF [(match_operand:SF 1 "vsx_register_operand" "f")]
1030 UNSPEC_VSX_CVSPDP))]
1031 "VECTOR_UNIT_VSX_P (DFmode)"
1033 [(set_attr "type" "fp")])
1035 ;; Convert from 64-bit to 32-bit types
1036 ;; Note, favor the Altivec registers since the usual use of these instructions
1037 ;; is in vector converts and we need to use the Altivec vperm instruction.
1039 (define_insn "vsx_xvcvdpsxws"
1040 [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
1041 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
1042 UNSPEC_VSX_CVDPSXWS))]
1043 "VECTOR_UNIT_VSX_P (V2DFmode)"
1044 "xvcvdpsxws %x0,%x1"
1045 [(set_attr "type" "vecfloat")])
1047 (define_insn "vsx_xvcvdpuxws"
1048 [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
1049 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
1050 UNSPEC_VSX_CVDPUXWS))]
1051 "VECTOR_UNIT_VSX_P (V2DFmode)"
1052 "xvcvdpuxws %x0,%x1"
1053 [(set_attr "type" "vecfloat")])
1055 (define_insn "vsx_xvcvsxdsp"
1056 [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
1057 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
1058 UNSPEC_VSX_CVSXDSP))]
1059 "VECTOR_UNIT_VSX_P (V2DFmode)"
1061 [(set_attr "type" "vecfloat")])
1063 (define_insn "vsx_xvcvuxdsp"
1064 [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
1065 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
1066 UNSPEC_VSX_CVUXDSP))]
1067 "VECTOR_UNIT_VSX_P (V2DFmode)"
1069 [(set_attr "type" "vecfloat")])
1071 ;; Convert from 32-bit to 64-bit types
1072 (define_insn "vsx_xvcvsxwdp"
1073 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1074 (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
1075 UNSPEC_VSX_CVSXWDP))]
1076 "VECTOR_UNIT_VSX_P (V2DFmode)"
1078 [(set_attr "type" "vecfloat")])
1080 (define_insn "vsx_xvcvuxwdp"
1081 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1082 (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
1083 UNSPEC_VSX_CVUXWDP))]
1084 "VECTOR_UNIT_VSX_P (V2DFmode)"
1086 [(set_attr "type" "vecfloat")])
1088 (define_insn "vsx_xvcvspsxds"
1089 [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
1090 (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
1091 UNSPEC_VSX_CVSPSXDS))]
1092 "VECTOR_UNIT_VSX_P (V2DFmode)"
1093 "xvcvspsxds %x0,%x1"
1094 [(set_attr "type" "vecfloat")])
1096 (define_insn "vsx_xvcvspuxds"
1097 [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
1098 (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
1099 UNSPEC_VSX_CVSPUXDS))]
1100 "VECTOR_UNIT_VSX_P (V2DFmode)"
1101 "xvcvspuxds %x0,%x1"
1102 [(set_attr "type" "vecfloat")])
1104 ;; Logical and permute operations
1105 (define_insn "*vsx_and<mode>3"
1106 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1108 (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
1109 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
1110 "VECTOR_MEM_VSX_P (<MODE>mode)"
1111 "xxland %x0,%x1,%x2"
1112 [(set_attr "type" "vecsimple")])
1114 (define_insn "*vsx_ior<mode>3"
1115 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1116 (ior:VSX_L (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)"
1120 [(set_attr "type" "vecsimple")])
1122 (define_insn "*vsx_xor<mode>3"
1123 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1125 (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
1126 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
1127 "VECTOR_MEM_VSX_P (<MODE>mode)"
1128 "xxlxor %x0,%x1,%x2"
1129 [(set_attr "type" "vecsimple")])
1131 (define_insn "*vsx_one_cmpl<mode>2"
1132 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1134 (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")))]
1135 "VECTOR_MEM_VSX_P (<MODE>mode)"
1136 "xxlnor %x0,%x1,%x1"
1137 [(set_attr "type" "vecsimple")])
1139 (define_insn "*vsx_nor<mode>3"
1140 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1143 (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
1144 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa"))))]
1145 "VECTOR_MEM_VSX_P (<MODE>mode)"
1146 "xxlnor %x0,%x1,%x2"
1147 [(set_attr "type" "vecsimple")])
1149 (define_insn "*vsx_andc<mode>3"
1150 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1153 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa"))
1154 (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")))]
1155 "VECTOR_MEM_VSX_P (<MODE>mode)"
1156 "xxlandc %x0,%x1,%x2"
1157 [(set_attr "type" "vecsimple")])
1160 ;; Permute operations
1162 ;; Build a V2DF/V2DI vector from two scalars
1163 (define_insn "vsx_concat_<mode>"
1164 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
1166 [(match_operand:<VS_scalar> 1 "vsx_register_operand" "ws,wa")
1167 (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")]
1168 UNSPEC_VSX_CONCAT))]
1169 "VECTOR_MEM_VSX_P (<MODE>mode)"
1170 "xxpermdi %x0,%x1,%x2,0"
1171 [(set_attr "type" "vecperm")])
1173 ;; Special purpose concat using xxpermdi to glue two single precision values
1174 ;; together, relying on the fact that internally scalar floats are represented
1175 ;; as doubles. This is used to initialize a V4SF vector with 4 floats
1176 (define_insn "vsx_concat_v2sf"
1177 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1179 [(match_operand:SF 1 "vsx_register_operand" "f,f")
1180 (match_operand:SF 2 "vsx_register_operand" "f,f")]
1181 UNSPEC_VSX_CONCAT))]
1182 "VECTOR_MEM_VSX_P (V2DFmode)"
1183 "xxpermdi %x0,%x1,%x2,0"
1184 [(set_attr "type" "vecperm")])
1186 ;; Set the element of a V2DI/VD2F mode
1187 (define_insn "vsx_set_<mode>"
1188 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
1189 (unspec:VSX_D [(match_operand:VSX_D 1 "vsx_register_operand" "wd,wa")
1190 (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")
1191 (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
1193 "VECTOR_MEM_VSX_P (<MODE>mode)"
1195 if (INTVAL (operands[3]) == 0)
1196 return \"xxpermdi %x0,%x1,%x2,1\";
1197 else if (INTVAL (operands[3]) == 1)
1198 return \"xxpermdi %x0,%x2,%x1,0\";
1202 [(set_attr "type" "vecperm")])
1204 ;; Extract a DF/DI element from V2DF/V2DI
1205 (define_insn "vsx_extract_<mode>"
1206 [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,d,?wa")
1207 (vec_select:<VS_scalar> (match_operand:VSX_D 1 "vsx_register_operand" "wd,wd,wa")
1209 [(match_operand:QI 2 "u5bit_cint_operand" "i,i,i")])))]
1210 "VECTOR_MEM_VSX_P (<MODE>mode)"
1212 gcc_assert (UINTVAL (operands[2]) <= 1);
1213 operands[3] = GEN_INT (INTVAL (operands[2]) << 1);
1214 return \"xxpermdi %x0,%x1,%x1,%3\";
1216 [(set_attr "type" "vecperm")])
1218 ;; Optimize extracting element 0 from memory
1219 (define_insn "*vsx_extract_<mode>_zero"
1220 [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,d,?wa")
1221 (vec_select:<VS_scalar>
1222 (match_operand:VSX_D 1 "indexed_or_indirect_operand" "Z,Z,Z")
1223 (parallel [(const_int 0)])))]
1224 "VECTOR_MEM_VSX_P (<MODE>mode) && WORDS_BIG_ENDIAN"
1226 [(set_attr "type" "fpload")
1227 (set_attr "length" "4")])
1229 ;; General double word oriented permute, allow the other vector types for
1230 ;; optimizing the permute instruction.
1231 (define_insn "vsx_xxpermdi_<mode>"
1232 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=wd,?wa")
1233 (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "wd,wa")
1234 (match_operand:VSX_L 2 "vsx_register_operand" "wd,wa")
1235 (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
1236 UNSPEC_VSX_XXPERMDI))]
1237 "VECTOR_MEM_VSX_P (<MODE>mode)"
1238 "xxpermdi %x0,%x1,%x2,%3"
1239 [(set_attr "type" "vecperm")])
1241 ;; Varient of xxpermdi that is emitted by the vec_interleave functions
1242 (define_insn "*vsx_xxpermdi2_<mode>"
1243 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd")
1245 (vec_select:<VS_scalar>
1246 (match_operand:VSX_D 1 "vsx_register_operand" "wd")
1248 [(match_operand:QI 2 "u5bit_cint_operand" "i")]))
1249 (vec_select:<VS_scalar>
1250 (match_operand:VSX_D 3 "vsx_register_operand" "wd")
1252 [(match_operand:QI 4 "u5bit_cint_operand" "i")]))))]
1253 "VECTOR_MEM_VSX_P (<MODE>mode)"
1255 gcc_assert ((UINTVAL (operands[2]) <= 1) && (UINTVAL (operands[4]) <= 1));
1256 operands[5] = GEN_INT (((INTVAL (operands[2]) & 1) << 1)
1257 | (INTVAL (operands[4]) & 1));
1258 return \"xxpermdi %x0,%x1,%x3,%5\";
1260 [(set_attr "type" "vecperm")])
1263 (define_insn "vsx_splat_<mode>"
1264 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,wd,wd,?wa,?wa,?wa")
1265 (vec_duplicate:VSX_D
1266 (match_operand:<VS_scalar> 1 "input_operand" "ws,f,Z,wa,wa,Z")))]
1267 "VECTOR_MEM_VSX_P (<MODE>mode)"
1269 xxpermdi %x0,%x1,%x1,0
1270 xxpermdi %x0,%x1,%x1,0
1272 xxpermdi %x0,%x1,%x1,0
1273 xxpermdi %x0,%x1,%x1,0
1275 [(set_attr "type" "vecperm,vecperm,vecload,vecperm,vecperm,vecload")])
1278 (define_insn "vsx_xxspltw_<mode>"
1279 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1280 (vec_duplicate:VSX_W
1281 (vec_select:<VS_scalar>
1282 (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1284 [(match_operand:QI 2 "u5bit_cint_operand" "i,i")]))))]
1285 "VECTOR_MEM_VSX_P (<MODE>mode)"
1286 "xxspltw %x0,%x1,%2"
1287 [(set_attr "type" "vecperm")])
1289 ;; V4SF/V4SI interleave
1290 (define_insn "vsx_xxmrghw_<mode>"
1291 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1294 (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1295 (parallel [(const_int 0)
1300 (match_operand:VSX_W 2 "vsx_register_operand" "wf,wa")
1301 (parallel [(const_int 2)
1306 "VECTOR_MEM_VSX_P (<MODE>mode)"
1307 "xxmrghw %x0,%x1,%x2"
1308 [(set_attr "type" "vecperm")])
1310 (define_insn "vsx_xxmrglw_<mode>"
1311 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1314 (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1315 (parallel [(const_int 2)
1320 (match_operand:VSX_W 2 "vsx_register_operand" "wf,?wa")
1321 (parallel [(const_int 0)
1326 "VECTOR_MEM_VSX_P (<MODE>mode)"
1327 "xxmrglw %x0,%x1,%x2"
1328 [(set_attr "type" "vecperm")])
1330 ;; Shift left double by word immediate
1331 (define_insn "vsx_xxsldwi_<mode>"
1332 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=wa")
1333 (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "wa")
1334 (match_operand:VSX_L 2 "vsx_register_operand" "wa")
1335 (match_operand:QI 3 "u5bit_cint_operand" "i")]
1337 "VECTOR_MEM_VSX_P (<MODE>mode)"
1338 "xxsldwi %x0,%x1,%x2,%3"
1339 [(set_attr "type" "vecperm")])