1;; PowerPC paired single and double hummer description
2;; Copyright (C) 2007-2018 Free Software Foundation, Inc.
3;; Contributed by David Edelsohn <edelsohn@gnu.org> and Revital Eres
4;; <eres@il.ibm.com>
5
6;; This file is part of GCC.
7
8;; GCC is free software; you can redistribute it and/or modify it
9;; under the terms of the GNU General Public License as published
10;; by the Free Software Foundation; either version 3, or (at your
11;; option) any later version.
12
13;; GCC is distributed in the hope that it will be useful, but WITHOUT
14;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16;; License for more details.
17;;
18;; You should have received a copy of the GNU General Public License
19;; along with this program; see the file COPYING3.  If not see
20;; <http://www.gnu.org/licenses/>.
21
22(define_c_enum "unspec"
23  [UNSPEC_INTERHI_V2SF
24   UNSPEC_INTERLO_V2SF
25   UNSPEC_EXTEVEN_V2SF
26   UNSPEC_EXTODD_V2SF
27  ])
28
29(define_insn "negv2sf2"
30  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
31	(neg:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "f")))]
32  "TARGET_PAIRED_FLOAT"
33  "ps_neg %0,%1"
34  [(set_attr "type" "fp")])
35
36(define_insn "sqrtv2sf2"
37  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
38	(sqrt:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "f")))]
39  "TARGET_PAIRED_FLOAT"
40  "ps_rsqrte %0,%1"
41  [(set_attr "type" "fp")])
42
43(define_insn "absv2sf2"
44  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
45	(abs:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "f")))]
46  "TARGET_PAIRED_FLOAT"
47  "ps_abs %0,%1"
48  [(set_attr "type" "fp")])
49
50(define_insn "nabsv2sf2"
51  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
52	(neg:V2SF (abs:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "f"))))]
53  "TARGET_PAIRED_FLOAT"
54  "ps_nabs %0,%1"
55  [(set_attr "type" "fp")])
56
57(define_insn "addv2sf3"
58  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
59	(plus:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "%f")
60		   (match_operand:V2SF 2 "gpc_reg_operand" "f")))]
61  "TARGET_PAIRED_FLOAT"
62  "ps_add %0,%1,%2"
63  [(set_attr "type" "fp")])
64
65(define_insn "subv2sf3"
66  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
67        (minus:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "f")
68                    (match_operand:V2SF 2 "gpc_reg_operand" "f")))]
69  "TARGET_PAIRED_FLOAT"
70  "ps_sub %0,%1,%2"
71  [(set_attr "type" "fp")])
72
73(define_insn "mulv2sf3"
74  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
75	(mult:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "%f")
76		   (match_operand:V2SF 2 "gpc_reg_operand" "f")))]
77  "TARGET_PAIRED_FLOAT"
78  "ps_mul %0,%1,%2"
79  [(set_attr "type" "fp")])
80
81(define_insn "resv2sf2"
82  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
83	(unspec:V2SF [(match_operand:V2SF 1 "gpc_reg_operand" "f")] UNSPEC_FRES))]
84  "TARGET_PAIRED_FLOAT && flag_finite_math_only"
85  "ps_res %0,%1"
86  [(set_attr "type" "fp")])
87
88(define_insn "divv2sf3"
89  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
90	(div:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "f")
91		  (match_operand:V2SF 2 "gpc_reg_operand" "f")))]
92  "TARGET_PAIRED_FLOAT"
93  "ps_div %0,%1,%2"
94  [(set_attr "type" "sdiv")])
95
96(define_insn "paired_madds0"
97 [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
98       (vec_concat:V2SF
99	 (fma:SF
100           (vec_select:SF (match_operand:V2SF 1 "gpc_reg_operand" "f")
101			  (parallel [(const_int 0)]))
102	   (vec_select:SF (match_operand:V2SF 2 "gpc_reg_operand" "f")
103                          (parallel [(const_int 0)]))
104	   (vec_select:SF (match_operand:V2SF 3 "gpc_reg_operand" "f")
105                          (parallel [(const_int 0)])))
106	 (fma:SF
107	   (vec_select:SF (match_dup 1)
108                          (parallel [(const_int 1)]))
109	   (vec_select:SF (match_dup 2)
110                          (parallel [(const_int 0)]))
111	   (vec_select:SF (match_dup 3)
112                          (parallel [(const_int 1)])))))]
113  "TARGET_PAIRED_FLOAT"
114  "ps_madds0 %0,%1,%2,%3"
115  [(set_attr "type" "fp")])
116
117(define_insn "paired_madds1"
118 [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
119       (vec_concat:V2SF
120         (fma:SF
121	   (vec_select:SF (match_operand:V2SF 1 "gpc_reg_operand" "f")
122                          (parallel [(const_int 0)]))
123           (vec_select:SF (match_operand:V2SF 2 "gpc_reg_operand" "f")
124                          (parallel [(const_int 1)]))
125           (vec_select:SF (match_operand:V2SF 3 "gpc_reg_operand" "f")
126                          (parallel [(const_int 0)])))
127	 (fma:SF
128	   (vec_select:SF (match_dup 1)
129                          (parallel [(const_int 1)]))
130           (vec_select:SF (match_dup 2)
131                          (parallel [(const_int 1)]))
132           (vec_select:SF (match_dup 3)
133                          (parallel [(const_int 1)])))))]
134  "TARGET_PAIRED_FLOAT"
135  "ps_madds1 %0,%1,%2,%3"
136  [(set_attr "type" "fp")])
137
138(define_insn "*paired_madd"
139  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
140	(fma:V2SF
141	  (match_operand:V2SF 1 "gpc_reg_operand" "f")
142	  (match_operand:V2SF 2 "gpc_reg_operand" "f")
143	  (match_operand:V2SF 3 "gpc_reg_operand" "f")))]
144  "TARGET_PAIRED_FLOAT"
145  "ps_madd %0,%1,%2,%3"
146  [(set_attr "type" "fp")])
147
148(define_insn "*paired_msub"
149  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
150	(fma:V2SF
151	  (match_operand:V2SF 1 "gpc_reg_operand" "f")
152	  (match_operand:V2SF 2 "gpc_reg_operand" "f")
153	  (neg:V2SF (match_operand:V2SF 3 "gpc_reg_operand" "f"))))]
154  "TARGET_PAIRED_FLOAT"
155  "ps_msub %0,%1,%2,%3"
156  [(set_attr "type" "fp")])
157
158(define_insn "*paired_nmadd"
159  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
160	(neg:V2SF
161	  (fma:V2SF
162	    (match_operand:V2SF 1 "gpc_reg_operand" "f")
163	    (match_operand:V2SF 2 "gpc_reg_operand" "f")
164	    (match_operand:V2SF 3 "gpc_reg_operand" "f"))))]
165  "TARGET_PAIRED_FLOAT"
166  "ps_nmadd %0,%1,%2,%3"
167  [(set_attr "type" "fp")])
168
169(define_insn "*paired_nmsub"
170  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
171	(neg:V2SF
172	  (fma:V2SF
173	    (match_operand:V2SF 1 "gpc_reg_operand" "f")
174	    (match_operand:V2SF 2 "gpc_reg_operand" "f")
175	    (neg:V2SF (match_operand:V2SF 3 "gpc_reg_operand" "f")))))]
176  "TARGET_PAIRED_FLOAT"
177  "ps_nmsub %0,%1,%2,%3"
178  [(set_attr "type" "dmul")])
179
180(define_insn "selv2sf4"
181  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
182	(vec_concat:V2SF
183	 (if_then_else:SF (ge (vec_select:SF (match_operand:V2SF 1 "gpc_reg_operand" "f")
184					     (parallel [(const_int 0)]))
185			      (match_operand:SF 4 "zero_fp_constant" "F"))
186			  (vec_select:SF (match_operand:V2SF 2 "gpc_reg_operand" "f")
187					 (parallel [(const_int 0)]))
188			  (vec_select:SF (match_operand:V2SF 3 "gpc_reg_operand" "f")
189					 (parallel [(const_int 0)])))
190	 (if_then_else:SF (ge (vec_select:SF (match_dup 1)
191					     (parallel [(const_int 1)]))
192			      (match_dup 4))
193			  (vec_select:SF (match_dup 2)
194					 (parallel [(const_int 1)]))
195			  (vec_select:SF (match_dup 3)
196					 (parallel [(const_int 1)])))))]
197
198  "TARGET_PAIRED_FLOAT"
199  "ps_sel %0,%1,%2,%3"
200  [(set_attr "type" "fp")])
201
202(define_insn "*movv2sf_paired"
203  [(set (match_operand:V2SF 0 "nonimmediate_operand" "=Z,f,f,Y,r,r,f")
204		 (match_operand:V2SF 1 "input_operand" "f,Z,f,r,Y,r,W"))]
205  "TARGET_PAIRED_FLOAT
206   && (register_operand (operands[0], V2SFmode)
207       || register_operand (operands[1], V2SFmode))"
208{
209  switch (which_alternative)
210    {
211    case 0: return "psq_stx %1,%y0,0,0";
212    case 1: return "psq_lx %0,%y1,0,0";
213    case 2: return "ps_mr %0,%1";
214    case 3: return "#";
215    case 4: return "#";
216    case 5: return "#";
217    case 6: return "#";
218    default: gcc_unreachable ();
219    }
220}
221  [(set_attr "type" "fpstore,fpload,fp,*,*,*,*")])
222
223(define_insn "paired_stx"
224  [(set (match_operand:V2SF 0 "memory_operand" "=Z")
225        (match_operand:V2SF 1 "gpc_reg_operand" "f"))]
226  "TARGET_PAIRED_FLOAT"
227  "psq_stx %1,%y0,0,0"
228  [(set_attr "type" "fpstore")])
229
230(define_insn "paired_lx"
231  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
232        (match_operand:V2SF 1 "memory_operand" "Z"))]
233  "TARGET_PAIRED_FLOAT"
234  "psq_lx %0,%y1,0,0"
235  [(set_attr "type" "fpload")])
236
237
238(define_split
239  [(set (match_operand:V2SF 0 "nonimmediate_operand" "")
240        (match_operand:V2SF 1 "input_operand" ""))]
241  "TARGET_PAIRED_FLOAT && reload_completed
242   && gpr_or_gpr_p (operands[0], operands[1])"
243  [(pc)]
244  {
245  rs6000_split_multireg_move (operands[0], operands[1]); DONE;
246  })
247
248(define_insn "paired_cmpu0"
249  [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
250	(compare:CCFP (vec_select:SF
251		       (match_operand:V2SF 1 "gpc_reg_operand" "f")
252		       (parallel [(const_int 0)]))
253		      (vec_select:SF
254		       (match_operand:V2SF 2 "gpc_reg_operand" "f")
255		       (parallel [(const_int 0)]))))]
256  "TARGET_PAIRED_FLOAT"
257  "ps_cmpu0 %0,%1,%2"
258  [(set_attr "type" "fpcompare")])
259
260(define_insn "paired_cmpu1"
261  [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
262	(compare:CCFP (vec_select:SF
263		       (match_operand:V2SF 1 "gpc_reg_operand" "f")
264		       (parallel [(const_int 1)]))
265		      (vec_select:SF
266		       (match_operand:V2SF 2 "gpc_reg_operand" "f")
267		       (parallel [(const_int 1)]))))]
268  "TARGET_PAIRED_FLOAT"
269  "ps_cmpu1 %0,%1,%2"
270  [(set_attr "type" "fpcompare")])
271
272(define_insn "paired_merge00"
273  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
274	(vec_select:V2SF
275	  (vec_concat:V4SF
276	    (match_operand:V2SF 1 "gpc_reg_operand" "f")
277	    (match_operand:V2SF 2 "gpc_reg_operand" "f"))
278	  (parallel [(const_int 0) (const_int 2)])))]
279  "TARGET_PAIRED_FLOAT"
280  "ps_merge00 %0, %1, %2"
281  [(set_attr "type" "fp")])
282
283(define_insn "paired_merge01"
284  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
285	(vec_select:V2SF
286	  (vec_concat:V4SF
287	    (match_operand:V2SF 1 "gpc_reg_operand" "f")
288	    (match_operand:V2SF 2 "gpc_reg_operand" "f"))
289	  (parallel [(const_int 0) (const_int 3)])))]
290  "TARGET_PAIRED_FLOAT"
291  "ps_merge01 %0, %1, %2"
292  [(set_attr "type" "fp")])
293
294(define_insn "paired_merge10"
295  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
296	(vec_select:V2SF
297	  (vec_concat:V4SF
298	    (match_operand:V2SF 1 "gpc_reg_operand" "f")
299	    (match_operand:V2SF 2 "gpc_reg_operand" "f"))
300	  (parallel [(const_int 1) (const_int 2)])))]
301  "TARGET_PAIRED_FLOAT"
302  "ps_merge10 %0, %1, %2"
303  [(set_attr "type" "fp")])
304
305(define_insn "paired_merge11"
306  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
307	(vec_select:V2SF
308	  (vec_concat:V4SF
309	    (match_operand:V2SF 1 "gpc_reg_operand" "f")
310	    (match_operand:V2SF 2 "gpc_reg_operand" "f"))
311	  (parallel [(const_int 1) (const_int 3)])))]
312  "TARGET_PAIRED_FLOAT"
313  "ps_merge11 %0, %1, %2"
314  [(set_attr "type" "fp")])
315
316(define_insn "paired_sum0"
317  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
318	(vec_concat:V2SF (plus:SF (vec_select:SF
319				   (match_operand:V2SF 1 "gpc_reg_operand" "f")
320				   (parallel [(const_int 0)]))
321				  (vec_select:SF
322				   (match_operand:V2SF 2 "gpc_reg_operand" "f")
323				   (parallel [(const_int 1)])))
324			 (vec_select:SF
325			  (match_operand:V2SF 3 "gpc_reg_operand" "f")
326			  (parallel [(const_int 1)]))))]
327  "TARGET_PAIRED_FLOAT"
328  "ps_sum0 %0,%1,%2,%3"
329  [(set_attr "type" "fp")])
330
331(define_insn "paired_sum1"
332  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
333	(vec_concat:V2SF (vec_select:SF
334			  (match_operand:V2SF 2 "gpc_reg_operand" "f")
335			  (parallel [(const_int 1)]))
336			 (plus:SF (vec_select:SF
337				   (match_operand:V2SF 1 "gpc_reg_operand" "f")
338				   (parallel [(const_int 0)]))
339				  (vec_select:SF
340				   (match_operand:V2SF 3 "gpc_reg_operand" "f")
341				   (parallel [(const_int 1)])))))]
342  "TARGET_PAIRED_FLOAT"
343  "ps_sum1 %0,%1,%2,%3"
344  [(set_attr "type" "fp")])
345
346(define_insn "paired_muls0"
347  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
348	(mult:V2SF (match_operand:V2SF 2 "gpc_reg_operand" "f")
349		   (vec_duplicate:V2SF
350		    (vec_select:SF (match_operand:V2SF 1 "gpc_reg_operand" "f")
351				   (parallel [(const_int 0)])))))]
352  "TARGET_PAIRED_FLOAT"
353  "ps_muls0 %0, %1, %2"
354  [(set_attr "type" "fp")])
355
356
357(define_insn "paired_muls1"
358  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
359	(mult:V2SF (match_operand:V2SF 2 "gpc_reg_operand" "f")
360		   (vec_duplicate:V2SF
361		    (vec_select:SF (match_operand:V2SF 1 "gpc_reg_operand" "f")
362				   (parallel [(const_int 1)])))))]
363  "TARGET_PAIRED_FLOAT"
364  "ps_muls1 %0, %1, %2"
365  [(set_attr "type" "fp")])
366
367(define_expand "vec_initv2sfsf"
368  [(match_operand:V2SF 0 "gpc_reg_operand" "=f")
369   (match_operand 1 "" "")]
370  "TARGET_PAIRED_FLOAT"
371{
372  paired_expand_vector_init (operands[0], operands[1]);
373  DONE;
374})
375
376(define_insn "*vconcatsf"
377  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
378        (vec_concat:V2SF
379         (match_operand:SF 1 "gpc_reg_operand" "f")
380         (match_operand:SF 2 "gpc_reg_operand" "f")))]
381  "TARGET_PAIRED_FLOAT"
382  "ps_merge00 %0, %1, %2"
383  [(set_attr "type" "fp")])
384
385(define_expand "sminv2sf3"
386  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
387        (smin:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "f")
388                   (match_operand:V2SF 2 "gpc_reg_operand" "f")))]
389  "TARGET_PAIRED_FLOAT"
390{
391  rtx tmp = gen_reg_rtx (V2SFmode);
392
393  emit_insn (gen_subv2sf3 (tmp, operands[1], operands[2]));
394  emit_insn (gen_selv2sf4 (operands[0], tmp, operands[2], operands[1], CONST0_RTX (SFmode)));
395  DONE;
396})
397
398(define_expand "smaxv2sf3"
399  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
400        (smax:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "f")
401                   (match_operand:V2SF 2 "gpc_reg_operand" "f")))]
402  "TARGET_PAIRED_FLOAT"
403{
404  rtx tmp = gen_reg_rtx (V2SFmode);
405
406  emit_insn (gen_subv2sf3 (tmp, operands[1], operands[2]));
407  emit_insn (gen_selv2sf4 (operands[0], tmp, operands[1], operands[2], CONST0_RTX (SFmode)));
408  DONE;
409})
410
411(define_expand "reduc_smax_scal_v2sf"
412  [(match_operand:SF 0 "gpc_reg_operand" "=f")
413   (match_operand:V2SF 1 "gpc_reg_operand" "f")]
414  "TARGET_PAIRED_FLOAT"
415{
416  rtx tmp_swap = gen_reg_rtx (V2SFmode);
417  rtx tmp = gen_reg_rtx (V2SFmode);
418  rtx vec_res = gen_reg_rtx (V2SFmode);
419  rtx di_res = gen_reg_rtx (DImode);
420
421  emit_insn (gen_paired_merge10 (tmp_swap, operands[1], operands[1]));
422  emit_insn (gen_subv2sf3 (tmp, operands[1], tmp_swap));
423  emit_insn (gen_selv2sf4 (vec_res, tmp, operands[1], tmp_swap,
424			   CONST0_RTX (SFmode)));
425  emit_move_insn (di_res, simplify_gen_subreg (DImode, vec_res, V2SFmode, 0));
426  emit_move_insn (operands[0], simplify_gen_subreg (SFmode, di_res, DImode,
427						    BYTES_BIG_ENDIAN ? 4 : 0));
428
429  DONE;
430})
431
432(define_expand "reduc_smin_scal_v2sf"
433  [(match_operand:SF 0 "gpc_reg_operand" "=f")
434   (match_operand:V2SF 1 "gpc_reg_operand" "f")]
435  "TARGET_PAIRED_FLOAT"
436{
437  rtx tmp_swap = gen_reg_rtx (V2SFmode);
438  rtx tmp = gen_reg_rtx (V2SFmode);
439  rtx vec_res = gen_reg_rtx (V2SFmode);
440  rtx di_res = gen_reg_rtx (DImode);
441
442  emit_insn (gen_paired_merge10 (tmp_swap, operands[1], operands[1]));
443  emit_insn (gen_subv2sf3 (tmp, operands[1], tmp_swap));
444  emit_insn (gen_selv2sf4 (vec_res, tmp, tmp_swap, operands[1],
445			   CONST0_RTX (SFmode)));
446  emit_move_insn (di_res, simplify_gen_subreg (DImode, vec_res, V2SFmode, 0));
447  emit_move_insn (operands[0], simplify_gen_subreg (SFmode, di_res, DImode,
448						    BYTES_BIG_ENDIAN ? 4 : 0));
449
450  DONE;
451})
452
453(define_expand "reduc_plus_scal_v2sf"
454  [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
455        (match_operand:V2SF 1 "gpc_reg_operand" "f"))]
456  "TARGET_PAIRED_FLOAT"
457{
458  rtx vec_res = gen_reg_rtx (V2SFmode);
459  rtx di_res = gen_reg_rtx (DImode);
460
461  emit_insn (gen_paired_sum1 (vec_res, operands[1], operands[1], operands[1]));
462  emit_move_insn (di_res, simplify_gen_subreg (DImode, vec_res, V2SFmode, 0));
463  emit_move_insn (operands[0], simplify_gen_subreg (SFmode, di_res, DImode,
464						    BYTES_BIG_ENDIAN ? 4 : 0));
465  DONE;
466})
467
468(define_expand "movmisalignv2sf"
469  [(set (match_operand:V2SF 0 "nonimmediate_operand" "")
470        (match_operand:V2SF 1 "any_operand" ""))]
471  "TARGET_PAIRED_FLOAT"
472{
473  paired_expand_vector_move (operands);
474  DONE;
475})
476
477(define_expand "vcondv2sfv2sf"
478  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
479        (if_then_else:V2SF
480         (match_operator 3 "gpc_reg_operand"
481                         [(match_operand:V2SF 4 "gpc_reg_operand" "f")
482                          (match_operand:V2SF 5 "gpc_reg_operand" "f")])
483         (match_operand:V2SF 1 "gpc_reg_operand" "f")
484         (match_operand:V2SF 2 "gpc_reg_operand" "f")))]
485  "TARGET_PAIRED_FLOAT && flag_unsafe_math_optimizations"
486{
487  if (paired_emit_vector_cond_expr (operands[0], operands[1], operands[2],
488                                    operands[3], operands[4], operands[5]))
489    DONE;
490  else
491    FAIL;
492})
493