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)
198 (UNSPEC_VSX_RSQRTE 514)
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 (ge:VSX_B (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")
857 (match_operand:VSX_B 3 "zero_constant" "j,j"))
858 (abs:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa"))
859 (neg:VSX_B (abs:VSX_B (match_dup 1)))))]
860 "VECTOR_UNIT_VSX_P (<MODE>mode)"
861 "x<VSv>cpsgn<VSs> %x0,%x2,%x1"
862 [(set_attr "type" "<VStype_simple>")
863 (set_attr "fp_type" "<VSfptype_simple>")])
865 ;; For the conversions, limit the register class for the integer value to be
866 ;; the fprs because we don't want to add the altivec registers to movdi/movsi.
867 ;; For the unsigned tests, there isn't a generic double -> unsigned conversion
868 ;; in rs6000.md so don't test VECTOR_UNIT_VSX_P, just test against VSX.
869 (define_insn "vsx_float<VSi><mode>2"
870 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
871 (float:VSX_B (match_operand:<VSI> 1 "vsx_register_operand" "<VSr2>,<VSr3>")))]
872 "VECTOR_UNIT_VSX_P (<MODE>mode)"
873 "x<VSv>cvsx<VSc><VSs> %x0,%x1"
874 [(set_attr "type" "<VStype_simple>")
875 (set_attr "fp_type" "<VSfptype_simple>")])
877 (define_insn "vsx_floatuns<VSi><mode>2"
878 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
879 (unsigned_float:VSX_B (match_operand:<VSI> 1 "vsx_register_operand" "<VSr2>,<VSr3>")))]
880 "VECTOR_UNIT_VSX_P (<MODE>mode)"
881 "x<VSv>cvux<VSc><VSs> %x0,%x1"
882 [(set_attr "type" "<VStype_simple>")
883 (set_attr "fp_type" "<VSfptype_simple>")])
885 (define_insn "vsx_fix_trunc<mode><VSi>2"
886 [(set (match_operand:<VSI> 0 "vsx_register_operand" "=<VSr2>,?<VSr3>")
887 (fix:<VSI> (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
888 "VECTOR_UNIT_VSX_P (<MODE>mode)"
889 "x<VSv>cv<VSs>sx<VSc>s %x0,%x1"
890 [(set_attr "type" "<VStype_simple>")
891 (set_attr "fp_type" "<VSfptype_simple>")])
893 (define_insn "vsx_fixuns_trunc<mode><VSi>2"
894 [(set (match_operand:<VSI> 0 "vsx_register_operand" "=<VSr2>,?<VSr3>")
895 (unsigned_fix:<VSI> (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
896 "VECTOR_UNIT_VSX_P (<MODE>mode)"
897 "x<VSv>cv<VSs>ux<VSc>s %x0,%x1"
898 [(set_attr "type" "<VStype_simple>")
899 (set_attr "fp_type" "<VSfptype_simple>")])
901 ;; Math rounding functions
902 (define_insn "vsx_x<VSv>r<VSs>i"
903 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
904 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
905 UNSPEC_VSX_ROUND_I))]
906 "VECTOR_UNIT_VSX_P (<MODE>mode)"
907 "x<VSv>r<VSs>i %x0,%x1"
908 [(set_attr "type" "<VStype_simple>")
909 (set_attr "fp_type" "<VSfptype_simple>")])
911 (define_insn "vsx_x<VSv>r<VSs>ic"
912 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
913 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
914 UNSPEC_VSX_ROUND_IC))]
915 "VECTOR_UNIT_VSX_P (<MODE>mode)"
916 "x<VSv>r<VSs>ic %x0,%x1"
917 [(set_attr "type" "<VStype_simple>")
918 (set_attr "fp_type" "<VSfptype_simple>")])
920 (define_insn "vsx_btrunc<mode>2"
921 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
922 (fix:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
923 "VECTOR_UNIT_VSX_P (<MODE>mode)"
924 "x<VSv>r<VSs>iz %x0,%x1"
925 [(set_attr "type" "<VStype_simple>")
926 (set_attr "fp_type" "<VSfptype_simple>")])
928 (define_insn "*vsx_b2trunc<mode>2"
929 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
930 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
932 "VECTOR_UNIT_VSX_P (<MODE>mode)"
933 "x<VSv>r<VSs>iz %x0,%x1"
934 [(set_attr "type" "<VStype_simple>")
935 (set_attr "fp_type" "<VSfptype_simple>")])
937 (define_insn "vsx_floor<mode>2"
938 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
939 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
941 "VECTOR_UNIT_VSX_P (<MODE>mode)"
942 "x<VSv>r<VSs>im %x0,%x1"
943 [(set_attr "type" "<VStype_simple>")
944 (set_attr "fp_type" "<VSfptype_simple>")])
946 (define_insn "vsx_ceil<mode>2"
947 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
948 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
950 "VECTOR_UNIT_VSX_P (<MODE>mode)"
951 "x<VSv>r<VSs>ip %x0,%x1"
952 [(set_attr "type" "<VStype_simple>")
953 (set_attr "fp_type" "<VSfptype_simple>")])
956 ;; VSX convert to/from double vector
958 ;; Convert between single and double precision
959 ;; Don't use xscvspdp and xscvdpsp for scalar conversions, since the normal
960 ;; scalar single precision instructions internally use the double format.
961 ;; Prefer the altivec registers, since we likely will need to do a vperm
962 (define_insn "vsx_<VS_spdp_insn>"
963 [(set (match_operand:<VS_spdp_res> 0 "vsx_register_operand" "=<VSr4>,?wa")
964 (unspec:<VS_spdp_res> [(match_operand:VSX_SPDP 1 "vsx_register_operand" "<VSr5>,wa")]
966 "VECTOR_UNIT_VSX_P (<MODE>mode)"
967 "<VS_spdp_insn> %x0,%x1"
968 [(set_attr "type" "<VS_spdp_type>")])
970 ;; xscvspdp, represent the scalar SF type as V4SF
971 (define_insn "vsx_xscvspdp"
972 [(set (match_operand:DF 0 "vsx_register_operand" "=ws,?wa")
973 (unspec:DF [(match_operand:V4SF 1 "vsx_register_operand" "wa,wa")]
975 "VECTOR_UNIT_VSX_P (DFmode)"
977 [(set_attr "type" "fp")])
979 ;; xscvdpsp used for splat'ing a scalar to V4SF, knowing that the internal SF
980 ;; format of scalars is actually DF.
981 (define_insn "vsx_xscvdpsp_scalar"
982 [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
983 (unspec:V4SF [(match_operand:SF 1 "vsx_register_operand" "f")]
985 "VECTOR_UNIT_VSX_P (DFmode)"
987 [(set_attr "type" "fp")])
989 ;; Convert from 64-bit to 32-bit types
990 ;; Note, favor the Altivec registers since the usual use of these instructions
991 ;; is in vector converts and we need to use the Altivec vperm instruction.
993 (define_insn "vsx_xvcvdpsxws"
994 [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
995 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
996 UNSPEC_VSX_CVDPSXWS))]
997 "VECTOR_UNIT_VSX_P (V2DFmode)"
999 [(set_attr "type" "vecfloat")])
1001 (define_insn "vsx_xvcvdpuxws"
1002 [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
1003 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
1004 UNSPEC_VSX_CVDPUXWS))]
1005 "VECTOR_UNIT_VSX_P (V2DFmode)"
1006 "xvcvdpuxws %x0,%x1"
1007 [(set_attr "type" "vecfloat")])
1009 (define_insn "vsx_xvcvsxdsp"
1010 [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
1011 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
1012 UNSPEC_VSX_CVSXDSP))]
1013 "VECTOR_UNIT_VSX_P (V2DFmode)"
1015 [(set_attr "type" "vecfloat")])
1017 (define_insn "vsx_xvcvuxdsp"
1018 [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
1019 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
1020 UNSPEC_VSX_CVUXDSP))]
1021 "VECTOR_UNIT_VSX_P (V2DFmode)"
1023 [(set_attr "type" "vecfloat")])
1025 ;; Convert from 32-bit to 64-bit types
1026 (define_insn "vsx_xvcvsxwdp"
1027 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1028 (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
1029 UNSPEC_VSX_CVSXWDP))]
1030 "VECTOR_UNIT_VSX_P (V2DFmode)"
1032 [(set_attr "type" "vecfloat")])
1034 (define_insn "vsx_xvcvuxwdp"
1035 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1036 (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
1037 UNSPEC_VSX_CVUXWDP))]
1038 "VECTOR_UNIT_VSX_P (V2DFmode)"
1040 [(set_attr "type" "vecfloat")])
1042 (define_insn "vsx_xvcvspsxds"
1043 [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
1044 (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
1045 UNSPEC_VSX_CVSPSXDS))]
1046 "VECTOR_UNIT_VSX_P (V2DFmode)"
1047 "xvcvspsxds %x0,%x1"
1048 [(set_attr "type" "vecfloat")])
1050 (define_insn "vsx_xvcvspuxds"
1051 [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
1052 (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
1053 UNSPEC_VSX_CVSPUXDS))]
1054 "VECTOR_UNIT_VSX_P (V2DFmode)"
1055 "xvcvspuxds %x0,%x1"
1056 [(set_attr "type" "vecfloat")])
1058 ;; Logical and permute operations
1059 (define_insn "*vsx_and<mode>3"
1060 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1062 (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
1063 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
1064 "VECTOR_MEM_VSX_P (<MODE>mode)"
1065 "xxland %x0,%x1,%x2"
1066 [(set_attr "type" "vecsimple")])
1068 (define_insn "*vsx_ior<mode>3"
1069 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1070 (ior:VSX_L (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
1071 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
1072 "VECTOR_MEM_VSX_P (<MODE>mode)"
1074 [(set_attr "type" "vecsimple")])
1076 (define_insn "*vsx_xor<mode>3"
1077 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1079 (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
1080 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
1081 "VECTOR_MEM_VSX_P (<MODE>mode)"
1082 "xxlxor %x0,%x1,%x2"
1083 [(set_attr "type" "vecsimple")])
1085 (define_insn "*vsx_one_cmpl<mode>2"
1086 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1088 (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")))]
1089 "VECTOR_MEM_VSX_P (<MODE>mode)"
1090 "xxlnor %x0,%x1,%x1"
1091 [(set_attr "type" "vecsimple")])
1093 (define_insn "*vsx_nor<mode>3"
1094 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1097 (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
1098 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa"))))]
1099 "VECTOR_MEM_VSX_P (<MODE>mode)"
1100 "xxlnor %x0,%x1,%x2"
1101 [(set_attr "type" "vecsimple")])
1103 (define_insn "*vsx_andc<mode>3"
1104 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1107 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa"))
1108 (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")))]
1109 "VECTOR_MEM_VSX_P (<MODE>mode)"
1110 "xxlandc %x0,%x1,%x2"
1111 [(set_attr "type" "vecsimple")])
1114 ;; Permute operations
1116 ;; Build a V2DF/V2DI vector from two scalars
1117 (define_insn "vsx_concat_<mode>"
1118 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
1120 [(match_operand:<VS_scalar> 1 "vsx_register_operand" "ws,wa")
1121 (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")]
1122 UNSPEC_VSX_CONCAT))]
1123 "VECTOR_MEM_VSX_P (<MODE>mode)"
1124 "xxpermdi %x0,%x1,%x2,0"
1125 [(set_attr "type" "vecperm")])
1127 ;; Special purpose concat using xxpermdi to glue two single precision values
1128 ;; together, relying on the fact that internally scalar floats are represented
1129 ;; as doubles. This is used to initialize a V4SF vector with 4 floats
1130 (define_insn "vsx_concat_v2sf"
1131 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1133 [(match_operand:SF 1 "vsx_register_operand" "f,f")
1134 (match_operand:SF 2 "vsx_register_operand" "f,f")]
1135 UNSPEC_VSX_CONCAT))]
1136 "VECTOR_MEM_VSX_P (V2DFmode)"
1137 "xxpermdi %x0,%x1,%x2,0"
1138 [(set_attr "type" "vecperm")])
1140 ;; Set the element of a V2DI/VD2F mode
1141 (define_insn "vsx_set_<mode>"
1142 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
1143 (unspec:VSX_D [(match_operand:VSX_D 1 "vsx_register_operand" "wd,wa")
1144 (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")
1145 (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
1147 "VECTOR_MEM_VSX_P (<MODE>mode)"
1149 if (INTVAL (operands[3]) == 0)
1150 return \"xxpermdi %x0,%x1,%x2,1\";
1151 else if (INTVAL (operands[3]) == 1)
1152 return \"xxpermdi %x0,%x2,%x1,0\";
1156 [(set_attr "type" "vecperm")])
1158 ;; Extract a DF/DI element from V2DF/V2DI
1159 (define_insn "vsx_extract_<mode>"
1160 [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,d,?wa")
1161 (vec_select:<VS_scalar> (match_operand:VSX_D 1 "vsx_register_operand" "wd,wd,wa")
1163 [(match_operand:QI 2 "u5bit_cint_operand" "i,i,i")])))]
1164 "VECTOR_MEM_VSX_P (<MODE>mode)"
1166 gcc_assert (UINTVAL (operands[2]) <= 1);
1167 operands[3] = GEN_INT (INTVAL (operands[2]) << 1);
1168 return \"xxpermdi %x0,%x1,%x1,%3\";
1170 [(set_attr "type" "vecperm")])
1172 ;; Optimize extracting element 0 from memory
1173 (define_insn "*vsx_extract_<mode>_zero"
1174 [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,d,?wa")
1175 (vec_select:<VS_scalar>
1176 (match_operand:VSX_D 1 "indexed_or_indirect_operand" "Z,Z,Z")
1177 (parallel [(const_int 0)])))]
1178 "VECTOR_MEM_VSX_P (<MODE>mode) && WORDS_BIG_ENDIAN"
1180 [(set_attr "type" "fpload")
1181 (set_attr "length" "4")])
1183 ;; General double word oriented permute, allow the other vector types for
1184 ;; optimizing the permute instruction.
1185 (define_insn "vsx_xxpermdi_<mode>"
1186 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=wd,?wa")
1187 (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "wd,wa")
1188 (match_operand:VSX_L 2 "vsx_register_operand" "wd,wa")
1189 (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
1190 UNSPEC_VSX_XXPERMDI))]
1191 "VECTOR_MEM_VSX_P (<MODE>mode)"
1192 "xxpermdi %x0,%x1,%x2,%3"
1193 [(set_attr "type" "vecperm")])
1195 ;; Varient of xxpermdi that is emitted by the vec_interleave functions
1196 (define_insn "*vsx_xxpermdi2_<mode>"
1197 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd")
1199 (vec_select:<VS_scalar>
1200 (match_operand:VSX_D 1 "vsx_register_operand" "wd")
1202 [(match_operand:QI 2 "u5bit_cint_operand" "i")]))
1203 (vec_select:<VS_scalar>
1204 (match_operand:VSX_D 3 "vsx_register_operand" "wd")
1206 [(match_operand:QI 4 "u5bit_cint_operand" "i")]))))]
1207 "VECTOR_MEM_VSX_P (<MODE>mode)"
1209 gcc_assert ((UINTVAL (operands[2]) <= 1) && (UINTVAL (operands[4]) <= 1));
1210 operands[5] = GEN_INT (((INTVAL (operands[2]) & 1) << 1)
1211 | (INTVAL (operands[4]) & 1));
1212 return \"xxpermdi %x0,%x1,%x3,%5\";
1214 [(set_attr "type" "vecperm")])
1217 (define_insn "vsx_splat_<mode>"
1218 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,wd,wd,?wa,?wa,?wa")
1219 (vec_duplicate:VSX_D
1220 (match_operand:<VS_scalar> 1 "input_operand" "ws,f,Z,wa,wa,Z")))]
1221 "VECTOR_MEM_VSX_P (<MODE>mode)"
1223 xxpermdi %x0,%x1,%x1,0
1224 xxpermdi %x0,%x1,%x1,0
1226 xxpermdi %x0,%x1,%x1,0
1227 xxpermdi %x0,%x1,%x1,0
1229 [(set_attr "type" "vecperm,vecperm,vecload,vecperm,vecperm,vecload")])
1232 (define_insn "vsx_xxspltw_<mode>"
1233 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1234 (vec_duplicate:VSX_W
1235 (vec_select:<VS_scalar>
1236 (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1238 [(match_operand:QI 2 "u5bit_cint_operand" "i,i")]))))]
1239 "VECTOR_MEM_VSX_P (<MODE>mode)"
1240 "xxspltw %x0,%x1,%2"
1241 [(set_attr "type" "vecperm")])
1243 ;; V4SF/V4SI interleave
1244 (define_insn "vsx_xxmrghw_<mode>"
1245 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1248 (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1249 (parallel [(const_int 0)
1254 (match_operand:VSX_W 2 "vsx_register_operand" "wf,wa")
1255 (parallel [(const_int 2)
1260 "VECTOR_MEM_VSX_P (<MODE>mode)"
1261 "xxmrghw %x0,%x1,%x2"
1262 [(set_attr "type" "vecperm")])
1264 (define_insn "vsx_xxmrglw_<mode>"
1265 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1268 (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1269 (parallel [(const_int 2)
1274 (match_operand:VSX_W 2 "vsx_register_operand" "wf,?wa")
1275 (parallel [(const_int 0)
1280 "VECTOR_MEM_VSX_P (<MODE>mode)"
1281 "xxmrglw %x0,%x1,%x2"
1282 [(set_attr "type" "vecperm")])
1284 ;; Shift left double by word immediate
1285 (define_insn "vsx_xxsldwi_<mode>"
1286 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=wa")
1287 (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "wa")
1288 (match_operand:VSX_L 2 "vsx_register_operand" "wa")
1289 (match_operand:QI 3 "u5bit_cint_operand" "i")]
1291 "VECTOR_MEM_VSX_P (<MODE>mode)"
1292 "xxsldwi %x0,%x1,%x2,%3"
1293 [(set_attr "type" "vecperm")])