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 ;; Map into the appropriate load/store name based on the type
42 (define_mode_attr VSm [(V16QI "vw4")
51 ;; Map into the appropriate suffix based on the type
52 (define_mode_attr VSs [(V16QI "sp")
62 ;; Map the register class used
63 (define_mode_attr VSr [(V16QI "v")
73 ;; Map the register class used for float<->int conversions
74 (define_mode_attr VSr2 [(V2DF "wd")
78 (define_mode_attr VSr3 [(V2DF "wa")
82 ;; Map the register class for sp<->dp float conversions, destination
83 (define_mode_attr VSr4 [(SF "ws")
88 ;; Map the register class for sp<->dp float conversions, destination
89 (define_mode_attr VSr5 [(SF "ws")
94 ;; Same size integer type for floating point data
95 (define_mode_attr VSi [(V4SF "v4si")
99 (define_mode_attr VSI [(V4SF "V4SI")
103 ;; Word size for same size conversion
104 (define_mode_attr VSc [(V4SF "w")
108 ;; Map into either s or v, depending on whether this is a scalar or vector
110 (define_mode_attr VSv [(V16QI "v")
119 ;; Appropriate type for add ops (and other simple FP ops)
120 (define_mode_attr VStype_simple [(V2DF "vecfloat")
124 (define_mode_attr VSfptype_simple [(V2DF "fp_addsub_d")
128 ;; Appropriate type for multiply ops
129 (define_mode_attr VStype_mul [(V2DF "vecfloat")
133 (define_mode_attr VSfptype_mul [(V2DF "fp_mul_d")
137 ;; Appropriate type for divide ops. For now, just lump the vector divide with
138 ;; the scalar divides
139 (define_mode_attr VStype_div [(V2DF "ddiv")
143 (define_mode_attr VSfptype_div [(V2DF "fp_div_d")
147 ;; Appropriate type for sqrt ops. For now, just lump the vector sqrt with
149 (define_mode_attr VStype_sqrt [(V2DF "dsqrt")
153 (define_mode_attr VSfptype_sqrt [(V2DF "fp_sqrt_d")
157 ;; Iterator and modes for sp<->dp conversions
158 ;; Because scalar SF values are represented internally as double, use the
159 ;; V4SF type to represent this than SF.
160 (define_mode_iterator VSX_SPDP [DF V4SF V2DF])
162 (define_mode_attr VS_spdp_res [(DF "V4SF")
166 (define_mode_attr VS_spdp_insn [(DF "xscvdpsp")
170 (define_mode_attr VS_spdp_type [(DF "fp")
174 ;; Map the scalar mode for a vector type
175 (define_mode_attr VS_scalar [(V2DF "DF")
182 ;; Constants for creating unspecs
184 [(UNSPEC_VSX_CONCAT 500)
185 (UNSPEC_VSX_CVDPSXWS 501)
186 (UNSPEC_VSX_CVDPUXWS 502)
187 (UNSPEC_VSX_CVSPDP 503)
188 (UNSPEC_VSX_CVSXWDP 504)
189 (UNSPEC_VSX_CVUXWDP 505)
190 (UNSPEC_VSX_CVSXDSP 506)
191 (UNSPEC_VSX_CVUXDSP 507)
192 (UNSPEC_VSX_CVSPSXDS 508)
193 (UNSPEC_VSX_CVSPUXDS 509)
194 (UNSPEC_VSX_MADD 510)
195 (UNSPEC_VSX_MSUB 511)
196 (UNSPEC_VSX_NMADD 512)
197 (UNSPEC_VSX_NMSUB 513)
199 (UNSPEC_VSX_TDIV 515)
200 (UNSPEC_VSX_TSQRT 516)
201 (UNSPEC_VSX_XXPERMDI 517)
203 (UNSPEC_VSX_ROUND_I 519)
204 (UNSPEC_VSX_ROUND_IC 520)
205 (UNSPEC_VSX_SLDWI 521)])
208 (define_insn "*vsx_mov<mode>"
209 [(set (match_operand:VSX_M 0 "nonimmediate_operand" "=Z,<VSr>,<VSr>,?Z,?wa,?wa,*o,*r,*r,<VSr>,?wa,v,wZ,v")
210 (match_operand:VSX_M 1 "input_operand" "<VSr>,Z,<VSr>,wa,Z,wa,r,o,r,j,j,W,v,wZ"))]
211 "VECTOR_MEM_VSX_P (<MODE>mode)
212 && (register_operand (operands[0], <MODE>mode)
213 || register_operand (operands[1], <MODE>mode))"
215 switch (which_alternative)
219 gcc_assert (MEM_P (operands[0])
220 && GET_CODE (XEXP (operands[0], 0)) != PRE_INC
221 && GET_CODE (XEXP (operands[0], 0)) != PRE_DEC
222 && GET_CODE (XEXP (operands[0], 0)) != PRE_MODIFY);
223 return "stx<VSm>x %x1,%y0";
227 gcc_assert (MEM_P (operands[1])
228 && GET_CODE (XEXP (operands[1], 0)) != PRE_INC
229 && GET_CODE (XEXP (operands[1], 0)) != PRE_DEC
230 && GET_CODE (XEXP (operands[1], 0)) != PRE_MODIFY);
231 return "lx<VSm>x %x0,%y1";
235 return "xxlor %x0,%x1,%x1";
244 return "xxlxor %x0,%x0,%x0";
247 return output_vec_const_move (operands);
250 gcc_assert (MEM_P (operands[0])
251 && GET_CODE (XEXP (operands[0], 0)) != PRE_INC
252 && GET_CODE (XEXP (operands[0], 0)) != PRE_DEC
253 && GET_CODE (XEXP (operands[0], 0)) != PRE_MODIFY);
254 return "stvx %1,%y0";
257 gcc_assert (MEM_P (operands[0])
258 && GET_CODE (XEXP (operands[0], 0)) != PRE_INC
259 && GET_CODE (XEXP (operands[0], 0)) != PRE_DEC
260 && GET_CODE (XEXP (operands[0], 0)) != PRE_MODIFY);
267 [(set_attr "type" "vecstore,vecload,vecsimple,vecstore,vecload,vecsimple,*,*,*,vecsimple,vecsimple,*,vecstore,vecload")])
269 ;; Unlike other VSX moves, allow the GPRs, since a normal use of TImode is for
270 ;; unions. However for plain data movement, slightly favor the vector loads
271 (define_insn "*vsx_movti"
272 [(set (match_operand:TI 0 "nonimmediate_operand" "=Z,wa,wa,?o,?r,?r,wa,v,v,wZ")
273 (match_operand:TI 1 "input_operand" "wa,Z,wa,r,o,r,j,W,wZ,v"))]
274 "VECTOR_MEM_VSX_P (TImode)
275 && (register_operand (operands[0], TImode)
276 || register_operand (operands[1], TImode))"
278 switch (which_alternative)
281 return "stxvd2x %x1,%y0";
284 return "lxvd2x %x0,%y1";
287 return "xxlor %x0,%x1,%x1";
295 return "xxlxor %x0,%x0,%x0";
298 return output_vec_const_move (operands);
301 return "stvx %1,%y0";
310 [(set_attr "type" "vecstore,vecload,vecsimple,*,*,*,vecsimple,*,vecstore,vecload")])
313 ;; VSX scalar and vector floating point arithmetic instructions
314 (define_insn "*vsx_add<mode>3"
315 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
316 (plus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
317 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
318 "VECTOR_UNIT_VSX_P (<MODE>mode)"
319 "x<VSv>add<VSs> %x0,%x1,%x2"
320 [(set_attr "type" "<VStype_simple>")
321 (set_attr "fp_type" "<VSfptype_simple>")])
323 (define_insn "*vsx_sub<mode>3"
324 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
325 (minus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
326 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
327 "VECTOR_UNIT_VSX_P (<MODE>mode)"
328 "x<VSv>sub<VSs> %x0,%x1,%x2"
329 [(set_attr "type" "<VStype_simple>")
330 (set_attr "fp_type" "<VSfptype_simple>")])
332 (define_insn "*vsx_mul<mode>3"
333 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
334 (mult:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
335 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
336 "VECTOR_UNIT_VSX_P (<MODE>mode)"
337 "x<VSv>mul<VSs> %x0,%x1,%x2"
338 [(set_attr "type" "<VStype_mul>")
339 (set_attr "fp_type" "<VSfptype_mul>")])
341 (define_insn "*vsx_div<mode>3"
342 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
343 (div:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
344 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
345 "VECTOR_UNIT_VSX_P (<MODE>mode)"
346 "x<VSv>div<VSs> %x0,%x1,%x2"
347 [(set_attr "type" "<VStype_div>")
348 (set_attr "fp_type" "<VSfptype_div>")])
350 ;; *tdiv* instruction returning the FG flag
351 (define_expand "vsx_tdiv<mode>3_fg"
353 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
354 (match_operand:VSX_B 2 "vsx_register_operand" "")]
356 (set (match_operand:SI 0 "gpc_reg_operand" "")
359 "VECTOR_UNIT_VSX_P (<MODE>mode)"
361 operands[3] = gen_reg_rtx (CCFPmode);
364 ;; *tdiv* instruction returning the FE flag
365 (define_expand "vsx_tdiv<mode>3_fe"
367 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
368 (match_operand:VSX_B 2 "vsx_register_operand" "")]
370 (set (match_operand:SI 0 "gpc_reg_operand" "")
373 "VECTOR_UNIT_VSX_P (<MODE>mode)"
375 operands[3] = gen_reg_rtx (CCFPmode);
378 (define_insn "*vsx_tdiv<mode>3_internal"
379 [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
380 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
381 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")]
383 "VECTOR_UNIT_VSX_P (<MODE>mode)"
384 "x<VSv>tdiv<VSs> %0,%x1,%x2"
385 [(set_attr "type" "<VStype_simple>")
386 (set_attr "fp_type" "<VSfptype_simple>")])
388 (define_insn "vsx_fre<mode>2"
389 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
390 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
392 "VECTOR_UNIT_VSX_P (<MODE>mode)"
393 "x<VSv>re<VSs> %x0,%x1"
394 [(set_attr "type" "<VStype_simple>")
395 (set_attr "fp_type" "<VSfptype_simple>")])
397 (define_insn "*vsx_neg<mode>2"
398 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
399 (neg:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
400 "VECTOR_UNIT_VSX_P (<MODE>mode)"
401 "x<VSv>neg<VSs> %x0,%x1"
402 [(set_attr "type" "<VStype_simple>")
403 (set_attr "fp_type" "<VSfptype_simple>")])
405 (define_insn "*vsx_abs<mode>2"
406 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
407 (abs:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
408 "VECTOR_UNIT_VSX_P (<MODE>mode)"
409 "x<VSv>abs<VSs> %x0,%x1"
410 [(set_attr "type" "<VStype_simple>")
411 (set_attr "fp_type" "<VSfptype_simple>")])
413 (define_insn "vsx_nabs<mode>2"
414 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
417 (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa"))))]
418 "VECTOR_UNIT_VSX_P (<MODE>mode)"
419 "x<VSv>nabs<VSs> %x0,%x1"
420 [(set_attr "type" "<VStype_simple>")
421 (set_attr "fp_type" "<VSfptype_simple>")])
423 (define_insn "vsx_smax<mode>3"
424 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
425 (smax:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
426 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
427 "VECTOR_UNIT_VSX_P (<MODE>mode)"
428 "x<VSv>max<VSs> %x0,%x1,%x2"
429 [(set_attr "type" "<VStype_simple>")
430 (set_attr "fp_type" "<VSfptype_simple>")])
432 (define_insn "*vsx_smin<mode>3"
433 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
434 (smin:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
435 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
436 "VECTOR_UNIT_VSX_P (<MODE>mode)"
437 "x<VSv>min<VSs> %x0,%x1,%x2"
438 [(set_attr "type" "<VStype_simple>")
439 (set_attr "fp_type" "<VSfptype_simple>")])
441 (define_insn "*vsx_sqrt<mode>2"
442 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
443 (sqrt:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
444 "VECTOR_UNIT_VSX_P (<MODE>mode)"
445 "x<VSv>sqrt<VSs> %x0,%x1"
446 [(set_attr "type" "<VStype_sqrt>")
447 (set_attr "fp_type" "<VSfptype_sqrt>")])
449 (define_insn "*vsx_rsqrte<mode>2"
450 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
451 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
453 "VECTOR_UNIT_VSX_P (<MODE>mode)"
454 "x<VSv>rsqrte<VSs> %x0,%x1"
455 [(set_attr "type" "<VStype_simple>")
456 (set_attr "fp_type" "<VSfptype_simple>")])
458 ;; *tsqrt* returning the fg flag
459 (define_expand "vsx_tsqrt<mode>2_fg"
461 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
463 (set (match_operand:SI 0 "gpc_reg_operand" "")
466 "VECTOR_UNIT_VSX_P (<MODE>mode)"
468 operands[3] = gen_reg_rtx (CCFPmode);
471 ;; *tsqrt* returning the fe flag
472 (define_expand "vsx_tsqrt<mode>2_fe"
474 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
476 (set (match_operand:SI 0 "gpc_reg_operand" "")
479 "VECTOR_UNIT_VSX_P (<MODE>mode)"
481 operands[3] = gen_reg_rtx (CCFPmode);
484 (define_insn "*vsx_tsqrt<mode>2_internal"
485 [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
486 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
488 "VECTOR_UNIT_VSX_P (<MODE>mode)"
489 "x<VSv>tsqrt<VSs> %0,%x1"
490 [(set_attr "type" "<VStype_simple>")
491 (set_attr "fp_type" "<VSfptype_simple>")])
493 ;; Fused vector multiply/add instructions
495 ;; Note we have a pattern for the multiply/add operations that uses unspec and
496 ;; does not check -mfused-madd to allow users to use these ops when they know
497 ;; they want the fused multiply/add.
499 (define_expand "vsx_fmadd<mode>4"
500 [(set (match_operand:VSX_B 0 "vsx_register_operand" "")
503 (match_operand:VSX_B 1 "vsx_register_operand" "")
504 (match_operand:VSX_B 2 "vsx_register_operand" ""))
505 (match_operand:VSX_B 3 "vsx_register_operand" "")))]
506 "VECTOR_UNIT_VSX_P (<MODE>mode)"
508 if (!TARGET_FUSED_MADD)
510 emit_insn (gen_vsx_fmadd<mode>4_2 (operands[0], operands[1], operands[2],
516 (define_insn "*vsx_fmadd<mode>4_1"
517 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
520 (match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
521 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0"))
522 (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")))]
523 "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD"
525 x<VSv>madda<VSs> %x0,%x1,%x2
526 x<VSv>maddm<VSs> %x0,%x1,%x3
527 x<VSv>madda<VSs> %x0,%x1,%x2
528 x<VSv>maddm<VSs> %x0,%x1,%x3"
529 [(set_attr "type" "<VStype_mul>")
530 (set_attr "fp_type" "<VSfptype_mul>")])
532 (define_insn "vsx_fmadd<mode>4_2"
533 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
534 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
535 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
536 (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")]
538 "VECTOR_UNIT_VSX_P (<MODE>mode)"
540 x<VSv>madda<VSs> %x0,%x1,%x2
541 x<VSv>maddm<VSs> %x0,%x1,%x3
542 x<VSv>madda<VSs> %x0,%x1,%x2
543 x<VSv>maddm<VSs> %x0,%x1,%x3"
544 [(set_attr "type" "<VStype_mul>")
545 (set_attr "fp_type" "<VSfptype_mul>")])
547 (define_expand "vsx_fmsub<mode>4"
548 [(set (match_operand:VSX_B 0 "vsx_register_operand" "")
551 (match_operand:VSX_B 1 "vsx_register_operand" "")
552 (match_operand:VSX_B 2 "vsx_register_operand" ""))
553 (match_operand:VSX_B 3 "vsx_register_operand" "")))]
554 "VECTOR_UNIT_VSX_P (<MODE>mode)"
556 if (!TARGET_FUSED_MADD)
558 emit_insn (gen_vsx_fmsub<mode>4_2 (operands[0], operands[1], operands[2],
564 (define_insn "*vsx_fmsub<mode>4_1"
565 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
568 (match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
569 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0"))
570 (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")))]
571 "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD"
573 x<VSv>msuba<VSs> %x0,%x1,%x2
574 x<VSv>msubm<VSs> %x0,%x1,%x3
575 x<VSv>msuba<VSs> %x0,%x1,%x2
576 x<VSv>msubm<VSs> %x0,%x1,%x3"
577 [(set_attr "type" "<VStype_mul>")
578 (set_attr "fp_type" "<VSfptype_mul>")])
580 (define_insn "vsx_fmsub<mode>4_2"
581 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
582 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
583 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
584 (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")]
586 "VECTOR_UNIT_VSX_P (<MODE>mode)"
588 x<VSv>msuba<VSs> %x0,%x1,%x2
589 x<VSv>msubm<VSs> %x0,%x1,%x3
590 x<VSv>msuba<VSs> %x0,%x1,%x2
591 x<VSv>msubm<VSs> %x0,%x1,%x3"
592 [(set_attr "type" "<VStype_mul>")
593 (set_attr "fp_type" "<VSfptype_mul>")])
595 (define_expand "vsx_fnmadd<mode>4"
596 [(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 && HONOR_SIGNED_ZEROS (DFmode))
604 emit_insn (gen_vsx_fnmadd<mode>4_1 (operands[0], operands[1],
605 operands[2], operands[3]));
608 else if (TARGET_FUSED_MADD && !HONOR_SIGNED_ZEROS (DFmode))
610 emit_insn (gen_vsx_fnmadd<mode>4_2 (operands[0], operands[1],
611 operands[2], operands[3]));
616 emit_insn (gen_vsx_fnmadd<mode>4_3 (operands[0], operands[1],
617 operands[2], operands[3]));
622 (define_insn "vsx_fnmadd<mode>4_1"
623 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
627 (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSr>,wa,wa")
628 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0"))
629 (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
630 "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD
631 && HONOR_SIGNED_ZEROS (DFmode)"
633 x<VSv>nmadda<VSs> %x0,%x1,%x2
634 x<VSv>nmaddm<VSs> %x0,%x1,%x3
635 x<VSv>nmadda<VSs> %x0,%x1,%x2
636 x<VSv>nmaddm<VSs> %x0,%x1,%x3"
637 [(set_attr "type" "<VStype_mul>")
638 (set_attr "fp_type" "<VSfptype_mul>")])
640 (define_insn "vsx_fnmadd<mode>4_2"
641 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
645 (match_operand:VSX_B 1 "gpc_reg_operand" "<VSr>,<VSr>,wa,wa"))
646 (match_operand:VSX_B 2 "gpc_reg_operand" "<VSr>,0,wa,0"))
647 (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")))]
648 "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD
649 && !HONOR_SIGNED_ZEROS (DFmode)"
651 x<VSv>nmadda<VSs> %x0,%x1,%x2
652 x<VSv>nmaddm<VSs> %x0,%x1,%x3
653 x<VSv>nmadda<VSs> %x0,%x1,%x2
654 x<VSv>nmaddm<VSs> %x0,%x1,%x3"
655 [(set_attr "type" "<VStype_mul>")
656 (set_attr "fp_type" "<VSfptype_mul>")])
658 (define_insn "vsx_fnmadd<mode>4_3"
659 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
660 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSr>,wa,wa")
661 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
662 (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")]
664 "VECTOR_UNIT_VSX_P (<MODE>mode)"
666 x<VSv>nmadda<VSs> %x0,%x1,%x2
667 x<VSv>nmaddm<VSs> %x0,%x1,%x3
668 x<VSv>nmadda<VSs> %x0,%x1,%x2
669 x<VSv>nmaddm<VSs> %x0,%x1,%x3"
670 [(set_attr "type" "<VStype_mul>")
671 (set_attr "fp_type" "<VSfptype_mul>")])
673 (define_expand "vsx_fnmsub<mode>4"
674 [(match_operand:VSX_B 0 "vsx_register_operand" "")
675 (match_operand:VSX_B 1 "vsx_register_operand" "")
676 (match_operand:VSX_B 2 "vsx_register_operand" "")
677 (match_operand:VSX_B 3 "vsx_register_operand" "")]
678 "VECTOR_UNIT_VSX_P (<MODE>mode)"
680 if (TARGET_FUSED_MADD && HONOR_SIGNED_ZEROS (DFmode))
682 emit_insn (gen_vsx_fnmsub<mode>4_1 (operands[0], operands[1],
683 operands[2], operands[3]));
686 else if (TARGET_FUSED_MADD && !HONOR_SIGNED_ZEROS (DFmode))
688 emit_insn (gen_vsx_fnmsub<mode>4_2 (operands[0], operands[1],
689 operands[2], operands[3]));
694 emit_insn (gen_vsx_fnmsub<mode>4_3 (operands[0], operands[1],
695 operands[2], operands[3]));
700 (define_insn "vsx_fnmsub<mode>4_1"
701 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
705 (match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
706 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0"))
707 (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
708 "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD
709 && HONOR_SIGNED_ZEROS (DFmode)"
711 x<VSv>nmsuba<VSs> %x0,%x1,%x2
712 x<VSv>nmsubm<VSs> %x0,%x1,%x3
713 x<VSv>nmsuba<VSs> %x0,%x1,%x2
714 x<VSv>nmsubm<VSs> %x0,%x1,%x3"
715 [(set_attr "type" "<VStype_mul>")
716 (set_attr "fp_type" "<VSfptype_mul>")])
718 (define_insn "vsx_fnmsub<mode>4_2"
719 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
721 (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")
723 (match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
724 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0"))))]
725 "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD
726 && !HONOR_SIGNED_ZEROS (DFmode)"
728 x<VSv>nmsuba<VSs> %x0,%x1,%x2
729 x<VSv>nmsubm<VSs> %x0,%x1,%x3
730 x<VSv>nmsuba<VSs> %x0,%x1,%x2
731 x<VSv>nmsubm<VSs> %x0,%x1,%x3"
732 [(set_attr "type" "<VStype_mul>")
733 (set_attr "fp_type" "<VSfptype_mul>")])
735 (define_insn "vsx_fnmsub<mode>4_3"
736 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
737 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
738 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
739 (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")]
741 "VECTOR_UNIT_VSX_P (<MODE>mode)"
743 x<VSv>nmsuba<VSs> %x0,%x1,%x2
744 x<VSv>nmsubm<VSs> %x0,%x1,%x3
745 x<VSv>nmsuba<VSs> %x0,%x1,%x2
746 x<VSv>nmsubm<VSs> %x0,%x1,%x3"
747 [(set_attr "type" "<VStype_mul>")
748 (set_attr "fp_type" "<VSfptype_mul>")])
750 ;; Vector conditional expressions (no scalar version for these instructions)
751 (define_insn "vsx_eq<mode>"
752 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
753 (eq:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
754 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
755 "VECTOR_UNIT_VSX_P (<MODE>mode)"
756 "xvcmpeq<VSs> %x0,%x1,%x2"
757 [(set_attr "type" "<VStype_simple>")
758 (set_attr "fp_type" "<VSfptype_simple>")])
760 (define_insn "vsx_gt<mode>"
761 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
762 (gt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
763 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
764 "VECTOR_UNIT_VSX_P (<MODE>mode)"
765 "xvcmpgt<VSs> %x0,%x1,%x2"
766 [(set_attr "type" "<VStype_simple>")
767 (set_attr "fp_type" "<VSfptype_simple>")])
769 (define_insn "*vsx_ge<mode>"
770 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
771 (ge:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
772 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
773 "VECTOR_UNIT_VSX_P (<MODE>mode)"
774 "xvcmpge<VSs> %x0,%x1,%x2"
775 [(set_attr "type" "<VStype_simple>")
776 (set_attr "fp_type" "<VSfptype_simple>")])
778 ;; Floating point scalar compare
779 (define_insn "*vsx_cmpdf_internal1"
780 [(set (match_operand:CCFP 0 "cc_reg_operand" "=y,?y")
781 (compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "ws,wa")
782 (match_operand:DF 2 "gpc_reg_operand" "ws,wa")))]
783 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
784 && VECTOR_UNIT_VSX_P (DFmode)"
785 "xscmpudp %0,%x1,%x2"
786 [(set_attr "type" "fpcompare")])
788 ;; Compare vectors producing a vector result and a predicate, setting CR6 to
789 ;; indicate a combined status
790 (define_insn "*vsx_eq_<mode>_p"
793 [(eq:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
794 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
796 (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
797 (eq:VSX_F (match_dup 1)
799 "VECTOR_UNIT_VSX_P (<MODE>mode)"
800 "xvcmpeq<VSs>. %x0,%x1,%x2"
801 [(set_attr "type" "veccmp")])
803 (define_insn "*vsx_gt_<mode>_p"
806 [(gt:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
807 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
809 (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
810 (gt:VSX_F (match_dup 1)
812 "VECTOR_UNIT_VSX_P (<MODE>mode)"
813 "xvcmpgt<VSs>. %x0,%x1,%x2"
814 [(set_attr "type" "veccmp")])
816 (define_insn "*vsx_ge_<mode>_p"
819 [(ge:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
820 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
822 (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
823 (ge:VSX_F (match_dup 1)
825 "VECTOR_UNIT_VSX_P (<MODE>mode)"
826 "xvcmpge<VSs>. %x0,%x1,%x2"
827 [(set_attr "type" "veccmp")])
830 (define_insn "*vsx_xxsel<mode>"
831 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
833 (ne:CC (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
835 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
836 (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
837 "VECTOR_MEM_VSX_P (<MODE>mode)"
838 "xxsel %x0,%x3,%x2,%x1"
839 [(set_attr "type" "vecperm")])
841 (define_insn "*vsx_xxsel<mode>_uns"
842 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
844 (ne:CCUNS (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
846 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
847 (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
848 "VECTOR_MEM_VSX_P (<MODE>mode)"
849 "xxsel %x0,%x3,%x2,%x1"
850 [(set_attr "type" "vecperm")])
853 (define_insn "vsx_copysign<mode>3"
854 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
856 [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
857 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")]
859 "VECTOR_UNIT_VSX_P (<MODE>mode)"
860 "x<VSv>cpsgn<VSs> %x0,%x2,%x1"
861 [(set_attr "type" "<VStype_simple>")
862 (set_attr "fp_type" "<VSfptype_simple>")])
864 ;; For the conversions, limit the register class for the integer value to be
865 ;; the fprs because we don't want to add the altivec registers to movdi/movsi.
866 ;; For the unsigned tests, there isn't a generic double -> unsigned conversion
867 ;; in rs6000.md so don't test VECTOR_UNIT_VSX_P, just test against VSX.
868 (define_insn "vsx_float<VSi><mode>2"
869 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
870 (float:VSX_B (match_operand:<VSI> 1 "vsx_register_operand" "<VSr2>,<VSr3>")))]
871 "VECTOR_UNIT_VSX_P (<MODE>mode)"
872 "x<VSv>cvsx<VSc><VSs> %x0,%x1"
873 [(set_attr "type" "<VStype_simple>")
874 (set_attr "fp_type" "<VSfptype_simple>")])
876 (define_insn "vsx_floatuns<VSi><mode>2"
877 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
878 (unsigned_float:VSX_B (match_operand:<VSI> 1 "vsx_register_operand" "<VSr2>,<VSr3>")))]
879 "VECTOR_UNIT_VSX_P (<MODE>mode)"
880 "x<VSv>cvux<VSc><VSs> %x0,%x1"
881 [(set_attr "type" "<VStype_simple>")
882 (set_attr "fp_type" "<VSfptype_simple>")])
884 (define_insn "vsx_fix_trunc<mode><VSi>2"
885 [(set (match_operand:<VSI> 0 "vsx_register_operand" "=<VSr2>,?<VSr3>")
886 (fix:<VSI> (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
887 "VECTOR_UNIT_VSX_P (<MODE>mode)"
888 "x<VSv>cv<VSs>sx<VSc>s %x0,%x1"
889 [(set_attr "type" "<VStype_simple>")
890 (set_attr "fp_type" "<VSfptype_simple>")])
892 (define_insn "vsx_fixuns_trunc<mode><VSi>2"
893 [(set (match_operand:<VSI> 0 "vsx_register_operand" "=<VSr2>,?<VSr3>")
894 (unsigned_fix:<VSI> (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
895 "VECTOR_UNIT_VSX_P (<MODE>mode)"
896 "x<VSv>cv<VSs>ux<VSc>s %x0,%x1"
897 [(set_attr "type" "<VStype_simple>")
898 (set_attr "fp_type" "<VSfptype_simple>")])
900 ;; Math rounding functions
901 (define_insn "vsx_x<VSv>r<VSs>i"
902 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
903 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
904 UNSPEC_VSX_ROUND_I))]
905 "VECTOR_UNIT_VSX_P (<MODE>mode)"
906 "x<VSv>r<VSs>i %x0,%x1"
907 [(set_attr "type" "<VStype_simple>")
908 (set_attr "fp_type" "<VSfptype_simple>")])
910 (define_insn "vsx_x<VSv>r<VSs>ic"
911 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
912 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
913 UNSPEC_VSX_ROUND_IC))]
914 "VECTOR_UNIT_VSX_P (<MODE>mode)"
915 "x<VSv>r<VSs>ic %x0,%x1"
916 [(set_attr "type" "<VStype_simple>")
917 (set_attr "fp_type" "<VSfptype_simple>")])
919 (define_insn "vsx_btrunc<mode>2"
920 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
921 (fix:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
922 "VECTOR_UNIT_VSX_P (<MODE>mode)"
923 "x<VSv>r<VSs>iz %x0,%x1"
924 [(set_attr "type" "<VStype_simple>")
925 (set_attr "fp_type" "<VSfptype_simple>")])
927 (define_insn "*vsx_b2trunc<mode>2"
928 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
929 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
931 "VECTOR_UNIT_VSX_P (<MODE>mode)"
932 "x<VSv>r<VSs>iz %x0,%x1"
933 [(set_attr "type" "<VStype_simple>")
934 (set_attr "fp_type" "<VSfptype_simple>")])
936 (define_insn "vsx_floor<mode>2"
937 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
938 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
940 "VECTOR_UNIT_VSX_P (<MODE>mode)"
941 "x<VSv>r<VSs>im %x0,%x1"
942 [(set_attr "type" "<VStype_simple>")
943 (set_attr "fp_type" "<VSfptype_simple>")])
945 (define_insn "vsx_ceil<mode>2"
946 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
947 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
949 "VECTOR_UNIT_VSX_P (<MODE>mode)"
950 "x<VSv>r<VSs>ip %x0,%x1"
951 [(set_attr "type" "<VStype_simple>")
952 (set_attr "fp_type" "<VSfptype_simple>")])
955 ;; VSX convert to/from double vector
957 ;; Convert between single and double precision
958 ;; Don't use xscvspdp and xscvdpsp for scalar conversions, since the normal
959 ;; scalar single precision instructions internally use the double format.
960 ;; Prefer the altivec registers, since we likely will need to do a vperm
961 (define_insn "vsx_<VS_spdp_insn>"
962 [(set (match_operand:<VS_spdp_res> 0 "vsx_register_operand" "=<VSr4>,?wa")
963 (unspec:<VS_spdp_res> [(match_operand:VSX_SPDP 1 "vsx_register_operand" "<VSr5>,wa")]
965 "VECTOR_UNIT_VSX_P (<MODE>mode)"
966 "<VS_spdp_insn> %x0,%x1"
967 [(set_attr "type" "<VS_spdp_type>")])
969 ;; xscvspdp, represent the scalar SF type as V4SF
970 (define_insn "vsx_xscvspdp"
971 [(set (match_operand:DF 0 "vsx_register_operand" "=ws,?wa")
972 (unspec:DF [(match_operand:V4SF 1 "vsx_register_operand" "wa,wa")]
974 "VECTOR_UNIT_VSX_P (DFmode)"
976 [(set_attr "type" "fp")])
978 ;; xscvdpsp used for splat'ing a scalar to V4SF, knowing that the internal SF
979 ;; format of scalars is actually DF.
980 (define_insn "vsx_xscvdpsp_scalar"
981 [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
982 (unspec:V4SF [(match_operand:SF 1 "vsx_register_operand" "f")]
984 "VECTOR_UNIT_VSX_P (DFmode)"
986 [(set_attr "type" "fp")])
988 ;; Convert from 64-bit to 32-bit types
989 ;; Note, favor the Altivec registers since the usual use of these instructions
990 ;; is in vector converts and we need to use the Altivec vperm instruction.
992 (define_insn "vsx_xvcvdpsxws"
993 [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
994 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
995 UNSPEC_VSX_CVDPSXWS))]
996 "VECTOR_UNIT_VSX_P (V2DFmode)"
998 [(set_attr "type" "vecfloat")])
1000 (define_insn "vsx_xvcvdpuxws"
1001 [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
1002 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
1003 UNSPEC_VSX_CVDPUXWS))]
1004 "VECTOR_UNIT_VSX_P (V2DFmode)"
1005 "xvcvdpuxws %x0,%x1"
1006 [(set_attr "type" "vecfloat")])
1008 (define_insn "vsx_xvcvsxdsp"
1009 [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
1010 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
1011 UNSPEC_VSX_CVSXDSP))]
1012 "VECTOR_UNIT_VSX_P (V2DFmode)"
1014 [(set_attr "type" "vecfloat")])
1016 (define_insn "vsx_xvcvuxdsp"
1017 [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
1018 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
1019 UNSPEC_VSX_CVUXDSP))]
1020 "VECTOR_UNIT_VSX_P (V2DFmode)"
1022 [(set_attr "type" "vecfloat")])
1024 ;; Convert from 32-bit to 64-bit types
1025 (define_insn "vsx_xvcvsxwdp"
1026 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1027 (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
1028 UNSPEC_VSX_CVSXWDP))]
1029 "VECTOR_UNIT_VSX_P (V2DFmode)"
1031 [(set_attr "type" "vecfloat")])
1033 (define_insn "vsx_xvcvuxwdp"
1034 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1035 (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
1036 UNSPEC_VSX_CVUXWDP))]
1037 "VECTOR_UNIT_VSX_P (V2DFmode)"
1039 [(set_attr "type" "vecfloat")])
1041 (define_insn "vsx_xvcvspsxds"
1042 [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
1043 (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
1044 UNSPEC_VSX_CVSPSXDS))]
1045 "VECTOR_UNIT_VSX_P (V2DFmode)"
1046 "xvcvspsxds %x0,%x1"
1047 [(set_attr "type" "vecfloat")])
1049 (define_insn "vsx_xvcvspuxds"
1050 [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
1051 (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
1052 UNSPEC_VSX_CVSPUXDS))]
1053 "VECTOR_UNIT_VSX_P (V2DFmode)"
1054 "xvcvspuxds %x0,%x1"
1055 [(set_attr "type" "vecfloat")])
1057 ;; Logical and permute operations
1058 (define_insn "*vsx_and<mode>3"
1059 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1061 (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
1062 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
1063 "VECTOR_MEM_VSX_P (<MODE>mode)"
1064 "xxland %x0,%x1,%x2"
1065 [(set_attr "type" "vecsimple")])
1067 (define_insn "*vsx_ior<mode>3"
1068 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1069 (ior:VSX_L (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
1070 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
1071 "VECTOR_MEM_VSX_P (<MODE>mode)"
1073 [(set_attr "type" "vecsimple")])
1075 (define_insn "*vsx_xor<mode>3"
1076 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1078 (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
1079 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
1080 "VECTOR_MEM_VSX_P (<MODE>mode)"
1081 "xxlxor %x0,%x1,%x2"
1082 [(set_attr "type" "vecsimple")])
1084 (define_insn "*vsx_one_cmpl<mode>2"
1085 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1087 (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")))]
1088 "VECTOR_MEM_VSX_P (<MODE>mode)"
1089 "xxlnor %x0,%x1,%x1"
1090 [(set_attr "type" "vecsimple")])
1092 (define_insn "*vsx_nor<mode>3"
1093 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1096 (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
1097 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa"))))]
1098 "VECTOR_MEM_VSX_P (<MODE>mode)"
1099 "xxlnor %x0,%x1,%x2"
1100 [(set_attr "type" "vecsimple")])
1102 (define_insn "*vsx_andc<mode>3"
1103 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1106 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa"))
1107 (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")))]
1108 "VECTOR_MEM_VSX_P (<MODE>mode)"
1109 "xxlandc %x0,%x1,%x2"
1110 [(set_attr "type" "vecsimple")])
1113 ;; Permute operations
1115 ;; Build a V2DF/V2DI vector from two scalars
1116 (define_insn "vsx_concat_<mode>"
1117 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
1119 [(match_operand:<VS_scalar> 1 "vsx_register_operand" "ws,wa")
1120 (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")]
1121 UNSPEC_VSX_CONCAT))]
1122 "VECTOR_MEM_VSX_P (<MODE>mode)"
1123 "xxpermdi %x0,%x1,%x2,0"
1124 [(set_attr "type" "vecperm")])
1126 ;; Special purpose concat using xxpermdi to glue two single precision values
1127 ;; together, relying on the fact that internally scalar floats are represented
1128 ;; as doubles. This is used to initialize a V4SF vector with 4 floats
1129 (define_insn "vsx_concat_v2sf"
1130 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1132 [(match_operand:SF 1 "vsx_register_operand" "f,f")
1133 (match_operand:SF 2 "vsx_register_operand" "f,f")]
1134 UNSPEC_VSX_CONCAT))]
1135 "VECTOR_MEM_VSX_P (V2DFmode)"
1136 "xxpermdi %x0,%x1,%x2,0"
1137 [(set_attr "type" "vecperm")])
1139 ;; Set the element of a V2DI/VD2F mode
1140 (define_insn "vsx_set_<mode>"
1141 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
1142 (unspec:VSX_D [(match_operand:VSX_D 1 "vsx_register_operand" "wd,wa")
1143 (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")
1144 (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
1146 "VECTOR_MEM_VSX_P (<MODE>mode)"
1148 if (INTVAL (operands[3]) == 0)
1149 return \"xxpermdi %x0,%x1,%x2,1\";
1150 else if (INTVAL (operands[3]) == 1)
1151 return \"xxpermdi %x0,%x2,%x1,0\";
1155 [(set_attr "type" "vecperm")])
1157 ;; Extract a DF/DI element from V2DF/V2DI
1158 (define_insn "vsx_extract_<mode>"
1159 [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,d,?wa")
1160 (vec_select:<VS_scalar> (match_operand:VSX_D 1 "vsx_register_operand" "wd,wd,wa")
1162 [(match_operand:QI 2 "u5bit_cint_operand" "i,i,i")])))]
1163 "VECTOR_MEM_VSX_P (<MODE>mode)"
1165 gcc_assert (UINTVAL (operands[2]) <= 1);
1166 operands[3] = GEN_INT (INTVAL (operands[2]) << 1);
1167 return \"xxpermdi %x0,%x1,%x1,%3\";
1169 [(set_attr "type" "vecperm")])
1171 ;; Optimize extracting element 0 from memory
1172 (define_insn "*vsx_extract_<mode>_zero"
1173 [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,d,?wa")
1174 (vec_select:<VS_scalar>
1175 (match_operand:VSX_D 1 "indexed_or_indirect_operand" "Z,Z,Z")
1176 (parallel [(const_int 0)])))]
1177 "VECTOR_MEM_VSX_P (<MODE>mode) && WORDS_BIG_ENDIAN"
1179 [(set_attr "type" "fpload")
1180 (set_attr "length" "4")])
1182 ;; General double word oriented permute, allow the other vector types for
1183 ;; optimizing the permute instruction.
1184 (define_insn "vsx_xxpermdi_<mode>"
1185 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=wd,?wa")
1186 (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "wd,wa")
1187 (match_operand:VSX_L 2 "vsx_register_operand" "wd,wa")
1188 (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
1189 UNSPEC_VSX_XXPERMDI))]
1190 "VECTOR_MEM_VSX_P (<MODE>mode)"
1191 "xxpermdi %x0,%x1,%x2,%3"
1192 [(set_attr "type" "vecperm")])
1194 ;; Varient of xxpermdi that is emitted by the vec_interleave functions
1195 (define_insn "*vsx_xxpermdi2_<mode>"
1196 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd")
1198 (vec_select:<VS_scalar>
1199 (match_operand:VSX_D 1 "vsx_register_operand" "wd")
1201 [(match_operand:QI 2 "u5bit_cint_operand" "i")]))
1202 (vec_select:<VS_scalar>
1203 (match_operand:VSX_D 3 "vsx_register_operand" "wd")
1205 [(match_operand:QI 4 "u5bit_cint_operand" "i")]))))]
1206 "VECTOR_MEM_VSX_P (<MODE>mode)"
1208 gcc_assert ((UINTVAL (operands[2]) <= 1) && (UINTVAL (operands[4]) <= 1));
1209 operands[5] = GEN_INT (((INTVAL (operands[2]) & 1) << 1)
1210 | (INTVAL (operands[4]) & 1));
1211 return \"xxpermdi %x0,%x1,%x3,%5\";
1213 [(set_attr "type" "vecperm")])
1216 (define_insn "vsx_splat_<mode>"
1217 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,wd,wd,?wa,?wa,?wa")
1218 (vec_duplicate:VSX_D
1219 (match_operand:<VS_scalar> 1 "input_operand" "ws,f,Z,wa,wa,Z")))]
1220 "VECTOR_MEM_VSX_P (<MODE>mode)"
1222 xxpermdi %x0,%x1,%x1,0
1223 xxpermdi %x0,%x1,%x1,0
1225 xxpermdi %x0,%x1,%x1,0
1226 xxpermdi %x0,%x1,%x1,0
1228 [(set_attr "type" "vecperm,vecperm,vecload,vecperm,vecperm,vecload")])
1231 (define_insn "vsx_xxspltw_<mode>"
1232 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1233 (vec_duplicate:VSX_W
1234 (vec_select:<VS_scalar>
1235 (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1237 [(match_operand:QI 2 "u5bit_cint_operand" "i,i")]))))]
1238 "VECTOR_MEM_VSX_P (<MODE>mode)"
1239 "xxspltw %x0,%x1,%2"
1240 [(set_attr "type" "vecperm")])
1242 ;; V4SF/V4SI interleave
1243 (define_insn "vsx_xxmrghw_<mode>"
1244 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1247 (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1248 (parallel [(const_int 0)
1253 (match_operand:VSX_W 2 "vsx_register_operand" "wf,wa")
1254 (parallel [(const_int 2)
1259 "VECTOR_MEM_VSX_P (<MODE>mode)"
1260 "xxmrghw %x0,%x1,%x2"
1261 [(set_attr "type" "vecperm")])
1263 (define_insn "vsx_xxmrglw_<mode>"
1264 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1267 (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1268 (parallel [(const_int 2)
1273 (match_operand:VSX_W 2 "vsx_register_operand" "wf,?wa")
1274 (parallel [(const_int 0)
1279 "VECTOR_MEM_VSX_P (<MODE>mode)"
1280 "xxmrglw %x0,%x1,%x2"
1281 [(set_attr "type" "vecperm")])
1283 ;; Shift left double by word immediate
1284 (define_insn "vsx_xxsldwi_<mode>"
1285 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=wa")
1286 (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "wa")
1287 (match_operand:VSX_L 2 "vsx_register_operand" "wa")
1288 (match_operand:QI 3 "u5bit_cint_operand" "i")]
1290 "VECTOR_MEM_VSX_P (<MODE>mode)"
1291 "xxsldwi %x0,%x1,%x2,%3"
1292 [(set_attr "type" "vecperm")])