1 ;; MIPS Paired-Single Floating and MIPS-3D Instructions.
2 ;; Copyright (C) 2004 Free Software Foundation, Inc.
4 ;; This file is part of GCC.
6 ;; GCC is free software; you can redistribute it and/or modify
7 ;; it under the terms of the GNU General Public License as published by
8 ;; the Free Software Foundation; either version 2, or (at your option)
11 ;; GCC is distributed in the hope that it will be useful,
12 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ;; GNU General Public License for more details.
16 ;; You should have received a copy of the GNU General Public License
17 ;; along with GCC; see the file COPYING. If not, write to
18 ;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
19 ;; Boston, MA 02110-1301, USA.
21 (define_insn "*movcc_v2sf_<mode>"
22 [(set (match_operand:V2SF 0 "register_operand" "=f,f")
24 (match_operator:GPR 4 "equality_operator"
25 [(match_operand:GPR 1 "register_operand" "d,d")
27 (match_operand:V2SF 2 "register_operand" "f,0")
28 (match_operand:V2SF 3 "register_operand" "0,f")))]
29 "TARGET_PAIRED_SINGLE_FLOAT"
33 [(set_attr "type" "condmove")
34 (set_attr "mode" "SF")])
36 (define_insn "mips_cond_move_tf_ps"
37 [(set (match_operand:V2SF 0 "register_operand" "=f,f")
38 (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f,0")
39 (match_operand:V2SF 2 "register_operand" "0,f")
40 (match_operand:CCV2 3 "register_operand" "z,z")]
42 "TARGET_PAIRED_SINGLE_FLOAT"
46 [(set_attr "type" "condmove")
47 (set_attr "mode" "SF")])
49 (define_expand "movv2sfcc"
50 [(set (match_dup 4) (match_operand 1 "comparison_operator"))
51 (set (match_operand:V2SF 0 "register_operand")
52 (if_then_else:V2SF (match_dup 5)
53 (match_operand:V2SF 2 "register_operand")
54 (match_operand:V2SF 3 "register_operand")))]
55 "TARGET_PAIRED_SINGLE_FLOAT"
57 /* We can only support MOVN.PS and MOVZ.PS.
58 NOTE: MOVT.PS and MOVF.PS have different semantics from MOVN.PS and
59 MOVZ.PS. MOVT.PS and MOVF.PS depend on two CC values and move
60 each item independently. */
62 if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) != MODE_INT)
65 gen_conditional_move (operands);
69 ; pul.ps - Pair Upper Lower
70 (define_insn "mips_pul_ps"
71 [(set (match_operand:V2SF 0 "register_operand" "=f")
73 (match_operand:V2SF 1 "register_operand" "f")
74 (match_operand:V2SF 2 "register_operand" "f")
76 "TARGET_PAIRED_SINGLE_FLOAT"
78 [(set_attr "type" "fmove")
79 (set_attr "mode" "SF")])
81 ; puu.ps - Pair upper upper
82 (define_insn "mips_puu_ps"
83 [(set (match_operand:V2SF 0 "register_operand" "=f")
85 (match_operand:V2SF 1 "register_operand" "f")
86 (vec_select:V2SF (match_operand:V2SF 2 "register_operand" "f")
87 (parallel [(const_int 1)
90 "TARGET_PAIRED_SINGLE_FLOAT"
92 [(set_attr "type" "fmove")
93 (set_attr "mode" "SF")])
95 ; pll.ps - Pair Lower Lower
96 (define_insn "mips_pll_ps"
97 [(set (match_operand:V2SF 0 "register_operand" "=f")
99 (vec_select:V2SF (match_operand:V2SF 1 "register_operand" "f")
100 (parallel [(const_int 1)
102 (match_operand:V2SF 2 "register_operand" "f")
104 "TARGET_PAIRED_SINGLE_FLOAT"
106 [(set_attr "type" "fmove")
107 (set_attr "mode" "SF")])
109 ; plu.ps - Pair Lower Upper
110 (define_insn "mips_plu_ps"
111 [(set (match_operand:V2SF 0 "register_operand" "=f")
113 (vec_select:V2SF (match_operand:V2SF 1 "register_operand" "f")
114 (parallel [(const_int 1)
116 (vec_select:V2SF (match_operand:V2SF 2 "register_operand" "f")
117 (parallel [(const_int 1)
120 "TARGET_PAIRED_SINGLE_FLOAT"
122 [(set_attr "type" "fmove")
123 (set_attr "mode" "SF")])
126 (define_expand "vec_initv2sf"
127 [(match_operand:V2SF 0 "register_operand")
128 (match_operand:V2SF 1 "")]
129 "TARGET_PAIRED_SINGLE_FLOAT"
131 rtx op0 = force_reg (SFmode, XVECEXP (operands[1], 0, 0));
132 rtx op1 = force_reg (SFmode, XVECEXP (operands[1], 0, 1));
133 emit_insn (gen_vec_initv2sf_internal (operands[0], op0, op1));
137 (define_insn "vec_initv2sf_internal"
138 [(set (match_operand:V2SF 0 "register_operand" "=f")
140 (match_operand:SF 1 "register_operand" "f")
141 (match_operand:SF 2 "register_operand" "f")))]
142 "TARGET_PAIRED_SINGLE_FLOAT"
144 if (BYTES_BIG_ENDIAN)
145 return "cvt.ps.s\t%0,%1,%2";
147 return "cvt.ps.s\t%0,%2,%1";
149 [(set_attr "type" "fcvt")
150 (set_attr "mode" "SF")])
152 ;; ??? This is only generated if we perform a vector operation that has to be
153 ;; emulated. There is no other way to get a vector mode bitfield extract
156 (define_insn "vec_extractv2sf"
157 [(set (match_operand:SF 0 "register_operand" "=f")
158 (vec_select:SF (match_operand:V2SF 1 "register_operand" "f")
160 [(match_operand 2 "const_0_or_1_operand" "")])))]
161 "TARGET_PAIRED_SINGLE_FLOAT"
163 if (INTVAL (operands[2]) == !BYTES_BIG_ENDIAN)
164 return "cvt.s.pu\t%0,%1";
166 return "cvt.s.pl\t%0,%1";
168 [(set_attr "type" "fcvt")
169 (set_attr "mode" "SF")])
171 ;; ??? This is only generated if we disable the vec_init pattern. There is
172 ;; no other way to get a vector mode bitfield store currently.
174 (define_expand "vec_setv2sf"
175 [(match_operand:V2SF 0 "register_operand")
176 (match_operand:SF 1 "register_operand")
177 (match_operand 2 "const_0_or_1_operand")]
178 "TARGET_PAIRED_SINGLE_FLOAT"
182 /* We don't have an insert instruction, so we duplicate the float, and
183 then use a PUL instruction. */
184 temp = gen_reg_rtx (V2SFmode);
185 emit_insn (gen_mips_cvt_ps_s (temp, operands[1], operands[1]));
186 if (INTVAL (operands[2]) == !BYTES_BIG_ENDIAN)
187 emit_insn (gen_mips_pul_ps (operands[0], temp, operands[0]));
189 emit_insn (gen_mips_pul_ps (operands[0], operands[0], temp));
193 ; cvt.ps.s - Floating Point Convert Pair to Paired Single
194 (define_expand "mips_cvt_ps_s"
195 [(match_operand:V2SF 0 "register_operand")
196 (match_operand:SF 1 "register_operand")
197 (match_operand:SF 2 "register_operand")]
198 "TARGET_PAIRED_SINGLE_FLOAT"
200 if (BYTES_BIG_ENDIAN)
201 emit_insn (gen_vec_initv2sf_internal (operands[0], operands[1],
204 emit_insn (gen_vec_initv2sf_internal (operands[0], operands[2],
209 ; cvt.s.pl - Floating Point Convert Pair Lower to Single Floating Point
210 (define_expand "mips_cvt_s_pl"
211 [(set (match_operand:SF 0 "register_operand")
212 (vec_select:SF (match_operand:V2SF 1 "register_operand")
213 (parallel [(match_dup 2)])))]
214 "TARGET_PAIRED_SINGLE_FLOAT"
215 { operands[2] = GEN_INT (BYTES_BIG_ENDIAN); })
217 ; cvt.s.pu - Floating Point Convert Pair Upper to Single Floating Point
218 (define_expand "mips_cvt_s_pu"
219 [(set (match_operand:SF 0 "register_operand")
220 (vec_select:SF (match_operand:V2SF 1 "register_operand")
221 (parallel [(match_dup 2)])))]
222 "TARGET_PAIRED_SINGLE_FLOAT"
223 { operands[2] = GEN_INT (!BYTES_BIG_ENDIAN); })
225 ; alnv.ps - Floating Point Align Variable
226 (define_insn "mips_alnv_ps"
227 [(set (match_operand:V2SF 0 "register_operand" "=f")
228 (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f")
229 (match_operand:V2SF 2 "register_operand" "f")
230 (match_operand:SI 3 "register_operand" "d")]
232 "TARGET_PAIRED_SINGLE_FLOAT"
233 "alnv.ps\t%0,%1,%2,%3"
234 [(set_attr "type" "fmove")
235 (set_attr "mode" "SF")])
237 ; addr.ps - Floating Point Reduction Add
238 (define_insn "mips_addr_ps"
239 [(set (match_operand:V2SF 0 "register_operand" "=f")
240 (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f")
241 (match_operand:V2SF 2 "register_operand" "f")]
245 [(set_attr "type" "fadd")
246 (set_attr "mode" "SF")])
248 ; cvt.pw.ps - Floating Point Convert Paired Single to Paired Word
249 (define_insn "mips_cvt_pw_ps"
250 [(set (match_operand:V2SF 0 "register_operand" "=f")
251 (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f")]
255 [(set_attr "type" "fcvt")
256 (set_attr "mode" "SF")])
258 ; cvt.ps.pw - Floating Point Convert Paired Word to Paired Single
259 (define_insn "mips_cvt_ps_pw"
260 [(set (match_operand:V2SF 0 "register_operand" "=f")
261 (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f")]
265 [(set_attr "type" "fcvt")
266 (set_attr "mode" "SF")])
268 ; mulr.ps - Floating Point Reduction Multiply
269 (define_insn "mips_mulr_ps"
270 [(set (match_operand:V2SF 0 "register_operand" "=f")
271 (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f")
272 (match_operand:V2SF 2 "register_operand" "f")]
276 [(set_attr "type" "fmul")
277 (set_attr "mode" "SF")])
280 (define_expand "mips_abs_ps"
281 [(set (match_operand:V2SF 0 "register_operand")
282 (unspec:V2SF [(match_operand:V2SF 1 "register_operand")]
284 "TARGET_PAIRED_SINGLE_FLOAT"
286 /* If we can ignore NaNs, this operation is equivalent to the
288 if (!HONOR_NANS (V2SFmode))
290 emit_insn (gen_absv2sf2 (operands[0], operands[1]));
295 (define_insn "*mips_abs_ps"
296 [(set (match_operand:V2SF 0 "register_operand" "=f")
297 (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f")]
299 "TARGET_PAIRED_SINGLE_FLOAT"
301 [(set_attr "type" "fabs")
302 (set_attr "mode" "SF")])
304 ;----------------------------------------------------------------------------
305 ; Floating Point Comparisons for Scalars
306 ;----------------------------------------------------------------------------
308 (define_insn "mips_cabs_cond_<fmt>"
309 [(set (match_operand:CC 0 "register_operand" "=z")
310 (unspec:CC [(match_operand:SCALARF 1 "register_operand" "f")
311 (match_operand:SCALARF 2 "register_operand" "f")
312 (match_operand 3 "const_int_operand" "")]
315 "cabs.%Y3.<fmt>\t%0,%1,%2"
316 [(set_attr "type" "fcmp")
317 (set_attr "mode" "FPSW")])
320 ;----------------------------------------------------------------------------
321 ; Floating Point Comparisons for Four Singles
322 ;----------------------------------------------------------------------------
324 (define_insn_and_split "mips_c_cond_4s"
325 [(set (match_operand:CCV4 0 "register_operand" "=z")
326 (unspec:CCV4 [(match_operand:V2SF 1 "register_operand" "f")
327 (match_operand:V2SF 2 "register_operand" "f")
328 (match_operand:V2SF 3 "register_operand" "f")
329 (match_operand:V2SF 4 "register_operand" "f")
330 (match_operand 5 "const_int_operand" "")]
332 "TARGET_PAIRED_SINGLE_FLOAT"
334 "&& reload_completed"
336 (unspec:CCV2 [(match_dup 1)
341 (unspec:CCV2 [(match_dup 3)
346 operands[6] = simplify_gen_subreg (CCV2mode, operands[0], CCV4mode, 0);
347 operands[7] = simplify_gen_subreg (CCV2mode, operands[0], CCV4mode, 8);
349 [(set_attr "type" "fcmp")
350 (set_attr "length" "8")
351 (set_attr "mode" "FPSW")])
353 (define_insn_and_split "mips_cabs_cond_4s"
354 [(set (match_operand:CCV4 0 "register_operand" "=z")
355 (unspec:CCV4 [(match_operand:V2SF 1 "register_operand" "f")
356 (match_operand:V2SF 2 "register_operand" "f")
357 (match_operand:V2SF 3 "register_operand" "f")
358 (match_operand:V2SF 4 "register_operand" "f")
359 (match_operand 5 "const_int_operand" "")]
363 "&& reload_completed"
365 (unspec:CCV2 [(match_dup 1)
370 (unspec:CCV2 [(match_dup 3)
375 operands[6] = simplify_gen_subreg (CCV2mode, operands[0], CCV4mode, 0);
376 operands[7] = simplify_gen_subreg (CCV2mode, operands[0], CCV4mode, 8);
378 [(set_attr "type" "fcmp")
379 (set_attr "length" "8")
380 (set_attr "mode" "FPSW")])
383 ;----------------------------------------------------------------------------
384 ; Floating Point Comparisons for Paired Singles
385 ;----------------------------------------------------------------------------
387 (define_insn "mips_c_cond_ps"
388 [(set (match_operand:CCV2 0 "register_operand" "=z")
389 (unspec:CCV2 [(match_operand:V2SF 1 "register_operand" "f")
390 (match_operand:V2SF 2 "register_operand" "f")
391 (match_operand 3 "const_int_operand" "")]
393 "TARGET_PAIRED_SINGLE_FLOAT"
395 [(set_attr "type" "fcmp")
396 (set_attr "mode" "FPSW")])
398 (define_insn "mips_cabs_cond_ps"
399 [(set (match_operand:CCV2 0 "register_operand" "=z")
400 (unspec:CCV2 [(match_operand:V2SF 1 "register_operand" "f")
401 (match_operand:V2SF 2 "register_operand" "f")
402 (match_operand 3 "const_int_operand" "")]
405 "cabs.%Y3.ps\t%0,%1,%2"
406 [(set_attr "type" "fcmp")
407 (set_attr "mode" "FPSW")])
409 ;; An expander for generating an scc operation.
410 (define_expand "scc_ps"
411 [(set (match_operand:CCV2 0)
412 (unspec:CCV2 [(match_operand 1)] UNSPEC_SCC))])
414 (define_insn "s<code>_ps"
415 [(set (match_operand:CCV2 0 "register_operand" "=z")
417 [(fcond (match_operand:V2SF 1 "register_operand" "f")
418 (match_operand:V2SF 2 "register_operand" "f"))]
420 "TARGET_PAIRED_SINGLE_FLOAT"
421 "c.<fcond>.ps\t%0,%1,%2"
422 [(set_attr "type" "fcmp")
423 (set_attr "mode" "FPSW")])
425 (define_insn "s<code>_ps"
426 [(set (match_operand:CCV2 0 "register_operand" "=z")
428 [(swapped_fcond (match_operand:V2SF 1 "register_operand" "f")
429 (match_operand:V2SF 2 "register_operand" "f"))]
431 "TARGET_PAIRED_SINGLE_FLOAT"
432 "c.<swapped_fcond>.ps\t%0,%2,%1"
433 [(set_attr "type" "fcmp")
434 (set_attr "mode" "FPSW")])
436 ;----------------------------------------------------------------------------
437 ; Floating Point Branch Instructions.
438 ;----------------------------------------------------------------------------
440 ; Branch on Any of Four Floating Point Condition Codes True
441 (define_insn "bc1any4t"
443 (if_then_else (ne (match_operand:CCV4 0 "register_operand" "z")
445 (label_ref (match_operand 1 "" ""))
448 "%*bc1any4t\t%0,%1%/"
449 [(set_attr "type" "branch")
450 (set_attr "mode" "none")])
452 ; Branch on Any of Four Floating Point Condition Codes False
453 (define_insn "bc1any4f"
455 (if_then_else (ne (match_operand:CCV4 0 "register_operand" "z")
457 (label_ref (match_operand 1 "" ""))
460 "%*bc1any4f\t%0,%1%/"
461 [(set_attr "type" "branch")
462 (set_attr "mode" "none")])
464 ; Branch on Any of Two Floating Point Condition Codes True
465 (define_insn "bc1any2t"
467 (if_then_else (ne (match_operand:CCV2 0 "register_operand" "z")
469 (label_ref (match_operand 1 "" ""))
472 "%*bc1any2t\t%0,%1%/"
473 [(set_attr "type" "branch")
474 (set_attr "mode" "none")])
476 ; Branch on Any of Two Floating Point Condition Codes False
477 (define_insn "bc1any2f"
479 (if_then_else (ne (match_operand:CCV2 0 "register_operand" "z")
481 (label_ref (match_operand 1 "" ""))
484 "%*bc1any2f\t%0,%1%/"
485 [(set_attr "type" "branch")
486 (set_attr "mode" "none")])
488 ; Used to access one register in a CCV2 pair. Operand 0 is the register
489 ; pair and operand 1 is the index of the register we want (a CONST_INT).
490 (define_expand "single_cc"
491 [(ne (unspec:CC [(match_operand 0) (match_operand 1)] UNSPEC_SINGLE_CC)
494 ; This is a normal floating-point branch pattern, but rather than check
495 ; a single CCmode register, it checks one register in a CCV2 pair.
496 ; Operand 2 is the register pair and operand 3 is the index of the
498 (define_insn "*branch_upper_lower"
501 (match_operator 0 "equality_operator"
502 [(unspec:CC [(match_operand:CCV2 2 "register_operand" "z")
503 (match_operand 3 "const_int_operand")]
506 (label_ref (match_operand 1 "" ""))
511 = gen_rtx_REG (CCmode, REGNO (operands[2]) + INTVAL (operands[3]));
512 return mips_output_conditional_branch (insn, operands,
513 MIPS_BRANCH ("b%F0", "%2,%1"),
514 MIPS_BRANCH ("b%W0", "%2,%1"));
516 [(set_attr "type" "branch")
517 (set_attr "mode" "none")])
519 ; As above, but with the sense of the condition reversed.
520 (define_insn "*branch_upper_lower_inverted"
523 (match_operator 0 "equality_operator"
524 [(unspec:CC [(match_operand:CCV2 2 "register_operand" "z")
525 (match_operand 3 "const_int_operand")]
529 (label_ref (match_operand 1 "" ""))))]
533 = gen_rtx_REG (CCmode, REGNO (operands[2]) + INTVAL (operands[3]));
534 return mips_output_conditional_branch (insn, operands,
535 MIPS_BRANCH ("b%W0", "%2,%1"),
536 MIPS_BRANCH ("b%F0", "%2,%1"));
538 [(set_attr "type" "branch")
539 (set_attr "mode" "none")])
541 ;----------------------------------------------------------------------------
542 ; Floating Point Reduced Precision Reciprocal Square Root Instructions.
543 ;----------------------------------------------------------------------------
545 (define_insn "mips_rsqrt1_<fmt>"
546 [(set (match_operand:ANYF 0 "register_operand" "=f")
547 (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f")]
550 "rsqrt1.<fmt>\t%0,%1"
551 [(set_attr "type" "frsqrt1")
552 (set_attr "mode" "<UNITMODE>")])
554 (define_insn "mips_rsqrt2_<fmt>"
555 [(set (match_operand:ANYF 0 "register_operand" "=f")
556 (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f")
557 (match_operand:ANYF 2 "register_operand" "f")]
560 "rsqrt2.<fmt>\t%0,%1,%2"
561 [(set_attr "type" "frsqrt2")
562 (set_attr "mode" "<UNITMODE>")])
564 (define_insn "mips_recip1_<fmt>"
565 [(set (match_operand:ANYF 0 "register_operand" "=f")
566 (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f")]
569 "recip1.<fmt>\t%0,%1"
570 [(set_attr "type" "frdiv1")
571 (set_attr "mode" "<UNITMODE>")])
573 (define_insn "mips_recip2_<fmt>"
574 [(set (match_operand:ANYF 0 "register_operand" "=f")
575 (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f")
576 (match_operand:ANYF 2 "register_operand" "f")]
579 "recip2.<fmt>\t%0,%1,%2"
580 [(set_attr "type" "frdiv2")
581 (set_attr "mode" "<UNITMODE>")])
583 (define_expand "vcondv2sf"
584 [(set (match_operand:V2SF 0 "register_operand")
587 [(match_operand:V2SF 4 "register_operand")
588 (match_operand:V2SF 5 "register_operand")])
589 (match_operand:V2SF 1 "register_operand")
590 (match_operand:V2SF 2 "register_operand")))]
591 "TARGET_PAIRED_SINGLE_FLOAT"
593 mips_expand_vcondv2sf (operands[0], operands[1], operands[2],
594 GET_CODE (operands[3]), operands[4], operands[5]);
598 (define_expand "sminv2sf3"
599 [(set (match_operand:V2SF 0 "register_operand")
600 (smin:V2SF (match_operand:V2SF 1 "register_operand")
601 (match_operand:V2SF 2 "register_operand")))]
602 "TARGET_PAIRED_SINGLE_FLOAT"
604 mips_expand_vcondv2sf (operands[0], operands[1], operands[2],
605 LE, operands[1], operands[2]);
609 (define_expand "smaxv2sf3"
610 [(set (match_operand:V2SF 0 "register_operand")
611 (smax:V2SF (match_operand:V2SF 1 "register_operand")
612 (match_operand:V2SF 2 "register_operand")))]
613 "TARGET_PAIRED_SINGLE_FLOAT"
615 mips_expand_vcondv2sf (operands[0], operands[1], operands[2],
616 LE, operands[2], operands[1]);