]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/mips/mips-ps-3d.md
Update copyright years.
[thirdparty/gcc.git] / gcc / config / mips / mips-ps-3d.md
1 ;; MIPS Paired-Single Floating and MIPS-3D Instructions.
2 ;; Copyright (C) 2004-2022 Free Software Foundation, Inc.
3 ;;
4 ;; This file is part of GCC.
5 ;;
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 3, or (at your option)
9 ;; any later version.
10 ;;
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.
15 ;;
16 ;; You should have received a copy of the GNU General Public License
17 ;; along with GCC; see the file COPYING3. If not see
18 ;; <http://www.gnu.org/licenses/>.
19
20 (define_c_enum "unspec" [
21 UNSPEC_MOVE_TF_PS
22 UNSPEC_C
23
24 ;; MIPS64/MIPS32R2 alnv.ps
25 UNSPEC_ALNV_PS
26
27 ;; MIPS-3D instructions
28 UNSPEC_CABS
29
30 UNSPEC_ADDR_PS
31 UNSPEC_CVT_PW_PS
32 UNSPEC_CVT_PS_PW
33 UNSPEC_MULR_PS
34 UNSPEC_ABS_PS
35
36 UNSPEC_RSQRT1
37 UNSPEC_RSQRT2
38 UNSPEC_RECIP1
39 UNSPEC_RECIP2
40 UNSPEC_SINGLE_CC
41 UNSPEC_SCC
42 ])
43
44 (define_insn "*movcc_v2sf_<mode>"
45 [(set (match_operand:V2SF 0 "register_operand" "=f,f")
46 (if_then_else:V2SF
47 (match_operator:GPR 4 "equality_operator"
48 [(match_operand:GPR 1 "register_operand" "d,d")
49 (const_int 0)])
50 (match_operand:V2SF 2 "register_operand" "f,0")
51 (match_operand:V2SF 3 "register_operand" "0,f")))]
52 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
53 "@
54 mov%T4.ps\t%0,%2,%1
55 mov%t4.ps\t%0,%3,%1"
56 [(set_attr "type" "condmove")
57 (set_attr "mode" "SF")])
58
59 (define_insn "mips_cond_move_tf_ps"
60 [(set (match_operand:V2SF 0 "register_operand" "=f,f")
61 (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f,0")
62 (match_operand:V2SF 2 "register_operand" "0,f")
63 (match_operand:CCV2 3 "register_operand" "z,z")]
64 UNSPEC_MOVE_TF_PS))]
65 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
66 "@
67 movt.ps\t%0,%1,%3
68 movf.ps\t%0,%2,%3"
69 [(set_attr "type" "condmove")
70 (set_attr "mode" "SF")])
71
72 (define_expand "movv2sfcc"
73 [(set (match_dup 4) (match_operand 1 "comparison_operator"))
74 (set (match_operand:V2SF 0 "register_operand")
75 (if_then_else:V2SF (match_dup 5)
76 (match_operand:V2SF 2 "register_operand")
77 (match_operand:V2SF 3 "register_operand")))]
78 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
79 {
80 /* We can only support MOVN.PS and MOVZ.PS.
81 NOTE: MOVT.PS and MOVF.PS have different semantics from MOVN.PS and
82 MOVZ.PS. MOVT.PS and MOVF.PS depend on two CC values and move
83 each item independently. */
84
85 if (GET_MODE_CLASS (GET_MODE (XEXP (operands[1], 0))) != MODE_INT)
86 FAIL;
87
88 mips_expand_conditional_move (operands);
89 DONE;
90 })
91
92 (define_insn "vec_perm_const_ps"
93 [(set (match_operand:V2SF 0 "register_operand" "=f")
94 (vec_select:V2SF
95 (vec_concat:V4SF
96 (match_operand:V2SF 1 "register_operand" "f")
97 (match_operand:V2SF 2 "register_operand" "f"))
98 (parallel [(match_operand:SI 3 "const_0_or_1_operand" "")
99 (match_operand:SI 4 "const_2_or_3_operand" "")])))]
100 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
101 {
102 /* Let <op>L be the lower part of operand <op> and <op>U be the upper part.
103 The P[UL][UL].PS instruction always specifies the upper part of the
104 result first, so the instruction is:
105
106 P<aUL><bUL>.PS %0,<aop>,<bop>
107
108 where 0U == <aop><aUL> and 0L == <bop><bUL>.
109
110 GCC's vector indices are specified in memory order, which means
111 that vector element 0 is the lower part (L) on little-endian targets
112 and the upper part (U) on big-endian targets. vec_concat likewise
113 concatenates in memory order, which means that operand 3 (being
114 0 or 1) selects part of operand 1 and operand 4 (being 2 or 3)
115 selects part of operand 2.
116
117 Let:
118
119 I3 = INTVAL (operands[3])
120 I4 = INTVAL (operands[4]) - 2
121
122 Taking the two endiannesses in turn:
123
124 Little-endian:
125
126 The semantics of the RTL pattern are:
127
128 { 0L, 0U } = { X[I3], X[I4 + 2] }, where X = { 1L, 1U, 2L, 2U }
129
130 so: 0L = { 1L, 1U }[I3] (= <bop><bUL>)
131 0U = { 2L, 2U }[I4] (= <aop><aUL>)
132
133 <aop> = 2, <aUL> = I4 ? U : L
134 <bop> = 1, <bUL> = I3 ? U : L
135
136 [LL] !I4 && !I3 [UL] I4 && !I3
137 [LU] !I4 && I3 [UU] I4 && I3
138
139 Big-endian:
140
141 The semantics of the RTL pattern are:
142
143 { 0U, 0L } = { X[I3], X[I4 + 2] }, where X = { 1U, 1L, 2U, 2L }
144
145 so: 0U = { 1U, 1L }[I3] (= <aop><aUL>)
146 0L = { 2U, 2L }[I4] (= <bop><bUL>)
147
148 <aop> = 1, <aUL> = I3 ? L : U
149 <bop> = 2, <bUL> = I4 ? L : U
150
151 [UU] !I3 && !I4 [UL] !I3 && I4
152 [LU] I3 && !I4 [LL] I3 && I4. */
153
154 static const char * const mnemonics[2][4] = {
155 /* LE */ { "pll.ps\t%0,%2,%1", "pul.ps\t%0,%2,%1",
156 "plu.ps\t%0,%2,%1", "puu.ps\t%0,%2,%1" },
157 /* BE */ { "puu.ps\t%0,%1,%2", "pul.ps\t%0,%1,%2",
158 "plu.ps\t%0,%1,%2", "pll.ps\t%0,%1,%2" },
159 };
160
161 unsigned mask = INTVAL (operands[3]) * 2 + (INTVAL (operands[4]) - 2);
162 return mnemonics[BYTES_BIG_ENDIAN][mask];
163 }
164 [(set_attr "type" "fmove")
165 (set_attr "mode" "SF")])
166
167 ;; Expanders for builtins. The instruction:
168 ;;
169 ;; P[UL][UL].PS <result>, <a>, <b>
170 ;;
171 ;; says that the upper part of <result> is taken from half of <a> and
172 ;; the lower part of <result> is taken from half of <b>. This means
173 ;; that the P[UL][UL].PS operand order matches memory order on big-endian
174 ;; targets; <a> is element 0 of the V2SF result while <b> is element 1.
175 ;; However, the P[UL][UL].PS operand order is the reverse of memory order
176 ;; on little-endian targets; <a> is element 1 of the V2SF result while
177 ;; <b> is element 0. The arguments to vec_perm_const_ps are always in
178 ;; memory order.
179 ;;
180 ;; Similarly, "U" corresponds to element 0 on big-endian targets but
181 ;; to element 1 on little-endian targets.
182
183 (define_expand "mips_puu_ps"
184 [(match_operand:V2SF 0 "register_operand" "")
185 (match_operand:V2SF 1 "register_operand" "")
186 (match_operand:V2SF 2 "register_operand" "")]
187 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
188 {
189 if (BYTES_BIG_ENDIAN)
190 emit_insn (gen_vec_perm_const_ps (operands[0], operands[1], operands[2],
191 const0_rtx, const2_rtx));
192 else
193 emit_insn (gen_vec_perm_const_ps (operands[0], operands[2], operands[1],
194 const1_rtx, GEN_INT (3)));
195 DONE;
196 })
197
198 (define_expand "mips_pul_ps"
199 [(match_operand:V2SF 0 "register_operand" "")
200 (match_operand:V2SF 1 "register_operand" "")
201 (match_operand:V2SF 2 "register_operand" "")]
202 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
203 {
204 if (BYTES_BIG_ENDIAN)
205 emit_insn (gen_vec_perm_const_ps (operands[0], operands[1], operands[2],
206 const0_rtx, GEN_INT (3)));
207 else
208 emit_insn (gen_vec_perm_const_ps (operands[0], operands[2], operands[1],
209 const0_rtx, GEN_INT (3)));
210 DONE;
211 })
212
213 (define_expand "mips_plu_ps"
214 [(match_operand:V2SF 0 "register_operand" "")
215 (match_operand:V2SF 1 "register_operand" "")
216 (match_operand:V2SF 2 "register_operand" "")]
217 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
218 {
219 if (BYTES_BIG_ENDIAN)
220 emit_insn (gen_vec_perm_const_ps (operands[0], operands[1], operands[2],
221 const1_rtx, const2_rtx));
222 else
223 emit_insn (gen_vec_perm_const_ps (operands[0], operands[2], operands[1],
224 const1_rtx, const2_rtx));
225 DONE;
226 })
227
228 (define_expand "mips_pll_ps"
229 [(match_operand:V2SF 0 "register_operand" "")
230 (match_operand:V2SF 1 "register_operand" "")
231 (match_operand:V2SF 2 "register_operand" "")]
232 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
233 {
234 if (BYTES_BIG_ENDIAN)
235 emit_insn (gen_vec_perm_const_ps (operands[0], operands[1], operands[2],
236 const1_rtx, GEN_INT (3)));
237 else
238 emit_insn (gen_vec_perm_const_ps (operands[0], operands[2], operands[1],
239 const0_rtx, const2_rtx));
240 DONE;
241 })
242
243 ; vec_init
244 (define_expand "vec_initv2sfsf"
245 [(match_operand:V2SF 0 "register_operand")
246 (match_operand:V2SF 1 "")]
247 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
248 {
249 mips_expand_vector_init (operands[0], operands[1]);
250 DONE;
251 })
252
253 (define_insn "vec_concatv2sf"
254 [(set (match_operand:V2SF 0 "register_operand" "=f")
255 (vec_concat:V2SF
256 (match_operand:SF 1 "register_operand" "f")
257 (match_operand:SF 2 "register_operand" "f")))]
258 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
259 {
260 if (BYTES_BIG_ENDIAN)
261 return "cvt.ps.s\t%0,%1,%2";
262 else
263 return "cvt.ps.s\t%0,%2,%1";
264 }
265 [(set_attr "type" "fcvt")
266 (set_attr "mode" "SF")])
267
268 ;; ??? This is only generated if we perform a vector operation that has to be
269 ;; emulated. There is no other way to get a vector mode bitfield extract
270 ;; currently.
271
272 (define_insn "vec_extractv2sfsf"
273 [(set (match_operand:SF 0 "register_operand" "=f")
274 (vec_select:SF (match_operand:V2SF 1 "register_operand" "f")
275 (parallel
276 [(match_operand 2 "const_0_or_1_operand" "")])))]
277 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
278 {
279 if (INTVAL (operands[2]) == !BYTES_BIG_ENDIAN)
280 return "cvt.s.pu\t%0,%1";
281 else
282 return "cvt.s.pl\t%0,%1";
283 }
284 [(set_attr "type" "fcvt")
285 (set_attr "mode" "SF")])
286
287 ;; ??? This is only generated if we disable the vec_init pattern. There is
288 ;; no other way to get a vector mode bitfield store currently.
289
290 (define_expand "vec_setv2sf"
291 [(set (match_operand:V2SF 0 "register_operand" "")
292 (vec_select:V2SF
293 (vec_concat:V4SF
294 (match_operand:SF 1 "register_operand" "")
295 (match_dup 0))
296 (parallel [(match_operand 2 "const_0_or_1_operand" "")
297 (match_dup 3)])))]
298 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
299 {
300 /* We don't have an insert instruction, so we duplicate the float, and
301 then use a PUL instruction. */
302 rtx temp = gen_reg_rtx (V2SFmode);
303 emit_insn (gen_vec_concatv2sf (temp, operands[1], operands[1]));
304 operands[1] = temp;
305 operands[3] = GEN_INT (1 - INTVAL (operands[2]) + 2);
306 })
307
308 ; cvt.ps.s - Floating Point Convert Pair to Paired Single
309 (define_expand "mips_cvt_ps_s"
310 [(match_operand:V2SF 0 "register_operand")
311 (match_operand:SF 1 "register_operand")
312 (match_operand:SF 2 "register_operand")]
313 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
314 {
315 if (BYTES_BIG_ENDIAN)
316 emit_insn (gen_vec_concatv2sf (operands[0], operands[1], operands[2]));
317 else
318 emit_insn (gen_vec_concatv2sf (operands[0], operands[2], operands[1]));
319 DONE;
320 })
321
322 ; cvt.s.pl - Floating Point Convert Pair Lower to Single Floating Point
323 (define_expand "mips_cvt_s_pl"
324 [(set (match_operand:SF 0 "register_operand")
325 (vec_select:SF (match_operand:V2SF 1 "register_operand")
326 (parallel [(match_dup 2)])))]
327 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
328 { operands[2] = GEN_INT (BYTES_BIG_ENDIAN); })
329
330 ; cvt.s.pu - Floating Point Convert Pair Upper to Single Floating Point
331 (define_expand "mips_cvt_s_pu"
332 [(set (match_operand:SF 0 "register_operand")
333 (vec_select:SF (match_operand:V2SF 1 "register_operand")
334 (parallel [(match_dup 2)])))]
335 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
336 { operands[2] = GEN_INT (!BYTES_BIG_ENDIAN); })
337
338 ; alnv.ps - Floating Point Align Variable
339 (define_insn "mips_alnv_ps"
340 [(set (match_operand:V2SF 0 "register_operand" "=f")
341 (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f")
342 (match_operand:V2SF 2 "register_operand" "f")
343 (match_operand:SI 3 "register_operand" "d")]
344 UNSPEC_ALNV_PS))]
345 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
346 "alnv.ps\t%0,%1,%2,%3"
347 [(set_attr "type" "fmove")
348 (set_attr "mode" "SF")])
349
350 ; addr.ps - Floating Point Reduction Add
351 (define_insn "mips_addr_ps"
352 [(set (match_operand:V2SF 0 "register_operand" "=f")
353 (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f")
354 (match_operand:V2SF 2 "register_operand" "f")]
355 UNSPEC_ADDR_PS))]
356 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
357 "addr.ps\t%0,%1,%2"
358 [(set_attr "type" "fadd")
359 (set_attr "mode" "SF")])
360
361 (define_expand "reduc_plus_scal_v2sf"
362 [(match_operand:SF 0 "register_operand" "=f")
363 (match_operand:V2SF 1 "register_operand" "f")]
364 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
365 {
366 rtx temp = gen_reg_rtx (V2SFmode);
367 emit_insn (gen_mips_addr_ps (temp, operands[1], operands[1]));
368 rtx lane = BYTES_BIG_ENDIAN ? const1_rtx : const0_rtx;
369 emit_insn (gen_vec_extractv2sfsf (operands[0], temp, lane));
370 DONE;
371 })
372
373 ; cvt.pw.ps - Floating Point Convert Paired Single to Paired Word
374 (define_insn "mips_cvt_pw_ps"
375 [(set (match_operand:V2SF 0 "register_operand" "=f")
376 (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f")]
377 UNSPEC_CVT_PW_PS))]
378 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
379 "cvt.pw.ps\t%0,%1"
380 [(set_attr "type" "fcvt")
381 (set_attr "mode" "SF")])
382
383 ; cvt.ps.pw - Floating Point Convert Paired Word to Paired Single
384 (define_insn "mips_cvt_ps_pw"
385 [(set (match_operand:V2SF 0 "register_operand" "=f")
386 (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f")]
387 UNSPEC_CVT_PS_PW))]
388 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
389 "cvt.ps.pw\t%0,%1"
390 [(set_attr "type" "fcvt")
391 (set_attr "mode" "SF")])
392
393 ; mulr.ps - Floating Point Reduction Multiply
394 (define_insn "mips_mulr_ps"
395 [(set (match_operand:V2SF 0 "register_operand" "=f")
396 (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f")
397 (match_operand:V2SF 2 "register_operand" "f")]
398 UNSPEC_MULR_PS))]
399 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
400 "mulr.ps\t%0,%1,%2"
401 [(set_attr "type" "fmul")
402 (set_attr "mode" "SF")])
403
404 ; abs.ps
405 (define_expand "mips_abs_ps"
406 [(set (match_operand:V2SF 0 "register_operand")
407 (unspec:V2SF [(match_operand:V2SF 1 "register_operand")]
408 UNSPEC_ABS_PS))]
409 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
410 {
411 /* If we can ignore NaNs, this operation is equivalent to the
412 rtl ABS code. */
413 if (!HONOR_NANS (V2SFmode))
414 {
415 emit_insn (gen_absv2sf2 (operands[0], operands[1]));
416 DONE;
417 }
418 })
419
420 (define_insn "*mips_abs_ps"
421 [(set (match_operand:V2SF 0 "register_operand" "=f")
422 (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f")]
423 UNSPEC_ABS_PS))]
424 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
425 "abs.ps\t%0,%1"
426 [(set_attr "type" "fabs")
427 (set_attr "mode" "SF")])
428
429 ;----------------------------------------------------------------------------
430 ; Floating Point Comparisons for Scalars
431 ;----------------------------------------------------------------------------
432
433 (define_insn "mips_cabs_cond_<fmt>"
434 [(set (match_operand:CC 0 "register_operand" "=z")
435 (unspec:CC [(match_operand:SCALARF 1 "register_operand" "f")
436 (match_operand:SCALARF 2 "register_operand" "f")
437 (match_operand 3 "const_int_operand" "")]
438 UNSPEC_CABS))]
439 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
440 "cabs.%Y3.<fmt>\t%0,%1,%2"
441 [(set_attr "type" "fcmp")
442 (set_attr "mode" "FPSW")])
443
444
445 ;----------------------------------------------------------------------------
446 ; Floating Point Comparisons for Four Singles
447 ;----------------------------------------------------------------------------
448
449 (define_insn_and_split "mips_c_cond_4s"
450 [(set (match_operand:CCV4 0 "register_operand" "=z")
451 (unspec:CCV4 [(match_operand:V2SF 1 "register_operand" "f")
452 (match_operand:V2SF 2 "register_operand" "f")
453 (match_operand:V2SF 3 "register_operand" "f")
454 (match_operand:V2SF 4 "register_operand" "f")
455 (match_operand 5 "const_int_operand" "")]
456 UNSPEC_C))]
457 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
458 "#"
459 "&& reload_completed"
460 [(set (match_dup 6)
461 (unspec:CCV2 [(match_dup 1)
462 (match_dup 2)
463 (match_dup 5)]
464 UNSPEC_C))
465 (set (match_dup 7)
466 (unspec:CCV2 [(match_dup 3)
467 (match_dup 4)
468 (match_dup 5)]
469 UNSPEC_C))]
470 {
471 operands[6] = simplify_gen_subreg (CCV2mode, operands[0], CCV4mode, 0);
472 operands[7] = simplify_gen_subreg (CCV2mode, operands[0], CCV4mode, 8);
473 }
474 [(set_attr "type" "fcmp")
475 (set_attr "insn_count" "2")
476 (set_attr "mode" "FPSW")])
477
478 (define_insn_and_split "mips_cabs_cond_4s"
479 [(set (match_operand:CCV4 0 "register_operand" "=z")
480 (unspec:CCV4 [(match_operand:V2SF 1 "register_operand" "f")
481 (match_operand:V2SF 2 "register_operand" "f")
482 (match_operand:V2SF 3 "register_operand" "f")
483 (match_operand:V2SF 4 "register_operand" "f")
484 (match_operand 5 "const_int_operand" "")]
485 UNSPEC_CABS))]
486 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
487 "#"
488 "&& reload_completed"
489 [(set (match_dup 6)
490 (unspec:CCV2 [(match_dup 1)
491 (match_dup 2)
492 (match_dup 5)]
493 UNSPEC_CABS))
494 (set (match_dup 7)
495 (unspec:CCV2 [(match_dup 3)
496 (match_dup 4)
497 (match_dup 5)]
498 UNSPEC_CABS))]
499 {
500 operands[6] = simplify_gen_subreg (CCV2mode, operands[0], CCV4mode, 0);
501 operands[7] = simplify_gen_subreg (CCV2mode, operands[0], CCV4mode, 8);
502 }
503 [(set_attr "type" "fcmp")
504 (set_attr "insn_count" "2")
505 (set_attr "mode" "FPSW")])
506
507
508 ;----------------------------------------------------------------------------
509 ; Floating Point Comparisons for Paired Singles
510 ;----------------------------------------------------------------------------
511
512 (define_insn "mips_c_cond_ps"
513 [(set (match_operand:CCV2 0 "register_operand" "=z")
514 (unspec:CCV2 [(match_operand:V2SF 1 "register_operand" "f")
515 (match_operand:V2SF 2 "register_operand" "f")
516 (match_operand 3 "const_int_operand" "")]
517 UNSPEC_C))]
518 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
519 "c.%Y3.ps\t%0,%1,%2"
520 [(set_attr "type" "fcmp")
521 (set_attr "mode" "FPSW")])
522
523 (define_insn "mips_cabs_cond_ps"
524 [(set (match_operand:CCV2 0 "register_operand" "=z")
525 (unspec:CCV2 [(match_operand:V2SF 1 "register_operand" "f")
526 (match_operand:V2SF 2 "register_operand" "f")
527 (match_operand 3 "const_int_operand" "")]
528 UNSPEC_CABS))]
529 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
530 "cabs.%Y3.ps\t%0,%1,%2"
531 [(set_attr "type" "fcmp")
532 (set_attr "mode" "FPSW")])
533
534 ;; An expander for generating an scc operation.
535 (define_expand "scc_ps"
536 [(set (match_operand:CCV2 0)
537 (unspec:CCV2 [(match_operand 1)] UNSPEC_SCC))])
538
539 (define_insn "s<code>_ps"
540 [(set (match_operand:CCV2 0 "register_operand" "=z")
541 (unspec:CCV2
542 [(fcond (match_operand:V2SF 1 "register_operand" "f")
543 (match_operand:V2SF 2 "register_operand" "f"))]
544 UNSPEC_SCC))]
545 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
546 "c.<fcond>.ps\t%0,%1,%2"
547 [(set_attr "type" "fcmp")
548 (set_attr "mode" "FPSW")])
549
550 (define_insn "s<code>_ps"
551 [(set (match_operand:CCV2 0 "register_operand" "=z")
552 (unspec:CCV2
553 [(swapped_fcond (match_operand:V2SF 1 "register_operand" "f")
554 (match_operand:V2SF 2 "register_operand" "f"))]
555 UNSPEC_SCC))]
556 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
557 "c.<swapped_fcond>.ps\t%0,%2,%1"
558 [(set_attr "type" "fcmp")
559 (set_attr "mode" "FPSW")])
560
561 ;----------------------------------------------------------------------------
562 ; Floating Point Branch Instructions.
563 ;----------------------------------------------------------------------------
564
565 ; Branch on Any of Four Floating Point Condition Codes True
566 (define_insn "bc1any4t"
567 [(set (pc)
568 (if_then_else (ne (match_operand:CCV4 1 "register_operand" "z")
569 (const_int 0))
570 (label_ref (match_operand 0 "" ""))
571 (pc)))]
572 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
573 "%*bc1any4t\t%1,%0%/"
574 [(set_attr "type" "branch")])
575
576 ; Branch on Any of Four Floating Point Condition Codes False
577 (define_insn "bc1any4f"
578 [(set (pc)
579 (if_then_else (ne (match_operand:CCV4 1 "register_operand" "z")
580 (const_int -1))
581 (label_ref (match_operand 0 "" ""))
582 (pc)))]
583 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
584 "%*bc1any4f\t%1,%0%/"
585 [(set_attr "type" "branch")])
586
587 ; Branch on Any of Two Floating Point Condition Codes True
588 (define_insn "bc1any2t"
589 [(set (pc)
590 (if_then_else (ne (match_operand:CCV2 1 "register_operand" "z")
591 (const_int 0))
592 (label_ref (match_operand 0 "" ""))
593 (pc)))]
594 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
595 "%*bc1any2t\t%1,%0%/"
596 [(set_attr "type" "branch")])
597
598 ; Branch on Any of Two Floating Point Condition Codes False
599 (define_insn "bc1any2f"
600 [(set (pc)
601 (if_then_else (ne (match_operand:CCV2 1 "register_operand" "z")
602 (const_int -1))
603 (label_ref (match_operand 0 "" ""))
604 (pc)))]
605 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
606 "%*bc1any2f\t%1,%0%/"
607 [(set_attr "type" "branch")])
608
609 ; Used to access one register in a CCV2 pair. Operand 0 is the register
610 ; pair and operand 1 is the index of the register we want (a CONST_INT).
611 (define_expand "single_cc"
612 [(ne (unspec:CC [(match_operand 0) (match_operand 1)] UNSPEC_SINGLE_CC)
613 (const_int 0))])
614
615 ; This is a normal floating-point branch pattern, but rather than check
616 ; a single CCmode register, it checks one register in a CCV2 pair.
617 ; Operand 2 is the register pair and operand 3 is the index of the
618 ; register we want.
619 (define_insn "*branch_upper_lower"
620 [(set (pc)
621 (if_then_else
622 (match_operator 1 "equality_operator"
623 [(unspec:CC [(match_operand:CCV2 2 "register_operand" "z")
624 (match_operand 3 "const_int_operand")]
625 UNSPEC_SINGLE_CC)
626 (const_int 0)])
627 (label_ref (match_operand 0 "" ""))
628 (pc)))]
629 "TARGET_HARD_FLOAT"
630 {
631 operands[2]
632 = gen_rtx_REG (CCmode, REGNO (operands[2]) + INTVAL (operands[3]));
633 return mips_output_conditional_branch (insn, operands,
634 MIPS_BRANCH ("b%F1", "%2,%0"),
635 MIPS_BRANCH ("b%W1", "%2,%0"));
636 }
637 [(set_attr "type" "branch")])
638
639 ; As above, but with the sense of the condition reversed.
640 (define_insn "*branch_upper_lower_inverted"
641 [(set (pc)
642 (if_then_else
643 (match_operator 1 "equality_operator"
644 [(unspec:CC [(match_operand:CCV2 2 "register_operand" "z")
645 (match_operand 3 "const_int_operand")]
646 UNSPEC_SINGLE_CC)
647 (const_int 0)])
648 (pc)
649 (label_ref (match_operand 0 "" ""))))]
650 "TARGET_HARD_FLOAT"
651 {
652 operands[2]
653 = gen_rtx_REG (CCmode, REGNO (operands[2]) + INTVAL (operands[3]));
654 return mips_output_conditional_branch (insn, operands,
655 MIPS_BRANCH ("b%W1", "%2,%0"),
656 MIPS_BRANCH ("b%F1", "%2,%0"));
657 }
658 [(set_attr "type" "branch")])
659
660 ;----------------------------------------------------------------------------
661 ; Floating Point Reduced Precision Reciprocal Square Root Instructions.
662 ;----------------------------------------------------------------------------
663
664 (define_insn "mips_rsqrt1_<fmt>"
665 [(set (match_operand:ANYF 0 "register_operand" "=f")
666 (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f")]
667 UNSPEC_RSQRT1))]
668 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
669 "rsqrt1.<fmt>\t%0,%1"
670 [(set_attr "type" "frsqrt1")
671 (set_attr "mode" "<UNITMODE>")])
672
673 (define_insn "mips_rsqrt2_<fmt>"
674 [(set (match_operand:ANYF 0 "register_operand" "=f")
675 (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f")
676 (match_operand:ANYF 2 "register_operand" "f")]
677 UNSPEC_RSQRT2))]
678 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
679 "rsqrt2.<fmt>\t%0,%1,%2"
680 [(set_attr "type" "frsqrt2")
681 (set_attr "mode" "<UNITMODE>")])
682
683 (define_insn "mips_recip1_<fmt>"
684 [(set (match_operand:ANYF 0 "register_operand" "=f")
685 (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f")]
686 UNSPEC_RECIP1))]
687 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
688 "recip1.<fmt>\t%0,%1"
689 [(set_attr "type" "frdiv1")
690 (set_attr "mode" "<UNITMODE>")])
691
692 (define_insn "mips_recip2_<fmt>"
693 [(set (match_operand:ANYF 0 "register_operand" "=f")
694 (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f")
695 (match_operand:ANYF 2 "register_operand" "f")]
696 UNSPEC_RECIP2))]
697 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
698 "recip2.<fmt>\t%0,%1,%2"
699 [(set_attr "type" "frdiv2")
700 (set_attr "mode" "<UNITMODE>")])
701
702 (define_expand "vcondv2sfv2sf"
703 [(set (match_operand:V2SF 0 "register_operand")
704 (if_then_else:V2SF
705 (match_operator 3 ""
706 [(match_operand:V2SF 4 "register_operand")
707 (match_operand:V2SF 5 "register_operand")])
708 (match_operand:V2SF 1 "register_operand")
709 (match_operand:V2SF 2 "register_operand")))]
710 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
711 {
712 mips_expand_vcondv2sf (operands[0], operands[1], operands[2],
713 GET_CODE (operands[3]), operands[4], operands[5]);
714 DONE;
715 })
716
717 (define_expand "sminv2sf3"
718 [(set (match_operand:V2SF 0 "register_operand")
719 (smin:V2SF (match_operand:V2SF 1 "register_operand")
720 (match_operand:V2SF 2 "register_operand")))]
721 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
722 {
723 mips_expand_vcondv2sf (operands[0], operands[1], operands[2],
724 LE, operands[1], operands[2]);
725 DONE;
726 })
727
728 (define_expand "smaxv2sf3"
729 [(set (match_operand:V2SF 0 "register_operand")
730 (smax:V2SF (match_operand:V2SF 1 "register_operand")
731 (match_operand:V2SF 2 "register_operand")))]
732 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
733 {
734 mips_expand_vcondv2sf (operands[0], operands[1], operands[2],
735 LE, operands[2], operands[1]);
736 DONE;
737 })
738
739 (define_expand "reduc_smin_scal_v2sf"
740 [(match_operand:SF 0 "register_operand")
741 (match_operand:V2SF 1 "register_operand")]
742 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
743 {
744 rtx temp = gen_reg_rtx (V2SFmode);
745 mips_expand_vec_reduc (temp, operands[1], gen_sminv2sf3);
746 rtx lane = BYTES_BIG_ENDIAN ? const1_rtx : const0_rtx;
747 emit_insn (gen_vec_extractv2sfsf (operands[0], temp, lane));
748 DONE;
749 })
750
751 (define_expand "reduc_smax_scal_v2sf"
752 [(match_operand:SF 0 "register_operand")
753 (match_operand:V2SF 1 "register_operand")]
754 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
755 {
756 rtx temp = gen_reg_rtx (V2SFmode);
757 mips_expand_vec_reduc (temp, operands[1], gen_smaxv2sf3);
758 rtx lane = BYTES_BIG_ENDIAN ? const1_rtx : const0_rtx;
759 emit_insn (gen_vec_extractv2sfsf (operands[0], temp, lane));
760 DONE;
761 })