]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/mips/mips-ps-3d.md
Update copyright years.
[thirdparty/gcc.git] / gcc / config / mips / mips-ps-3d.md
CommitLineData
06a4ab70 1;; MIPS Paired-Single Floating and MIPS-3D Instructions.
aeee4812 2;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
06a4ab70
CF
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
2f83c7d6 8;; the Free Software Foundation; either version 3, or (at your option)
06a4ab70
CF
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
2f83c7d6
NC
17;; along with GCC; see the file COPYING3. If not see
18;; <http://www.gnu.org/licenses/>.
06a4ab70 19
24609606
RS
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
afa396ff 44(define_insn "*movcc_v2sf_<mode>"
06a4ab70
CF
45 [(set (match_operand:V2SF 0 "register_operand" "=f,f")
46 (if_then_else:V2SF
afa396ff
RS
47 (match_operator:GPR 4 "equality_operator"
48 [(match_operand:GPR 1 "register_operand" "d,d")
06a4ab70
CF
49 (const_int 0)])
50 (match_operand:V2SF 2 "register_operand" "f,0")
51 (match_operand:V2SF 3 "register_operand" "0,f")))]
254d1646 52 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
06a4ab70
CF
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")
49135706
RS
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))]
254d1646 65 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
06a4ab70 66 "@
308cd611
RS
67 movt.ps\t%0,%1,%3
68 movf.ps\t%0,%2,%3"
06a4ab70
CF
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")))]
254d1646 78 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
06a4ab70
CF
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
f90b7a5a 85 if (GET_MODE_CLASS (GET_MODE (XEXP (operands[1], 0))) != MODE_INT)
06a4ab70
CF
86 FAIL;
87
65239d20 88 mips_expand_conditional_move (operands);
06a4ab70
CF
89 DONE;
90})
91
7dab511c 92(define_insn "vec_perm_const_ps"
06a4ab70 93 [(set (match_operand:V2SF 0 "register_operand" "=f")
7dab511c
RH
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" "")])))]
254d1646 100 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
7dab511c
RH
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:
06a4ab70 105
7dab511c 106 P<aUL><bUL>.PS %0,<aop>,<bop>
06a4ab70 107
7dab511c 108 where 0U == <aop><aUL> and 0L == <bop><bUL>.
06a4ab70 109
7dab511c
RH
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}
06a4ab70
CF
164 [(set_attr "type" "fmove")
165 (set_attr "mode" "SF")])
166
7dab511c
RH
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
06a4ab70 243; vec_init
ff03930a 244(define_expand "vec_initv2sfsf"
06a4ab70
CF
245 [(match_operand:V2SF 0 "register_operand")
246 (match_operand:V2SF 1 "")]
254d1646 247 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
06a4ab70 248{
7dab511c 249 mips_expand_vector_init (operands[0], operands[1]);
06a4ab70
CF
250 DONE;
251})
252
7dab511c 253(define_insn "vec_concatv2sf"
06a4ab70
CF
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")))]
254d1646 258 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
06a4ab70
CF
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
ff03930a 272(define_insn "vec_extractv2sfsf"
06a4ab70
CF
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" "")])))]
254d1646 277 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
06a4ab70
CF
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"
7dab511c
RH
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)])))]
254d1646 298 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
06a4ab70 299{
06a4ab70
CF
300 /* We don't have an insert instruction, so we duplicate the float, and
301 then use a PUL instruction. */
7dab511c
RH
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);
06a4ab70
CF
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")]
254d1646 313 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
06a4ab70
CF
314{
315 if (BYTES_BIG_ENDIAN)
7dab511c 316 emit_insn (gen_vec_concatv2sf (operands[0], operands[1], operands[2]));
06a4ab70 317 else
7dab511c 318 emit_insn (gen_vec_concatv2sf (operands[0], operands[2], operands[1]));
06a4ab70
CF
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)])))]
254d1646 327 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
06a4ab70
CF
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)])))]
254d1646 335 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
06a4ab70
CF
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))]
254d1646 345 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
06a4ab70
CF
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))]
63b9d91a 356 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
06a4ab70
CF
357 "addr.ps\t%0,%1,%2"
358 [(set_attr "type" "fadd")
359 (set_attr "mode" "SF")])
360
59a2f0fa
AL
361(define_expand "reduc_plus_scal_v2sf"
362 [(match_operand:SF 0 "register_operand" "=f")
363 (match_operand:V2SF 1 "register_operand" "f")]
63b9d91a 364 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
59a2f0fa
AL
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;
ff03930a 369 emit_insn (gen_vec_extractv2sfsf (operands[0], temp, lane));
59a2f0fa
AL
370 DONE;
371 })
7dab511c 372
06a4ab70
CF
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))]
63b9d91a 378 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
06a4ab70
CF
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))]
63b9d91a 388 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
06a4ab70
CF
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))]
63b9d91a 399 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
06a4ab70
CF
400 "mulr.ps\t%0,%1,%2"
401 [(set_attr "type" "fmul")
402 (set_attr "mode" "SF")])
403
1bded8e1
RS
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))]
254d1646 409 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
1bded8e1
RS
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))]
254d1646 424 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
1bded8e1
RS
425 "abs.ps\t%0,%1"
426 [(set_attr "type" "fabs")
427 (set_attr "mode" "SF")])
428
06a4ab70 429;----------------------------------------------------------------------------
c112cf2b 430; Floating Point Comparisons for Scalars
06a4ab70
CF
431;----------------------------------------------------------------------------
432
308cd611 433(define_insn "mips_cabs_cond_<fmt>"
06a4ab70 434 [(set (match_operand:CC 0 "register_operand" "=z")
308cd611
RS
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))]
63b9d91a 439 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
308cd611 440 "cabs.%Y3.<fmt>\t%0,%1,%2"
06a4ab70
CF
441 [(set_attr "type" "fcmp")
442 (set_attr "mode" "FPSW")])
443
06a4ab70 444
308cd611 445;----------------------------------------------------------------------------
c112cf2b 446; Floating Point Comparisons for Four Singles
308cd611 447;----------------------------------------------------------------------------
06a4ab70 448
308cd611 449(define_insn_and_split "mips_c_cond_4s"
06a4ab70
CF
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")
308cd611
RS
454 (match_operand:V2SF 4 "register_operand" "f")
455 (match_operand 5 "const_int_operand" "")]
456 UNSPEC_C))]
254d1646 457 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
308cd611
RS
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}
06a4ab70 474 [(set_attr "type" "fcmp")
710b6cc1 475 (set_attr "insn_count" "2")
06a4ab70
CF
476 (set_attr "mode" "FPSW")])
477
308cd611 478(define_insn_and_split "mips_cabs_cond_4s"
06a4ab70
CF
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")
308cd611
RS
483 (match_operand:V2SF 4 "register_operand" "f")
484 (match_operand 5 "const_int_operand" "")]
485 UNSPEC_CABS))]
63b9d91a 486 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
308cd611
RS
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}
06a4ab70 503 [(set_attr "type" "fcmp")
710b6cc1 504 (set_attr "insn_count" "2")
06a4ab70
CF
505 (set_attr "mode" "FPSW")])
506
06a4ab70
CF
507
508;----------------------------------------------------------------------------
c112cf2b 509; Floating Point Comparisons for Paired Singles
06a4ab70 510;----------------------------------------------------------------------------
06a4ab70 511
308cd611 512(define_insn "mips_c_cond_ps"
06a4ab70
CF
513 [(set (match_operand:CCV2 0 "register_operand" "=z")
514 (unspec:CCV2 [(match_operand:V2SF 1 "register_operand" "f")
308cd611
RS
515 (match_operand:V2SF 2 "register_operand" "f")
516 (match_operand 3 "const_int_operand" "")]
517 UNSPEC_C))]
254d1646 518 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
308cd611 519 "c.%Y3.ps\t%0,%1,%2"
06a4ab70
CF
520 [(set_attr "type" "fcmp")
521 (set_attr "mode" "FPSW")])
522
308cd611 523(define_insn "mips_cabs_cond_ps"
06a4ab70
CF
524 [(set (match_operand:CCV2 0 "register_operand" "=z")
525 (unspec:CCV2 [(match_operand:V2SF 1 "register_operand" "f")
308cd611
RS
526 (match_operand:V2SF 2 "register_operand" "f")
527 (match_operand 3 "const_int_operand" "")]
528 UNSPEC_CABS))]
63b9d91a 529 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
308cd611 530 "cabs.%Y3.ps\t%0,%1,%2"
06a4ab70
CF
531 [(set_attr "type" "fcmp")
532 (set_attr "mode" "FPSW")])
533
ec4fc7ed
RS
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))]
254d1646 545 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
ec4fc7ed
RS
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))]
254d1646 556 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
ec4fc7ed
RS
557 "c.<swapped_fcond>.ps\t%0,%2,%1"
558 [(set_attr "type" "fcmp")
559 (set_attr "mode" "FPSW")])
06a4ab70
CF
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)
0c433c31 568 (if_then_else (ne (match_operand:CCV4 1 "register_operand" "z")
a8c1d5f8 569 (const_int 0))
0c433c31 570 (label_ref (match_operand 0 "" ""))
06a4ab70 571 (pc)))]
63b9d91a 572 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
0c433c31
RS
573 "%*bc1any4t\t%1,%0%/"
574 [(set_attr "type" "branch")])
06a4ab70
CF
575
576; Branch on Any of Four Floating Point Condition Codes False
577(define_insn "bc1any4f"
578 [(set (pc)
0c433c31 579 (if_then_else (ne (match_operand:CCV4 1 "register_operand" "z")
a8c1d5f8 580 (const_int -1))
0c433c31 581 (label_ref (match_operand 0 "" ""))
06a4ab70 582 (pc)))]
63b9d91a 583 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
0c433c31
RS
584 "%*bc1any4f\t%1,%0%/"
585 [(set_attr "type" "branch")])
06a4ab70
CF
586
587; Branch on Any of Two Floating Point Condition Codes True
588(define_insn "bc1any2t"
589 [(set (pc)
0c433c31 590 (if_then_else (ne (match_operand:CCV2 1 "register_operand" "z")
a8c1d5f8 591 (const_int 0))
0c433c31 592 (label_ref (match_operand 0 "" ""))
06a4ab70 593 (pc)))]
63b9d91a 594 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
0c433c31
RS
595 "%*bc1any2t\t%1,%0%/"
596 [(set_attr "type" "branch")])
06a4ab70 597
06a4ab70
CF
598; Branch on Any of Two Floating Point Condition Codes False
599(define_insn "bc1any2f"
600 [(set (pc)
0c433c31 601 (if_then_else (ne (match_operand:CCV2 1 "register_operand" "z")
a8c1d5f8 602 (const_int -1))
0c433c31 603 (label_ref (match_operand 0 "" ""))
06a4ab70 604 (pc)))]
63b9d91a 605 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
0c433c31
RS
606 "%*bc1any2f\t%1,%0%/"
607 [(set_attr "type" "branch")])
06a4ab70 608
a8c1d5f8
RS
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
0c433c31 622 (match_operator 1 "equality_operator"
a8c1d5f8
RS
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)])
0c433c31 627 (label_ref (match_operand 0 "" ""))
a8c1d5f8
RS
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,
0c433c31
RS
634 MIPS_BRANCH ("b%F1", "%2,%0"),
635 MIPS_BRANCH ("b%W1", "%2,%0"));
a8c1d5f8 636}
0c433c31 637 [(set_attr "type" "branch")])
a8c1d5f8
RS
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
0c433c31 643 (match_operator 1 "equality_operator"
a8c1d5f8
RS
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)
0c433c31 649 (label_ref (match_operand 0 "" ""))))]
a8c1d5f8
RS
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,
0c433c31
RS
655 MIPS_BRANCH ("b%W1", "%2,%0"),
656 MIPS_BRANCH ("b%F1", "%2,%0"));
a8c1d5f8 657}
0c433c31 658 [(set_attr "type" "branch")])
a8c1d5f8 659
06a4ab70
CF
660;----------------------------------------------------------------------------
661; Floating Point Reduced Precision Reciprocal Square Root Instructions.
662;----------------------------------------------------------------------------
663
afa396ff
RS
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))]
63b9d91a 668 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
afa396ff 669 "rsqrt1.<fmt>\t%0,%1"
b30d77c4 670 [(set_attr "type" "frsqrt1")
afa396ff 671 (set_attr "mode" "<UNITMODE>")])
06a4ab70 672
afa396ff
RS
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))]
63b9d91a 678 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
afa396ff 679 "rsqrt2.<fmt>\t%0,%1,%2"
b30d77c4 680 [(set_attr "type" "frsqrt2")
afa396ff 681 (set_attr "mode" "<UNITMODE>")])
06a4ab70 682
afa396ff
RS
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))]
63b9d91a 687 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
afa396ff 688 "recip1.<fmt>\t%0,%1"
b30d77c4 689 [(set_attr "type" "frdiv1")
afa396ff 690 (set_attr "mode" "<UNITMODE>")])
06a4ab70 691
afa396ff
RS
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))]
63b9d91a 697 "TARGET_HARD_FLOAT && TARGET_MIPS3D"
afa396ff 698 "recip2.<fmt>\t%0,%1,%2"
b30d77c4 699 [(set_attr "type" "frdiv2")
afa396ff 700 (set_attr "mode" "<UNITMODE>")])
ec4fc7ed 701
e9e1d143 702(define_expand "vcondv2sfv2sf"
ec4fc7ed
RS
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")))]
254d1646 710 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
ec4fc7ed
RS
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")))]
254d1646 721 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
ec4fc7ed
RS
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")))]
254d1646 732 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
ec4fc7ed
RS
733{
734 mips_expand_vcondv2sf (operands[0], operands[1], operands[2],
735 LE, operands[2], operands[1]);
736 DONE;
737})
7dab511c 738
59a2f0fa
AL
739(define_expand "reduc_smin_scal_v2sf"
740 [(match_operand:SF 0 "register_operand")
7dab511c
RH
741 (match_operand:V2SF 1 "register_operand")]
742 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
743{
59a2f0fa
AL
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;
ff03930a 747 emit_insn (gen_vec_extractv2sfsf (operands[0], temp, lane));
7dab511c
RH
748 DONE;
749})
750
59a2f0fa
AL
751(define_expand "reduc_smax_scal_v2sf"
752 [(match_operand:SF 0 "register_operand")
7dab511c
RH
753 (match_operand:V2SF 1 "register_operand")]
754 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
755{
59a2f0fa
AL
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;
ff03930a 759 emit_insn (gen_vec_extractv2sfsf (operands[0], temp, lane));
7dab511c
RH
760 DONE;
761})