1;; Machine Description for shared bits common to IWMMXT and Neon.
2;; Copyright (C) 2006-2020 Free Software Foundation, Inc.
3;; Written by CodeSourcery.
4;;
5;; This file is part of GCC.
6;;
7;; GCC is free software; you can redistribute it and/or modify it
8;; under the terms of the GNU General Public License as published by
9;; the Free Software Foundation; either version 3, or (at your option)
10;; any later version.
11;;
12;; GCC is distributed in the hope that it will be useful, but
13;; WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15;; General Public License for more details.
16;;
17;; You should have received a copy of the GNU General Public License
18;; along with GCC; see the file COPYING3.  If not see
19;; <http://www.gnu.org/licenses/>.
20
21;; Vector Moves
22
23(define_expand "mov<mode>"
24  [(set (match_operand:VNIM1 0 "nonimmediate_operand")
25	(match_operand:VNIM1 1 "general_operand"))]
26  "TARGET_NEON
27   || (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (<MODE>mode))
28   || (TARGET_HAVE_MVE && VALID_MVE_SI_MODE (<MODE>mode))
29   || (TARGET_HAVE_MVE_FLOAT && VALID_MVE_SF_MODE (<MODE>mode))"
30   {
31  gcc_checking_assert (aligned_operand (operands[0], <MODE>mode));
32  gcc_checking_assert (aligned_operand (operands[1], <MODE>mode));
33  if (can_create_pseudo_p ())
34    {
35      if (!REG_P (operands[0]))
36	operands[1] = force_reg (<MODE>mode, operands[1]);
37      else if ((TARGET_NEON || TARGET_HAVE_MVE || TARGET_HAVE_MVE_FLOAT)
38	       && (CONSTANT_P (operands[1])))
39	{
40	  operands[1] = neon_make_constant (operands[1]);
41	  gcc_assert (operands[1] != NULL_RTX);
42	}
43    }
44})
45
46(define_expand "mov<mode>"
47  [(set (match_operand:VNINOTM1 0 "nonimmediate_operand")
48	(match_operand:VNINOTM1 1 "general_operand"))]
49  "TARGET_NEON
50   || (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (<MODE>mode))"
51{
52  gcc_checking_assert (aligned_operand (operands[0], <MODE>mode));
53  gcc_checking_assert (aligned_operand (operands[1], <MODE>mode));
54  if (can_create_pseudo_p ())
55    {
56      if (!REG_P (operands[0]))
57	operands[1] = force_reg (<MODE>mode, operands[1]);
58      else if (TARGET_NEON && CONSTANT_P (operands[1]))
59	{
60	  operands[1] = neon_make_constant (operands[1]);
61	  gcc_assert (operands[1] != NULL_RTX);
62	}
63    }
64})
65
66(define_expand "movv8hf"
67  [(set (match_operand:V8HF 0 "s_register_operand")
68       (match_operand:V8HF 1 "s_register_operand"))]
69   "TARGET_NEON || TARGET_HAVE_MVE_FLOAT"
70{
71  gcc_checking_assert (aligned_operand (operands[0], E_V8HFmode));
72  gcc_checking_assert (aligned_operand (operands[1], E_V8HFmode));
73   if (can_create_pseudo_p ())
74     {
75       if (!REG_P (operands[0]))
76	 operands[1] = force_reg (E_V8HFmode, operands[1]);
77	else if (TARGET_HAVE_MVE_FLOAT && CONSTANT_P (operands[1]))
78	  {
79	    operands[1] = neon_make_constant (operands[1]);
80	    gcc_assert (operands[1] != NULL_RTX);
81	  }
82     }
83})
84
85;; Vector arithmetic.  Expanders are blank, then unnamed insns implement
86;; patterns separately for Neon, IWMMXT and MVE.
87
88(define_expand "add<mode>3"
89  [(set (match_operand:VNIM 0 "s_register_operand")
90	(plus:VNIM (match_operand:VNIM 1 "s_register_operand")
91		   (match_operand:VNIM 2 "s_register_operand")))]
92  "(TARGET_NEON && ((<MODE>mode != V2SFmode && <MODE>mode != V4SFmode)
93		    || flag_unsafe_math_optimizations))
94   || (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (<MODE>mode))
95   || (TARGET_HAVE_MVE && VALID_MVE_SI_MODE(<MODE>mode))
96   || (TARGET_HAVE_MVE_FLOAT && VALID_MVE_SF_MODE(<MODE>mode))"
97{
98})
99
100;; Vector arithmetic.  Expanders are blank, then unnamed insns implement
101;; patterns separately for Neon and MVE.
102
103(define_expand "addv8hf3"
104  [(set (match_operand:V8HF 0 "s_register_operand")
105	(plus:V8HF (match_operand:V8HF 1 "s_register_operand")
106		   (match_operand:V8HF 2 "s_register_operand")))]
107  "(TARGET_HAVE_MVE_FLOAT && VALID_MVE_SF_MODE(V8HFmode))
108   || (TARGET_NEON_FP16INST && flag_unsafe_math_optimizations)"
109{
110  if (TARGET_NEON_FP16INST && flag_unsafe_math_optimizations)
111    emit_insn (gen_addv8hf3_neon (operands[0], operands[1], operands[2]));
112})
113
114;; Vector arithmetic.  Expanders are blank, then unnamed insns implement
115;; patterns separately for Neon and IWMMXT.
116
117(define_expand "add<mode>3"
118  [(set (match_operand:VNINOTM 0 "s_register_operand")
119	(plus:VNINOTM (match_operand:VNINOTM 1 "s_register_operand")
120		      (match_operand:VNINOTM 2 "s_register_operand")))]
121  "(TARGET_NEON && ((<MODE>mode != V2SFmode && <MODE>mode != V4SFmode)
122		    || flag_unsafe_math_optimizations))
123   || (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (<MODE>mode))"
124{
125})
126
127;; Vector arithmetic. Expanders are blank, then unnamed insns implement
128;; patterns separately for IWMMXT and Neon.
129
130(define_expand "sub<mode>3"
131  [(set (match_operand:VALL 0 "s_register_operand")
132        (minus:VALL (match_operand:VALL 1 "s_register_operand")
133                    (match_operand:VALL 2 "s_register_operand")))]
134  "(TARGET_NEON && ((<MODE>mode != V2SFmode && <MODE>mode != V4SFmode)
135		    || flag_unsafe_math_optimizations))
136   || (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (<MODE>mode))"
137{
138})
139
140(define_expand "mul<mode>3"
141  [(set (match_operand:VALLW 0 "s_register_operand")
142        (mult:VALLW (match_operand:VALLW 1 "s_register_operand")
143		    (match_operand:VALLW 2 "s_register_operand")))]
144  "(TARGET_NEON && ((<MODE>mode != V2SFmode && <MODE>mode != V4SFmode)
145		    || flag_unsafe_math_optimizations))
146   || (<MODE>mode == V4HImode && TARGET_REALLY_IWMMXT)"
147{
148})
149
150(define_expand "smin<mode>3"
151  [(set (match_operand:VALLW 0 "s_register_operand")
152	(smin:VALLW (match_operand:VALLW 1 "s_register_operand")
153		    (match_operand:VALLW 2 "s_register_operand")))]
154  "(TARGET_NEON && ((<MODE>mode != V2SFmode && <MODE>mode != V4SFmode)
155		    || flag_unsafe_math_optimizations))
156   || (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (<MODE>mode))"
157{
158})
159
160(define_expand "umin<mode>3"
161  [(set (match_operand:VINTW 0 "s_register_operand")
162	(umin:VINTW (match_operand:VINTW 1 "s_register_operand")
163		    (match_operand:VINTW 2 "s_register_operand")))]
164  "TARGET_NEON
165   || (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (<MODE>mode))"
166{
167})
168
169(define_expand "smax<mode>3"
170  [(set (match_operand:VALLW 0 "s_register_operand")
171	(smax:VALLW (match_operand:VALLW 1 "s_register_operand")
172		    (match_operand:VALLW 2 "s_register_operand")))]
173  "(TARGET_NEON && ((<MODE>mode != V2SFmode && <MODE>mode != V4SFmode)
174		    || flag_unsafe_math_optimizations))
175   || (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (<MODE>mode))"
176{
177})
178
179(define_expand "umax<mode>3"
180  [(set (match_operand:VINTW 0 "s_register_operand")
181	(umax:VINTW (match_operand:VINTW 1 "s_register_operand")
182		    (match_operand:VINTW 2 "s_register_operand")))]
183  "TARGET_NEON
184   || (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (<MODE>mode))"
185{
186})
187
188(define_expand "vec_perm<mode>"
189  [(match_operand:VE 0 "s_register_operand")
190   (match_operand:VE 1 "s_register_operand")
191   (match_operand:VE 2 "s_register_operand")
192   (match_operand:VE 3 "s_register_operand")]
193  "TARGET_NEON && !BYTES_BIG_ENDIAN"
194{
195  arm_expand_vec_perm (operands[0], operands[1], operands[2], operands[3]);
196  DONE;
197})
198
199(define_expand "vec_extract<mode><V_elem_l>"
200 [(match_operand:<V_elem> 0 "nonimmediate_operand")
201  (match_operand:VQX_NOBF 1 "s_register_operand")
202  (match_operand:SI 2 "immediate_operand")]
203 "TARGET_NEON || TARGET_HAVE_MVE"
204{
205  if (TARGET_NEON)
206    emit_insn (gen_neon_vec_extract<mode><V_elem_l> (operands[0], operands[1],
207						     operands[2]));
208  else if (TARGET_HAVE_MVE)
209    emit_insn (gen_mve_vec_extract<mode><V_elem_l> (operands[0], operands[1],
210						     operands[2]));
211  else
212    gcc_unreachable ();
213  DONE;
214})
215
216(define_expand "vec_set<mode>"
217  [(match_operand:VQX_NOBF 0 "s_register_operand" "")
218   (match_operand:<V_elem> 1 "s_register_operand" "")
219   (match_operand:SI 2 "immediate_operand" "")]
220  "TARGET_NEON || TARGET_HAVE_MVE"
221{
222  HOST_WIDE_INT elem = HOST_WIDE_INT_1 << INTVAL (operands[2]);
223  if (TARGET_NEON)
224    emit_insn (gen_vec_set<mode>_internal (operands[0], operands[1],
225					   GEN_INT (elem), operands[0]));
226  else
227    emit_insn (gen_mve_vec_set<mode>_internal (operands[0], operands[1],
228					       GEN_INT (elem), operands[0]));
229  DONE;
230})
231