]>
Commit | Line | Data |
---|---|---|
06a4ab70 | 1 | ;; MIPS Paired-Single Floating and MIPS-3D Instructions. |
a5544970 | 2 | ;; Copyright (C) 2004-2019 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 | }) |