1 ;; ARM NEON coprocessor Machine Description
2 ;; Copyright (C) 2006-2013 Free Software Foundation, Inc.
3 ;; Written by CodeSourcery.
5 ;; This file is part of GCC.
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)
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.
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/>.
22 ;; Attribute used to permit string comparisons against <VQH_mnem> in
23 ;; neon_type attribute definitions.
24 (define_attr "vqh_mnem" "vadd,vmin,vmax" (const_string "vadd"))
26 (define_insn "*neon_mov<mode>"
27 [(set (match_operand:VDX 0 "nonimmediate_operand"
28 "=w,Un,w, w, ?r,?w,?r,?r, ?Us")
29 (match_operand:VDX 1 "general_operand"
30 " w,w, Dn,Uni, w, r, r, Usi,r"))]
32 && (register_operand (operands[0], <MODE>mode)
33 || register_operand (operands[1], <MODE>mode))"
35 if (which_alternative == 2)
38 static char templ[40];
40 is_valid = neon_immediate_valid_for_move (operands[1], <MODE>mode,
41 &operands[1], &width);
43 gcc_assert (is_valid != 0);
46 return "vmov.f32\t%P0, %1 @ <mode>";
48 sprintf (templ, "vmov.i%d\t%%P0, %%x1 @ <mode>", width);
53 switch (which_alternative)
55 case 0: return "vmov\t%P0, %P1 @ <mode>";
56 case 1: case 3: return output_move_neon (operands);
57 case 2: gcc_unreachable ();
58 case 4: return "vmov\t%Q0, %R0, %P1 @ <mode>";
59 case 5: return "vmov\t%P0, %Q1, %R1 @ <mode>";
60 default: return output_move_double (operands, true, NULL);
63 [(set_attr "neon_type" "neon_int_1,*,neon_vmov,*,neon_mrrc,neon_mcr_2_mcrr,*,*,*")
64 (set_attr "type" "*,f_stored,*,f_loadd,*,*,alu_reg,load2,store2")
65 (set_attr "insn" "*,*,*,*,*,*,mov,*,*")
66 (set_attr "length" "4,4,4,4,4,4,8,8,8")
67 (set_attr "arm_pool_range" "*,*,*,1020,*,*,*,1020,*")
68 (set_attr "thumb2_pool_range" "*,*,*,1018,*,*,*,1018,*")
69 (set_attr "neg_pool_range" "*,*,*,1004,*,*,*,1004,*")])
71 (define_insn "*neon_mov<mode>"
72 [(set (match_operand:VQXMOV 0 "nonimmediate_operand"
73 "=w,Un,w, w, ?r,?w,?r,?r, ?Us")
74 (match_operand:VQXMOV 1 "general_operand"
75 " w,w, Dn,Uni, w, r, r, Usi, r"))]
77 && (register_operand (operands[0], <MODE>mode)
78 || register_operand (operands[1], <MODE>mode))"
80 if (which_alternative == 2)
83 static char templ[40];
85 is_valid = neon_immediate_valid_for_move (operands[1], <MODE>mode,
86 &operands[1], &width);
88 gcc_assert (is_valid != 0);
91 return "vmov.f32\t%q0, %1 @ <mode>";
93 sprintf (templ, "vmov.i%d\t%%q0, %%1 @ <mode>", width);
98 switch (which_alternative)
100 case 0: return "vmov\t%q0, %q1 @ <mode>";
101 case 1: case 3: return output_move_neon (operands);
102 case 2: gcc_unreachable ();
103 case 4: return "vmov\t%Q0, %R0, %e1 @ <mode>\;vmov\t%J0, %K0, %f1";
104 case 5: return "vmov\t%e0, %Q1, %R1 @ <mode>\;vmov\t%f0, %J1, %K1";
105 default: return output_move_quad (operands);
108 [(set_attr "neon_type" "neon_int_1,neon_stm_2,neon_vmov,neon_ldm_2,\
109 neon_mrrc,neon_mcr_2_mcrr,*,*,*")
110 (set_attr "type" "*,*,*,*,*,*,alu_reg,load4,store4")
111 (set_attr "insn" "*,*,*,*,*,*,mov,*,*")
112 (set_attr "length" "4,8,4,8,8,8,16,8,16")
113 (set_attr "arm_pool_range" "*,*,*,1020,*,*,*,1020,*")
114 (set_attr "thumb2_pool_range" "*,*,*,1018,*,*,*,1018,*")
115 (set_attr "neg_pool_range" "*,*,*,996,*,*,*,996,*")])
117 (define_expand "movti"
118 [(set (match_operand:TI 0 "nonimmediate_operand" "")
119 (match_operand:TI 1 "general_operand" ""))]
122 if (can_create_pseudo_p ())
124 if (!REG_P (operands[0]))
125 operands[1] = force_reg (TImode, operands[1]);
129 (define_expand "mov<mode>"
130 [(set (match_operand:VSTRUCT 0 "nonimmediate_operand" "")
131 (match_operand:VSTRUCT 1 "general_operand" ""))]
134 if (can_create_pseudo_p ())
136 if (!REG_P (operands[0]))
137 operands[1] = force_reg (<MODE>mode, operands[1]);
141 (define_insn "*neon_mov<mode>"
142 [(set (match_operand:VSTRUCT 0 "nonimmediate_operand" "=w,Ut,w")
143 (match_operand:VSTRUCT 1 "general_operand" " w,w, Ut"))]
145 && (register_operand (operands[0], <MODE>mode)
146 || register_operand (operands[1], <MODE>mode))"
148 switch (which_alternative)
151 case 1: case 2: return output_move_neon (operands);
152 default: gcc_unreachable ();
155 [(set_attr "neon_type" "neon_int_1,neon_stm_2,neon_ldm_2")
156 (set (attr "length") (symbol_ref "arm_attr_length_move_neon (insn)"))])
159 [(set (match_operand:EI 0 "s_register_operand" "")
160 (match_operand:EI 1 "s_register_operand" ""))]
161 "TARGET_NEON && reload_completed"
162 [(set (match_dup 0) (match_dup 1))
163 (set (match_dup 2) (match_dup 3))]
165 int rdest = REGNO (operands[0]);
166 int rsrc = REGNO (operands[1]);
169 dest[0] = gen_rtx_REG (TImode, rdest);
170 src[0] = gen_rtx_REG (TImode, rsrc);
171 dest[1] = gen_rtx_REG (DImode, rdest + 4);
172 src[1] = gen_rtx_REG (DImode, rsrc + 4);
174 neon_disambiguate_copy (operands, dest, src, 2);
178 [(set (match_operand:OI 0 "s_register_operand" "")
179 (match_operand:OI 1 "s_register_operand" ""))]
180 "TARGET_NEON && reload_completed"
181 [(set (match_dup 0) (match_dup 1))
182 (set (match_dup 2) (match_dup 3))]
184 int rdest = REGNO (operands[0]);
185 int rsrc = REGNO (operands[1]);
188 dest[0] = gen_rtx_REG (TImode, rdest);
189 src[0] = gen_rtx_REG (TImode, rsrc);
190 dest[1] = gen_rtx_REG (TImode, rdest + 4);
191 src[1] = gen_rtx_REG (TImode, rsrc + 4);
193 neon_disambiguate_copy (operands, dest, src, 2);
197 [(set (match_operand:CI 0 "s_register_operand" "")
198 (match_operand:CI 1 "s_register_operand" ""))]
199 "TARGET_NEON && reload_completed"
200 [(set (match_dup 0) (match_dup 1))
201 (set (match_dup 2) (match_dup 3))
202 (set (match_dup 4) (match_dup 5))]
204 int rdest = REGNO (operands[0]);
205 int rsrc = REGNO (operands[1]);
208 dest[0] = gen_rtx_REG (TImode, rdest);
209 src[0] = gen_rtx_REG (TImode, rsrc);
210 dest[1] = gen_rtx_REG (TImode, rdest + 4);
211 src[1] = gen_rtx_REG (TImode, rsrc + 4);
212 dest[2] = gen_rtx_REG (TImode, rdest + 8);
213 src[2] = gen_rtx_REG (TImode, rsrc + 8);
215 neon_disambiguate_copy (operands, dest, src, 3);
219 [(set (match_operand:XI 0 "s_register_operand" "")
220 (match_operand:XI 1 "s_register_operand" ""))]
221 "TARGET_NEON && reload_completed"
222 [(set (match_dup 0) (match_dup 1))
223 (set (match_dup 2) (match_dup 3))
224 (set (match_dup 4) (match_dup 5))
225 (set (match_dup 6) (match_dup 7))]
227 int rdest = REGNO (operands[0]);
228 int rsrc = REGNO (operands[1]);
231 dest[0] = gen_rtx_REG (TImode, rdest);
232 src[0] = gen_rtx_REG (TImode, rsrc);
233 dest[1] = gen_rtx_REG (TImode, rdest + 4);
234 src[1] = gen_rtx_REG (TImode, rsrc + 4);
235 dest[2] = gen_rtx_REG (TImode, rdest + 8);
236 src[2] = gen_rtx_REG (TImode, rsrc + 8);
237 dest[3] = gen_rtx_REG (TImode, rdest + 12);
238 src[3] = gen_rtx_REG (TImode, rsrc + 12);
240 neon_disambiguate_copy (operands, dest, src, 4);
243 (define_expand "movmisalign<mode>"
244 [(set (match_operand:VDQX 0 "neon_struct_or_register_operand")
245 (unspec:VDQX [(match_operand:VDQX 1 "neon_struct_or_register_operand")]
246 UNSPEC_MISALIGNED_ACCESS))]
247 "TARGET_NEON && !BYTES_BIG_ENDIAN"
249 /* This pattern is not permitted to fail during expansion: if both arguments
250 are non-registers (e.g. memory := constant, which can be created by the
251 auto-vectorizer), force operand 1 into a register. */
252 if (!s_register_operand (operands[0], <MODE>mode)
253 && !s_register_operand (operands[1], <MODE>mode))
254 operands[1] = force_reg (<MODE>mode, operands[1]);
257 (define_insn "*movmisalign<mode>_neon_store"
258 [(set (match_operand:VDX 0 "neon_struct_operand" "=Um")
259 (unspec:VDX [(match_operand:VDX 1 "s_register_operand" " w")]
260 UNSPEC_MISALIGNED_ACCESS))]
261 "TARGET_NEON && !BYTES_BIG_ENDIAN"
262 "vst1.<V_sz_elem>\t{%P1}, %A0"
263 [(set_attr "neon_type" "neon_vst1_1_2_regs_vst2_2_regs")])
265 (define_insn "*movmisalign<mode>_neon_load"
266 [(set (match_operand:VDX 0 "s_register_operand" "=w")
267 (unspec:VDX [(match_operand:VDX 1 "neon_struct_operand" " Um")]
268 UNSPEC_MISALIGNED_ACCESS))]
269 "TARGET_NEON && !BYTES_BIG_ENDIAN"
270 "vld1.<V_sz_elem>\t{%P0}, %A1"
271 [(set_attr "neon_type" "neon_vld1_1_2_regs")])
273 (define_insn "*movmisalign<mode>_neon_store"
274 [(set (match_operand:VQX 0 "neon_struct_operand" "=Um")
275 (unspec:VQX [(match_operand:VQX 1 "s_register_operand" " w")]
276 UNSPEC_MISALIGNED_ACCESS))]
277 "TARGET_NEON && !BYTES_BIG_ENDIAN"
278 "vst1.<V_sz_elem>\t{%q1}, %A0"
279 [(set_attr "neon_type" "neon_vst1_1_2_regs_vst2_2_regs")])
281 (define_insn "*movmisalign<mode>_neon_load"
282 [(set (match_operand:VQX 0 "s_register_operand" "=w")
283 (unspec:VQX [(match_operand:VQX 1 "neon_struct_operand" " Um")]
284 UNSPEC_MISALIGNED_ACCESS))]
285 "TARGET_NEON && !BYTES_BIG_ENDIAN"
286 "vld1.<V_sz_elem>\t{%q0}, %A1"
287 [(set_attr "neon_type" "neon_vld1_1_2_regs")])
289 (define_insn "vec_set<mode>_internal"
290 [(set (match_operand:VD 0 "s_register_operand" "=w,w")
293 (match_operand:<V_elem> 1 "nonimmediate_operand" "Um,r"))
294 (match_operand:VD 3 "s_register_operand" "0,0")
295 (match_operand:SI 2 "immediate_operand" "i,i")))]
298 int elt = ffs ((int) INTVAL (operands[2])) - 1;
299 if (BYTES_BIG_ENDIAN)
300 elt = GET_MODE_NUNITS (<MODE>mode) - 1 - elt;
301 operands[2] = GEN_INT (elt);
303 if (which_alternative == 0)
304 return "vld1.<V_sz_elem>\t{%P0[%c2]}, %A1";
306 return "vmov.<V_sz_elem>\t%P0[%c2], %1";
308 [(set_attr "neon_type" "neon_vld1_vld2_lane,neon_mcr")])
310 (define_insn "vec_set<mode>_internal"
311 [(set (match_operand:VQ 0 "s_register_operand" "=w,w")
314 (match_operand:<V_elem> 1 "nonimmediate_operand" "Um,r"))
315 (match_operand:VQ 3 "s_register_operand" "0,0")
316 (match_operand:SI 2 "immediate_operand" "i,i")))]
319 HOST_WIDE_INT elem = ffs ((int) INTVAL (operands[2])) - 1;
320 int half_elts = GET_MODE_NUNITS (<MODE>mode) / 2;
321 int elt = elem % half_elts;
322 int hi = (elem / half_elts) * 2;
323 int regno = REGNO (operands[0]);
325 if (BYTES_BIG_ENDIAN)
326 elt = half_elts - 1 - elt;
328 operands[0] = gen_rtx_REG (<V_HALF>mode, regno + hi);
329 operands[2] = GEN_INT (elt);
331 if (which_alternative == 0)
332 return "vld1.<V_sz_elem>\t{%P0[%c2]}, %A1";
334 return "vmov.<V_sz_elem>\t%P0[%c2], %1";
336 [(set_attr "neon_type" "neon_vld1_vld2_lane,neon_mcr")]
339 (define_insn "vec_setv2di_internal"
340 [(set (match_operand:V2DI 0 "s_register_operand" "=w,w")
343 (match_operand:DI 1 "nonimmediate_operand" "Um,r"))
344 (match_operand:V2DI 3 "s_register_operand" "0,0")
345 (match_operand:SI 2 "immediate_operand" "i,i")))]
348 HOST_WIDE_INT elem = ffs ((int) INTVAL (operands[2])) - 1;
349 int regno = REGNO (operands[0]) + 2 * elem;
351 operands[0] = gen_rtx_REG (DImode, regno);
353 if (which_alternative == 0)
354 return "vld1.64\t%P0, %A1";
356 return "vmov\t%P0, %Q1, %R1";
358 [(set_attr "neon_type" "neon_vld1_1_2_regs,neon_mcr_2_mcrr")]
361 (define_expand "vec_set<mode>"
362 [(match_operand:VDQ 0 "s_register_operand" "")
363 (match_operand:<V_elem> 1 "s_register_operand" "")
364 (match_operand:SI 2 "immediate_operand" "")]
367 HOST_WIDE_INT elem = (HOST_WIDE_INT) 1 << INTVAL (operands[2]);
368 emit_insn (gen_vec_set<mode>_internal (operands[0], operands[1],
369 GEN_INT (elem), operands[0]));
373 (define_insn "vec_extract<mode>"
374 [(set (match_operand:<V_elem> 0 "nonimmediate_operand" "=Um,r")
376 (match_operand:VD 1 "s_register_operand" "w,w")
377 (parallel [(match_operand:SI 2 "immediate_operand" "i,i")])))]
380 if (BYTES_BIG_ENDIAN)
382 int elt = INTVAL (operands[2]);
383 elt = GET_MODE_NUNITS (<MODE>mode) - 1 - elt;
384 operands[2] = GEN_INT (elt);
387 if (which_alternative == 0)
388 return "vst1.<V_sz_elem>\t{%P1[%c2]}, %A0";
390 return "vmov.<V_uf_sclr>\t%0, %P1[%c2]";
392 [(set_attr "neon_type" "neon_vst1_vst2_lane,neon_bp_simple")]
395 (define_insn "vec_extract<mode>"
396 [(set (match_operand:<V_elem> 0 "nonimmediate_operand" "=Um,r")
398 (match_operand:VQ 1 "s_register_operand" "w,w")
399 (parallel [(match_operand:SI 2 "immediate_operand" "i,i")])))]
402 int half_elts = GET_MODE_NUNITS (<MODE>mode) / 2;
403 int elt = INTVAL (operands[2]) % half_elts;
404 int hi = (INTVAL (operands[2]) / half_elts) * 2;
405 int regno = REGNO (operands[1]);
407 if (BYTES_BIG_ENDIAN)
408 elt = half_elts - 1 - elt;
410 operands[1] = gen_rtx_REG (<V_HALF>mode, regno + hi);
411 operands[2] = GEN_INT (elt);
413 if (which_alternative == 0)
414 return "vst1.<V_sz_elem>\t{%P1[%c2]}, %A0";
416 return "vmov.<V_uf_sclr>\t%0, %P1[%c2]";
418 [(set_attr "neon_type" "neon_vst1_vst2_lane,neon_bp_simple")]
421 (define_insn "vec_extractv2di"
422 [(set (match_operand:DI 0 "nonimmediate_operand" "=Um,r")
424 (match_operand:V2DI 1 "s_register_operand" "w,w")
425 (parallel [(match_operand:SI 2 "immediate_operand" "i,i")])))]
428 int regno = REGNO (operands[1]) + 2 * INTVAL (operands[2]);
430 operands[1] = gen_rtx_REG (DImode, regno);
432 if (which_alternative == 0)
433 return "vst1.64\t{%P1}, %A0 @ v2di";
435 return "vmov\t%Q0, %R0, %P1 @ v2di";
437 [(set_attr "neon_type" "neon_vst1_vst2_lane,neon_int_1")]
440 (define_expand "vec_init<mode>"
441 [(match_operand:VDQ 0 "s_register_operand" "")
442 (match_operand 1 "" "")]
445 neon_expand_vector_init (operands[0], operands[1]);
449 ;; Doubleword and quadword arithmetic.
451 ;; NOTE: some other instructions also support 64-bit integer
452 ;; element size, which we could potentially use for "long long" operations.
454 (define_insn "*add<mode>3_neon"
455 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
456 (plus:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
457 (match_operand:VDQ 2 "s_register_operand" "w")))]
458 "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
459 "vadd.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
460 [(set (attr "neon_type")
461 (if_then_else (match_test "<Is_float_mode>")
462 (if_then_else (match_test "<Is_d_reg>")
463 (const_string "neon_fp_vadd_ddd_vabs_dd")
464 (const_string "neon_fp_vadd_qqq_vabs_qq"))
465 (const_string "neon_int_1")))]
468 (define_insn "adddi3_neon"
469 [(set (match_operand:DI 0 "s_register_operand" "=w,?&r,?&r,?w,?&r,?&r,?&r")
470 (plus:DI (match_operand:DI 1 "s_register_operand" "%w,0,0,w,r,0,r")
471 (match_operand:DI 2 "arm_adddi_operand" "w,r,0,w,r,Dd,Dd")))
472 (clobber (reg:CC CC_REGNUM))]
475 switch (which_alternative)
477 case 0: /* fall through */
478 case 3: return "vadd.i64\t%P0, %P1, %P2";
484 default: gcc_unreachable ();
487 [(set_attr "neon_type" "neon_int_1,*,*,neon_int_1,*,*,*")
488 (set_attr "conds" "*,clob,clob,*,clob,clob,clob")
489 (set_attr "length" "*,8,8,*,8,8,8")
490 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits,*,*,*")]
493 (define_insn "*sub<mode>3_neon"
494 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
495 (minus:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
496 (match_operand:VDQ 2 "s_register_operand" "w")))]
497 "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
498 "vsub.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
499 [(set (attr "neon_type")
500 (if_then_else (match_test "<Is_float_mode>")
501 (if_then_else (match_test "<Is_d_reg>")
502 (const_string "neon_fp_vadd_ddd_vabs_dd")
503 (const_string "neon_fp_vadd_qqq_vabs_qq"))
504 (const_string "neon_int_2")))]
507 (define_insn "subdi3_neon"
508 [(set (match_operand:DI 0 "s_register_operand" "=w,?&r,?&r,?&r,?w")
509 (minus:DI (match_operand:DI 1 "s_register_operand" "w,0,r,0,w")
510 (match_operand:DI 2 "s_register_operand" "w,r,0,0,w")))
511 (clobber (reg:CC CC_REGNUM))]
514 switch (which_alternative)
516 case 0: /* fall through */
517 case 4: return "vsub.i64\t%P0, %P1, %P2";
518 case 1: /* fall through */
519 case 2: /* fall through */
520 case 3: return "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2";
521 default: gcc_unreachable ();
524 [(set_attr "neon_type" "neon_int_2,*,*,*,neon_int_2")
525 (set_attr "conds" "*,clob,clob,clob,*")
526 (set_attr "length" "*,8,8,8,*")
527 (set_attr "arch" "neon_for_64bits,*,*,*,avoid_neon_for_64bits")]
530 (define_insn "*mul<mode>3_neon"
531 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
532 (mult:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
533 (match_operand:VDQ 2 "s_register_operand" "w")))]
534 "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
535 "vmul.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
536 [(set (attr "neon_type")
537 (if_then_else (match_test "<Is_float_mode>")
538 (if_then_else (match_test "<Is_d_reg>")
539 (const_string "neon_fp_vadd_ddd_vabs_dd")
540 (const_string "neon_fp_vadd_qqq_vabs_qq"))
541 (if_then_else (match_test "<Is_d_reg>")
543 (match_test "<Scalar_mul_8_16>")
544 (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
545 (const_string "neon_mul_qqq_8_16_32_ddd_32"))
546 (if_then_else (match_test "<Scalar_mul_8_16>")
547 (const_string "neon_mul_qqq_8_16_32_ddd_32")
548 (const_string "neon_mul_qqq_8_16_32_ddd_32")))))]
551 (define_insn "mul<mode>3add<mode>_neon"
552 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
553 (plus:VDQ (mult:VDQ (match_operand:VDQ 2 "s_register_operand" "w")
554 (match_operand:VDQ 3 "s_register_operand" "w"))
555 (match_operand:VDQ 1 "s_register_operand" "0")))]
556 "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
557 "vmla.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
558 [(set (attr "neon_type")
559 (if_then_else (match_test "<Is_float_mode>")
560 (if_then_else (match_test "<Is_d_reg>")
561 (const_string "neon_fp_vmla_ddd")
562 (const_string "neon_fp_vmla_qqq"))
563 (if_then_else (match_test "<Is_d_reg>")
565 (match_test "<Scalar_mul_8_16>")
566 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
567 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
568 (if_then_else (match_test "<Scalar_mul_8_16>")
569 (const_string "neon_mla_qqq_8_16")
570 (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
573 (define_insn "mul<mode>3neg<mode>add<mode>_neon"
574 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
575 (minus:VDQ (match_operand:VDQ 1 "s_register_operand" "0")
576 (mult:VDQ (match_operand:VDQ 2 "s_register_operand" "w")
577 (match_operand:VDQ 3 "s_register_operand" "w"))))]
578 "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
579 "vmls.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
580 [(set (attr "neon_type")
581 (if_then_else (match_test "<Is_float_mode>")
582 (if_then_else (match_test "<Is_d_reg>")
583 (const_string "neon_fp_vmla_ddd")
584 (const_string "neon_fp_vmla_qqq"))
585 (if_then_else (match_test "<Is_d_reg>")
587 (match_test "<Scalar_mul_8_16>")
588 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
589 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
590 (if_then_else (match_test "<Scalar_mul_8_16>")
591 (const_string "neon_mla_qqq_8_16")
592 (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
595 ;; Fused multiply-accumulate
596 ;; We define each insn twice here:
597 ;; 1: with flag_unsafe_math_optimizations for the widening multiply phase
598 ;; to be able to use when converting to FMA.
599 ;; 2: without flag_unsafe_math_optimizations for the intrinsics to use.
600 (define_insn "fma<VCVTF:mode>4"
601 [(set (match_operand:VCVTF 0 "register_operand" "=w")
602 (fma:VCVTF (match_operand:VCVTF 1 "register_operand" "w")
603 (match_operand:VCVTF 2 "register_operand" "w")
604 (match_operand:VCVTF 3 "register_operand" "0")))]
605 "TARGET_NEON && TARGET_FMA && flag_unsafe_math_optimizations"
606 "vfma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
607 [(set (attr "neon_type")
608 (if_then_else (match_test "<Is_d_reg>")
609 (const_string "neon_fp_vmla_ddd")
610 (const_string "neon_fp_vmla_qqq")))]
613 (define_insn "fma<VCVTF:mode>4_intrinsic"
614 [(set (match_operand:VCVTF 0 "register_operand" "=w")
615 (fma:VCVTF (match_operand:VCVTF 1 "register_operand" "w")
616 (match_operand:VCVTF 2 "register_operand" "w")
617 (match_operand:VCVTF 3 "register_operand" "0")))]
618 "TARGET_NEON && TARGET_FMA"
619 "vfma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
620 [(set (attr "neon_type")
621 (if_then_else (match_test "<Is_d_reg>")
622 (const_string "neon_fp_vmla_ddd")
623 (const_string "neon_fp_vmla_qqq")))]
626 (define_insn "*fmsub<VCVTF:mode>4"
627 [(set (match_operand:VCVTF 0 "register_operand" "=w")
628 (fma:VCVTF (neg:VCVTF (match_operand:VCVTF 1 "register_operand" "w"))
629 (match_operand:VCVTF 2 "register_operand" "w")
630 (match_operand:VCVTF 3 "register_operand" "0")))]
631 "TARGET_NEON && TARGET_FMA && flag_unsafe_math_optimizations"
632 "vfms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
633 [(set (attr "neon_type")
634 (if_then_else (match_test "<Is_d_reg>")
635 (const_string "neon_fp_vmla_ddd")
636 (const_string "neon_fp_vmla_qqq")))]
639 (define_insn "fmsub<VCVTF:mode>4_intrinsic"
640 [(set (match_operand:VCVTF 0 "register_operand" "=w")
641 (fma:VCVTF (neg:VCVTF (match_operand:VCVTF 1 "register_operand" "w"))
642 (match_operand:VCVTF 2 "register_operand" "w")
643 (match_operand:VCVTF 3 "register_operand" "0")))]
644 "TARGET_NEON && TARGET_FMA"
645 "vfms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
646 [(set (attr "neon_type")
647 (if_then_else (match_test "<Is_d_reg>")
648 (const_string "neon_fp_vmla_ddd")
649 (const_string "neon_fp_vmla_qqq")))]
652 (define_insn "neon_vrint<NEON_VRINT:nvrint_variant><VCVTF:mode>"
653 [(set (match_operand:VCVTF 0 "s_register_operand" "=w")
654 (unspec:VCVTF [(match_operand:VCVTF 1
655 "s_register_operand" "w")]
657 "TARGET_NEON && TARGET_FPU_ARMV8"
658 "vrint<nvrint_variant>%?.f32\\t%<V_reg>0, %<V_reg>1"
659 [(set (attr "neon_type")
660 (if_then_else (match_test "<Is_d_reg>")
661 (const_string "neon_fp_vadd_ddd_vabs_dd")
662 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
665 (define_insn "ior<mode>3"
666 [(set (match_operand:VDQ 0 "s_register_operand" "=w,w")
667 (ior:VDQ (match_operand:VDQ 1 "s_register_operand" "w,0")
668 (match_operand:VDQ 2 "neon_logic_op2" "w,Dl")))]
671 switch (which_alternative)
673 case 0: return "vorr\t%<V_reg>0, %<V_reg>1, %<V_reg>2";
674 case 1: return neon_output_logic_immediate ("vorr", &operands[2],
675 <MODE>mode, 0, VALID_NEON_QREG_MODE (<MODE>mode));
676 default: gcc_unreachable ();
679 [(set_attr "neon_type" "neon_int_1")]
682 ;; The concrete forms of the Neon immediate-logic instructions are vbic and
683 ;; vorr. We support the pseudo-instruction vand instead, because that
684 ;; corresponds to the canonical form the middle-end expects to use for
685 ;; immediate bitwise-ANDs.
687 (define_insn "and<mode>3"
688 [(set (match_operand:VDQ 0 "s_register_operand" "=w,w")
689 (and:VDQ (match_operand:VDQ 1 "s_register_operand" "w,0")
690 (match_operand:VDQ 2 "neon_inv_logic_op2" "w,DL")))]
693 switch (which_alternative)
695 case 0: return "vand\t%<V_reg>0, %<V_reg>1, %<V_reg>2";
696 case 1: return neon_output_logic_immediate ("vand", &operands[2],
697 <MODE>mode, 1, VALID_NEON_QREG_MODE (<MODE>mode));
698 default: gcc_unreachable ();
701 [(set_attr "neon_type" "neon_int_1")]
704 (define_insn "orn<mode>3_neon"
705 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
706 (ior:VDQ (not:VDQ (match_operand:VDQ 2 "s_register_operand" "w"))
707 (match_operand:VDQ 1 "s_register_operand" "w")))]
709 "vorn\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
710 [(set_attr "neon_type" "neon_int_1")]
713 ;; TODO: investigate whether we should disable
714 ;; this and bicdi3_neon for the A8 in line with the other
716 (define_insn_and_split "orndi3_neon"
717 [(set (match_operand:DI 0 "s_register_operand" "=w,?&r,?&r,?&r")
718 (ior:DI (not:DI (match_operand:DI 2 "s_register_operand" "w,0,0,r"))
719 (match_operand:DI 1 "s_register_operand" "w,r,r,0")))]
727 (TARGET_NEON && !(IS_VFP_REGNUM (REGNO (operands[0]))))"
728 [(set (match_dup 0) (ior:SI (not:SI (match_dup 2)) (match_dup 1)))
729 (set (match_dup 3) (ior:SI (not:SI (match_dup 4)) (match_dup 5)))]
734 operands[3] = gen_highpart (SImode, operands[0]);
735 operands[0] = gen_lowpart (SImode, operands[0]);
736 operands[4] = gen_highpart (SImode, operands[2]);
737 operands[2] = gen_lowpart (SImode, operands[2]);
738 operands[5] = gen_highpart (SImode, operands[1]);
739 operands[1] = gen_lowpart (SImode, operands[1]);
743 emit_insn (gen_one_cmpldi2 (operands[0], operands[2]));
744 emit_insn (gen_iordi3 (operands[0], operands[1], operands[0]));
748 [(set_attr "neon_type" "neon_int_1,*,*,*")
749 (set_attr "length" "*,16,8,8")
750 (set_attr "arch" "any,a,t2,t2")]
753 (define_insn "bic<mode>3_neon"
754 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
755 (and:VDQ (not:VDQ (match_operand:VDQ 2 "s_register_operand" "w"))
756 (match_operand:VDQ 1 "s_register_operand" "w")))]
758 "vbic\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
759 [(set_attr "neon_type" "neon_int_1")]
762 ;; Compare to *anddi_notdi_di.
763 (define_insn "bicdi3_neon"
764 [(set (match_operand:DI 0 "s_register_operand" "=w,?=&r,?&r")
765 (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "w,r,0"))
766 (match_operand:DI 1 "s_register_operand" "w,0,r")))]
772 [(set_attr "neon_type" "neon_int_1,*,*")
773 (set_attr "length" "*,8,8")]
776 (define_insn "xor<mode>3"
777 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
778 (xor:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
779 (match_operand:VDQ 2 "s_register_operand" "w")))]
781 "veor\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
782 [(set_attr "neon_type" "neon_int_1")]
785 (define_insn "one_cmpl<mode>2"
786 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
787 (not:VDQ (match_operand:VDQ 1 "s_register_operand" "w")))]
789 "vmvn\t%<V_reg>0, %<V_reg>1"
790 [(set_attr "neon_type" "neon_int_1")]
793 (define_insn "abs<mode>2"
794 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
795 (abs:VDQW (match_operand:VDQW 1 "s_register_operand" "w")))]
797 "vabs.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
798 [(set (attr "neon_type")
799 (if_then_else (match_test "<Is_float_mode>")
800 (if_then_else (match_test "<Is_d_reg>")
801 (const_string "neon_fp_vadd_ddd_vabs_dd")
802 (const_string "neon_fp_vadd_qqq_vabs_qq"))
803 (const_string "neon_int_3")))]
806 (define_insn "neg<mode>2"
807 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
808 (neg:VDQW (match_operand:VDQW 1 "s_register_operand" "w")))]
810 "vneg.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
811 [(set (attr "neon_type")
812 (if_then_else (match_test "<Is_float_mode>")
813 (if_then_else (match_test "<Is_d_reg>")
814 (const_string "neon_fp_vadd_ddd_vabs_dd")
815 (const_string "neon_fp_vadd_qqq_vabs_qq"))
816 (const_string "neon_int_3")))]
819 (define_insn "negdi2_neon"
820 [(set (match_operand:DI 0 "s_register_operand" "=&w, w,r,&r")
821 (neg:DI (match_operand:DI 1 "s_register_operand" " w, w,0, r")))
822 (clobber (match_scratch:DI 2 "= X,&w,X, X"))
823 (clobber (reg:CC CC_REGNUM))]
826 [(set_attr "length" "8")]
829 ; Split negdi2_neon for vfp registers
831 [(set (match_operand:DI 0 "s_register_operand" "")
832 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
833 (clobber (match_scratch:DI 2 ""))
834 (clobber (reg:CC CC_REGNUM))]
835 "TARGET_NEON && reload_completed && IS_VFP_REGNUM (REGNO (operands[0]))"
836 [(set (match_dup 2) (const_int 0))
837 (parallel [(set (match_dup 0) (minus:DI (match_dup 2) (match_dup 1)))
838 (clobber (reg:CC CC_REGNUM))])]
840 if (!REG_P (operands[2]))
841 operands[2] = operands[0];
845 ; Split negdi2_neon for core registers
847 [(set (match_operand:DI 0 "s_register_operand" "")
848 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
849 (clobber (match_scratch:DI 2 ""))
850 (clobber (reg:CC CC_REGNUM))]
851 "TARGET_32BIT && reload_completed
852 && arm_general_register_operand (operands[0], DImode)"
853 [(parallel [(set (match_dup 0) (neg:DI (match_dup 1)))
854 (clobber (reg:CC CC_REGNUM))])]
858 (define_insn "*umin<mode>3_neon"
859 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
860 (umin:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")
861 (match_operand:VDQIW 2 "s_register_operand" "w")))]
863 "vmin.<V_u_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
864 [(set_attr "neon_type" "neon_int_5")]
867 (define_insn "*umax<mode>3_neon"
868 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
869 (umax:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")
870 (match_operand:VDQIW 2 "s_register_operand" "w")))]
872 "vmax.<V_u_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
873 [(set_attr "neon_type" "neon_int_5")]
876 (define_insn "*smin<mode>3_neon"
877 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
878 (smin:VDQW (match_operand:VDQW 1 "s_register_operand" "w")
879 (match_operand:VDQW 2 "s_register_operand" "w")))]
881 "vmin.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
882 [(set (attr "neon_type")
883 (if_then_else (match_test "<Is_float_mode>")
884 (const_string "neon_fp_vadd_ddd_vabs_dd")
885 (const_string "neon_int_5")))]
888 (define_insn "*smax<mode>3_neon"
889 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
890 (smax:VDQW (match_operand:VDQW 1 "s_register_operand" "w")
891 (match_operand:VDQW 2 "s_register_operand" "w")))]
893 "vmax.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
894 [(set (attr "neon_type")
895 (if_then_else (match_test "<Is_float_mode>")
896 (const_string "neon_fp_vadd_ddd_vabs_dd")
897 (const_string "neon_int_5")))]
900 ; TODO: V2DI shifts are current disabled because there are bugs in the
901 ; generic vectorizer code. It ends up creating a V2DI constructor with
904 (define_insn "vashl<mode>3"
905 [(set (match_operand:VDQIW 0 "s_register_operand" "=w,w")
906 (ashift:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w,w")
907 (match_operand:VDQIW 2 "imm_lshift_or_reg_neon" "w,Dn")))]
910 switch (which_alternative)
912 case 0: return "vshl.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2";
913 case 1: return neon_output_shift_immediate ("vshl", 'i', &operands[2],
915 VALID_NEON_QREG_MODE (<MODE>mode),
917 default: gcc_unreachable ();
920 [(set (attr "neon_type")
921 (if_then_else (match_test "<Is_d_reg>")
922 (const_string "neon_vshl_ddd")
923 (const_string "neon_shift_3")))]
926 (define_insn "vashr<mode>3_imm"
927 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
928 (ashiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")
929 (match_operand:VDQIW 2 "imm_for_neon_rshift_operand" "Dn")))]
932 return neon_output_shift_immediate ("vshr", 's', &operands[2],
933 <MODE>mode, VALID_NEON_QREG_MODE (<MODE>mode),
936 [(set (attr "neon_type")
937 (if_then_else (match_test "<Is_d_reg>")
938 (const_string "neon_vshl_ddd")
939 (const_string "neon_shift_3")))]
942 (define_insn "vlshr<mode>3_imm"
943 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
944 (lshiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")
945 (match_operand:VDQIW 2 "imm_for_neon_rshift_operand" "Dn")))]
948 return neon_output_shift_immediate ("vshr", 'u', &operands[2],
949 <MODE>mode, VALID_NEON_QREG_MODE (<MODE>mode),
952 [(set (attr "neon_type")
953 (if_then_else (match_test "<Is_d_reg>")
954 (const_string "neon_vshl_ddd")
955 (const_string "neon_shift_3")))]
958 ; Used for implementing logical shift-right, which is a left-shift by a negative
959 ; amount, with signed operands. This is essentially the same as ashl<mode>3
960 ; above, but using an unspec in case GCC tries anything tricky with negative
963 (define_insn "ashl<mode>3_signed"
964 [(set (match_operand:VDQI 0 "s_register_operand" "=w")
965 (unspec:VDQI [(match_operand:VDQI 1 "s_register_operand" "w")
966 (match_operand:VDQI 2 "s_register_operand" "w")]
967 UNSPEC_ASHIFT_SIGNED))]
969 "vshl.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
970 [(set (attr "neon_type")
971 (if_then_else (match_test "<Is_d_reg>")
972 (const_string "neon_vshl_ddd")
973 (const_string "neon_shift_3")))]
976 ; Used for implementing logical shift-right, which is a left-shift by a negative
977 ; amount, with unsigned operands.
979 (define_insn "ashl<mode>3_unsigned"
980 [(set (match_operand:VDQI 0 "s_register_operand" "=w")
981 (unspec:VDQI [(match_operand:VDQI 1 "s_register_operand" "w")
982 (match_operand:VDQI 2 "s_register_operand" "w")]
983 UNSPEC_ASHIFT_UNSIGNED))]
985 "vshl.<V_u_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
986 [(set (attr "neon_type")
987 (if_then_else (match_test "<Is_d_reg>")
988 (const_string "neon_vshl_ddd")
989 (const_string "neon_shift_3")))]
992 (define_expand "vashr<mode>3"
993 [(set (match_operand:VDQIW 0 "s_register_operand" "")
994 (ashiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "")
995 (match_operand:VDQIW 2 "imm_rshift_or_reg_neon" "")))]
998 if (s_register_operand (operands[2], <MODE>mode))
1000 rtx neg = gen_reg_rtx (<MODE>mode);
1001 emit_insn (gen_neg<mode>2 (neg, operands[2]));
1002 emit_insn (gen_ashl<mode>3_signed (operands[0], operands[1], neg));
1005 emit_insn (gen_vashr<mode>3_imm (operands[0], operands[1], operands[2]));
1009 (define_expand "vlshr<mode>3"
1010 [(set (match_operand:VDQIW 0 "s_register_operand" "")
1011 (lshiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "")
1012 (match_operand:VDQIW 2 "imm_rshift_or_reg_neon" "")))]
1015 if (s_register_operand (operands[2], <MODE>mode))
1017 rtx neg = gen_reg_rtx (<MODE>mode);
1018 emit_insn (gen_neg<mode>2 (neg, operands[2]));
1019 emit_insn (gen_ashl<mode>3_unsigned (operands[0], operands[1], neg));
1022 emit_insn (gen_vlshr<mode>3_imm (operands[0], operands[1], operands[2]));
1028 ;; This pattern loads a 32-bit shift count into a 64-bit NEON register,
1029 ;; leaving the upper half uninitalized. This is OK since the shift
1030 ;; instruction only looks at the low 8 bits anyway. To avoid confusing
1031 ;; data flow analysis however, we pretend the full register is set
1033 (define_insn "neon_load_count"
1034 [(set (match_operand:DI 0 "s_register_operand" "=w,w")
1035 (unspec:DI [(match_operand:SI 1 "nonimmediate_operand" "Um,r")]
1036 UNSPEC_LOAD_COUNT))]
1039 vld1.32\t{%P0[0]}, %A1
1040 vmov.32\t%P0[0], %1"
1041 [(set_attr "neon_type" "neon_vld1_vld2_lane,neon_mcr")]
1044 (define_insn "ashldi3_neon_noclobber"
1045 [(set (match_operand:DI 0 "s_register_operand" "=w,w")
1046 (ashift:DI (match_operand:DI 1 "s_register_operand" " w,w")
1047 (match_operand:DI 2 "reg_or_int_operand" " i,w")))]
1048 "TARGET_NEON && reload_completed
1049 && (!CONST_INT_P (operands[2])
1050 || (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 64))"
1052 vshl.u64\t%P0, %P1, %2
1053 vshl.u64\t%P0, %P1, %P2"
1054 [(set_attr "neon_type" "neon_vshl_ddd,neon_vshl_ddd")]
1057 (define_insn_and_split "ashldi3_neon"
1058 [(set (match_operand:DI 0 "s_register_operand" "= w, w,?&r,?r, ?w,w")
1059 (ashift:DI (match_operand:DI 1 "s_register_operand" " 0w, w, 0r, r, 0w,w")
1060 (match_operand:SI 2 "general_operand" "rUm, i, r, i,rUm,i")))
1061 (clobber (match_scratch:SI 3 "= X, X,?&r, X, X,X"))
1062 (clobber (match_scratch:SI 4 "= X, X,?&r, X, X,X"))
1063 (clobber (match_scratch:DI 5 "=&w, X, X, X, &w,X"))
1064 (clobber (reg:CC_C CC_REGNUM))]
1067 "TARGET_NEON && reload_completed"
1071 if (IS_VFP_REGNUM (REGNO (operands[0])))
1073 if (CONST_INT_P (operands[2]))
1075 if (INTVAL (operands[2]) < 1)
1077 emit_insn (gen_movdi (operands[0], operands[1]));
1080 else if (INTVAL (operands[2]) > 63)
1081 operands[2] = gen_rtx_CONST_INT (VOIDmode, 63);
1085 emit_insn (gen_neon_load_count (operands[5], operands[2]));
1086 operands[2] = operands[5];
1089 /* Ditch the unnecessary clobbers. */
1090 emit_insn (gen_ashldi3_neon_noclobber (operands[0], operands[1],
1095 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 1)
1096 /* This clobbers CC. */
1097 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
1099 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
1100 operands[2], operands[3], operands[4]);
1104 [(set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")
1105 (set_attr "opt" "*,*,speed,speed,*,*")]
1108 ; The shift amount needs to be negated for right-shifts
1109 (define_insn "signed_shift_di3_neon"
1110 [(set (match_operand:DI 0 "s_register_operand" "=w")
1111 (unspec:DI [(match_operand:DI 1 "s_register_operand" " w")
1112 (match_operand:DI 2 "s_register_operand" " w")]
1113 UNSPEC_ASHIFT_SIGNED))]
1114 "TARGET_NEON && reload_completed"
1115 "vshl.s64\t%P0, %P1, %P2"
1116 [(set_attr "neon_type" "neon_vshl_ddd")]
1119 ; The shift amount needs to be negated for right-shifts
1120 (define_insn "unsigned_shift_di3_neon"
1121 [(set (match_operand:DI 0 "s_register_operand" "=w")
1122 (unspec:DI [(match_operand:DI 1 "s_register_operand" " w")
1123 (match_operand:DI 2 "s_register_operand" " w")]
1124 UNSPEC_ASHIFT_UNSIGNED))]
1125 "TARGET_NEON && reload_completed"
1126 "vshl.u64\t%P0, %P1, %P2"
1127 [(set_attr "neon_type" "neon_vshl_ddd")]
1130 (define_insn "ashrdi3_neon_imm_noclobber"
1131 [(set (match_operand:DI 0 "s_register_operand" "=w")
1132 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" " w")
1133 (match_operand:DI 2 "const_int_operand" " i")))]
1134 "TARGET_NEON && reload_completed
1135 && INTVAL (operands[2]) > 0 && INTVAL (operands[2]) <= 64"
1136 "vshr.s64\t%P0, %P1, %2"
1137 [(set_attr "neon_type" "neon_vshl_ddd")]
1140 (define_insn "lshrdi3_neon_imm_noclobber"
1141 [(set (match_operand:DI 0 "s_register_operand" "=w")
1142 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" " w")
1143 (match_operand:DI 2 "const_int_operand" " i")))]
1144 "TARGET_NEON && reload_completed
1145 && INTVAL (operands[2]) > 0 && INTVAL (operands[2]) <= 64"
1146 "vshr.u64\t%P0, %P1, %2"
1147 [(set_attr "neon_type" "neon_vshl_ddd")]
1152 (define_insn_and_split "<shift>di3_neon"
1153 [(set (match_operand:DI 0 "s_register_operand" "= w, w,?&r,?r,?w,?w")
1154 (rshifts:DI (match_operand:DI 1 "s_register_operand" " 0w, w, 0r, r,0w, w")
1155 (match_operand:SI 2 "reg_or_int_operand" " r, i, r, i, r, i")))
1156 (clobber (match_scratch:SI 3 "=2r, X, &r, X,2r, X"))
1157 (clobber (match_scratch:SI 4 "= X, X, &r, X, X, X"))
1158 (clobber (match_scratch:DI 5 "=&w, X, X, X,&w, X"))
1159 (clobber (reg:CC CC_REGNUM))]
1162 "TARGET_NEON && reload_completed"
1166 if (IS_VFP_REGNUM (REGNO (operands[0])))
1168 if (CONST_INT_P (operands[2]))
1170 if (INTVAL (operands[2]) < 1)
1172 emit_insn (gen_movdi (operands[0], operands[1]));
1175 else if (INTVAL (operands[2]) > 64)
1176 operands[2] = gen_rtx_CONST_INT (VOIDmode, 64);
1178 /* Ditch the unnecessary clobbers. */
1179 emit_insn (gen_<shift>di3_neon_imm_noclobber (operands[0],
1185 /* We must use a negative left-shift. */
1186 emit_insn (gen_negsi2 (operands[3], operands[2]));
1187 emit_insn (gen_neon_load_count (operands[5], operands[3]));
1188 emit_insn (gen_<shifttype>_shift_di3_neon (operands[0], operands[1],
1194 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 1)
1195 /* This clobbers CC. */
1196 emit_insn (gen_arm_<shift>di3_1bit (operands[0], operands[1]));
1198 /* This clobbers CC (ASHIFTRT by register only). */
1199 arm_emit_coreregs_64bit_shift (<CODE>, operands[0], operands[1],
1200 operands[2], operands[3], operands[4]);
1205 [(set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")
1206 (set_attr "opt" "*,*,speed,speed,*,*")]
1209 ;; Widening operations
1211 (define_insn "widen_ssum<mode>3"
1212 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1213 (plus:<V_widen> (sign_extend:<V_widen>
1214 (match_operand:VW 1 "s_register_operand" "%w"))
1215 (match_operand:<V_widen> 2 "s_register_operand" "w")))]
1217 "vaddw.<V_s_elem>\t%q0, %q2, %P1"
1218 [(set_attr "neon_type" "neon_int_3")]
1221 (define_insn "widen_usum<mode>3"
1222 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1223 (plus:<V_widen> (zero_extend:<V_widen>
1224 (match_operand:VW 1 "s_register_operand" "%w"))
1225 (match_operand:<V_widen> 2 "s_register_operand" "w")))]
1227 "vaddw.<V_u_elem>\t%q0, %q2, %P1"
1228 [(set_attr "neon_type" "neon_int_3")]
1231 ;; VEXT can be used to synthesize coarse whole-vector shifts with 8-bit
1232 ;; shift-count granularity. That's good enough for the middle-end's current
1235 ;; Note that it's not safe to perform such an operation in big-endian mode,
1236 ;; due to element-ordering issues.
1238 (define_expand "vec_shr_<mode>"
1239 [(match_operand:VDQ 0 "s_register_operand" "")
1240 (match_operand:VDQ 1 "s_register_operand" "")
1241 (match_operand:SI 2 "const_multiple_of_8_operand" "")]
1242 "TARGET_NEON && !BYTES_BIG_ENDIAN"
1245 HOST_WIDE_INT num_bits = INTVAL (operands[2]);
1246 const int width = GET_MODE_BITSIZE (<MODE>mode);
1247 const enum machine_mode bvecmode = (width == 128) ? V16QImode : V8QImode;
1248 rtx (*gen_ext) (rtx, rtx, rtx, rtx) =
1249 (width == 128) ? gen_neon_vextv16qi : gen_neon_vextv8qi;
1251 if (num_bits == width)
1253 emit_move_insn (operands[0], operands[1]);
1257 zero_reg = force_reg (bvecmode, CONST0_RTX (bvecmode));
1258 operands[0] = gen_lowpart (bvecmode, operands[0]);
1259 operands[1] = gen_lowpart (bvecmode, operands[1]);
1261 emit_insn (gen_ext (operands[0], operands[1], zero_reg,
1262 GEN_INT (num_bits / BITS_PER_UNIT)));
1266 (define_expand "vec_shl_<mode>"
1267 [(match_operand:VDQ 0 "s_register_operand" "")
1268 (match_operand:VDQ 1 "s_register_operand" "")
1269 (match_operand:SI 2 "const_multiple_of_8_operand" "")]
1270 "TARGET_NEON && !BYTES_BIG_ENDIAN"
1273 HOST_WIDE_INT num_bits = INTVAL (operands[2]);
1274 const int width = GET_MODE_BITSIZE (<MODE>mode);
1275 const enum machine_mode bvecmode = (width == 128) ? V16QImode : V8QImode;
1276 rtx (*gen_ext) (rtx, rtx, rtx, rtx) =
1277 (width == 128) ? gen_neon_vextv16qi : gen_neon_vextv8qi;
1281 emit_move_insn (operands[0], CONST0_RTX (<MODE>mode));
1285 num_bits = width - num_bits;
1287 zero_reg = force_reg (bvecmode, CONST0_RTX (bvecmode));
1288 operands[0] = gen_lowpart (bvecmode, operands[0]);
1289 operands[1] = gen_lowpart (bvecmode, operands[1]);
1291 emit_insn (gen_ext (operands[0], zero_reg, operands[1],
1292 GEN_INT (num_bits / BITS_PER_UNIT)));
1296 ;; Helpers for quad-word reduction operations
1298 ; Add (or smin, smax...) the low N/2 elements of the N-element vector
1299 ; operand[1] to the high N/2 elements of same. Put the result in operand[0], an
1300 ; N/2-element vector.
1302 (define_insn "quad_halves_<code>v4si"
1303 [(set (match_operand:V2SI 0 "s_register_operand" "=w")
1305 (vec_select:V2SI (match_operand:V4SI 1 "s_register_operand" "w")
1306 (parallel [(const_int 0) (const_int 1)]))
1307 (vec_select:V2SI (match_dup 1)
1308 (parallel [(const_int 2) (const_int 3)]))))]
1310 "<VQH_mnem>.<VQH_sign>32\t%P0, %e1, %f1"
1311 [(set_attr "vqh_mnem" "<VQH_mnem>")
1312 (set (attr "neon_type")
1313 (if_then_else (eq_attr "vqh_mnem" "vadd")
1314 (const_string "neon_int_1") (const_string "neon_int_5")))]
1317 (define_insn "quad_halves_<code>v4sf"
1318 [(set (match_operand:V2SF 0 "s_register_operand" "=w")
1320 (vec_select:V2SF (match_operand:V4SF 1 "s_register_operand" "w")
1321 (parallel [(const_int 0) (const_int 1)]))
1322 (vec_select:V2SF (match_dup 1)
1323 (parallel [(const_int 2) (const_int 3)]))))]
1324 "TARGET_NEON && flag_unsafe_math_optimizations"
1325 "<VQH_mnem>.f32\t%P0, %e1, %f1"
1326 [(set_attr "vqh_mnem" "<VQH_mnem>")
1327 (set (attr "neon_type")
1328 (if_then_else (eq_attr "vqh_mnem" "vadd")
1329 (const_string "neon_int_1") (const_string "neon_int_5")))]
1332 (define_insn "quad_halves_<code>v8hi"
1333 [(set (match_operand:V4HI 0 "s_register_operand" "+w")
1335 (vec_select:V4HI (match_operand:V8HI 1 "s_register_operand" "w")
1336 (parallel [(const_int 0) (const_int 1)
1337 (const_int 2) (const_int 3)]))
1338 (vec_select:V4HI (match_dup 1)
1339 (parallel [(const_int 4) (const_int 5)
1340 (const_int 6) (const_int 7)]))))]
1342 "<VQH_mnem>.<VQH_sign>16\t%P0, %e1, %f1"
1343 [(set_attr "vqh_mnem" "<VQH_mnem>")
1344 (set (attr "neon_type")
1345 (if_then_else (eq_attr "vqh_mnem" "vadd")
1346 (const_string "neon_int_1") (const_string "neon_int_5")))]
1349 (define_insn "quad_halves_<code>v16qi"
1350 [(set (match_operand:V8QI 0 "s_register_operand" "+w")
1352 (vec_select:V8QI (match_operand:V16QI 1 "s_register_operand" "w")
1353 (parallel [(const_int 0) (const_int 1)
1354 (const_int 2) (const_int 3)
1355 (const_int 4) (const_int 5)
1356 (const_int 6) (const_int 7)]))
1357 (vec_select:V8QI (match_dup 1)
1358 (parallel [(const_int 8) (const_int 9)
1359 (const_int 10) (const_int 11)
1360 (const_int 12) (const_int 13)
1361 (const_int 14) (const_int 15)]))))]
1363 "<VQH_mnem>.<VQH_sign>8\t%P0, %e1, %f1"
1364 [(set_attr "vqh_mnem" "<VQH_mnem>")
1365 (set (attr "neon_type")
1366 (if_then_else (eq_attr "vqh_mnem" "vadd")
1367 (const_string "neon_int_1") (const_string "neon_int_5")))]
1370 (define_expand "move_hi_quad_<mode>"
1371 [(match_operand:ANY128 0 "s_register_operand" "")
1372 (match_operand:<V_HALF> 1 "s_register_operand" "")]
1375 emit_move_insn (simplify_gen_subreg (<V_HALF>mode, operands[0], <MODE>mode,
1376 GET_MODE_SIZE (<V_HALF>mode)),
1381 (define_expand "move_lo_quad_<mode>"
1382 [(match_operand:ANY128 0 "s_register_operand" "")
1383 (match_operand:<V_HALF> 1 "s_register_operand" "")]
1386 emit_move_insn (simplify_gen_subreg (<V_HALF>mode, operands[0],
1392 ;; Reduction operations
1394 (define_expand "reduc_splus_<mode>"
1395 [(match_operand:VD 0 "s_register_operand" "")
1396 (match_operand:VD 1 "s_register_operand" "")]
1397 "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
1399 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1400 &gen_neon_vpadd_internal<mode>);
1404 (define_expand "reduc_splus_<mode>"
1405 [(match_operand:VQ 0 "s_register_operand" "")
1406 (match_operand:VQ 1 "s_register_operand" "")]
1407 "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)
1408 && !BYTES_BIG_ENDIAN"
1410 rtx step1 = gen_reg_rtx (<V_HALF>mode);
1411 rtx res_d = gen_reg_rtx (<V_HALF>mode);
1413 emit_insn (gen_quad_halves_plus<mode> (step1, operands[1]));
1414 emit_insn (gen_reduc_splus_<V_half> (res_d, step1));
1415 emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d));
1420 (define_insn "reduc_splus_v2di"
1421 [(set (match_operand:V2DI 0 "s_register_operand" "=w")
1422 (unspec:V2DI [(match_operand:V2DI 1 "s_register_operand" "w")]
1424 "TARGET_NEON && !BYTES_BIG_ENDIAN"
1425 "vadd.i64\t%e0, %e1, %f1"
1426 [(set_attr "neon_type" "neon_int_1")]
1429 ;; NEON does not distinguish between signed and unsigned addition except on
1430 ;; widening operations.
1431 (define_expand "reduc_uplus_<mode>"
1432 [(match_operand:VDQI 0 "s_register_operand" "")
1433 (match_operand:VDQI 1 "s_register_operand" "")]
1434 "TARGET_NEON && (<Is_d_reg> || !BYTES_BIG_ENDIAN)"
1436 emit_insn (gen_reduc_splus_<mode> (operands[0], operands[1]));
1440 (define_expand "reduc_smin_<mode>"
1441 [(match_operand:VD 0 "s_register_operand" "")
1442 (match_operand:VD 1 "s_register_operand" "")]
1443 "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
1445 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1446 &gen_neon_vpsmin<mode>);
1450 (define_expand "reduc_smin_<mode>"
1451 [(match_operand:VQ 0 "s_register_operand" "")
1452 (match_operand:VQ 1 "s_register_operand" "")]
1453 "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)
1454 && !BYTES_BIG_ENDIAN"
1456 rtx step1 = gen_reg_rtx (<V_HALF>mode);
1457 rtx res_d = gen_reg_rtx (<V_HALF>mode);
1459 emit_insn (gen_quad_halves_smin<mode> (step1, operands[1]));
1460 emit_insn (gen_reduc_smin_<V_half> (res_d, step1));
1461 emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d));
1466 (define_expand "reduc_smax_<mode>"
1467 [(match_operand:VD 0 "s_register_operand" "")
1468 (match_operand:VD 1 "s_register_operand" "")]
1469 "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
1471 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1472 &gen_neon_vpsmax<mode>);
1476 (define_expand "reduc_smax_<mode>"
1477 [(match_operand:VQ 0 "s_register_operand" "")
1478 (match_operand:VQ 1 "s_register_operand" "")]
1479 "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)
1480 && !BYTES_BIG_ENDIAN"
1482 rtx step1 = gen_reg_rtx (<V_HALF>mode);
1483 rtx res_d = gen_reg_rtx (<V_HALF>mode);
1485 emit_insn (gen_quad_halves_smax<mode> (step1, operands[1]));
1486 emit_insn (gen_reduc_smax_<V_half> (res_d, step1));
1487 emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d));
1492 (define_expand "reduc_umin_<mode>"
1493 [(match_operand:VDI 0 "s_register_operand" "")
1494 (match_operand:VDI 1 "s_register_operand" "")]
1497 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1498 &gen_neon_vpumin<mode>);
1502 (define_expand "reduc_umin_<mode>"
1503 [(match_operand:VQI 0 "s_register_operand" "")
1504 (match_operand:VQI 1 "s_register_operand" "")]
1505 "TARGET_NEON && !BYTES_BIG_ENDIAN"
1507 rtx step1 = gen_reg_rtx (<V_HALF>mode);
1508 rtx res_d = gen_reg_rtx (<V_HALF>mode);
1510 emit_insn (gen_quad_halves_umin<mode> (step1, operands[1]));
1511 emit_insn (gen_reduc_umin_<V_half> (res_d, step1));
1512 emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d));
1517 (define_expand "reduc_umax_<mode>"
1518 [(match_operand:VDI 0 "s_register_operand" "")
1519 (match_operand:VDI 1 "s_register_operand" "")]
1522 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1523 &gen_neon_vpumax<mode>);
1527 (define_expand "reduc_umax_<mode>"
1528 [(match_operand:VQI 0 "s_register_operand" "")
1529 (match_operand:VQI 1 "s_register_operand" "")]
1530 "TARGET_NEON && !BYTES_BIG_ENDIAN"
1532 rtx step1 = gen_reg_rtx (<V_HALF>mode);
1533 rtx res_d = gen_reg_rtx (<V_HALF>mode);
1535 emit_insn (gen_quad_halves_umax<mode> (step1, operands[1]));
1536 emit_insn (gen_reduc_umax_<V_half> (res_d, step1));
1537 emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d));
1542 (define_insn "neon_vpadd_internal<mode>"
1543 [(set (match_operand:VD 0 "s_register_operand" "=w")
1544 (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
1545 (match_operand:VD 2 "s_register_operand" "w")]
1548 "vpadd.<V_if_elem>\t%P0, %P1, %P2"
1549 ;; Assume this schedules like vadd.
1550 [(set (attr "neon_type")
1551 (if_then_else (match_test "<Is_float_mode>")
1552 (if_then_else (match_test "<Is_d_reg>")
1553 (const_string "neon_fp_vadd_ddd_vabs_dd")
1554 (const_string "neon_fp_vadd_qqq_vabs_qq"))
1555 (const_string "neon_int_1")))]
1558 (define_insn "neon_vpsmin<mode>"
1559 [(set (match_operand:VD 0 "s_register_operand" "=w")
1560 (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
1561 (match_operand:VD 2 "s_register_operand" "w")]
1564 "vpmin.<V_s_elem>\t%P0, %P1, %P2"
1565 ;; Assume this schedules like vmin.
1566 [(set (attr "neon_type")
1567 (if_then_else (match_test "<Is_float_mode>")
1568 (const_string "neon_fp_vadd_ddd_vabs_dd")
1569 (const_string "neon_int_5")))]
1572 (define_insn "neon_vpsmax<mode>"
1573 [(set (match_operand:VD 0 "s_register_operand" "=w")
1574 (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
1575 (match_operand:VD 2 "s_register_operand" "w")]
1578 "vpmax.<V_s_elem>\t%P0, %P1, %P2"
1579 ;; Assume this schedules like vmax.
1580 [(set (attr "neon_type")
1581 (if_then_else (match_test "<Is_float_mode>")
1582 (const_string "neon_fp_vadd_ddd_vabs_dd")
1583 (const_string "neon_int_5")))]
1586 (define_insn "neon_vpumin<mode>"
1587 [(set (match_operand:VDI 0 "s_register_operand" "=w")
1588 (unspec:VDI [(match_operand:VDI 1 "s_register_operand" "w")
1589 (match_operand:VDI 2 "s_register_operand" "w")]
1592 "vpmin.<V_u_elem>\t%P0, %P1, %P2"
1593 ;; Assume this schedules like umin.
1594 [(set_attr "neon_type" "neon_int_5")]
1597 (define_insn "neon_vpumax<mode>"
1598 [(set (match_operand:VDI 0 "s_register_operand" "=w")
1599 (unspec:VDI [(match_operand:VDI 1 "s_register_operand" "w")
1600 (match_operand:VDI 2 "s_register_operand" "w")]
1603 "vpmax.<V_u_elem>\t%P0, %P1, %P2"
1604 ;; Assume this schedules like umax.
1605 [(set_attr "neon_type" "neon_int_5")]
1608 ;; Saturating arithmetic
1610 ; NOTE: Neon supports many more saturating variants of instructions than the
1611 ; following, but these are all GCC currently understands.
1612 ; FIXME: Actually, GCC doesn't know how to create saturating add/sub by itself
1613 ; yet either, although these patterns may be used by intrinsics when they're
1616 (define_insn "*ss_add<mode>_neon"
1617 [(set (match_operand:VD 0 "s_register_operand" "=w")
1618 (ss_plus:VD (match_operand:VD 1 "s_register_operand" "w")
1619 (match_operand:VD 2 "s_register_operand" "w")))]
1621 "vqadd.<V_s_elem>\t%P0, %P1, %P2"
1622 [(set_attr "neon_type" "neon_int_4")]
1625 (define_insn "*us_add<mode>_neon"
1626 [(set (match_operand:VD 0 "s_register_operand" "=w")
1627 (us_plus:VD (match_operand:VD 1 "s_register_operand" "w")
1628 (match_operand:VD 2 "s_register_operand" "w")))]
1630 "vqadd.<V_u_elem>\t%P0, %P1, %P2"
1631 [(set_attr "neon_type" "neon_int_4")]
1634 (define_insn "*ss_sub<mode>_neon"
1635 [(set (match_operand:VD 0 "s_register_operand" "=w")
1636 (ss_minus:VD (match_operand:VD 1 "s_register_operand" "w")
1637 (match_operand:VD 2 "s_register_operand" "w")))]
1639 "vqsub.<V_s_elem>\t%P0, %P1, %P2"
1640 [(set_attr "neon_type" "neon_int_5")]
1643 (define_insn "*us_sub<mode>_neon"
1644 [(set (match_operand:VD 0 "s_register_operand" "=w")
1645 (us_minus:VD (match_operand:VD 1 "s_register_operand" "w")
1646 (match_operand:VD 2 "s_register_operand" "w")))]
1648 "vqsub.<V_u_elem>\t%P0, %P1, %P2"
1649 [(set_attr "neon_type" "neon_int_5")]
1652 ;; Conditional instructions. These are comparisons with conditional moves for
1653 ;; vectors. They perform the assignment:
1655 ;; Vop0 = (Vop4 <op3> Vop5) ? Vop1 : Vop2;
1657 ;; where op3 is <, <=, ==, !=, >= or >. Operations are performed
1660 (define_expand "vcond<mode><mode>"
1661 [(set (match_operand:VDQW 0 "s_register_operand" "")
1663 (match_operator 3 "comparison_operator"
1664 [(match_operand:VDQW 4 "s_register_operand" "")
1665 (match_operand:VDQW 5 "nonmemory_operand" "")])
1666 (match_operand:VDQW 1 "s_register_operand" "")
1667 (match_operand:VDQW 2 "s_register_operand" "")))]
1668 "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
1670 HOST_WIDE_INT magic_word = (<MODE>mode == V2SFmode || <MODE>mode == V4SFmode)
1672 rtx magic_rtx = GEN_INT (magic_word);
1674 int swap_bsl_operands = 0;
1675 rtx mask = gen_reg_rtx (<V_cmp_result>mode);
1676 rtx tmp = gen_reg_rtx (<V_cmp_result>mode);
1678 rtx (*base_comparison) (rtx, rtx, rtx, rtx);
1679 rtx (*complimentary_comparison) (rtx, rtx, rtx, rtx);
1681 switch (GET_CODE (operands[3]))
1686 if (!REG_P (operands[5])
1687 && (operands[5] != CONST0_RTX (<MODE>mode)))
1688 operands[5] = force_reg (<MODE>mode, operands[5]);
1691 if (!REG_P (operands[5]))
1692 operands[5] = force_reg (<MODE>mode, operands[5]);
1695 switch (GET_CODE (operands[3]))
1705 base_comparison = gen_neon_vcge<mode>;
1706 complimentary_comparison = gen_neon_vcgt<mode>;
1714 base_comparison = gen_neon_vcgt<mode>;
1715 complimentary_comparison = gen_neon_vcge<mode>;
1720 base_comparison = gen_neon_vceq<mode>;
1721 complimentary_comparison = gen_neon_vceq<mode>;
1727 switch (GET_CODE (operands[3]))
1734 /* The easy case. Here we emit one of vcge, vcgt or vceq.
1735 As a LT b <=> b GE a && a LE b <=> b GT a. Our transformations are:
1743 emit_insn (base_comparison (mask, operands[4], operands[5], magic_rtx));
1745 emit_insn (complimentary_comparison (mask, operands[5], operands[4], magic_rtx));
1752 /* Vector compare returns false for lanes which are unordered, so if we use
1753 the inverse of the comparison we actually want to emit, then
1754 swap the operands to BSL, we will end up with the correct result.
1755 Note that a NE NaN and NaN NE b are true for all a, b.
1757 Our transformations are:
1762 a NE b -> !(a EQ b) */
1765 emit_insn (base_comparison (mask, operands[4], operands[5], magic_rtx));
1767 emit_insn (complimentary_comparison (mask, operands[5], operands[4], magic_rtx));
1769 swap_bsl_operands = 1;
1772 /* We check (a > b || b > a). combining these comparisons give us
1773 true iff !(a != b && a ORDERED b), swapping the operands to BSL
1774 will then give us (a == b || a UNORDERED b) as intended. */
1776 emit_insn (gen_neon_vcgt<mode> (mask, operands[4], operands[5], magic_rtx));
1777 emit_insn (gen_neon_vcgt<mode> (tmp, operands[5], operands[4], magic_rtx));
1778 emit_insn (gen_ior<v_cmp_result>3 (mask, mask, tmp));
1779 swap_bsl_operands = 1;
1782 /* Operands are ORDERED iff (a > b || b >= a).
1783 Swapping the operands to BSL will give the UNORDERED case. */
1784 swap_bsl_operands = 1;
1787 emit_insn (gen_neon_vcgt<mode> (tmp, operands[4], operands[5], magic_rtx));
1788 emit_insn (gen_neon_vcge<mode> (mask, operands[5], operands[4], magic_rtx));
1789 emit_insn (gen_ior<v_cmp_result>3 (mask, mask, tmp));
1795 if (swap_bsl_operands)
1796 emit_insn (gen_neon_vbsl<mode> (operands[0], mask, operands[2],
1799 emit_insn (gen_neon_vbsl<mode> (operands[0], mask, operands[1],
1804 (define_expand "vcondu<mode><mode>"
1805 [(set (match_operand:VDQIW 0 "s_register_operand" "")
1807 (match_operator 3 "arm_comparison_operator"
1808 [(match_operand:VDQIW 4 "s_register_operand" "")
1809 (match_operand:VDQIW 5 "s_register_operand" "")])
1810 (match_operand:VDQIW 1 "s_register_operand" "")
1811 (match_operand:VDQIW 2 "s_register_operand" "")))]
1815 int inverse = 0, immediate_zero = 0;
1817 mask = gen_reg_rtx (<V_cmp_result>mode);
1819 if (operands[5] == CONST0_RTX (<MODE>mode))
1821 else if (!REG_P (operands[5]))
1822 operands[5] = force_reg (<MODE>mode, operands[5]);
1824 switch (GET_CODE (operands[3]))
1827 emit_insn (gen_neon_vcge<mode> (mask, operands[4], operands[5],
1832 emit_insn (gen_neon_vcgt<mode> (mask, operands[4], operands[5],
1837 emit_insn (gen_neon_vceq<mode> (mask, operands[4], operands[5],
1843 emit_insn (gen_neon_vcle<mode> (mask, operands[4], operands[5],
1846 emit_insn (gen_neon_vcge<mode> (mask, operands[5], operands[4],
1852 emit_insn (gen_neon_vclt<mode> (mask, operands[4], operands[5],
1855 emit_insn (gen_neon_vcgt<mode> (mask, operands[5], operands[4],
1860 emit_insn (gen_neon_vceq<mode> (mask, operands[4], operands[5],
1870 emit_insn (gen_neon_vbsl<mode> (operands[0], mask, operands[2],
1873 emit_insn (gen_neon_vbsl<mode> (operands[0], mask, operands[1],
1879 ;; Patterns for builtins.
1881 ; good for plain vadd, vaddq.
1883 (define_expand "neon_vadd<mode>"
1884 [(match_operand:VDQX 0 "s_register_operand" "=w")
1885 (match_operand:VDQX 1 "s_register_operand" "w")
1886 (match_operand:VDQX 2 "s_register_operand" "w")
1887 (match_operand:SI 3 "immediate_operand" "i")]
1890 if (!<Is_float_mode> || flag_unsafe_math_optimizations)
1891 emit_insn (gen_add<mode>3 (operands[0], operands[1], operands[2]));
1893 emit_insn (gen_neon_vadd<mode>_unspec (operands[0], operands[1],
1898 ; Note that NEON operations don't support the full IEEE 754 standard: in
1899 ; particular, denormal values are flushed to zero. This means that GCC cannot
1900 ; use those instructions for autovectorization, etc. unless
1901 ; -funsafe-math-optimizations is in effect (in which case flush-to-zero
1902 ; behaviour is permissible). Intrinsic operations (provided by the arm_neon.h
1903 ; header) must work in either case: if -funsafe-math-optimizations is given,
1904 ; intrinsics expand to "canonical" RTL where possible, otherwise intrinsics
1905 ; expand to unspecs (which may potentially limit the extent to which they might
1906 ; be optimized by generic code).
1908 ; Used for intrinsics when flag_unsafe_math_optimizations is false.
1910 (define_insn "neon_vadd<mode>_unspec"
1911 [(set (match_operand:VDQX 0 "s_register_operand" "=w")
1912 (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w")
1913 (match_operand:VDQX 2 "s_register_operand" "w")]
1916 "vadd.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1917 [(set (attr "neon_type")
1918 (if_then_else (match_test "<Is_float_mode>")
1919 (if_then_else (match_test "<Is_d_reg>")
1920 (const_string "neon_fp_vadd_ddd_vabs_dd")
1921 (const_string "neon_fp_vadd_qqq_vabs_qq"))
1922 (const_string "neon_int_1")))]
1925 ; operand 3 represents in bits:
1926 ; bit 0: signed (vs unsigned).
1927 ; bit 1: rounding (vs none).
1929 (define_insn "neon_vaddl<mode>"
1930 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1931 (unspec:<V_widen> [(match_operand:VDI 1 "s_register_operand" "w")
1932 (match_operand:VDI 2 "s_register_operand" "w")
1933 (match_operand:SI 3 "immediate_operand" "i")]
1936 "vaddl.%T3%#<V_sz_elem>\t%q0, %P1, %P2"
1937 [(set_attr "neon_type" "neon_int_3")]
1940 (define_insn "neon_vaddw<mode>"
1941 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1942 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "w")
1943 (match_operand:VDI 2 "s_register_operand" "w")
1944 (match_operand:SI 3 "immediate_operand" "i")]
1947 "vaddw.%T3%#<V_sz_elem>\t%q0, %q1, %P2"
1948 [(set_attr "neon_type" "neon_int_2")]
1953 (define_insn "neon_vhadd<mode>"
1954 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
1955 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
1956 (match_operand:VDQIW 2 "s_register_operand" "w")
1957 (match_operand:SI 3 "immediate_operand" "i")]
1960 "v%O3hadd.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1961 [(set_attr "neon_type" "neon_int_4")]
1964 (define_insn "neon_vqadd<mode>"
1965 [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
1966 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
1967 (match_operand:VDQIX 2 "s_register_operand" "w")
1968 (match_operand:SI 3 "immediate_operand" "i")]
1971 "vqadd.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1972 [(set_attr "neon_type" "neon_int_4")]
1975 (define_insn "neon_vaddhn<mode>"
1976 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
1977 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
1978 (match_operand:VN 2 "s_register_operand" "w")
1979 (match_operand:SI 3 "immediate_operand" "i")]
1982 "v%O3addhn.<V_if_elem>\t%P0, %q1, %q2"
1983 [(set_attr "neon_type" "neon_int_4")]
1986 ;; We cannot replace this unspec with mul<mode>3 because of the odd
1987 ;; polynomial multiplication case that can specified by operand 3.
1988 (define_insn "neon_vmul<mode>"
1989 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
1990 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w")
1991 (match_operand:VDQW 2 "s_register_operand" "w")
1992 (match_operand:SI 3 "immediate_operand" "i")]
1995 "vmul.%F3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1996 [(set (attr "neon_type")
1997 (if_then_else (match_test "<Is_float_mode>")
1998 (if_then_else (match_test "<Is_d_reg>")
1999 (const_string "neon_fp_vadd_ddd_vabs_dd")
2000 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2001 (if_then_else (match_test "<Is_d_reg>")
2003 (match_test "<Scalar_mul_8_16>")
2004 (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
2005 (const_string "neon_mul_qqq_8_16_32_ddd_32"))
2006 (if_then_else (match_test "<Scalar_mul_8_16>")
2007 (const_string "neon_mul_qqq_8_16_32_ddd_32")
2008 (const_string "neon_mul_qqq_8_16_32_ddd_32")))))]
2011 (define_expand "neon_vmla<mode>"
2012 [(match_operand:VDQW 0 "s_register_operand" "=w")
2013 (match_operand:VDQW 1 "s_register_operand" "0")
2014 (match_operand:VDQW 2 "s_register_operand" "w")
2015 (match_operand:VDQW 3 "s_register_operand" "w")
2016 (match_operand:SI 4 "immediate_operand" "i")]
2019 if (!<Is_float_mode> || flag_unsafe_math_optimizations)
2020 emit_insn (gen_mul<mode>3add<mode>_neon (operands[0], operands[1],
2021 operands[2], operands[3]));
2023 emit_insn (gen_neon_vmla<mode>_unspec (operands[0], operands[1],
2024 operands[2], operands[3]));
2028 (define_expand "neon_vfma<VCVTF:mode>"
2029 [(match_operand:VCVTF 0 "s_register_operand")
2030 (match_operand:VCVTF 1 "s_register_operand")
2031 (match_operand:VCVTF 2 "s_register_operand")
2032 (match_operand:VCVTF 3 "s_register_operand")
2033 (match_operand:SI 4 "immediate_operand")]
2034 "TARGET_NEON && TARGET_FMA"
2036 emit_insn (gen_fma<mode>4_intrinsic (operands[0], operands[2], operands[3],
2041 (define_expand "neon_vfms<VCVTF:mode>"
2042 [(match_operand:VCVTF 0 "s_register_operand")
2043 (match_operand:VCVTF 1 "s_register_operand")
2044 (match_operand:VCVTF 2 "s_register_operand")
2045 (match_operand:VCVTF 3 "s_register_operand")
2046 (match_operand:SI 4 "immediate_operand")]
2047 "TARGET_NEON && TARGET_FMA"
2049 emit_insn (gen_fmsub<mode>4_intrinsic (operands[0], operands[2], operands[3],
2054 ; Used for intrinsics when flag_unsafe_math_optimizations is false.
2056 (define_insn "neon_vmla<mode>_unspec"
2057 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
2058 (unspec:VDQ [(match_operand:VDQ 1 "s_register_operand" "0")
2059 (match_operand:VDQ 2 "s_register_operand" "w")
2060 (match_operand:VDQ 3 "s_register_operand" "w")]
2063 "vmla.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
2064 [(set (attr "neon_type")
2065 (if_then_else (match_test "<Is_float_mode>")
2066 (if_then_else (match_test "<Is_d_reg>")
2067 (const_string "neon_fp_vmla_ddd")
2068 (const_string "neon_fp_vmla_qqq"))
2069 (if_then_else (match_test "<Is_d_reg>")
2071 (match_test "<Scalar_mul_8_16>")
2072 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
2073 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
2074 (if_then_else (match_test "<Scalar_mul_8_16>")
2075 (const_string "neon_mla_qqq_8_16")
2076 (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
2079 (define_insn "neon_vmlal<mode>"
2080 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2081 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
2082 (match_operand:VW 2 "s_register_operand" "w")
2083 (match_operand:VW 3 "s_register_operand" "w")
2084 (match_operand:SI 4 "immediate_operand" "i")]
2087 "vmlal.%T4%#<V_sz_elem>\t%q0, %P2, %P3"
2088 [(set (attr "neon_type")
2089 (if_then_else (match_test "<Scalar_mul_8_16>")
2090 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
2091 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
2094 (define_expand "neon_vmls<mode>"
2095 [(match_operand:VDQW 0 "s_register_operand" "=w")
2096 (match_operand:VDQW 1 "s_register_operand" "0")
2097 (match_operand:VDQW 2 "s_register_operand" "w")
2098 (match_operand:VDQW 3 "s_register_operand" "w")
2099 (match_operand:SI 4 "immediate_operand" "i")]
2102 if (!<Is_float_mode> || flag_unsafe_math_optimizations)
2103 emit_insn (gen_mul<mode>3neg<mode>add<mode>_neon (operands[0],
2104 operands[1], operands[2], operands[3]));
2106 emit_insn (gen_neon_vmls<mode>_unspec (operands[0], operands[1],
2107 operands[2], operands[3]));
2111 ; Used for intrinsics when flag_unsafe_math_optimizations is false.
2113 (define_insn "neon_vmls<mode>_unspec"
2114 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
2115 (unspec:VDQ [(match_operand:VDQ 1 "s_register_operand" "0")
2116 (match_operand:VDQ 2 "s_register_operand" "w")
2117 (match_operand:VDQ 3 "s_register_operand" "w")]
2120 "vmls.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
2121 [(set (attr "neon_type")
2122 (if_then_else (match_test "<Is_float_mode>")
2123 (if_then_else (match_test "<Is_d_reg>")
2124 (const_string "neon_fp_vmla_ddd")
2125 (const_string "neon_fp_vmla_qqq"))
2126 (if_then_else (match_test "<Is_d_reg>")
2128 (match_test "<Scalar_mul_8_16>")
2129 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
2130 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
2132 (match_test "<Scalar_mul_8_16>")
2133 (const_string "neon_mla_qqq_8_16")
2134 (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
2137 (define_insn "neon_vmlsl<mode>"
2138 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2139 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
2140 (match_operand:VW 2 "s_register_operand" "w")
2141 (match_operand:VW 3 "s_register_operand" "w")
2142 (match_operand:SI 4 "immediate_operand" "i")]
2145 "vmlsl.%T4%#<V_sz_elem>\t%q0, %P2, %P3"
2146 [(set (attr "neon_type")
2147 (if_then_else (match_test "<Scalar_mul_8_16>")
2148 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
2149 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
2152 (define_insn "neon_vqdmulh<mode>"
2153 [(set (match_operand:VMDQI 0 "s_register_operand" "=w")
2154 (unspec:VMDQI [(match_operand:VMDQI 1 "s_register_operand" "w")
2155 (match_operand:VMDQI 2 "s_register_operand" "w")
2156 (match_operand:SI 3 "immediate_operand" "i")]
2159 "vq%O3dmulh.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2160 [(set (attr "neon_type")
2161 (if_then_else (match_test "<Is_d_reg>")
2162 (if_then_else (match_test "<Scalar_mul_8_16>")
2163 (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
2164 (const_string "neon_mul_qqq_8_16_32_ddd_32"))
2165 (if_then_else (match_test "<Scalar_mul_8_16>")
2166 (const_string "neon_mul_qqq_8_16_32_ddd_32")
2167 (const_string "neon_mul_qqq_8_16_32_ddd_32"))))]
2170 (define_insn "neon_vqdmlal<mode>"
2171 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2172 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
2173 (match_operand:VMDI 2 "s_register_operand" "w")
2174 (match_operand:VMDI 3 "s_register_operand" "w")
2175 (match_operand:SI 4 "immediate_operand" "i")]
2178 "vqdmlal.<V_s_elem>\t%q0, %P2, %P3"
2179 [(set (attr "neon_type")
2180 (if_then_else (match_test "<Scalar_mul_8_16>")
2181 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
2182 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
2185 (define_insn "neon_vqdmlsl<mode>"
2186 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2187 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
2188 (match_operand:VMDI 2 "s_register_operand" "w")
2189 (match_operand:VMDI 3 "s_register_operand" "w")
2190 (match_operand:SI 4 "immediate_operand" "i")]
2193 "vqdmlsl.<V_s_elem>\t%q0, %P2, %P3"
2194 [(set (attr "neon_type")
2195 (if_then_else (match_test "<Scalar_mul_8_16>")
2196 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
2197 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
2200 (define_insn "neon_vmull<mode>"
2201 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2202 (unspec:<V_widen> [(match_operand:VW 1 "s_register_operand" "w")
2203 (match_operand:VW 2 "s_register_operand" "w")
2204 (match_operand:SI 3 "immediate_operand" "i")]
2207 "vmull.%T3%#<V_sz_elem>\t%q0, %P1, %P2"
2208 [(set (attr "neon_type")
2209 (if_then_else (match_test "<Scalar_mul_8_16>")
2210 (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
2211 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
2214 (define_insn "neon_vqdmull<mode>"
2215 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2216 (unspec:<V_widen> [(match_operand:VMDI 1 "s_register_operand" "w")
2217 (match_operand:VMDI 2 "s_register_operand" "w")
2218 (match_operand:SI 3 "immediate_operand" "i")]
2221 "vqdmull.<V_s_elem>\t%q0, %P1, %P2"
2222 [(set (attr "neon_type")
2223 (if_then_else (match_test "<Scalar_mul_8_16>")
2224 (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
2225 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
2228 (define_expand "neon_vsub<mode>"
2229 [(match_operand:VDQX 0 "s_register_operand" "=w")
2230 (match_operand:VDQX 1 "s_register_operand" "w")
2231 (match_operand:VDQX 2 "s_register_operand" "w")
2232 (match_operand:SI 3 "immediate_operand" "i")]
2235 if (!<Is_float_mode> || flag_unsafe_math_optimizations)
2236 emit_insn (gen_sub<mode>3 (operands[0], operands[1], operands[2]));
2238 emit_insn (gen_neon_vsub<mode>_unspec (operands[0], operands[1],
2243 ; Used for intrinsics when flag_unsafe_math_optimizations is false.
2245 (define_insn "neon_vsub<mode>_unspec"
2246 [(set (match_operand:VDQX 0 "s_register_operand" "=w")
2247 (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w")
2248 (match_operand:VDQX 2 "s_register_operand" "w")]
2251 "vsub.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2252 [(set (attr "neon_type")
2253 (if_then_else (match_test "<Is_float_mode>")
2254 (if_then_else (match_test "<Is_d_reg>")
2255 (const_string "neon_fp_vadd_ddd_vabs_dd")
2256 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2257 (const_string "neon_int_2")))]
2260 (define_insn "neon_vsubl<mode>"
2261 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2262 (unspec:<V_widen> [(match_operand:VDI 1 "s_register_operand" "w")
2263 (match_operand:VDI 2 "s_register_operand" "w")
2264 (match_operand:SI 3 "immediate_operand" "i")]
2267 "vsubl.%T3%#<V_sz_elem>\t%q0, %P1, %P2"
2268 [(set_attr "neon_type" "neon_int_2")]
2271 (define_insn "neon_vsubw<mode>"
2272 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2273 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "w")
2274 (match_operand:VDI 2 "s_register_operand" "w")
2275 (match_operand:SI 3 "immediate_operand" "i")]
2278 "vsubw.%T3%#<V_sz_elem>\t%q0, %q1, %P2"
2279 [(set_attr "neon_type" "neon_int_2")]
2282 (define_insn "neon_vqsub<mode>"
2283 [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
2284 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
2285 (match_operand:VDQIX 2 "s_register_operand" "w")
2286 (match_operand:SI 3 "immediate_operand" "i")]
2289 "vqsub.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2290 [(set_attr "neon_type" "neon_int_5")]
2293 (define_insn "neon_vhsub<mode>"
2294 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2295 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2296 (match_operand:VDQIW 2 "s_register_operand" "w")
2297 (match_operand:SI 3 "immediate_operand" "i")]
2300 "vhsub.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2301 [(set_attr "neon_type" "neon_int_5")]
2304 (define_insn "neon_vsubhn<mode>"
2305 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
2306 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
2307 (match_operand:VN 2 "s_register_operand" "w")
2308 (match_operand:SI 3 "immediate_operand" "i")]
2311 "v%O3subhn.<V_if_elem>\t%P0, %q1, %q2"
2312 [(set_attr "neon_type" "neon_int_4")]
2315 (define_insn "neon_vceq<mode>"
2316 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w,w")
2317 (unspec:<V_cmp_result>
2318 [(match_operand:VDQW 1 "s_register_operand" "w,w")
2319 (match_operand:VDQW 2 "reg_or_zero_operand" "w,Dz")
2320 (match_operand:SI 3 "immediate_operand" "i,i")]
2324 vceq.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2
2325 vceq.<V_if_elem>\t%<V_reg>0, %<V_reg>1, #0"
2326 [(set (attr "neon_type")
2327 (if_then_else (match_test "<Is_float_mode>")
2328 (if_then_else (match_test "<Is_d_reg>")
2329 (const_string "neon_fp_vadd_ddd_vabs_dd")
2330 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2331 (const_string "neon_int_5")))]
2334 (define_insn "neon_vcge<mode>"
2335 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w,w")
2336 (unspec:<V_cmp_result>
2337 [(match_operand:VDQW 1 "s_register_operand" "w,w")
2338 (match_operand:VDQW 2 "reg_or_zero_operand" "w,Dz")
2339 (match_operand:SI 3 "immediate_operand" "i,i")]
2343 vcge.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2
2344 vcge.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, #0"
2345 [(set (attr "neon_type")
2346 (if_then_else (match_test "<Is_float_mode>")
2347 (if_then_else (match_test "<Is_d_reg>")
2348 (const_string "neon_fp_vadd_ddd_vabs_dd")
2349 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2350 (const_string "neon_int_5")))]
2353 (define_insn "neon_vcgeu<mode>"
2354 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
2355 (unspec:<V_cmp_result>
2356 [(match_operand:VDQIW 1 "s_register_operand" "w")
2357 (match_operand:VDQIW 2 "s_register_operand" "w")
2358 (match_operand:SI 3 "immediate_operand" "i")]
2361 "vcge.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2362 [(set_attr "neon_type" "neon_int_5")]
2365 (define_insn "neon_vcgt<mode>"
2366 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w,w")
2367 (unspec:<V_cmp_result>
2368 [(match_operand:VDQW 1 "s_register_operand" "w,w")
2369 (match_operand:VDQW 2 "reg_or_zero_operand" "w,Dz")
2370 (match_operand:SI 3 "immediate_operand" "i,i")]
2374 vcgt.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2
2375 vcgt.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, #0"
2376 [(set (attr "neon_type")
2377 (if_then_else (match_test "<Is_float_mode>")
2378 (if_then_else (match_test "<Is_d_reg>")
2379 (const_string "neon_fp_vadd_ddd_vabs_dd")
2380 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2381 (const_string "neon_int_5")))]
2384 (define_insn "neon_vcgtu<mode>"
2385 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
2386 (unspec:<V_cmp_result>
2387 [(match_operand:VDQIW 1 "s_register_operand" "w")
2388 (match_operand:VDQIW 2 "s_register_operand" "w")
2389 (match_operand:SI 3 "immediate_operand" "i")]
2392 "vcgt.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2393 [(set_attr "neon_type" "neon_int_5")]
2396 ;; VCLE and VCLT only support comparisons with immediate zero (register
2397 ;; variants are VCGE and VCGT with operands reversed).
2399 (define_insn "neon_vcle<mode>"
2400 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
2401 (unspec:<V_cmp_result>
2402 [(match_operand:VDQW 1 "s_register_operand" "w")
2403 (match_operand:VDQW 2 "zero_operand" "Dz")
2404 (match_operand:SI 3 "immediate_operand" "i")]
2407 "vcle.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, #0"
2408 [(set (attr "neon_type")
2409 (if_then_else (match_test "<Is_float_mode>")
2410 (if_then_else (match_test "<Is_d_reg>")
2411 (const_string "neon_fp_vadd_ddd_vabs_dd")
2412 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2413 (const_string "neon_int_5")))]
2416 (define_insn "neon_vclt<mode>"
2417 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
2418 (unspec:<V_cmp_result>
2419 [(match_operand:VDQW 1 "s_register_operand" "w")
2420 (match_operand:VDQW 2 "zero_operand" "Dz")
2421 (match_operand:SI 3 "immediate_operand" "i")]
2424 "vclt.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, #0"
2425 [(set (attr "neon_type")
2426 (if_then_else (match_test "<Is_float_mode>")
2427 (if_then_else (match_test "<Is_d_reg>")
2428 (const_string "neon_fp_vadd_ddd_vabs_dd")
2429 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2430 (const_string "neon_int_5")))]
2433 (define_insn "neon_vcage<mode>"
2434 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
2435 (unspec:<V_cmp_result> [(match_operand:VCVTF 1 "s_register_operand" "w")
2436 (match_operand:VCVTF 2 "s_register_operand" "w")
2437 (match_operand:SI 3 "immediate_operand" "i")]
2440 "vacge.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2441 [(set (attr "neon_type")
2442 (if_then_else (match_test "<Is_d_reg>")
2443 (const_string "neon_fp_vadd_ddd_vabs_dd")
2444 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2447 (define_insn "neon_vcagt<mode>"
2448 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
2449 (unspec:<V_cmp_result> [(match_operand:VCVTF 1 "s_register_operand" "w")
2450 (match_operand:VCVTF 2 "s_register_operand" "w")
2451 (match_operand:SI 3 "immediate_operand" "i")]
2454 "vacgt.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2455 [(set (attr "neon_type")
2456 (if_then_else (match_test "<Is_d_reg>")
2457 (const_string "neon_fp_vadd_ddd_vabs_dd")
2458 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2461 (define_insn "neon_vtst<mode>"
2462 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2463 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2464 (match_operand:VDQIW 2 "s_register_operand" "w")
2465 (match_operand:SI 3 "immediate_operand" "i")]
2468 "vtst.<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2469 [(set_attr "neon_type" "neon_int_4")]
2472 (define_insn "neon_vabd<mode>"
2473 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
2474 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w")
2475 (match_operand:VDQW 2 "s_register_operand" "w")
2476 (match_operand:SI 3 "immediate_operand" "i")]
2479 "vabd.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2480 [(set (attr "neon_type")
2481 (if_then_else (match_test "<Is_float_mode>")
2482 (if_then_else (match_test "<Is_d_reg>")
2483 (const_string "neon_fp_vadd_ddd_vabs_dd")
2484 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2485 (const_string "neon_int_5")))]
2488 (define_insn "neon_vabdl<mode>"
2489 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2490 (unspec:<V_widen> [(match_operand:VW 1 "s_register_operand" "w")
2491 (match_operand:VW 2 "s_register_operand" "w")
2492 (match_operand:SI 3 "immediate_operand" "i")]
2495 "vabdl.%T3%#<V_sz_elem>\t%q0, %P1, %P2"
2496 [(set_attr "neon_type" "neon_int_5")]
2499 (define_insn "neon_vaba<mode>"
2500 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2501 (plus:VDQIW (unspec:VDQIW [(match_operand:VDQIW 2 "s_register_operand" "w")
2502 (match_operand:VDQIW 3 "s_register_operand" "w")
2503 (match_operand:SI 4 "immediate_operand" "i")]
2505 (match_operand:VDQIW 1 "s_register_operand" "0")))]
2507 "vaba.%T4%#<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
2508 [(set (attr "neon_type")
2509 (if_then_else (match_test "<Is_d_reg>")
2510 (const_string "neon_vaba") (const_string "neon_vaba_qqq")))]
2513 (define_insn "neon_vabal<mode>"
2514 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2515 (plus:<V_widen> (unspec:<V_widen> [(match_operand:VW 2 "s_register_operand" "w")
2516 (match_operand:VW 3 "s_register_operand" "w")
2517 (match_operand:SI 4 "immediate_operand" "i")]
2519 (match_operand:<V_widen> 1 "s_register_operand" "0")))]
2521 "vabal.%T4%#<V_sz_elem>\t%q0, %P2, %P3"
2522 [(set_attr "neon_type" "neon_vaba")]
2525 (define_insn "neon_vmax<mode>"
2526 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
2527 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w")
2528 (match_operand:VDQW 2 "s_register_operand" "w")
2529 (match_operand:SI 3 "immediate_operand" "i")]
2532 "vmax.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2533 [(set (attr "neon_type")
2534 (if_then_else (match_test "<Is_float_mode>")
2535 (if_then_else (match_test "<Is_d_reg>")
2536 (const_string "neon_fp_vadd_ddd_vabs_dd")
2537 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2538 (const_string "neon_int_5")))]
2541 (define_insn "neon_vmin<mode>"
2542 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
2543 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w")
2544 (match_operand:VDQW 2 "s_register_operand" "w")
2545 (match_operand:SI 3 "immediate_operand" "i")]
2548 "vmin.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2549 [(set (attr "neon_type")
2550 (if_then_else (match_test "<Is_float_mode>")
2551 (if_then_else (match_test "<Is_d_reg>")
2552 (const_string "neon_fp_vadd_ddd_vabs_dd")
2553 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2554 (const_string "neon_int_5")))]
2557 (define_expand "neon_vpadd<mode>"
2558 [(match_operand:VD 0 "s_register_operand" "=w")
2559 (match_operand:VD 1 "s_register_operand" "w")
2560 (match_operand:VD 2 "s_register_operand" "w")
2561 (match_operand:SI 3 "immediate_operand" "i")]
2564 emit_insn (gen_neon_vpadd_internal<mode> (operands[0], operands[1],
2569 (define_insn "neon_vpaddl<mode>"
2570 [(set (match_operand:<V_double_width> 0 "s_register_operand" "=w")
2571 (unspec:<V_double_width> [(match_operand:VDQIW 1 "s_register_operand" "w")
2572 (match_operand:SI 2 "immediate_operand" "i")]
2575 "vpaddl.%T2%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
2576 ;; Assume this schedules like vaddl.
2577 [(set_attr "neon_type" "neon_int_3")]
2580 (define_insn "neon_vpadal<mode>"
2581 [(set (match_operand:<V_double_width> 0 "s_register_operand" "=w")
2582 (unspec:<V_double_width> [(match_operand:<V_double_width> 1 "s_register_operand" "0")
2583 (match_operand:VDQIW 2 "s_register_operand" "w")
2584 (match_operand:SI 3 "immediate_operand" "i")]
2587 "vpadal.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>2"
2588 ;; Assume this schedules like vpadd.
2589 [(set_attr "neon_type" "neon_int_1")]
2592 (define_insn "neon_vpmax<mode>"
2593 [(set (match_operand:VD 0 "s_register_operand" "=w")
2594 (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
2595 (match_operand:VD 2 "s_register_operand" "w")
2596 (match_operand:SI 3 "immediate_operand" "i")]
2599 "vpmax.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2600 ;; Assume this schedules like vmax.
2601 [(set (attr "neon_type")
2602 (if_then_else (match_test "<Is_float_mode>")
2603 (const_string "neon_fp_vadd_ddd_vabs_dd")
2604 (const_string "neon_int_5")))]
2607 (define_insn "neon_vpmin<mode>"
2608 [(set (match_operand:VD 0 "s_register_operand" "=w")
2609 (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
2610 (match_operand:VD 2 "s_register_operand" "w")
2611 (match_operand:SI 3 "immediate_operand" "i")]
2614 "vpmin.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2615 ;; Assume this schedules like vmin.
2616 [(set (attr "neon_type")
2617 (if_then_else (match_test "<Is_float_mode>")
2618 (const_string "neon_fp_vadd_ddd_vabs_dd")
2619 (const_string "neon_int_5")))]
2622 (define_insn "neon_vrecps<mode>"
2623 [(set (match_operand:VCVTF 0 "s_register_operand" "=w")
2624 (unspec:VCVTF [(match_operand:VCVTF 1 "s_register_operand" "w")
2625 (match_operand:VCVTF 2 "s_register_operand" "w")
2626 (match_operand:SI 3 "immediate_operand" "i")]
2629 "vrecps.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2630 [(set (attr "neon_type")
2631 (if_then_else (match_test "<Is_d_reg>")
2632 (const_string "neon_fp_vrecps_vrsqrts_ddd")
2633 (const_string "neon_fp_vrecps_vrsqrts_qqq")))]
2636 (define_insn "neon_vrsqrts<mode>"
2637 [(set (match_operand:VCVTF 0 "s_register_operand" "=w")
2638 (unspec:VCVTF [(match_operand:VCVTF 1 "s_register_operand" "w")
2639 (match_operand:VCVTF 2 "s_register_operand" "w")
2640 (match_operand:SI 3 "immediate_operand" "i")]
2643 "vrsqrts.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2644 [(set (attr "neon_type")
2645 (if_then_else (match_test "<Is_d_reg>")
2646 (const_string "neon_fp_vrecps_vrsqrts_ddd")
2647 (const_string "neon_fp_vrecps_vrsqrts_qqq")))]
2650 (define_expand "neon_vabs<mode>"
2651 [(match_operand:VDQW 0 "s_register_operand" "")
2652 (match_operand:VDQW 1 "s_register_operand" "")
2653 (match_operand:SI 2 "immediate_operand" "")]
2656 emit_insn (gen_abs<mode>2 (operands[0], operands[1]));
2660 (define_insn "neon_vqabs<mode>"
2661 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2662 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2663 (match_operand:SI 2 "immediate_operand" "i")]
2666 "vqabs.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
2667 [(set_attr "neon_type" "neon_vqneg_vqabs")]
2670 (define_expand "neon_vneg<mode>"
2671 [(match_operand:VDQW 0 "s_register_operand" "")
2672 (match_operand:VDQW 1 "s_register_operand" "")
2673 (match_operand:SI 2 "immediate_operand" "")]
2676 emit_insn (gen_neg<mode>2 (operands[0], operands[1]));
2680 (define_insn "neon_vqneg<mode>"
2681 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2682 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2683 (match_operand:SI 2 "immediate_operand" "i")]
2686 "vqneg.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
2687 [(set_attr "neon_type" "neon_vqneg_vqabs")]
2690 (define_insn "neon_vcls<mode>"
2691 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2692 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2693 (match_operand:SI 2 "immediate_operand" "i")]
2696 "vcls.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
2697 [(set_attr "neon_type" "neon_int_1")]
2700 (define_insn "clz<mode>2"
2701 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2702 (clz:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")))]
2704 "vclz.<V_if_elem>\t%<V_reg>0, %<V_reg>1"
2705 [(set_attr "neon_type" "neon_int_1")]
2708 (define_expand "neon_vclz<mode>"
2709 [(match_operand:VDQIW 0 "s_register_operand" "")
2710 (match_operand:VDQIW 1 "s_register_operand" "")
2711 (match_operand:SI 2 "immediate_operand" "")]
2714 emit_insn (gen_clz<mode>2 (operands[0], operands[1]));
2718 (define_insn "popcount<mode>2"
2719 [(set (match_operand:VE 0 "s_register_operand" "=w")
2720 (popcount:VE (match_operand:VE 1 "s_register_operand" "w")))]
2722 "vcnt.<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
2723 [(set_attr "neon_type" "neon_int_1")]
2726 (define_expand "neon_vcnt<mode>"
2727 [(match_operand:VE 0 "s_register_operand" "=w")
2728 (match_operand:VE 1 "s_register_operand" "w")
2729 (match_operand:SI 2 "immediate_operand" "i")]
2732 emit_insn (gen_popcount<mode>2 (operands[0], operands[1]));
2736 (define_insn "neon_vrecpe<mode>"
2737 [(set (match_operand:V32 0 "s_register_operand" "=w")
2738 (unspec:V32 [(match_operand:V32 1 "s_register_operand" "w")
2739 (match_operand:SI 2 "immediate_operand" "i")]
2742 "vrecpe.<V_u_elem>\t%<V_reg>0, %<V_reg>1"
2743 [(set (attr "neon_type")
2744 (if_then_else (match_test "<Is_d_reg>")
2745 (const_string "neon_fp_vadd_ddd_vabs_dd")
2746 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2749 (define_insn "neon_vrsqrte<mode>"
2750 [(set (match_operand:V32 0 "s_register_operand" "=w")
2751 (unspec:V32 [(match_operand:V32 1 "s_register_operand" "w")
2752 (match_operand:SI 2 "immediate_operand" "i")]
2755 "vrsqrte.<V_u_elem>\t%<V_reg>0, %<V_reg>1"
2756 [(set (attr "neon_type")
2757 (if_then_else (match_test "<Is_d_reg>")
2758 (const_string "neon_fp_vadd_ddd_vabs_dd")
2759 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2762 (define_expand "neon_vmvn<mode>"
2763 [(match_operand:VDQIW 0 "s_register_operand" "")
2764 (match_operand:VDQIW 1 "s_register_operand" "")
2765 (match_operand:SI 2 "immediate_operand" "")]
2768 emit_insn (gen_one_cmpl<mode>2 (operands[0], operands[1]));
2772 (define_insn "neon_vget_lane<mode>_sext_internal"
2773 [(set (match_operand:SI 0 "s_register_operand" "=r")
2775 (vec_select:<V_elem>
2776 (match_operand:VD 1 "s_register_operand" "w")
2777 (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2780 if (BYTES_BIG_ENDIAN)
2782 int elt = INTVAL (operands[2]);
2783 elt = GET_MODE_NUNITS (<MODE>mode) - 1 - elt;
2784 operands[2] = GEN_INT (elt);
2786 return "vmov.s<V_sz_elem>\t%0, %P1[%c2]";
2788 [(set_attr "neon_type" "neon_bp_simple")]
2791 (define_insn "neon_vget_lane<mode>_zext_internal"
2792 [(set (match_operand:SI 0 "s_register_operand" "=r")
2794 (vec_select:<V_elem>
2795 (match_operand:VD 1 "s_register_operand" "w")
2796 (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2799 if (BYTES_BIG_ENDIAN)
2801 int elt = INTVAL (operands[2]);
2802 elt = GET_MODE_NUNITS (<MODE>mode) - 1 - elt;
2803 operands[2] = GEN_INT (elt);
2805 return "vmov.u<V_sz_elem>\t%0, %P1[%c2]";
2807 [(set_attr "neon_type" "neon_bp_simple")]
2810 (define_insn "neon_vget_lane<mode>_sext_internal"
2811 [(set (match_operand:SI 0 "s_register_operand" "=r")
2813 (vec_select:<V_elem>
2814 (match_operand:VQ 1 "s_register_operand" "w")
2815 (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2819 int regno = REGNO (operands[1]);
2820 unsigned int halfelts = GET_MODE_NUNITS (<MODE>mode) / 2;
2821 unsigned int elt = INTVAL (operands[2]);
2822 unsigned int elt_adj = elt % halfelts;
2824 if (BYTES_BIG_ENDIAN)
2825 elt_adj = halfelts - 1 - elt_adj;
2827 ops[0] = operands[0];
2828 ops[1] = gen_rtx_REG (<V_HALF>mode, regno + 2 * (elt / halfelts));
2829 ops[2] = GEN_INT (elt_adj);
2830 output_asm_insn ("vmov.s<V_sz_elem>\t%0, %P1[%c2]", ops);
2834 [(set_attr "neon_type" "neon_bp_simple")]
2837 (define_insn "neon_vget_lane<mode>_zext_internal"
2838 [(set (match_operand:SI 0 "s_register_operand" "=r")
2840 (vec_select:<V_elem>
2841 (match_operand:VQ 1 "s_register_operand" "w")
2842 (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2846 int regno = REGNO (operands[1]);
2847 unsigned int halfelts = GET_MODE_NUNITS (<MODE>mode) / 2;
2848 unsigned int elt = INTVAL (operands[2]);
2849 unsigned int elt_adj = elt % halfelts;
2851 if (BYTES_BIG_ENDIAN)
2852 elt_adj = halfelts - 1 - elt_adj;
2854 ops[0] = operands[0];
2855 ops[1] = gen_rtx_REG (<V_HALF>mode, regno + 2 * (elt / halfelts));
2856 ops[2] = GEN_INT (elt_adj);
2857 output_asm_insn ("vmov.u<V_sz_elem>\t%0, %P1[%c2]", ops);
2861 [(set_attr "neon_type" "neon_bp_simple")]
2864 (define_expand "neon_vget_lane<mode>"
2865 [(match_operand:<V_ext> 0 "s_register_operand" "")
2866 (match_operand:VDQW 1 "s_register_operand" "")
2867 (match_operand:SI 2 "immediate_operand" "")
2868 (match_operand:SI 3 "immediate_operand" "")]
2871 HOST_WIDE_INT magic = INTVAL (operands[3]);
2874 neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<MODE>mode));
2876 if (BYTES_BIG_ENDIAN)
2878 /* The intrinsics are defined in terms of a model where the
2879 element ordering in memory is vldm order, whereas the generic
2880 RTL is defined in terms of a model where the element ordering
2881 in memory is array order. Convert the lane number to conform
2883 unsigned int elt = INTVAL (operands[2]);
2884 unsigned int reg_nelts
2885 = 64 / GET_MODE_BITSIZE (GET_MODE_INNER (<MODE>mode));
2886 elt ^= reg_nelts - 1;
2887 operands[2] = GEN_INT (elt);
2890 if ((magic & 3) == 3 || GET_MODE_BITSIZE (GET_MODE_INNER (<MODE>mode)) == 32)
2891 insn = gen_vec_extract<mode> (operands[0], operands[1], operands[2]);
2894 if ((magic & 1) != 0)
2895 insn = gen_neon_vget_lane<mode>_sext_internal (operands[0], operands[1],
2898 insn = gen_neon_vget_lane<mode>_zext_internal (operands[0], operands[1],
2905 ; Operand 3 (info word) is ignored because it does nothing useful with 64-bit
2908 (define_expand "neon_vget_lanedi"
2909 [(match_operand:DI 0 "s_register_operand" "=r")
2910 (match_operand:DI 1 "s_register_operand" "w")
2911 (match_operand:SI 2 "immediate_operand" "i")
2912 (match_operand:SI 3 "immediate_operand" "i")]
2915 neon_lane_bounds (operands[2], 0, 1);
2916 emit_move_insn (operands[0], operands[1]);
2920 (define_expand "neon_vget_lanev2di"
2921 [(match_operand:DI 0 "s_register_operand" "")
2922 (match_operand:V2DI 1 "s_register_operand" "")
2923 (match_operand:SI 2 "immediate_operand" "")
2924 (match_operand:SI 3 "immediate_operand" "")]
2927 switch (INTVAL (operands[2]))
2930 emit_move_insn (operands[0], gen_lowpart (DImode, operands[1]));
2933 emit_move_insn (operands[0], gen_highpart (DImode, operands[1]));
2936 neon_lane_bounds (operands[2], 0, 1);
2942 (define_expand "neon_vset_lane<mode>"
2943 [(match_operand:VDQ 0 "s_register_operand" "=w")
2944 (match_operand:<V_elem> 1 "s_register_operand" "r")
2945 (match_operand:VDQ 2 "s_register_operand" "0")
2946 (match_operand:SI 3 "immediate_operand" "i")]
2949 unsigned int elt = INTVAL (operands[3]);
2950 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
2952 if (BYTES_BIG_ENDIAN)
2954 unsigned int reg_nelts
2955 = 64 / GET_MODE_BITSIZE (GET_MODE_INNER (<MODE>mode));
2956 elt ^= reg_nelts - 1;
2959 emit_insn (gen_vec_set<mode>_internal (operands[0], operands[1],
2960 GEN_INT (1 << elt), operands[2]));
2964 ; See neon_vget_lanedi comment for reasons operands 2 & 3 are ignored.
2966 (define_expand "neon_vset_lanedi"
2967 [(match_operand:DI 0 "s_register_operand" "=w")
2968 (match_operand:DI 1 "s_register_operand" "r")
2969 (match_operand:DI 2 "s_register_operand" "0")
2970 (match_operand:SI 3 "immediate_operand" "i")]
2973 neon_lane_bounds (operands[3], 0, 1);
2974 emit_move_insn (operands[0], operands[1]);
2978 (define_expand "neon_vcreate<mode>"
2979 [(match_operand:VDX 0 "s_register_operand" "")
2980 (match_operand:DI 1 "general_operand" "")]
2983 rtx src = gen_lowpart (<MODE>mode, operands[1]);
2984 emit_move_insn (operands[0], src);
2988 (define_insn "neon_vdup_n<mode>"
2989 [(set (match_operand:VX 0 "s_register_operand" "=w")
2990 (vec_duplicate:VX (match_operand:<V_elem> 1 "s_register_operand" "r")))]
2992 "vdup.<V_sz_elem>\t%<V_reg>0, %1"
2993 ;; Assume this schedules like vmov.
2994 [(set_attr "neon_type" "neon_bp_simple")]
2997 (define_insn "neon_vdup_n<mode>"
2998 [(set (match_operand:V32 0 "s_register_operand" "=w,w")
2999 (vec_duplicate:V32 (match_operand:<V_elem> 1 "s_register_operand" "r,t")))]
3002 vdup.<V_sz_elem>\t%<V_reg>0, %1
3003 vdup.<V_sz_elem>\t%<V_reg>0, %y1"
3004 ;; Assume this schedules like vmov.
3005 [(set_attr "neon_type" "neon_bp_simple")]
3008 (define_expand "neon_vdup_ndi"
3009 [(match_operand:DI 0 "s_register_operand" "=w")
3010 (match_operand:DI 1 "s_register_operand" "r")]
3013 emit_move_insn (operands[0], operands[1]);
3018 (define_insn "neon_vdup_nv2di"
3019 [(set (match_operand:V2DI 0 "s_register_operand" "=w,w")
3020 (vec_duplicate:V2DI (match_operand:DI 1 "s_register_operand" "r,w")))]
3023 vmov\t%e0, %Q1, %R1\;vmov\t%f0, %Q1, %R1
3024 vmov\t%e0, %P1\;vmov\t%f0, %P1"
3025 [(set_attr "length" "8")
3026 (set_attr "neon_type" "neon_bp_simple")]
3029 (define_insn "neon_vdup_lane<mode>_internal"
3030 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
3032 (vec_select:<V_elem>
3033 (match_operand:<V_double_vector_mode> 1 "s_register_operand" "w")
3034 (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
3037 if (BYTES_BIG_ENDIAN)
3039 int elt = INTVAL (operands[2]);
3040 elt = GET_MODE_NUNITS (<V_double_vector_mode>mode) - 1 - elt;
3041 operands[2] = GEN_INT (elt);
3044 return "vdup.<V_sz_elem>\t%P0, %P1[%c2]";
3046 return "vdup.<V_sz_elem>\t%q0, %P1[%c2]";
3048 ;; Assume this schedules like vmov.
3049 [(set_attr "neon_type" "neon_bp_simple")]
3052 (define_expand "neon_vdup_lane<mode>"
3053 [(match_operand:VDQW 0 "s_register_operand" "=w")
3054 (match_operand:<V_double_vector_mode> 1 "s_register_operand" "w")
3055 (match_operand:SI 2 "immediate_operand" "i")]
3058 neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<V_double_vector_mode>mode));
3059 if (BYTES_BIG_ENDIAN)
3061 unsigned int elt = INTVAL (operands[2]);
3062 unsigned int reg_nelts
3063 = 64 / GET_MODE_BITSIZE (GET_MODE_INNER (<V_double_vector_mode>mode));
3064 elt ^= reg_nelts - 1;
3065 operands[2] = GEN_INT (elt);
3067 emit_insn (gen_neon_vdup_lane<mode>_internal (operands[0], operands[1],
3072 ; Scalar index is ignored, since only zero is valid here.
3073 (define_expand "neon_vdup_lanedi"
3074 [(match_operand:DI 0 "s_register_operand" "=w")
3075 (match_operand:DI 1 "s_register_operand" "w")
3076 (match_operand:SI 2 "immediate_operand" "i")]
3079 neon_lane_bounds (operands[2], 0, 1);
3080 emit_move_insn (operands[0], operands[1]);
3084 ; Likewise for v2di, as the DImode second operand has only a single element.
3085 (define_expand "neon_vdup_lanev2di"
3086 [(match_operand:V2DI 0 "s_register_operand" "=w")
3087 (match_operand:DI 1 "s_register_operand" "w")
3088 (match_operand:SI 2 "immediate_operand" "i")]
3091 neon_lane_bounds (operands[2], 0, 1);
3092 emit_insn (gen_neon_vdup_nv2di (operands[0], operands[1]));
3096 ; Disabled before reload because we don't want combine doing something silly,
3097 ; but used by the post-reload expansion of neon_vcombine.
3098 (define_insn "*neon_vswp<mode>"
3099 [(set (match_operand:VDQX 0 "s_register_operand" "+w")
3100 (match_operand:VDQX 1 "s_register_operand" "+w"))
3101 (set (match_dup 1) (match_dup 0))]
3102 "TARGET_NEON && reload_completed"
3103 "vswp\t%<V_reg>0, %<V_reg>1"
3104 [(set (attr "neon_type")
3105 (if_then_else (match_test "<Is_d_reg>")
3106 (const_string "neon_bp_simple")
3107 (const_string "neon_bp_2cycle")))]
3110 ;; In this insn, operand 1 should be low, and operand 2 the high part of the
3112 ;; FIXME: A different implementation of this builtin could make it much
3113 ;; more likely that we wouldn't actually need to output anything (we could make
3114 ;; it so that the reg allocator puts things in the right places magically
3115 ;; instead). Lack of subregs for vectors makes that tricky though, I think.
3117 (define_insn_and_split "neon_vcombine<mode>"
3118 [(set (match_operand:<V_DOUBLE> 0 "s_register_operand" "=w")
3119 (vec_concat:<V_DOUBLE>
3120 (match_operand:VDX 1 "s_register_operand" "w")
3121 (match_operand:VDX 2 "s_register_operand" "w")))]
3124 "&& reload_completed"
3127 neon_split_vcombine (operands);
3131 (define_expand "neon_vget_high<mode>"
3132 [(match_operand:<V_HALF> 0 "s_register_operand")
3133 (match_operand:VQX 1 "s_register_operand")]
3136 emit_move_insn (operands[0],
3137 simplify_gen_subreg (<V_HALF>mode, operands[1], <MODE>mode,
3138 GET_MODE_SIZE (<V_HALF>mode)));
3142 (define_expand "neon_vget_low<mode>"
3143 [(match_operand:<V_HALF> 0 "s_register_operand")
3144 (match_operand:VQX 1 "s_register_operand")]
3147 emit_move_insn (operands[0],
3148 simplify_gen_subreg (<V_HALF>mode, operands[1],
3153 (define_insn "float<mode><V_cvtto>2"
3154 [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
3155 (float:<V_CVTTO> (match_operand:VCVTI 1 "s_register_operand" "w")))]
3156 "TARGET_NEON && !flag_rounding_math"
3157 "vcvt.f32.s32\t%<V_reg>0, %<V_reg>1"
3158 [(set (attr "neon_type")
3159 (if_then_else (match_test "<Is_d_reg>")
3160 (const_string "neon_fp_vadd_ddd_vabs_dd")
3161 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
3164 (define_insn "floatuns<mode><V_cvtto>2"
3165 [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
3166 (unsigned_float:<V_CVTTO> (match_operand:VCVTI 1 "s_register_operand" "w")))]
3167 "TARGET_NEON && !flag_rounding_math"
3168 "vcvt.f32.u32\t%<V_reg>0, %<V_reg>1"
3169 [(set (attr "neon_type")
3170 (if_then_else (match_test "<Is_d_reg>")
3171 (const_string "neon_fp_vadd_ddd_vabs_dd")
3172 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
3175 (define_insn "fix_trunc<mode><V_cvtto>2"
3176 [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
3177 (fix:<V_CVTTO> (match_operand:VCVTF 1 "s_register_operand" "w")))]
3179 "vcvt.s32.f32\t%<V_reg>0, %<V_reg>1"
3180 [(set (attr "neon_type")
3181 (if_then_else (match_test "<Is_d_reg>")
3182 (const_string "neon_fp_vadd_ddd_vabs_dd")
3183 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
3186 (define_insn "fixuns_trunc<mode><V_cvtto>2"
3187 [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
3188 (unsigned_fix:<V_CVTTO> (match_operand:VCVTF 1 "s_register_operand" "w")))]
3190 "vcvt.u32.f32\t%<V_reg>0, %<V_reg>1"
3191 [(set (attr "neon_type")
3192 (if_then_else (match_test "<Is_d_reg>")
3193 (const_string "neon_fp_vadd_ddd_vabs_dd")
3194 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
3197 (define_insn "neon_vcvt<mode>"
3198 [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
3199 (unspec:<V_CVTTO> [(match_operand:VCVTF 1 "s_register_operand" "w")
3200 (match_operand:SI 2 "immediate_operand" "i")]
3203 "vcvt.%T2%#32.f32\t%<V_reg>0, %<V_reg>1"
3204 [(set (attr "neon_type")
3205 (if_then_else (match_test "<Is_d_reg>")
3206 (const_string "neon_fp_vadd_ddd_vabs_dd")
3207 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
3210 (define_insn "neon_vcvt<mode>"
3211 [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
3212 (unspec:<V_CVTTO> [(match_operand:VCVTI 1 "s_register_operand" "w")
3213 (match_operand:SI 2 "immediate_operand" "i")]
3216 "vcvt.f32.%T2%#32\t%<V_reg>0, %<V_reg>1"
3217 [(set (attr "neon_type")
3218 (if_then_else (match_test "<Is_d_reg>")
3219 (const_string "neon_fp_vadd_ddd_vabs_dd")
3220 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
3223 (define_insn "neon_vcvtv4sfv4hf"
3224 [(set (match_operand:V4SF 0 "s_register_operand" "=w")
3225 (unspec:V4SF [(match_operand:V4HF 1 "s_register_operand" "w")]
3227 "TARGET_NEON && TARGET_FP16"
3228 "vcvt.f32.f16\t%q0, %P1"
3229 [(set_attr "neon_type" "neon_fp_vadd_ddd_vabs_dd")]
3232 (define_insn "neon_vcvtv4hfv4sf"
3233 [(set (match_operand:V4HF 0 "s_register_operand" "=w")
3234 (unspec:V4HF [(match_operand:V4SF 1 "s_register_operand" "w")]
3236 "TARGET_NEON && TARGET_FP16"
3237 "vcvt.f16.f32\t%P0, %q1"
3238 [(set_attr "neon_type" "neon_fp_vadd_ddd_vabs_dd")]
3241 (define_insn "neon_vcvt_n<mode>"
3242 [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
3243 (unspec:<V_CVTTO> [(match_operand:VCVTF 1 "s_register_operand" "w")
3244 (match_operand:SI 2 "immediate_operand" "i")
3245 (match_operand:SI 3 "immediate_operand" "i")]
3249 neon_const_bounds (operands[2], 1, 33);
3250 return "vcvt.%T3%#32.f32\t%<V_reg>0, %<V_reg>1, %2";
3252 [(set (attr "neon_type")
3253 (if_then_else (match_test "<Is_d_reg>")
3254 (const_string "neon_fp_vadd_ddd_vabs_dd")
3255 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
3258 (define_insn "neon_vcvt_n<mode>"
3259 [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
3260 (unspec:<V_CVTTO> [(match_operand:VCVTI 1 "s_register_operand" "w")
3261 (match_operand:SI 2 "immediate_operand" "i")
3262 (match_operand:SI 3 "immediate_operand" "i")]
3266 neon_const_bounds (operands[2], 1, 33);
3267 return "vcvt.f32.%T3%#32\t%<V_reg>0, %<V_reg>1, %2";
3269 [(set (attr "neon_type")
3270 (if_then_else (match_test "<Is_d_reg>")
3271 (const_string "neon_fp_vadd_ddd_vabs_dd")
3272 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
3275 (define_insn "neon_vmovn<mode>"
3276 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
3277 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
3278 (match_operand:SI 2 "immediate_operand" "i")]
3281 "vmovn.<V_if_elem>\t%P0, %q1"
3282 [(set_attr "neon_type" "neon_bp_simple")]
3285 (define_insn "neon_vqmovn<mode>"
3286 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
3287 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
3288 (match_operand:SI 2 "immediate_operand" "i")]
3291 "vqmovn.%T2%#<V_sz_elem>\t%P0, %q1"
3292 [(set_attr "neon_type" "neon_shift_2")]
3295 (define_insn "neon_vqmovun<mode>"
3296 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
3297 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
3298 (match_operand:SI 2 "immediate_operand" "i")]
3301 "vqmovun.<V_s_elem>\t%P0, %q1"
3302 [(set_attr "neon_type" "neon_shift_2")]
3305 (define_insn "neon_vmovl<mode>"
3306 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3307 (unspec:<V_widen> [(match_operand:VW 1 "s_register_operand" "w")
3308 (match_operand:SI 2 "immediate_operand" "i")]
3311 "vmovl.%T2%#<V_sz_elem>\t%q0, %P1"
3312 [(set_attr "neon_type" "neon_shift_1")]
3315 (define_insn "neon_vmul_lane<mode>"
3316 [(set (match_operand:VMD 0 "s_register_operand" "=w")
3317 (unspec:VMD [(match_operand:VMD 1 "s_register_operand" "w")
3318 (match_operand:VMD 2 "s_register_operand"
3319 "<scalar_mul_constraint>")
3320 (match_operand:SI 3 "immediate_operand" "i")
3321 (match_operand:SI 4 "immediate_operand" "i")]
3325 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
3326 return "vmul.<V_if_elem>\t%P0, %P1, %P2[%c3]";
3328 [(set (attr "neon_type")
3329 (if_then_else (match_test "<Is_float_mode>")
3330 (const_string "neon_fp_vmul_ddd")
3331 (if_then_else (match_test "<Scalar_mul_8_16>")
3332 (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
3333 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar"))))]
3336 (define_insn "neon_vmul_lane<mode>"
3337 [(set (match_operand:VMQ 0 "s_register_operand" "=w")
3338 (unspec:VMQ [(match_operand:VMQ 1 "s_register_operand" "w")
3339 (match_operand:<V_HALF> 2 "s_register_operand"
3340 "<scalar_mul_constraint>")
3341 (match_operand:SI 3 "immediate_operand" "i")
3342 (match_operand:SI 4 "immediate_operand" "i")]
3346 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<V_HALF>mode));
3347 return "vmul.<V_if_elem>\t%q0, %q1, %P2[%c3]";
3349 [(set (attr "neon_type")
3350 (if_then_else (match_test "<Is_float_mode>")
3351 (const_string "neon_fp_vmul_qqd")
3352 (if_then_else (match_test "<Scalar_mul_8_16>")
3353 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")
3354 (const_string "neon_mul_qqd_32_scalar"))))]
3357 (define_insn "neon_vmull_lane<mode>"
3358 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3359 (unspec:<V_widen> [(match_operand:VMDI 1 "s_register_operand" "w")
3360 (match_operand:VMDI 2 "s_register_operand"
3361 "<scalar_mul_constraint>")
3362 (match_operand:SI 3 "immediate_operand" "i")
3363 (match_operand:SI 4 "immediate_operand" "i")]
3364 UNSPEC_VMULL_LANE))]
3367 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
3368 return "vmull.%T4%#<V_sz_elem>\t%q0, %P1, %P2[%c3]";
3370 [(set (attr "neon_type")
3371 (if_then_else (match_test "<Scalar_mul_8_16>")
3372 (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
3373 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
3376 (define_insn "neon_vqdmull_lane<mode>"
3377 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3378 (unspec:<V_widen> [(match_operand:VMDI 1 "s_register_operand" "w")
3379 (match_operand:VMDI 2 "s_register_operand"
3380 "<scalar_mul_constraint>")
3381 (match_operand:SI 3 "immediate_operand" "i")
3382 (match_operand:SI 4 "immediate_operand" "i")]
3383 UNSPEC_VQDMULL_LANE))]
3386 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
3387 return "vqdmull.<V_s_elem>\t%q0, %P1, %P2[%c3]";
3389 [(set (attr "neon_type")
3390 (if_then_else (match_test "<Scalar_mul_8_16>")
3391 (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
3392 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
3395 (define_insn "neon_vqdmulh_lane<mode>"
3396 [(set (match_operand:VMQI 0 "s_register_operand" "=w")
3397 (unspec:VMQI [(match_operand:VMQI 1 "s_register_operand" "w")
3398 (match_operand:<V_HALF> 2 "s_register_operand"
3399 "<scalar_mul_constraint>")
3400 (match_operand:SI 3 "immediate_operand" "i")
3401 (match_operand:SI 4 "immediate_operand" "i")]
3402 UNSPEC_VQDMULH_LANE))]
3405 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
3406 return "vq%O4dmulh.%T4%#<V_sz_elem>\t%q0, %q1, %P2[%c3]";
3408 [(set (attr "neon_type")
3409 (if_then_else (match_test "<Scalar_mul_8_16>")
3410 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")
3411 (const_string "neon_mul_qqd_32_scalar")))]
3414 (define_insn "neon_vqdmulh_lane<mode>"
3415 [(set (match_operand:VMDI 0 "s_register_operand" "=w")
3416 (unspec:VMDI [(match_operand:VMDI 1 "s_register_operand" "w")
3417 (match_operand:VMDI 2 "s_register_operand"
3418 "<scalar_mul_constraint>")
3419 (match_operand:SI 3 "immediate_operand" "i")
3420 (match_operand:SI 4 "immediate_operand" "i")]
3421 UNSPEC_VQDMULH_LANE))]
3424 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
3425 return "vq%O4dmulh.%T4%#<V_sz_elem>\t%P0, %P1, %P2[%c3]";
3427 [(set (attr "neon_type")
3428 (if_then_else (match_test "<Scalar_mul_8_16>")
3429 (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
3430 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
3433 (define_insn "neon_vmla_lane<mode>"
3434 [(set (match_operand:VMD 0 "s_register_operand" "=w")
3435 (unspec:VMD [(match_operand:VMD 1 "s_register_operand" "0")
3436 (match_operand:VMD 2 "s_register_operand" "w")
3437 (match_operand:VMD 3 "s_register_operand"
3438 "<scalar_mul_constraint>")
3439 (match_operand:SI 4 "immediate_operand" "i")
3440 (match_operand:SI 5 "immediate_operand" "i")]
3444 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3445 return "vmla.<V_if_elem>\t%P0, %P2, %P3[%c4]";
3447 [(set (attr "neon_type")
3448 (if_then_else (match_test "<Is_float_mode>")
3449 (const_string "neon_fp_vmla_ddd_scalar")
3450 (if_then_else (match_test "<Scalar_mul_8_16>")
3451 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3452 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))))]
3455 (define_insn "neon_vmla_lane<mode>"
3456 [(set (match_operand:VMQ 0 "s_register_operand" "=w")
3457 (unspec:VMQ [(match_operand:VMQ 1 "s_register_operand" "0")
3458 (match_operand:VMQ 2 "s_register_operand" "w")
3459 (match_operand:<V_HALF> 3 "s_register_operand"
3460 "<scalar_mul_constraint>")
3461 (match_operand:SI 4 "immediate_operand" "i")
3462 (match_operand:SI 5 "immediate_operand" "i")]
3466 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3467 return "vmla.<V_if_elem>\t%q0, %q2, %P3[%c4]";
3469 [(set (attr "neon_type")
3470 (if_then_else (match_test "<Is_float_mode>")
3471 (const_string "neon_fp_vmla_qqq_scalar")
3472 (if_then_else (match_test "<Scalar_mul_8_16>")
3473 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")
3474 (const_string "neon_mla_qqq_32_qqd_32_scalar"))))]
3477 (define_insn "neon_vmlal_lane<mode>"
3478 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3479 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
3480 (match_operand:VMDI 2 "s_register_operand" "w")
3481 (match_operand:VMDI 3 "s_register_operand"
3482 "<scalar_mul_constraint>")
3483 (match_operand:SI 4 "immediate_operand" "i")
3484 (match_operand:SI 5 "immediate_operand" "i")]
3485 UNSPEC_VMLAL_LANE))]
3488 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3489 return "vmlal.%T5%#<V_sz_elem>\t%q0, %P2, %P3[%c4]";
3491 [(set (attr "neon_type")
3492 (if_then_else (match_test "<Scalar_mul_8_16>")
3493 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3494 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
3497 (define_insn "neon_vqdmlal_lane<mode>"
3498 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3499 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
3500 (match_operand:VMDI 2 "s_register_operand" "w")
3501 (match_operand:VMDI 3 "s_register_operand"
3502 "<scalar_mul_constraint>")
3503 (match_operand:SI 4 "immediate_operand" "i")
3504 (match_operand:SI 5 "immediate_operand" "i")]
3505 UNSPEC_VQDMLAL_LANE))]
3508 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3509 return "vqdmlal.<V_s_elem>\t%q0, %P2, %P3[%c4]";
3511 [(set (attr "neon_type")
3512 (if_then_else (match_test "<Scalar_mul_8_16>")
3513 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3514 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
3517 (define_insn "neon_vmls_lane<mode>"
3518 [(set (match_operand:VMD 0 "s_register_operand" "=w")
3519 (unspec:VMD [(match_operand:VMD 1 "s_register_operand" "0")
3520 (match_operand:VMD 2 "s_register_operand" "w")
3521 (match_operand:VMD 3 "s_register_operand"
3522 "<scalar_mul_constraint>")
3523 (match_operand:SI 4 "immediate_operand" "i")
3524 (match_operand:SI 5 "immediate_operand" "i")]
3528 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3529 return "vmls.<V_if_elem>\t%P0, %P2, %P3[%c4]";
3531 [(set (attr "neon_type")
3532 (if_then_else (match_test "<Is_float_mode>")
3533 (const_string "neon_fp_vmla_ddd_scalar")
3534 (if_then_else (match_test "<Scalar_mul_8_16>")
3535 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3536 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))))]
3539 (define_insn "neon_vmls_lane<mode>"
3540 [(set (match_operand:VMQ 0 "s_register_operand" "=w")
3541 (unspec:VMQ [(match_operand:VMQ 1 "s_register_operand" "0")
3542 (match_operand:VMQ 2 "s_register_operand" "w")
3543 (match_operand:<V_HALF> 3 "s_register_operand"
3544 "<scalar_mul_constraint>")
3545 (match_operand:SI 4 "immediate_operand" "i")
3546 (match_operand:SI 5 "immediate_operand" "i")]
3550 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3551 return "vmls.<V_if_elem>\t%q0, %q2, %P3[%c4]";
3553 [(set (attr "neon_type")
3554 (if_then_else (match_test "<Is_float_mode>")
3555 (const_string "neon_fp_vmla_qqq_scalar")
3556 (if_then_else (match_test "<Scalar_mul_8_16>")
3557 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")
3558 (const_string "neon_mla_qqq_32_qqd_32_scalar"))))]
3561 (define_insn "neon_vmlsl_lane<mode>"
3562 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3563 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
3564 (match_operand:VMDI 2 "s_register_operand" "w")
3565 (match_operand:VMDI 3 "s_register_operand"
3566 "<scalar_mul_constraint>")
3567 (match_operand:SI 4 "immediate_operand" "i")
3568 (match_operand:SI 5 "immediate_operand" "i")]
3569 UNSPEC_VMLSL_LANE))]
3572 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3573 return "vmlsl.%T5%#<V_sz_elem>\t%q0, %P2, %P3[%c4]";
3575 [(set (attr "neon_type")
3576 (if_then_else (match_test "<Scalar_mul_8_16>")
3577 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3578 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
3581 (define_insn "neon_vqdmlsl_lane<mode>"
3582 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3583 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
3584 (match_operand:VMDI 2 "s_register_operand" "w")
3585 (match_operand:VMDI 3 "s_register_operand"
3586 "<scalar_mul_constraint>")
3587 (match_operand:SI 4 "immediate_operand" "i")
3588 (match_operand:SI 5 "immediate_operand" "i")]
3589 UNSPEC_VQDMLSL_LANE))]
3592 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3593 return "vqdmlsl.<V_s_elem>\t%q0, %P2, %P3[%c4]";
3595 [(set (attr "neon_type")
3596 (if_then_else (match_test "<Scalar_mul_8_16>")
3597 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3598 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
3601 ; FIXME: For the "_n" multiply/multiply-accumulate insns, we copy a value in a
3602 ; core register into a temp register, then use a scalar taken from that. This
3603 ; isn't an optimal solution if e.g. the scalar has just been read from memory
3604 ; or extracted from another vector. The latter case it's currently better to
3605 ; use the "_lane" variant, and the former case can probably be implemented
3606 ; using vld1_lane, but that hasn't been done yet.
3608 (define_expand "neon_vmul_n<mode>"
3609 [(match_operand:VMD 0 "s_register_operand" "")
3610 (match_operand:VMD 1 "s_register_operand" "")
3611 (match_operand:<V_elem> 2 "s_register_operand" "")
3612 (match_operand:SI 3 "immediate_operand" "")]
3615 rtx tmp = gen_reg_rtx (<MODE>mode);
3616 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[2], tmp, const0_rtx));
3617 emit_insn (gen_neon_vmul_lane<mode> (operands[0], operands[1], tmp,
3618 const0_rtx, const0_rtx));
3622 (define_expand "neon_vmul_n<mode>"
3623 [(match_operand:VMQ 0 "s_register_operand" "")
3624 (match_operand:VMQ 1 "s_register_operand" "")
3625 (match_operand:<V_elem> 2 "s_register_operand" "")
3626 (match_operand:SI 3 "immediate_operand" "")]
3629 rtx tmp = gen_reg_rtx (<V_HALF>mode);
3630 emit_insn (gen_neon_vset_lane<V_half> (tmp, operands[2], tmp, const0_rtx));
3631 emit_insn (gen_neon_vmul_lane<mode> (operands[0], operands[1], tmp,
3632 const0_rtx, const0_rtx));
3636 (define_expand "neon_vmull_n<mode>"
3637 [(match_operand:<V_widen> 0 "s_register_operand" "")
3638 (match_operand:VMDI 1 "s_register_operand" "")
3639 (match_operand:<V_elem> 2 "s_register_operand" "")
3640 (match_operand:SI 3 "immediate_operand" "")]
3643 rtx tmp = gen_reg_rtx (<MODE>mode);
3644 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[2], tmp, const0_rtx));
3645 emit_insn (gen_neon_vmull_lane<mode> (operands[0], operands[1], tmp,
3646 const0_rtx, operands[3]));
3650 (define_expand "neon_vqdmull_n<mode>"
3651 [(match_operand:<V_widen> 0 "s_register_operand" "")
3652 (match_operand:VMDI 1 "s_register_operand" "")
3653 (match_operand:<V_elem> 2 "s_register_operand" "")
3654 (match_operand:SI 3 "immediate_operand" "")]
3657 rtx tmp = gen_reg_rtx (<MODE>mode);
3658 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[2], tmp, const0_rtx));
3659 emit_insn (gen_neon_vqdmull_lane<mode> (operands[0], operands[1], tmp,
3660 const0_rtx, const0_rtx));
3664 (define_expand "neon_vqdmulh_n<mode>"
3665 [(match_operand:VMDI 0 "s_register_operand" "")
3666 (match_operand:VMDI 1 "s_register_operand" "")
3667 (match_operand:<V_elem> 2 "s_register_operand" "")
3668 (match_operand:SI 3 "immediate_operand" "")]
3671 rtx tmp = gen_reg_rtx (<MODE>mode);
3672 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[2], tmp, const0_rtx));
3673 emit_insn (gen_neon_vqdmulh_lane<mode> (operands[0], operands[1], tmp,
3674 const0_rtx, operands[3]));
3678 (define_expand "neon_vqdmulh_n<mode>"
3679 [(match_operand:VMQI 0 "s_register_operand" "")
3680 (match_operand:VMQI 1 "s_register_operand" "")
3681 (match_operand:<V_elem> 2 "s_register_operand" "")
3682 (match_operand:SI 3 "immediate_operand" "")]
3685 rtx tmp = gen_reg_rtx (<V_HALF>mode);
3686 emit_insn (gen_neon_vset_lane<V_half> (tmp, operands[2], tmp, const0_rtx));
3687 emit_insn (gen_neon_vqdmulh_lane<mode> (operands[0], operands[1], tmp,
3688 const0_rtx, operands[3]));
3692 (define_expand "neon_vmla_n<mode>"
3693 [(match_operand:VMD 0 "s_register_operand" "")
3694 (match_operand:VMD 1 "s_register_operand" "")
3695 (match_operand:VMD 2 "s_register_operand" "")
3696 (match_operand:<V_elem> 3 "s_register_operand" "")
3697 (match_operand:SI 4 "immediate_operand" "")]
3700 rtx tmp = gen_reg_rtx (<MODE>mode);
3701 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx));
3702 emit_insn (gen_neon_vmla_lane<mode> (operands[0], operands[1], operands[2],
3703 tmp, const0_rtx, operands[4]));
3707 (define_expand "neon_vmla_n<mode>"
3708 [(match_operand:VMQ 0 "s_register_operand" "")
3709 (match_operand:VMQ 1 "s_register_operand" "")
3710 (match_operand:VMQ 2 "s_register_operand" "")
3711 (match_operand:<V_elem> 3 "s_register_operand" "")
3712 (match_operand:SI 4 "immediate_operand" "")]
3715 rtx tmp = gen_reg_rtx (<V_HALF>mode);
3716 emit_insn (gen_neon_vset_lane<V_half> (tmp, operands[3], tmp, const0_rtx));
3717 emit_insn (gen_neon_vmla_lane<mode> (operands[0], operands[1], operands[2],
3718 tmp, const0_rtx, operands[4]));
3722 (define_expand "neon_vmlal_n<mode>"
3723 [(match_operand:<V_widen> 0 "s_register_operand" "")
3724 (match_operand:<V_widen> 1 "s_register_operand" "")
3725 (match_operand:VMDI 2 "s_register_operand" "")
3726 (match_operand:<V_elem> 3 "s_register_operand" "")
3727 (match_operand:SI 4 "immediate_operand" "")]
3730 rtx tmp = gen_reg_rtx (<MODE>mode);
3731 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx));
3732 emit_insn (gen_neon_vmlal_lane<mode> (operands[0], operands[1], operands[2],
3733 tmp, const0_rtx, operands[4]));
3737 (define_expand "neon_vqdmlal_n<mode>"
3738 [(match_operand:<V_widen> 0 "s_register_operand" "")
3739 (match_operand:<V_widen> 1 "s_register_operand" "")
3740 (match_operand:VMDI 2 "s_register_operand" "")
3741 (match_operand:<V_elem> 3 "s_register_operand" "")
3742 (match_operand:SI 4 "immediate_operand" "")]
3745 rtx tmp = gen_reg_rtx (<MODE>mode);
3746 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx));
3747 emit_insn (gen_neon_vqdmlal_lane<mode> (operands[0], operands[1], operands[2],
3748 tmp, const0_rtx, operands[4]));
3752 (define_expand "neon_vmls_n<mode>"
3753 [(match_operand:VMD 0 "s_register_operand" "")
3754 (match_operand:VMD 1 "s_register_operand" "")
3755 (match_operand:VMD 2 "s_register_operand" "")
3756 (match_operand:<V_elem> 3 "s_register_operand" "")
3757 (match_operand:SI 4 "immediate_operand" "")]
3760 rtx tmp = gen_reg_rtx (<MODE>mode);
3761 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx));
3762 emit_insn (gen_neon_vmls_lane<mode> (operands[0], operands[1], operands[2],
3763 tmp, const0_rtx, operands[4]));
3767 (define_expand "neon_vmls_n<mode>"
3768 [(match_operand:VMQ 0 "s_register_operand" "")
3769 (match_operand:VMQ 1 "s_register_operand" "")
3770 (match_operand:VMQ 2 "s_register_operand" "")
3771 (match_operand:<V_elem> 3 "s_register_operand" "")
3772 (match_operand:SI 4 "immediate_operand" "")]
3775 rtx tmp = gen_reg_rtx (<V_HALF>mode);
3776 emit_insn (gen_neon_vset_lane<V_half> (tmp, operands[3], tmp, const0_rtx));
3777 emit_insn (gen_neon_vmls_lane<mode> (operands[0], operands[1], operands[2],
3778 tmp, const0_rtx, operands[4]));
3782 (define_expand "neon_vmlsl_n<mode>"
3783 [(match_operand:<V_widen> 0 "s_register_operand" "")
3784 (match_operand:<V_widen> 1 "s_register_operand" "")
3785 (match_operand:VMDI 2 "s_register_operand" "")
3786 (match_operand:<V_elem> 3 "s_register_operand" "")
3787 (match_operand:SI 4 "immediate_operand" "")]
3790 rtx tmp = gen_reg_rtx (<MODE>mode);
3791 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx));
3792 emit_insn (gen_neon_vmlsl_lane<mode> (operands[0], operands[1], operands[2],
3793 tmp, const0_rtx, operands[4]));
3797 (define_expand "neon_vqdmlsl_n<mode>"
3798 [(match_operand:<V_widen> 0 "s_register_operand" "")
3799 (match_operand:<V_widen> 1 "s_register_operand" "")
3800 (match_operand:VMDI 2 "s_register_operand" "")
3801 (match_operand:<V_elem> 3 "s_register_operand" "")
3802 (match_operand:SI 4 "immediate_operand" "")]
3805 rtx tmp = gen_reg_rtx (<MODE>mode);
3806 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx));
3807 emit_insn (gen_neon_vqdmlsl_lane<mode> (operands[0], operands[1], operands[2],
3808 tmp, const0_rtx, operands[4]));
3812 (define_insn "neon_vext<mode>"
3813 [(set (match_operand:VDQX 0 "s_register_operand" "=w")
3814 (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w")
3815 (match_operand:VDQX 2 "s_register_operand" "w")
3816 (match_operand:SI 3 "immediate_operand" "i")]
3820 neon_const_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
3821 return "vext.<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2, %3";
3823 [(set (attr "neon_type")
3824 (if_then_else (match_test "<Is_d_reg>")
3825 (const_string "neon_bp_simple")
3826 (const_string "neon_bp_2cycle")))]
3829 (define_insn "neon_vrev64<mode>"
3830 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
3831 (unspec:VDQ [(match_operand:VDQ 1 "s_register_operand" "w")
3832 (match_operand:SI 2 "immediate_operand" "i")]
3835 "vrev64.<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
3836 [(set_attr "neon_type" "neon_bp_simple")]
3839 (define_insn "neon_vrev32<mode>"
3840 [(set (match_operand:VX 0 "s_register_operand" "=w")
3841 (unspec:VX [(match_operand:VX 1 "s_register_operand" "w")
3842 (match_operand:SI 2 "immediate_operand" "i")]
3845 "vrev32.<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
3846 [(set_attr "neon_type" "neon_bp_simple")]
3849 (define_insn "neon_vrev16<mode>"
3850 [(set (match_operand:VE 0 "s_register_operand" "=w")
3851 (unspec:VE [(match_operand:VE 1 "s_register_operand" "w")
3852 (match_operand:SI 2 "immediate_operand" "i")]
3855 "vrev16.<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
3856 [(set_attr "neon_type" "neon_bp_simple")]
3859 ; vbsl_* intrinsics may compile to any of vbsl/vbif/vbit depending on register
3860 ; allocation. For an intrinsic of form:
3861 ; rD = vbsl_* (rS, rN, rM)
3862 ; We can use any of:
3863 ; vbsl rS, rN, rM (if D = S)
3864 ; vbit rD, rN, rS (if D = M, so 1-bits in rS choose bits from rN, else rM)
3865 ; vbif rD, rM, rS (if D = N, so 0-bits in rS choose bits from rM, else rN)
3867 (define_insn "neon_vbsl<mode>_internal"
3868 [(set (match_operand:VDQX 0 "s_register_operand" "=w,w,w")
3869 (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" " 0,w,w")
3870 (match_operand:VDQX 2 "s_register_operand" " w,w,0")
3871 (match_operand:VDQX 3 "s_register_operand" " w,0,w")]
3875 vbsl\t%<V_reg>0, %<V_reg>2, %<V_reg>3
3876 vbit\t%<V_reg>0, %<V_reg>2, %<V_reg>1
3877 vbif\t%<V_reg>0, %<V_reg>3, %<V_reg>1"
3878 [(set_attr "neon_type" "neon_int_1")]
3881 (define_expand "neon_vbsl<mode>"
3882 [(set (match_operand:VDQX 0 "s_register_operand" "")
3883 (unspec:VDQX [(match_operand:<V_cmp_result> 1 "s_register_operand" "")
3884 (match_operand:VDQX 2 "s_register_operand" "")
3885 (match_operand:VDQX 3 "s_register_operand" "")]
3889 /* We can't alias operands together if they have different modes. */
3890 operands[1] = gen_lowpart (<MODE>mode, operands[1]);
3893 (define_insn "neon_vshl<mode>"
3894 [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
3895 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
3896 (match_operand:VDQIX 2 "s_register_operand" "w")
3897 (match_operand:SI 3 "immediate_operand" "i")]
3900 "v%O3shl.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
3901 [(set (attr "neon_type")
3902 (if_then_else (match_test "<Is_d_reg>")
3903 (const_string "neon_vshl_ddd")
3904 (const_string "neon_shift_3")))]
3907 (define_insn "neon_vqshl<mode>"
3908 [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
3909 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
3910 (match_operand:VDQIX 2 "s_register_operand" "w")
3911 (match_operand:SI 3 "immediate_operand" "i")]
3914 "vq%O3shl.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
3915 [(set (attr "neon_type")
3916 (if_then_else (match_test "<Is_d_reg>")
3917 (const_string "neon_shift_2")
3918 (const_string "neon_vqshl_vrshl_vqrshl_qqq")))]
3921 (define_insn "neon_vshr_n<mode>"
3922 [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
3923 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
3924 (match_operand:SI 2 "immediate_operand" "i")
3925 (match_operand:SI 3 "immediate_operand" "i")]
3929 neon_const_bounds (operands[2], 1, neon_element_bits (<MODE>mode) + 1);
3930 return "v%O3shr.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %2";
3932 [(set_attr "neon_type" "neon_shift_1")]
3935 (define_insn "neon_vshrn_n<mode>"
3936 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
3937 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
3938 (match_operand:SI 2 "immediate_operand" "i")
3939 (match_operand:SI 3 "immediate_operand" "i")]
3943 neon_const_bounds (operands[2], 1, neon_element_bits (<MODE>mode) / 2 + 1);
3944 return "v%O3shrn.<V_if_elem>\t%P0, %q1, %2";
3946 [(set_attr "neon_type" "neon_shift_1")]
3949 (define_insn "neon_vqshrn_n<mode>"
3950 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
3951 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
3952 (match_operand:SI 2 "immediate_operand" "i")
3953 (match_operand:SI 3 "immediate_operand" "i")]
3957 neon_const_bounds (operands[2], 1, neon_element_bits (<MODE>mode) / 2 + 1);
3958 return "vq%O3shrn.%T3%#<V_sz_elem>\t%P0, %q1, %2";
3960 [(set_attr "neon_type" "neon_shift_2")]
3963 (define_insn "neon_vqshrun_n<mode>"
3964 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
3965 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
3966 (match_operand:SI 2 "immediate_operand" "i")
3967 (match_operand:SI 3 "immediate_operand" "i")]
3971 neon_const_bounds (operands[2], 1, neon_element_bits (<MODE>mode) / 2 + 1);
3972 return "vq%O3shrun.%T3%#<V_sz_elem>\t%P0, %q1, %2";
3974 [(set_attr "neon_type" "neon_shift_2")]
3977 (define_insn "neon_vshl_n<mode>"
3978 [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
3979 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
3980 (match_operand:SI 2 "immediate_operand" "i")
3981 (match_operand:SI 3 "immediate_operand" "i")]
3985 neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode));
3986 return "vshl.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %2";
3988 [(set_attr "neon_type" "neon_shift_1")]
3991 (define_insn "neon_vqshl_n<mode>"
3992 [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
3993 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
3994 (match_operand:SI 2 "immediate_operand" "i")
3995 (match_operand:SI 3 "immediate_operand" "i")]
3999 neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode));
4000 return "vqshl.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %2";
4002 [(set_attr "neon_type" "neon_shift_2")]
4005 (define_insn "neon_vqshlu_n<mode>"
4006 [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
4007 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
4008 (match_operand:SI 2 "immediate_operand" "i")
4009 (match_operand:SI 3 "immediate_operand" "i")]
4013 neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode));
4014 return "vqshlu.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %2";
4016 [(set_attr "neon_type" "neon_shift_2")]
4019 (define_insn "neon_vshll_n<mode>"
4020 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
4021 (unspec:<V_widen> [(match_operand:VW 1 "s_register_operand" "w")
4022 (match_operand:SI 2 "immediate_operand" "i")
4023 (match_operand:SI 3 "immediate_operand" "i")]
4027 /* The boundaries are: 0 < imm <= size. */
4028 neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode) + 1);
4029 return "vshll.%T3%#<V_sz_elem>\t%q0, %P1, %2";
4031 [(set_attr "neon_type" "neon_shift_1")]
4034 (define_insn "neon_vsra_n<mode>"
4035 [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
4036 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "0")
4037 (match_operand:VDQIX 2 "s_register_operand" "w")
4038 (match_operand:SI 3 "immediate_operand" "i")
4039 (match_operand:SI 4 "immediate_operand" "i")]
4043 neon_const_bounds (operands[3], 1, neon_element_bits (<MODE>mode) + 1);
4044 return "v%O4sra.%T4%#<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %3";
4046 [(set_attr "neon_type" "neon_vsra_vrsra")]
4049 (define_insn "neon_vsri_n<mode>"
4050 [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
4051 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "0")
4052 (match_operand:VDQIX 2 "s_register_operand" "w")
4053 (match_operand:SI 3 "immediate_operand" "i")]
4057 neon_const_bounds (operands[3], 1, neon_element_bits (<MODE>mode) + 1);
4058 return "vsri.<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %3";
4060 [(set (attr "neon_type")
4061 (if_then_else (match_test "<Is_d_reg>")
4062 (const_string "neon_shift_1")
4063 (const_string "neon_shift_3")))]
4066 (define_insn "neon_vsli_n<mode>"
4067 [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
4068 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "0")
4069 (match_operand:VDQIX 2 "s_register_operand" "w")
4070 (match_operand:SI 3 "immediate_operand" "i")]
4074 neon_const_bounds (operands[3], 0, neon_element_bits (<MODE>mode));
4075 return "vsli.<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %3";
4077 [(set (attr "neon_type")
4078 (if_then_else (match_test "<Is_d_reg>")
4079 (const_string "neon_shift_1")
4080 (const_string "neon_shift_3")))]
4083 (define_insn "neon_vtbl1v8qi"
4084 [(set (match_operand:V8QI 0 "s_register_operand" "=w")
4085 (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "w")
4086 (match_operand:V8QI 2 "s_register_operand" "w")]
4089 "vtbl.8\t%P0, {%P1}, %P2"
4090 [(set_attr "neon_type" "neon_bp_2cycle")]
4093 (define_insn "neon_vtbl2v8qi"
4094 [(set (match_operand:V8QI 0 "s_register_operand" "=w")
4095 (unspec:V8QI [(match_operand:TI 1 "s_register_operand" "w")
4096 (match_operand:V8QI 2 "s_register_operand" "w")]
4101 int tabbase = REGNO (operands[1]);
4103 ops[0] = operands[0];
4104 ops[1] = gen_rtx_REG (V8QImode, tabbase);
4105 ops[2] = gen_rtx_REG (V8QImode, tabbase + 2);
4106 ops[3] = operands[2];
4107 output_asm_insn ("vtbl.8\t%P0, {%P1, %P2}, %P3", ops);
4111 [(set_attr "neon_type" "neon_bp_2cycle")]
4114 (define_insn "neon_vtbl3v8qi"
4115 [(set (match_operand:V8QI 0 "s_register_operand" "=w")
4116 (unspec:V8QI [(match_operand:EI 1 "s_register_operand" "w")
4117 (match_operand:V8QI 2 "s_register_operand" "w")]
4122 int tabbase = REGNO (operands[1]);
4124 ops[0] = operands[0];
4125 ops[1] = gen_rtx_REG (V8QImode, tabbase);
4126 ops[2] = gen_rtx_REG (V8QImode, tabbase + 2);
4127 ops[3] = gen_rtx_REG (V8QImode, tabbase + 4);
4128 ops[4] = operands[2];
4129 output_asm_insn ("vtbl.8\t%P0, {%P1, %P2, %P3}, %P4", ops);
4133 [(set_attr "neon_type" "neon_bp_3cycle")]
4136 (define_insn "neon_vtbl4v8qi"
4137 [(set (match_operand:V8QI 0 "s_register_operand" "=w")
4138 (unspec:V8QI [(match_operand:OI 1 "s_register_operand" "w")
4139 (match_operand:V8QI 2 "s_register_operand" "w")]
4144 int tabbase = REGNO (operands[1]);
4146 ops[0] = operands[0];
4147 ops[1] = gen_rtx_REG (V8QImode, tabbase);
4148 ops[2] = gen_rtx_REG (V8QImode, tabbase + 2);
4149 ops[3] = gen_rtx_REG (V8QImode, tabbase + 4);
4150 ops[4] = gen_rtx_REG (V8QImode, tabbase + 6);
4151 ops[5] = operands[2];
4152 output_asm_insn ("vtbl.8\t%P0, {%P1, %P2, %P3, %P4}, %P5", ops);
4156 [(set_attr "neon_type" "neon_bp_3cycle")]
4159 ;; These three are used by the vec_perm infrastructure for V16QImode.
4160 (define_insn_and_split "neon_vtbl1v16qi"
4161 [(set (match_operand:V16QI 0 "s_register_operand" "=&w")
4162 (unspec:V16QI [(match_operand:V16QI 1 "s_register_operand" "w")
4163 (match_operand:V16QI 2 "s_register_operand" "w")]
4167 "&& reload_completed"
4170 rtx op0, op1, op2, part0, part2;
4174 op1 = gen_lowpart (TImode, operands[1]);
4177 ofs = subreg_lowpart_offset (V8QImode, V16QImode);
4178 part0 = simplify_subreg (V8QImode, op0, V16QImode, ofs);
4179 part2 = simplify_subreg (V8QImode, op2, V16QImode, ofs);
4180 emit_insn (gen_neon_vtbl2v8qi (part0, op1, part2));
4182 ofs = subreg_highpart_offset (V8QImode, V16QImode);
4183 part0 = simplify_subreg (V8QImode, op0, V16QImode, ofs);
4184 part2 = simplify_subreg (V8QImode, op2, V16QImode, ofs);
4185 emit_insn (gen_neon_vtbl2v8qi (part0, op1, part2));
4189 (define_insn_and_split "neon_vtbl2v16qi"
4190 [(set (match_operand:V16QI 0 "s_register_operand" "=&w")
4191 (unspec:V16QI [(match_operand:OI 1 "s_register_operand" "w")
4192 (match_operand:V16QI 2 "s_register_operand" "w")]
4196 "&& reload_completed"
4199 rtx op0, op1, op2, part0, part2;
4206 ofs = subreg_lowpart_offset (V8QImode, V16QImode);
4207 part0 = simplify_subreg (V8QImode, op0, V16QImode, ofs);
4208 part2 = simplify_subreg (V8QImode, op2, V16QImode, ofs);
4209 emit_insn (gen_neon_vtbl2v8qi (part0, op1, part2));
4211 ofs = subreg_highpart_offset (V8QImode, V16QImode);
4212 part0 = simplify_subreg (V8QImode, op0, V16QImode, ofs);
4213 part2 = simplify_subreg (V8QImode, op2, V16QImode, ofs);
4214 emit_insn (gen_neon_vtbl2v8qi (part0, op1, part2));
4218 ;; ??? Logically we should extend the regular neon_vcombine pattern to
4219 ;; handle quad-word input modes, producing octa-word output modes. But
4220 ;; that requires us to add support for octa-word vector modes in moves.
4221 ;; That seems overkill for this one use in vec_perm.
4222 (define_insn_and_split "neon_vcombinev16qi"
4223 [(set (match_operand:OI 0 "s_register_operand" "=w")
4224 (unspec:OI [(match_operand:V16QI 1 "s_register_operand" "w")
4225 (match_operand:V16QI 2 "s_register_operand" "w")]
4229 "&& reload_completed"
4232 neon_split_vcombine (operands);
4236 (define_insn "neon_vtbx1v8qi"
4237 [(set (match_operand:V8QI 0 "s_register_operand" "=w")
4238 (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "0")
4239 (match_operand:V8QI 2 "s_register_operand" "w")
4240 (match_operand:V8QI 3 "s_register_operand" "w")]
4243 "vtbx.8\t%P0, {%P2}, %P3"
4244 [(set_attr "neon_type" "neon_bp_2cycle")]
4247 (define_insn "neon_vtbx2v8qi"
4248 [(set (match_operand:V8QI 0 "s_register_operand" "=w")
4249 (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "0")
4250 (match_operand:TI 2 "s_register_operand" "w")
4251 (match_operand:V8QI 3 "s_register_operand" "w")]
4256 int tabbase = REGNO (operands[2]);
4258 ops[0] = operands[0];
4259 ops[1] = gen_rtx_REG (V8QImode, tabbase);
4260 ops[2] = gen_rtx_REG (V8QImode, tabbase + 2);
4261 ops[3] = operands[3];
4262 output_asm_insn ("vtbx.8\t%P0, {%P1, %P2}, %P3", ops);
4266 [(set_attr "neon_type" "neon_bp_2cycle")]
4269 (define_insn "neon_vtbx3v8qi"
4270 [(set (match_operand:V8QI 0 "s_register_operand" "=w")
4271 (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "0")
4272 (match_operand:EI 2 "s_register_operand" "w")
4273 (match_operand:V8QI 3 "s_register_operand" "w")]
4278 int tabbase = REGNO (operands[2]);
4280 ops[0] = operands[0];
4281 ops[1] = gen_rtx_REG (V8QImode, tabbase);
4282 ops[2] = gen_rtx_REG (V8QImode, tabbase + 2);
4283 ops[3] = gen_rtx_REG (V8QImode, tabbase + 4);
4284 ops[4] = operands[3];
4285 output_asm_insn ("vtbx.8\t%P0, {%P1, %P2, %P3}, %P4", ops);
4289 [(set_attr "neon_type" "neon_bp_3cycle")]
4292 (define_insn "neon_vtbx4v8qi"
4293 [(set (match_operand:V8QI 0 "s_register_operand" "=w")
4294 (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "0")
4295 (match_operand:OI 2 "s_register_operand" "w")
4296 (match_operand:V8QI 3 "s_register_operand" "w")]
4301 int tabbase = REGNO (operands[2]);
4303 ops[0] = operands[0];
4304 ops[1] = gen_rtx_REG (V8QImode, tabbase);
4305 ops[2] = gen_rtx_REG (V8QImode, tabbase + 2);
4306 ops[3] = gen_rtx_REG (V8QImode, tabbase + 4);
4307 ops[4] = gen_rtx_REG (V8QImode, tabbase + 6);
4308 ops[5] = operands[3];
4309 output_asm_insn ("vtbx.8\t%P0, {%P1, %P2, %P3, %P4}, %P5", ops);
4313 [(set_attr "neon_type" "neon_bp_3cycle")]
4316 (define_expand "neon_vtrn<mode>_internal"
4318 [(set (match_operand:VDQW 0 "s_register_operand" "")
4319 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "")
4320 (match_operand:VDQW 2 "s_register_operand" "")]
4322 (set (match_operand:VDQW 3 "s_register_operand" "")
4323 (unspec:VDQW [(match_dup 1) (match_dup 2)] UNSPEC_VTRN2))])]
4328 ;; Note: Different operand numbering to handle tied registers correctly.
4329 (define_insn "*neon_vtrn<mode>_insn"
4330 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
4331 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0")
4332 (match_operand:VDQW 3 "s_register_operand" "2")]
4334 (set (match_operand:VDQW 2 "s_register_operand" "=w")
4335 (unspec:VDQW [(match_dup 1) (match_dup 3)]
4338 "vtrn.<V_sz_elem>\t%<V_reg>0, %<V_reg>2"
4339 [(set (attr "neon_type")
4340 (if_then_else (match_test "<Is_d_reg>")
4341 (const_string "neon_bp_simple")
4342 (const_string "neon_bp_3cycle")))]
4345 (define_expand "neon_vtrn<mode>"
4346 [(match_operand:SI 0 "s_register_operand" "r")
4347 (match_operand:VDQW 1 "s_register_operand" "w")
4348 (match_operand:VDQW 2 "s_register_operand" "w")]
4351 neon_emit_pair_result_insn (<MODE>mode, gen_neon_vtrn<mode>_internal,
4352 operands[0], operands[1], operands[2]);
4356 (define_expand "neon_vzip<mode>_internal"
4358 [(set (match_operand:VDQW 0 "s_register_operand" "")
4359 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "")
4360 (match_operand:VDQW 2 "s_register_operand" "")]
4362 (set (match_operand:VDQW 3 "s_register_operand" "")
4363 (unspec:VDQW [(match_dup 1) (match_dup 2)] UNSPEC_VZIP2))])]
4368 ;; Note: Different operand numbering to handle tied registers correctly.
4369 (define_insn "*neon_vzip<mode>_insn"
4370 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
4371 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0")
4372 (match_operand:VDQW 3 "s_register_operand" "2")]
4374 (set (match_operand:VDQW 2 "s_register_operand" "=w")
4375 (unspec:VDQW [(match_dup 1) (match_dup 3)]
4378 "vzip.<V_sz_elem>\t%<V_reg>0, %<V_reg>2"
4379 [(set (attr "neon_type")
4380 (if_then_else (match_test "<Is_d_reg>")
4381 (const_string "neon_bp_simple")
4382 (const_string "neon_bp_3cycle")))]
4385 (define_expand "neon_vzip<mode>"
4386 [(match_operand:SI 0 "s_register_operand" "r")
4387 (match_operand:VDQW 1 "s_register_operand" "w")
4388 (match_operand:VDQW 2 "s_register_operand" "w")]
4391 neon_emit_pair_result_insn (<MODE>mode, gen_neon_vzip<mode>_internal,
4392 operands[0], operands[1], operands[2]);
4396 (define_expand "neon_vuzp<mode>_internal"
4398 [(set (match_operand:VDQW 0 "s_register_operand" "")
4399 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "")
4400 (match_operand:VDQW 2 "s_register_operand" "")]
4402 (set (match_operand:VDQW 3 "s_register_operand" "")
4403 (unspec:VDQW [(match_dup 1) (match_dup 2)] UNSPEC_VUZP2))])]
4408 ;; Note: Different operand numbering to handle tied registers correctly.
4409 (define_insn "*neon_vuzp<mode>_insn"
4410 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
4411 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0")
4412 (match_operand:VDQW 3 "s_register_operand" "2")]
4414 (set (match_operand:VDQW 2 "s_register_operand" "=w")
4415 (unspec:VDQW [(match_dup 1) (match_dup 3)]
4418 "vuzp.<V_sz_elem>\t%<V_reg>0, %<V_reg>2"
4419 [(set (attr "neon_type")
4420 (if_then_else (match_test "<Is_d_reg>")
4421 (const_string "neon_bp_simple")
4422 (const_string "neon_bp_3cycle")))]
4425 (define_expand "neon_vuzp<mode>"
4426 [(match_operand:SI 0 "s_register_operand" "r")
4427 (match_operand:VDQW 1 "s_register_operand" "w")
4428 (match_operand:VDQW 2 "s_register_operand" "w")]
4431 neon_emit_pair_result_insn (<MODE>mode, gen_neon_vuzp<mode>_internal,
4432 operands[0], operands[1], operands[2]);
4436 (define_expand "neon_vreinterpretv8qi<mode>"
4437 [(match_operand:V8QI 0 "s_register_operand" "")
4438 (match_operand:VDX 1 "s_register_operand" "")]
4441 neon_reinterpret (operands[0], operands[1]);
4445 (define_expand "neon_vreinterpretv4hi<mode>"
4446 [(match_operand:V4HI 0 "s_register_operand" "")
4447 (match_operand:VDX 1 "s_register_operand" "")]
4450 neon_reinterpret (operands[0], operands[1]);
4454 (define_expand "neon_vreinterpretv2si<mode>"
4455 [(match_operand:V2SI 0 "s_register_operand" "")
4456 (match_operand:VDX 1 "s_register_operand" "")]
4459 neon_reinterpret (operands[0], operands[1]);
4463 (define_expand "neon_vreinterpretv2sf<mode>"
4464 [(match_operand:V2SF 0 "s_register_operand" "")
4465 (match_operand:VDX 1 "s_register_operand" "")]
4468 neon_reinterpret (operands[0], operands[1]);
4472 (define_expand "neon_vreinterpretdi<mode>"
4473 [(match_operand:DI 0 "s_register_operand" "")
4474 (match_operand:VDX 1 "s_register_operand" "")]
4477 neon_reinterpret (operands[0], operands[1]);
4481 (define_expand "neon_vreinterpretv16qi<mode>"
4482 [(match_operand:V16QI 0 "s_register_operand" "")
4483 (match_operand:VQX 1 "s_register_operand" "")]
4486 neon_reinterpret (operands[0], operands[1]);
4490 (define_expand "neon_vreinterpretv8hi<mode>"
4491 [(match_operand:V8HI 0 "s_register_operand" "")
4492 (match_operand:VQX 1 "s_register_operand" "")]
4495 neon_reinterpret (operands[0], operands[1]);
4499 (define_expand "neon_vreinterpretv4si<mode>"
4500 [(match_operand:V4SI 0 "s_register_operand" "")
4501 (match_operand:VQX 1 "s_register_operand" "")]
4504 neon_reinterpret (operands[0], operands[1]);
4508 (define_expand "neon_vreinterpretv4sf<mode>"
4509 [(match_operand:V4SF 0 "s_register_operand" "")
4510 (match_operand:VQX 1 "s_register_operand" "")]
4513 neon_reinterpret (operands[0], operands[1]);
4517 (define_expand "neon_vreinterpretv2di<mode>"
4518 [(match_operand:V2DI 0 "s_register_operand" "")
4519 (match_operand:VQX 1 "s_register_operand" "")]
4522 neon_reinterpret (operands[0], operands[1]);
4526 (define_expand "vec_load_lanes<mode><mode>"
4527 [(set (match_operand:VDQX 0 "s_register_operand")
4528 (unspec:VDQX [(match_operand:VDQX 1 "neon_struct_operand")]
4532 (define_insn "neon_vld1<mode>"
4533 [(set (match_operand:VDQX 0 "s_register_operand" "=w")
4534 (unspec:VDQX [(match_operand:VDQX 1 "neon_struct_operand" "Um")]
4537 "vld1.<V_sz_elem>\t%h0, %A1"
4538 [(set_attr "neon_type" "neon_vld1_1_2_regs")]
4541 (define_insn "neon_vld1_lane<mode>"
4542 [(set (match_operand:VDX 0 "s_register_operand" "=w")
4543 (unspec:VDX [(match_operand:<V_elem> 1 "neon_struct_operand" "Um")
4544 (match_operand:VDX 2 "s_register_operand" "0")
4545 (match_operand:SI 3 "immediate_operand" "i")]
4549 HOST_WIDE_INT lane = INTVAL (operands[3]);
4550 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4551 if (lane < 0 || lane >= max)
4552 error ("lane out of range");
4554 return "vld1.<V_sz_elem>\t%P0, %A1";
4556 return "vld1.<V_sz_elem>\t{%P0[%c3]}, %A1";
4558 [(set (attr "neon_type")
4559 (if_then_else (eq (const_string "<V_mode_nunits>") (const_int 2))
4560 (const_string "neon_vld1_1_2_regs")
4561 (const_string "neon_vld1_vld2_lane")))]
4564 (define_insn "neon_vld1_lane<mode>"
4565 [(set (match_operand:VQX 0 "s_register_operand" "=w")
4566 (unspec:VQX [(match_operand:<V_elem> 1 "neon_struct_operand" "Um")
4567 (match_operand:VQX 2 "s_register_operand" "0")
4568 (match_operand:SI 3 "immediate_operand" "i")]
4572 HOST_WIDE_INT lane = INTVAL (operands[3]);
4573 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4574 int regno = REGNO (operands[0]);
4575 if (lane < 0 || lane >= max)
4576 error ("lane out of range");
4577 else if (lane >= max / 2)
4581 operands[3] = GEN_INT (lane);
4583 operands[0] = gen_rtx_REG (<V_HALF>mode, regno);
4585 return "vld1.<V_sz_elem>\t%P0, %A1";
4587 return "vld1.<V_sz_elem>\t{%P0[%c3]}, %A1";
4589 [(set (attr "neon_type")
4590 (if_then_else (eq (const_string "<V_mode_nunits>") (const_int 2))
4591 (const_string "neon_vld1_1_2_regs")
4592 (const_string "neon_vld1_vld2_lane")))]
4595 (define_insn "neon_vld1_dup<mode>"
4596 [(set (match_operand:VDX 0 "s_register_operand" "=w")
4597 (vec_duplicate:VDX (match_operand:<V_elem> 1 "neon_struct_operand" "Um")))]
4600 if (GET_MODE_NUNITS (<MODE>mode) > 1)
4601 return "vld1.<V_sz_elem>\t{%P0[]}, %A1";
4603 return "vld1.<V_sz_elem>\t%h0, %A1";
4605 [(set (attr "neon_type")
4606 (if_then_else (gt (const_string "<V_mode_nunits>") (const_string "1"))
4607 (const_string "neon_vld2_2_regs_vld1_vld2_all_lanes")
4608 (const_string "neon_vld1_1_2_regs")))]
4611 (define_insn "neon_vld1_dup<mode>"
4612 [(set (match_operand:VQ 0 "s_register_operand" "=w")
4613 (vec_duplicate:VQ (match_operand:<V_elem> 1 "neon_struct_operand" "Um")))]
4616 return "vld1.<V_sz_elem>\t{%e0[], %f0[]}, %A1";
4618 [(set_attr "neon_type" "neon_vld2_2_regs_vld1_vld2_all_lanes")]
4621 (define_insn_and_split "neon_vld1_dupv2di"
4622 [(set (match_operand:V2DI 0 "s_register_operand" "=w")
4623 (vec_duplicate:V2DI (match_operand:DI 1 "neon_struct_operand" "Um")))]
4626 "&& reload_completed"
4629 rtx tmprtx = gen_lowpart (DImode, operands[0]);
4630 emit_insn (gen_neon_vld1_dupdi (tmprtx, operands[1]));
4631 emit_move_insn (gen_highpart (DImode, operands[0]), tmprtx );
4634 [(set_attr "length" "8")
4635 (set_attr "neon_type" "neon_vld2_2_regs_vld1_vld2_all_lanes")]
4638 (define_expand "vec_store_lanes<mode><mode>"
4639 [(set (match_operand:VDQX 0 "neon_struct_operand")
4640 (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand")]
4644 (define_insn "neon_vst1<mode>"
4645 [(set (match_operand:VDQX 0 "neon_struct_operand" "=Um")
4646 (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w")]
4649 "vst1.<V_sz_elem>\t%h1, %A0"
4650 [(set_attr "neon_type" "neon_vst1_1_2_regs_vst2_2_regs")])
4652 (define_insn "neon_vst1_lane<mode>"
4653 [(set (match_operand:<V_elem> 0 "neon_struct_operand" "=Um")
4655 [(match_operand:VDX 1 "s_register_operand" "w")
4656 (match_operand:SI 2 "immediate_operand" "i")]
4660 HOST_WIDE_INT lane = INTVAL (operands[2]);
4661 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4662 if (lane < 0 || lane >= max)
4663 error ("lane out of range");
4665 return "vst1.<V_sz_elem>\t{%P1}, %A0";
4667 return "vst1.<V_sz_elem>\t{%P1[%c2]}, %A0";
4669 [(set (attr "neon_type")
4670 (if_then_else (eq (const_string "<V_mode_nunits>") (const_int 1))
4671 (const_string "neon_vst1_1_2_regs_vst2_2_regs")
4672 (const_string "neon_vst1_vst2_lane")))])
4674 (define_insn "neon_vst1_lane<mode>"
4675 [(set (match_operand:<V_elem> 0 "neon_struct_operand" "=Um")
4677 [(match_operand:VQX 1 "s_register_operand" "w")
4678 (match_operand:SI 2 "immediate_operand" "i")]
4682 HOST_WIDE_INT lane = INTVAL (operands[2]);
4683 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4684 int regno = REGNO (operands[1]);
4685 if (lane < 0 || lane >= max)
4686 error ("lane out of range");
4687 else if (lane >= max / 2)
4691 operands[2] = GEN_INT (lane);
4693 operands[1] = gen_rtx_REG (<V_HALF>mode, regno);
4695 return "vst1.<V_sz_elem>\t{%P1}, %A0";
4697 return "vst1.<V_sz_elem>\t{%P1[%c2]}, %A0";
4699 [(set_attr "neon_type" "neon_vst1_vst2_lane")]
4702 (define_expand "vec_load_lanesti<mode>"
4703 [(set (match_operand:TI 0 "s_register_operand")
4704 (unspec:TI [(match_operand:TI 1 "neon_struct_operand")
4705 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4709 (define_insn "neon_vld2<mode>"
4710 [(set (match_operand:TI 0 "s_register_operand" "=w")
4711 (unspec:TI [(match_operand:TI 1 "neon_struct_operand" "Um")
4712 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4716 if (<V_sz_elem> == 64)
4717 return "vld1.64\t%h0, %A1";
4719 return "vld2.<V_sz_elem>\t%h0, %A1";
4721 [(set (attr "neon_type")
4722 (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64"))
4723 (const_string "neon_vld1_1_2_regs")
4724 (const_string "neon_vld2_2_regs_vld1_vld2_all_lanes")))]
4727 (define_expand "vec_load_lanesoi<mode>"
4728 [(set (match_operand:OI 0 "s_register_operand")
4729 (unspec:OI [(match_operand:OI 1 "neon_struct_operand")
4730 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4734 (define_insn "neon_vld2<mode>"
4735 [(set (match_operand:OI 0 "s_register_operand" "=w")
4736 (unspec:OI [(match_operand:OI 1 "neon_struct_operand" "Um")
4737 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4740 "vld2.<V_sz_elem>\t%h0, %A1"
4741 [(set_attr "neon_type" "neon_vld2_2_regs_vld1_vld2_all_lanes")])
4743 (define_insn "neon_vld2_lane<mode>"
4744 [(set (match_operand:TI 0 "s_register_operand" "=w")
4745 (unspec:TI [(match_operand:<V_two_elem> 1 "neon_struct_operand" "Um")
4746 (match_operand:TI 2 "s_register_operand" "0")
4747 (match_operand:SI 3 "immediate_operand" "i")
4748 (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4752 HOST_WIDE_INT lane = INTVAL (operands[3]);
4753 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4754 int regno = REGNO (operands[0]);
4756 if (lane < 0 || lane >= max)
4757 error ("lane out of range");
4758 ops[0] = gen_rtx_REG (DImode, regno);
4759 ops[1] = gen_rtx_REG (DImode, regno + 2);
4760 ops[2] = operands[1];
4761 ops[3] = operands[3];
4762 output_asm_insn ("vld2.<V_sz_elem>\t{%P0[%c3], %P1[%c3]}, %A2", ops);
4765 [(set_attr "neon_type" "neon_vld1_vld2_lane")]
4768 (define_insn "neon_vld2_lane<mode>"
4769 [(set (match_operand:OI 0 "s_register_operand" "=w")
4770 (unspec:OI [(match_operand:<V_two_elem> 1 "neon_struct_operand" "Um")
4771 (match_operand:OI 2 "s_register_operand" "0")
4772 (match_operand:SI 3 "immediate_operand" "i")
4773 (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4777 HOST_WIDE_INT lane = INTVAL (operands[3]);
4778 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4779 int regno = REGNO (operands[0]);
4781 if (lane < 0 || lane >= max)
4782 error ("lane out of range");
4783 else if (lane >= max / 2)
4788 ops[0] = gen_rtx_REG (DImode, regno);
4789 ops[1] = gen_rtx_REG (DImode, regno + 4);
4790 ops[2] = operands[1];
4791 ops[3] = GEN_INT (lane);
4792 output_asm_insn ("vld2.<V_sz_elem>\t{%P0[%c3], %P1[%c3]}, %A2", ops);
4795 [(set_attr "neon_type" "neon_vld1_vld2_lane")]
4798 (define_insn "neon_vld2_dup<mode>"
4799 [(set (match_operand:TI 0 "s_register_operand" "=w")
4800 (unspec:TI [(match_operand:<V_two_elem> 1 "neon_struct_operand" "Um")
4801 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4805 if (GET_MODE_NUNITS (<MODE>mode) > 1)
4806 return "vld2.<V_sz_elem>\t{%e0[], %f0[]}, %A1";
4808 return "vld1.<V_sz_elem>\t%h0, %A1";
4810 [(set (attr "neon_type")
4811 (if_then_else (gt (const_string "<V_mode_nunits>") (const_string "1"))
4812 (const_string "neon_vld2_2_regs_vld1_vld2_all_lanes")
4813 (const_string "neon_vld1_1_2_regs")))]
4816 (define_expand "vec_store_lanesti<mode>"
4817 [(set (match_operand:TI 0 "neon_struct_operand")
4818 (unspec:TI [(match_operand:TI 1 "s_register_operand")
4819 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4823 (define_insn "neon_vst2<mode>"
4824 [(set (match_operand:TI 0 "neon_struct_operand" "=Um")
4825 (unspec:TI [(match_operand:TI 1 "s_register_operand" "w")
4826 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4830 if (<V_sz_elem> == 64)
4831 return "vst1.64\t%h1, %A0";
4833 return "vst2.<V_sz_elem>\t%h1, %A0";
4835 [(set (attr "neon_type")
4836 (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64"))
4837 (const_string "neon_vst1_1_2_regs_vst2_2_regs")
4838 (const_string "neon_vst1_1_2_regs_vst2_2_regs")))]
4841 (define_expand "vec_store_lanesoi<mode>"
4842 [(set (match_operand:OI 0 "neon_struct_operand")
4843 (unspec:OI [(match_operand:OI 1 "s_register_operand")
4844 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4848 (define_insn "neon_vst2<mode>"
4849 [(set (match_operand:OI 0 "neon_struct_operand" "=Um")
4850 (unspec:OI [(match_operand:OI 1 "s_register_operand" "w")
4851 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4854 "vst2.<V_sz_elem>\t%h1, %A0"
4855 [(set_attr "neon_type" "neon_vst1_1_2_regs_vst2_2_regs")]
4858 (define_insn "neon_vst2_lane<mode>"
4859 [(set (match_operand:<V_two_elem> 0 "neon_struct_operand" "=Um")
4860 (unspec:<V_two_elem>
4861 [(match_operand:TI 1 "s_register_operand" "w")
4862 (match_operand:SI 2 "immediate_operand" "i")
4863 (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4867 HOST_WIDE_INT lane = INTVAL (operands[2]);
4868 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4869 int regno = REGNO (operands[1]);
4871 if (lane < 0 || lane >= max)
4872 error ("lane out of range");
4873 ops[0] = operands[0];
4874 ops[1] = gen_rtx_REG (DImode, regno);
4875 ops[2] = gen_rtx_REG (DImode, regno + 2);
4876 ops[3] = operands[2];
4877 output_asm_insn ("vst2.<V_sz_elem>\t{%P1[%c3], %P2[%c3]}, %A0", ops);
4880 [(set_attr "neon_type" "neon_vst1_vst2_lane")]
4883 (define_insn "neon_vst2_lane<mode>"
4884 [(set (match_operand:<V_two_elem> 0 "neon_struct_operand" "=Um")
4885 (unspec:<V_two_elem>
4886 [(match_operand:OI 1 "s_register_operand" "w")
4887 (match_operand:SI 2 "immediate_operand" "i")
4888 (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4892 HOST_WIDE_INT lane = INTVAL (operands[2]);
4893 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
4894 int regno = REGNO (operands[1]);
4896 if (lane < 0 || lane >= max)
4897 error ("lane out of range");
4898 else if (lane >= max / 2)
4903 ops[0] = operands[0];
4904 ops[1] = gen_rtx_REG (DImode, regno);
4905 ops[2] = gen_rtx_REG (DImode, regno + 4);
4906 ops[3] = GEN_INT (lane);
4907 output_asm_insn ("vst2.<V_sz_elem>\t{%P1[%c3], %P2[%c3]}, %A0", ops);
4910 [(set_attr "neon_type" "neon_vst1_vst2_lane")]
4913 (define_expand "vec_load_lanesei<mode>"
4914 [(set (match_operand:EI 0 "s_register_operand")
4915 (unspec:EI [(match_operand:EI 1 "neon_struct_operand")
4916 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4920 (define_insn "neon_vld3<mode>"
4921 [(set (match_operand:EI 0 "s_register_operand" "=w")
4922 (unspec:EI [(match_operand:EI 1 "neon_struct_operand" "Um")
4923 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4927 if (<V_sz_elem> == 64)
4928 return "vld1.64\t%h0, %A1";
4930 return "vld3.<V_sz_elem>\t%h0, %A1";
4932 [(set (attr "neon_type")
4933 (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64"))
4934 (const_string "neon_vld1_1_2_regs")
4935 (const_string "neon_vld3_vld4")))]
4938 (define_expand "vec_load_lanesci<mode>"
4939 [(match_operand:CI 0 "s_register_operand")
4940 (match_operand:CI 1 "neon_struct_operand")
4941 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4944 emit_insn (gen_neon_vld3<mode> (operands[0], operands[1]));
4948 (define_expand "neon_vld3<mode>"
4949 [(match_operand:CI 0 "s_register_operand")
4950 (match_operand:CI 1 "neon_struct_operand")
4951 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4956 mem = adjust_address (operands[1], EImode, 0);
4957 emit_insn (gen_neon_vld3qa<mode> (operands[0], mem));
4958 mem = adjust_address (mem, EImode, GET_MODE_SIZE (EImode));
4959 emit_insn (gen_neon_vld3qb<mode> (operands[0], mem, operands[0]));
4963 (define_insn "neon_vld3qa<mode>"
4964 [(set (match_operand:CI 0 "s_register_operand" "=w")
4965 (unspec:CI [(match_operand:EI 1 "neon_struct_operand" "Um")
4966 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4970 int regno = REGNO (operands[0]);
4972 ops[0] = gen_rtx_REG (DImode, regno);
4973 ops[1] = gen_rtx_REG (DImode, regno + 4);
4974 ops[2] = gen_rtx_REG (DImode, regno + 8);
4975 ops[3] = operands[1];
4976 output_asm_insn ("vld3.<V_sz_elem>\t{%P0, %P1, %P2}, %A3", ops);
4979 [(set_attr "neon_type" "neon_vld3_vld4")]
4982 (define_insn "neon_vld3qb<mode>"
4983 [(set (match_operand:CI 0 "s_register_operand" "=w")
4984 (unspec:CI [(match_operand:EI 1 "neon_struct_operand" "Um")
4985 (match_operand:CI 2 "s_register_operand" "0")
4986 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4990 int regno = REGNO (operands[0]);
4992 ops[0] = gen_rtx_REG (DImode, regno + 2);
4993 ops[1] = gen_rtx_REG (DImode, regno + 6);
4994 ops[2] = gen_rtx_REG (DImode, regno + 10);
4995 ops[3] = operands[1];
4996 output_asm_insn ("vld3.<V_sz_elem>\t{%P0, %P1, %P2}, %A3", ops);
4999 [(set_attr "neon_type" "neon_vld3_vld4")]
5002 (define_insn "neon_vld3_lane<mode>"
5003 [(set (match_operand:EI 0 "s_register_operand" "=w")
5004 (unspec:EI [(match_operand:<V_three_elem> 1 "neon_struct_operand" "Um")
5005 (match_operand:EI 2 "s_register_operand" "0")
5006 (match_operand:SI 3 "immediate_operand" "i")
5007 (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5011 HOST_WIDE_INT lane = INTVAL (operands[3]);
5012 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
5013 int regno = REGNO (operands[0]);
5015 if (lane < 0 || lane >= max)
5016 error ("lane out of range");
5017 ops[0] = gen_rtx_REG (DImode, regno);
5018 ops[1] = gen_rtx_REG (DImode, regno + 2);
5019 ops[2] = gen_rtx_REG (DImode, regno + 4);
5020 ops[3] = operands[1];
5021 ops[4] = operands[3];
5022 output_asm_insn ("vld3.<V_sz_elem>\t{%P0[%c4], %P1[%c4], %P2[%c4]}, %3",
5026 [(set_attr "neon_type" "neon_vld3_vld4_lane")]
5029 (define_insn "neon_vld3_lane<mode>"
5030 [(set (match_operand:CI 0 "s_register_operand" "=w")
5031 (unspec:CI [(match_operand:<V_three_elem> 1 "neon_struct_operand" "Um")
5032 (match_operand:CI 2 "s_register_operand" "0")
5033 (match_operand:SI 3 "immediate_operand" "i")
5034 (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5038 HOST_WIDE_INT lane = INTVAL (operands[3]);
5039 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
5040 int regno = REGNO (operands[0]);
5042 if (lane < 0 || lane >= max)
5043 error ("lane out of range");
5044 else if (lane >= max / 2)
5049 ops[0] = gen_rtx_REG (DImode, regno);
5050 ops[1] = gen_rtx_REG (DImode, regno + 4);
5051 ops[2] = gen_rtx_REG (DImode, regno + 8);
5052 ops[3] = operands[1];
5053 ops[4] = GEN_INT (lane);
5054 output_asm_insn ("vld3.<V_sz_elem>\t{%P0[%c4], %P1[%c4], %P2[%c4]}, %3",
5058 [(set_attr "neon_type" "neon_vld3_vld4_lane")]
5061 (define_insn "neon_vld3_dup<mode>"
5062 [(set (match_operand:EI 0 "s_register_operand" "=w")
5063 (unspec:EI [(match_operand:<V_three_elem> 1 "neon_struct_operand" "Um")
5064 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5068 if (GET_MODE_NUNITS (<MODE>mode) > 1)
5070 int regno = REGNO (operands[0]);
5072 ops[0] = gen_rtx_REG (DImode, regno);
5073 ops[1] = gen_rtx_REG (DImode, regno + 2);
5074 ops[2] = gen_rtx_REG (DImode, regno + 4);
5075 ops[3] = operands[1];
5076 output_asm_insn ("vld3.<V_sz_elem>\t{%P0[], %P1[], %P2[]}, %3", ops);
5080 return "vld1.<V_sz_elem>\t%h0, %A1";
5082 [(set (attr "neon_type")
5083 (if_then_else (gt (const_string "<V_mode_nunits>") (const_string "1"))
5084 (const_string "neon_vld3_vld4_all_lanes")
5085 (const_string "neon_vld1_1_2_regs")))])
5087 (define_expand "vec_store_lanesei<mode>"
5088 [(set (match_operand:EI 0 "neon_struct_operand")
5089 (unspec:EI [(match_operand:EI 1 "s_register_operand")
5090 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5094 (define_insn "neon_vst3<mode>"
5095 [(set (match_operand:EI 0 "neon_struct_operand" "=Um")
5096 (unspec:EI [(match_operand:EI 1 "s_register_operand" "w")
5097 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5101 if (<V_sz_elem> == 64)
5102 return "vst1.64\t%h1, %A0";
5104 return "vst3.<V_sz_elem>\t%h1, %A0";
5106 [(set (attr "neon_type")
5107 (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64"))
5108 (const_string "neon_vst1_1_2_regs_vst2_2_regs")
5109 (const_string "neon_vst2_4_regs_vst3_vst4")))])
5111 (define_expand "vec_store_lanesci<mode>"
5112 [(match_operand:CI 0 "neon_struct_operand")
5113 (match_operand:CI 1 "s_register_operand")
5114 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5117 emit_insn (gen_neon_vst3<mode> (operands[0], operands[1]));
5121 (define_expand "neon_vst3<mode>"
5122 [(match_operand:CI 0 "neon_struct_operand")
5123 (match_operand:CI 1 "s_register_operand")
5124 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5129 mem = adjust_address (operands[0], EImode, 0);
5130 emit_insn (gen_neon_vst3qa<mode> (mem, operands[1]));
5131 mem = adjust_address (mem, EImode, GET_MODE_SIZE (EImode));
5132 emit_insn (gen_neon_vst3qb<mode> (mem, operands[1]));
5136 (define_insn "neon_vst3qa<mode>"
5137 [(set (match_operand:EI 0 "neon_struct_operand" "=Um")
5138 (unspec:EI [(match_operand:CI 1 "s_register_operand" "w")
5139 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5143 int regno = REGNO (operands[1]);
5145 ops[0] = operands[0];
5146 ops[1] = gen_rtx_REG (DImode, regno);
5147 ops[2] = gen_rtx_REG (DImode, regno + 4);
5148 ops[3] = gen_rtx_REG (DImode, regno + 8);
5149 output_asm_insn ("vst3.<V_sz_elem>\t{%P1, %P2, %P3}, %A0", ops);
5152 [(set_attr "neon_type" "neon_vst2_4_regs_vst3_vst4")]
5155 (define_insn "neon_vst3qb<mode>"
5156 [(set (match_operand:EI 0 "neon_struct_operand" "=Um")
5157 (unspec:EI [(match_operand:CI 1 "s_register_operand" "w")
5158 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5162 int regno = REGNO (operands[1]);
5164 ops[0] = operands[0];
5165 ops[1] = gen_rtx_REG (DImode, regno + 2);
5166 ops[2] = gen_rtx_REG (DImode, regno + 6);
5167 ops[3] = gen_rtx_REG (DImode, regno + 10);
5168 output_asm_insn ("vst3.<V_sz_elem>\t{%P1, %P2, %P3}, %A0", ops);
5171 [(set_attr "neon_type" "neon_vst2_4_regs_vst3_vst4")]
5174 (define_insn "neon_vst3_lane<mode>"
5175 [(set (match_operand:<V_three_elem> 0 "neon_struct_operand" "=Um")
5176 (unspec:<V_three_elem>
5177 [(match_operand:EI 1 "s_register_operand" "w")
5178 (match_operand:SI 2 "immediate_operand" "i")
5179 (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5183 HOST_WIDE_INT lane = INTVAL (operands[2]);
5184 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
5185 int regno = REGNO (operands[1]);
5187 if (lane < 0 || lane >= max)
5188 error ("lane out of range");
5189 ops[0] = operands[0];
5190 ops[1] = gen_rtx_REG (DImode, regno);
5191 ops[2] = gen_rtx_REG (DImode, regno + 2);
5192 ops[3] = gen_rtx_REG (DImode, regno + 4);
5193 ops[4] = operands[2];
5194 output_asm_insn ("vst3.<V_sz_elem>\t{%P1[%c4], %P2[%c4], %P3[%c4]}, %0",
5198 [(set_attr "neon_type" "neon_vst3_vst4_lane")]
5201 (define_insn "neon_vst3_lane<mode>"
5202 [(set (match_operand:<V_three_elem> 0 "neon_struct_operand" "=Um")
5203 (unspec:<V_three_elem>
5204 [(match_operand:CI 1 "s_register_operand" "w")
5205 (match_operand:SI 2 "immediate_operand" "i")
5206 (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5210 HOST_WIDE_INT lane = INTVAL (operands[2]);
5211 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
5212 int regno = REGNO (operands[1]);
5214 if (lane < 0 || lane >= max)
5215 error ("lane out of range");
5216 else if (lane >= max / 2)
5221 ops[0] = operands[0];
5222 ops[1] = gen_rtx_REG (DImode, regno);
5223 ops[2] = gen_rtx_REG (DImode, regno + 4);
5224 ops[3] = gen_rtx_REG (DImode, regno + 8);
5225 ops[4] = GEN_INT (lane);
5226 output_asm_insn ("vst3.<V_sz_elem>\t{%P1[%c4], %P2[%c4], %P3[%c4]}, %0",
5230 [(set_attr "neon_type" "neon_vst3_vst4_lane")])
5232 (define_expand "vec_load_lanesoi<mode>"
5233 [(set (match_operand:OI 0 "s_register_operand")
5234 (unspec:OI [(match_operand:OI 1 "neon_struct_operand")
5235 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5239 (define_insn "neon_vld4<mode>"
5240 [(set (match_operand:OI 0 "s_register_operand" "=w")
5241 (unspec:OI [(match_operand:OI 1 "neon_struct_operand" "Um")
5242 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5246 if (<V_sz_elem> == 64)
5247 return "vld1.64\t%h0, %A1";
5249 return "vld4.<V_sz_elem>\t%h0, %A1";
5251 [(set (attr "neon_type")
5252 (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64"))
5253 (const_string "neon_vld1_1_2_regs")
5254 (const_string "neon_vld3_vld4")))]
5257 (define_expand "vec_load_lanesxi<mode>"
5258 [(match_operand:XI 0 "s_register_operand")
5259 (match_operand:XI 1 "neon_struct_operand")
5260 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5263 emit_insn (gen_neon_vld4<mode> (operands[0], operands[1]));
5267 (define_expand "neon_vld4<mode>"
5268 [(match_operand:XI 0 "s_register_operand")
5269 (match_operand:XI 1 "neon_struct_operand")
5270 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5275 mem = adjust_address (operands[1], OImode, 0);
5276 emit_insn (gen_neon_vld4qa<mode> (operands[0], mem));
5277 mem = adjust_address (mem, OImode, GET_MODE_SIZE (OImode));
5278 emit_insn (gen_neon_vld4qb<mode> (operands[0], mem, operands[0]));
5282 (define_insn "neon_vld4qa<mode>"
5283 [(set (match_operand:XI 0 "s_register_operand" "=w")
5284 (unspec:XI [(match_operand:OI 1 "neon_struct_operand" "Um")
5285 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5289 int regno = REGNO (operands[0]);
5291 ops[0] = gen_rtx_REG (DImode, regno);
5292 ops[1] = gen_rtx_REG (DImode, regno + 4);
5293 ops[2] = gen_rtx_REG (DImode, regno + 8);
5294 ops[3] = gen_rtx_REG (DImode, regno + 12);
5295 ops[4] = operands[1];
5296 output_asm_insn ("vld4.<V_sz_elem>\t{%P0, %P1, %P2, %P3}, %A4", ops);
5299 [(set_attr "neon_type" "neon_vld3_vld4")]
5302 (define_insn "neon_vld4qb<mode>"
5303 [(set (match_operand:XI 0 "s_register_operand" "=w")
5304 (unspec:XI [(match_operand:OI 1 "neon_struct_operand" "Um")
5305 (match_operand:XI 2 "s_register_operand" "0")
5306 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5310 int regno = REGNO (operands[0]);
5312 ops[0] = gen_rtx_REG (DImode, regno + 2);
5313 ops[1] = gen_rtx_REG (DImode, regno + 6);
5314 ops[2] = gen_rtx_REG (DImode, regno + 10);
5315 ops[3] = gen_rtx_REG (DImode, regno + 14);
5316 ops[4] = operands[1];
5317 output_asm_insn ("vld4.<V_sz_elem>\t{%P0, %P1, %P2, %P3}, %A4", ops);
5320 [(set_attr "neon_type" "neon_vld3_vld4")]
5323 (define_insn "neon_vld4_lane<mode>"
5324 [(set (match_operand:OI 0 "s_register_operand" "=w")
5325 (unspec:OI [(match_operand:<V_four_elem> 1 "neon_struct_operand" "Um")
5326 (match_operand:OI 2 "s_register_operand" "0")
5327 (match_operand:SI 3 "immediate_operand" "i")
5328 (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5332 HOST_WIDE_INT lane = INTVAL (operands[3]);
5333 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
5334 int regno = REGNO (operands[0]);
5336 if (lane < 0 || lane >= max)
5337 error ("lane out of range");
5338 ops[0] = gen_rtx_REG (DImode, regno);
5339 ops[1] = gen_rtx_REG (DImode, regno + 2);
5340 ops[2] = gen_rtx_REG (DImode, regno + 4);
5341 ops[3] = gen_rtx_REG (DImode, regno + 6);
5342 ops[4] = operands[1];
5343 ops[5] = operands[3];
5344 output_asm_insn ("vld4.<V_sz_elem>\t{%P0[%c5], %P1[%c5], %P2[%c5], %P3[%c5]}, %A4",
5348 [(set_attr "neon_type" "neon_vld3_vld4_lane")]
5351 (define_insn "neon_vld4_lane<mode>"
5352 [(set (match_operand:XI 0 "s_register_operand" "=w")
5353 (unspec:XI [(match_operand:<V_four_elem> 1 "neon_struct_operand" "Um")
5354 (match_operand:XI 2 "s_register_operand" "0")
5355 (match_operand:SI 3 "immediate_operand" "i")
5356 (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5360 HOST_WIDE_INT lane = INTVAL (operands[3]);
5361 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
5362 int regno = REGNO (operands[0]);
5364 if (lane < 0 || lane >= max)
5365 error ("lane out of range");
5366 else if (lane >= max / 2)
5371 ops[0] = gen_rtx_REG (DImode, regno);
5372 ops[1] = gen_rtx_REG (DImode, regno + 4);
5373 ops[2] = gen_rtx_REG (DImode, regno + 8);
5374 ops[3] = gen_rtx_REG (DImode, regno + 12);
5375 ops[4] = operands[1];
5376 ops[5] = GEN_INT (lane);
5377 output_asm_insn ("vld4.<V_sz_elem>\t{%P0[%c5], %P1[%c5], %P2[%c5], %P3[%c5]}, %A4",
5381 [(set_attr "neon_type" "neon_vld3_vld4_lane")]
5384 (define_insn "neon_vld4_dup<mode>"
5385 [(set (match_operand:OI 0 "s_register_operand" "=w")
5386 (unspec:OI [(match_operand:<V_four_elem> 1 "neon_struct_operand" "Um")
5387 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5391 if (GET_MODE_NUNITS (<MODE>mode) > 1)
5393 int regno = REGNO (operands[0]);
5395 ops[0] = gen_rtx_REG (DImode, regno);
5396 ops[1] = gen_rtx_REG (DImode, regno + 2);
5397 ops[2] = gen_rtx_REG (DImode, regno + 4);
5398 ops[3] = gen_rtx_REG (DImode, regno + 6);
5399 ops[4] = operands[1];
5400 output_asm_insn ("vld4.<V_sz_elem>\t{%P0[], %P1[], %P2[], %P3[]}, %A4",
5405 return "vld1.<V_sz_elem>\t%h0, %A1";
5407 [(set (attr "neon_type")
5408 (if_then_else (gt (const_string "<V_mode_nunits>") (const_string "1"))
5409 (const_string "neon_vld3_vld4_all_lanes")
5410 (const_string "neon_vld1_1_2_regs")))]
5413 (define_expand "vec_store_lanesoi<mode>"
5414 [(set (match_operand:OI 0 "neon_struct_operand")
5415 (unspec:OI [(match_operand:OI 1 "s_register_operand")
5416 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5420 (define_insn "neon_vst4<mode>"
5421 [(set (match_operand:OI 0 "neon_struct_operand" "=Um")
5422 (unspec:OI [(match_operand:OI 1 "s_register_operand" "w")
5423 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5427 if (<V_sz_elem> == 64)
5428 return "vst1.64\t%h1, %A0";
5430 return "vst4.<V_sz_elem>\t%h1, %A0";
5432 [(set (attr "neon_type")
5433 (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64"))
5434 (const_string "neon_vst1_1_2_regs_vst2_2_regs")
5435 (const_string "neon_vst2_4_regs_vst3_vst4")))]
5438 (define_expand "vec_store_lanesxi<mode>"
5439 [(match_operand:XI 0 "neon_struct_operand")
5440 (match_operand:XI 1 "s_register_operand")
5441 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5444 emit_insn (gen_neon_vst4<mode> (operands[0], operands[1]));
5448 (define_expand "neon_vst4<mode>"
5449 [(match_operand:XI 0 "neon_struct_operand")
5450 (match_operand:XI 1 "s_register_operand")
5451 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5456 mem = adjust_address (operands[0], OImode, 0);
5457 emit_insn (gen_neon_vst4qa<mode> (mem, operands[1]));
5458 mem = adjust_address (mem, OImode, GET_MODE_SIZE (OImode));
5459 emit_insn (gen_neon_vst4qb<mode> (mem, operands[1]));
5463 (define_insn "neon_vst4qa<mode>"
5464 [(set (match_operand:OI 0 "neon_struct_operand" "=Um")
5465 (unspec:OI [(match_operand:XI 1 "s_register_operand" "w")
5466 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5470 int regno = REGNO (operands[1]);
5472 ops[0] = operands[0];
5473 ops[1] = gen_rtx_REG (DImode, regno);
5474 ops[2] = gen_rtx_REG (DImode, regno + 4);
5475 ops[3] = gen_rtx_REG (DImode, regno + 8);
5476 ops[4] = gen_rtx_REG (DImode, regno + 12);
5477 output_asm_insn ("vst4.<V_sz_elem>\t{%P1, %P2, %P3, %P4}, %A0", ops);
5480 [(set_attr "neon_type" "neon_vst2_4_regs_vst3_vst4")]
5483 (define_insn "neon_vst4qb<mode>"
5484 [(set (match_operand:OI 0 "neon_struct_operand" "=Um")
5485 (unspec:OI [(match_operand:XI 1 "s_register_operand" "w")
5486 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5490 int regno = REGNO (operands[1]);
5492 ops[0] = operands[0];
5493 ops[1] = gen_rtx_REG (DImode, regno + 2);
5494 ops[2] = gen_rtx_REG (DImode, regno + 6);
5495 ops[3] = gen_rtx_REG (DImode, regno + 10);
5496 ops[4] = gen_rtx_REG (DImode, regno + 14);
5497 output_asm_insn ("vst4.<V_sz_elem>\t{%P1, %P2, %P3, %P4}, %A0", ops);
5500 [(set_attr "neon_type" "neon_vst2_4_regs_vst3_vst4")]
5503 (define_insn "neon_vst4_lane<mode>"
5504 [(set (match_operand:<V_four_elem> 0 "neon_struct_operand" "=Um")
5505 (unspec:<V_four_elem>
5506 [(match_operand:OI 1 "s_register_operand" "w")
5507 (match_operand:SI 2 "immediate_operand" "i")
5508 (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5512 HOST_WIDE_INT lane = INTVAL (operands[2]);
5513 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
5514 int regno = REGNO (operands[1]);
5516 if (lane < 0 || lane >= max)
5517 error ("lane out of range");
5518 ops[0] = operands[0];
5519 ops[1] = gen_rtx_REG (DImode, regno);
5520 ops[2] = gen_rtx_REG (DImode, regno + 2);
5521 ops[3] = gen_rtx_REG (DImode, regno + 4);
5522 ops[4] = gen_rtx_REG (DImode, regno + 6);
5523 ops[5] = operands[2];
5524 output_asm_insn ("vst4.<V_sz_elem>\t{%P1[%c5], %P2[%c5], %P3[%c5], %P4[%c5]}, %A0",
5528 [(set_attr "neon_type" "neon_vst3_vst4_lane")]
5531 (define_insn "neon_vst4_lane<mode>"
5532 [(set (match_operand:<V_four_elem> 0 "neon_struct_operand" "=Um")
5533 (unspec:<V_four_elem>
5534 [(match_operand:XI 1 "s_register_operand" "w")
5535 (match_operand:SI 2 "immediate_operand" "i")
5536 (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5540 HOST_WIDE_INT lane = INTVAL (operands[2]);
5541 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode);
5542 int regno = REGNO (operands[1]);
5544 if (lane < 0 || lane >= max)
5545 error ("lane out of range");
5546 else if (lane >= max / 2)
5551 ops[0] = operands[0];
5552 ops[1] = gen_rtx_REG (DImode, regno);
5553 ops[2] = gen_rtx_REG (DImode, regno + 4);
5554 ops[3] = gen_rtx_REG (DImode, regno + 8);
5555 ops[4] = gen_rtx_REG (DImode, regno + 12);
5556 ops[5] = GEN_INT (lane);
5557 output_asm_insn ("vst4.<V_sz_elem>\t{%P1[%c5], %P2[%c5], %P3[%c5], %P4[%c5]}, %A0",
5561 [(set_attr "neon_type" "neon_vst3_vst4_lane")]
5564 (define_expand "neon_vand<mode>"
5565 [(match_operand:VDQX 0 "s_register_operand" "")
5566 (match_operand:VDQX 1 "s_register_operand" "")
5567 (match_operand:VDQX 2 "neon_inv_logic_op2" "")
5568 (match_operand:SI 3 "immediate_operand" "")]
5571 emit_insn (gen_and<mode>3 (operands[0], operands[1], operands[2]));
5575 (define_expand "neon_vorr<mode>"
5576 [(match_operand:VDQX 0 "s_register_operand" "")
5577 (match_operand:VDQX 1 "s_register_operand" "")
5578 (match_operand:VDQX 2 "neon_logic_op2" "")
5579 (match_operand:SI 3 "immediate_operand" "")]
5582 emit_insn (gen_ior<mode>3 (operands[0], operands[1], operands[2]));
5586 (define_expand "neon_veor<mode>"
5587 [(match_operand:VDQX 0 "s_register_operand" "")
5588 (match_operand:VDQX 1 "s_register_operand" "")
5589 (match_operand:VDQX 2 "s_register_operand" "")
5590 (match_operand:SI 3 "immediate_operand" "")]
5593 emit_insn (gen_xor<mode>3 (operands[0], operands[1], operands[2]));
5597 (define_expand "neon_vbic<mode>"
5598 [(match_operand:VDQX 0 "s_register_operand" "")
5599 (match_operand:VDQX 1 "s_register_operand" "")
5600 (match_operand:VDQX 2 "neon_logic_op2" "")
5601 (match_operand:SI 3 "immediate_operand" "")]
5604 emit_insn (gen_bic<mode>3_neon (operands[0], operands[1], operands[2]));
5608 (define_expand "neon_vorn<mode>"
5609 [(match_operand:VDQX 0 "s_register_operand" "")
5610 (match_operand:VDQX 1 "s_register_operand" "")
5611 (match_operand:VDQX 2 "neon_inv_logic_op2" "")
5612 (match_operand:SI 3 "immediate_operand" "")]
5615 emit_insn (gen_orn<mode>3_neon (operands[0], operands[1], operands[2]));
5619 (define_insn "neon_vec_unpack<US>_lo_<mode>"
5620 [(set (match_operand:<V_unpack> 0 "register_operand" "=w")
5621 (SE:<V_unpack> (vec_select:<V_HALF>
5622 (match_operand:VU 1 "register_operand" "w")
5623 (match_operand:VU 2 "vect_par_constant_low" ""))))]
5624 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5625 "vmovl.<US><V_sz_elem> %q0, %e1"
5626 [(set_attr "neon_type" "neon_shift_1")]
5629 (define_insn "neon_vec_unpack<US>_hi_<mode>"
5630 [(set (match_operand:<V_unpack> 0 "register_operand" "=w")
5631 (SE:<V_unpack> (vec_select:<V_HALF>
5632 (match_operand:VU 1 "register_operand" "w")
5633 (match_operand:VU 2 "vect_par_constant_high" ""))))]
5634 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5635 "vmovl.<US><V_sz_elem> %q0, %f1"
5636 [(set_attr "neon_type" "neon_shift_1")]
5639 (define_expand "vec_unpack<US>_hi_<mode>"
5640 [(match_operand:<V_unpack> 0 "register_operand" "")
5641 (SE:<V_unpack> (match_operand:VU 1 "register_operand"))]
5642 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5644 rtvec v = rtvec_alloc (<V_mode_nunits>/2) ;
5647 for (i = 0; i < (<V_mode_nunits>/2); i++)
5648 RTVEC_ELT (v, i) = GEN_INT ((<V_mode_nunits>/2) + i);
5650 t1 = gen_rtx_PARALLEL (<MODE>mode, v);
5651 emit_insn (gen_neon_vec_unpack<US>_hi_<mode> (operands[0],
5658 (define_expand "vec_unpack<US>_lo_<mode>"
5659 [(match_operand:<V_unpack> 0 "register_operand" "")
5660 (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))]
5661 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5663 rtvec v = rtvec_alloc (<V_mode_nunits>/2) ;
5666 for (i = 0; i < (<V_mode_nunits>/2) ; i++)
5667 RTVEC_ELT (v, i) = GEN_INT (i);
5668 t1 = gen_rtx_PARALLEL (<MODE>mode, v);
5669 emit_insn (gen_neon_vec_unpack<US>_lo_<mode> (operands[0],
5676 (define_insn "neon_vec_<US>mult_lo_<mode>"
5677 [(set (match_operand:<V_unpack> 0 "register_operand" "=w")
5678 (mult:<V_unpack> (SE:<V_unpack> (vec_select:<V_HALF>
5679 (match_operand:VU 1 "register_operand" "w")
5680 (match_operand:VU 2 "vect_par_constant_low" "")))
5681 (SE:<V_unpack> (vec_select:<V_HALF>
5682 (match_operand:VU 3 "register_operand" "w")
5684 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5685 "vmull.<US><V_sz_elem> %q0, %e1, %e3"
5686 [(set_attr "neon_type" "neon_shift_1")]
5689 (define_expand "vec_widen_<US>mult_lo_<mode>"
5690 [(match_operand:<V_unpack> 0 "register_operand" "")
5691 (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))
5692 (SE:<V_unpack> (match_operand:VU 2 "register_operand" ""))]
5693 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5695 rtvec v = rtvec_alloc (<V_mode_nunits>/2) ;
5698 for (i = 0; i < (<V_mode_nunits>/2) ; i++)
5699 RTVEC_ELT (v, i) = GEN_INT (i);
5700 t1 = gen_rtx_PARALLEL (<MODE>mode, v);
5702 emit_insn (gen_neon_vec_<US>mult_lo_<mode> (operands[0],
5710 (define_insn "neon_vec_<US>mult_hi_<mode>"
5711 [(set (match_operand:<V_unpack> 0 "register_operand" "=w")
5712 (mult:<V_unpack> (SE:<V_unpack> (vec_select:<V_HALF>
5713 (match_operand:VU 1 "register_operand" "w")
5714 (match_operand:VU 2 "vect_par_constant_high" "")))
5715 (SE:<V_unpack> (vec_select:<V_HALF>
5716 (match_operand:VU 3 "register_operand" "w")
5718 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5719 "vmull.<US><V_sz_elem> %q0, %f1, %f3"
5720 [(set_attr "neon_type" "neon_shift_1")]
5723 (define_expand "vec_widen_<US>mult_hi_<mode>"
5724 [(match_operand:<V_unpack> 0 "register_operand" "")
5725 (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))
5726 (SE:<V_unpack> (match_operand:VU 2 "register_operand" ""))]
5727 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5729 rtvec v = rtvec_alloc (<V_mode_nunits>/2) ;
5732 for (i = 0; i < (<V_mode_nunits>/2) ; i++)
5733 RTVEC_ELT (v, i) = GEN_INT (<V_mode_nunits>/2 + i);
5734 t1 = gen_rtx_PARALLEL (<MODE>mode, v);
5736 emit_insn (gen_neon_vec_<US>mult_hi_<mode> (operands[0],
5745 (define_insn "neon_vec_<US>shiftl_<mode>"
5746 [(set (match_operand:<V_widen> 0 "register_operand" "=w")
5747 (SE:<V_widen> (ashift:VW (match_operand:VW 1 "register_operand" "w")
5748 (match_operand:<V_innermode> 2 "const_neon_scalar_shift_amount_operand" ""))))]
5751 return "vshll.<US><V_sz_elem> %q0, %P1, %2";
5753 [(set_attr "neon_type" "neon_shift_1")]
5756 (define_expand "vec_widen_<US>shiftl_lo_<mode>"
5757 [(match_operand:<V_unpack> 0 "register_operand" "")
5758 (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))
5759 (match_operand:SI 2 "immediate_operand" "i")]
5760 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5762 emit_insn (gen_neon_vec_<US>shiftl_<V_half> (operands[0],
5763 simplify_gen_subreg (<V_HALF>mode, operands[1], <MODE>mode, 0),
5769 (define_expand "vec_widen_<US>shiftl_hi_<mode>"
5770 [(match_operand:<V_unpack> 0 "register_operand" "")
5771 (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))
5772 (match_operand:SI 2 "immediate_operand" "i")]
5773 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5775 emit_insn (gen_neon_vec_<US>shiftl_<V_half> (operands[0],
5776 simplify_gen_subreg (<V_HALF>mode, operands[1], <MODE>mode,
5777 GET_MODE_SIZE (<V_HALF>mode)),
5783 ;; Vectorize for non-neon-quad case
5784 (define_insn "neon_unpack<US>_<mode>"
5785 [(set (match_operand:<V_widen> 0 "register_operand" "=w")
5786 (SE:<V_widen> (match_operand:VDI 1 "register_operand" "w")))]
5788 "vmovl.<US><V_sz_elem> %q0, %P1"
5789 [(set_attr "neon_type" "neon_shift_1")]
5792 (define_expand "vec_unpack<US>_lo_<mode>"
5793 [(match_operand:<V_double_width> 0 "register_operand" "")
5794 (SE:<V_double_width>(match_operand:VDI 1 "register_operand"))]
5797 rtx tmpreg = gen_reg_rtx (<V_widen>mode);
5798 emit_insn (gen_neon_unpack<US>_<mode> (tmpreg, operands[1]));
5799 emit_insn (gen_neon_vget_low<V_widen_l> (operands[0], tmpreg));
5805 (define_expand "vec_unpack<US>_hi_<mode>"
5806 [(match_operand:<V_double_width> 0 "register_operand" "")
5807 (SE:<V_double_width>(match_operand:VDI 1 "register_operand"))]
5810 rtx tmpreg = gen_reg_rtx (<V_widen>mode);
5811 emit_insn (gen_neon_unpack<US>_<mode> (tmpreg, operands[1]));
5812 emit_insn (gen_neon_vget_high<V_widen_l> (operands[0], tmpreg));
5818 (define_insn "neon_vec_<US>mult_<mode>"
5819 [(set (match_operand:<V_widen> 0 "register_operand" "=w")
5820 (mult:<V_widen> (SE:<V_widen>
5821 (match_operand:VDI 1 "register_operand" "w"))
5823 (match_operand:VDI 2 "register_operand" "w"))))]
5825 "vmull.<US><V_sz_elem> %q0, %P1, %P2"
5826 [(set_attr "neon_type" "neon_shift_1")]
5829 (define_expand "vec_widen_<US>mult_hi_<mode>"
5830 [(match_operand:<V_double_width> 0 "register_operand" "")
5831 (SE:<V_double_width> (match_operand:VDI 1 "register_operand" ""))
5832 (SE:<V_double_width> (match_operand:VDI 2 "register_operand" ""))]
5835 rtx tmpreg = gen_reg_rtx (<V_widen>mode);
5836 emit_insn (gen_neon_vec_<US>mult_<mode> (tmpreg, operands[1], operands[2]));
5837 emit_insn (gen_neon_vget_high<V_widen_l> (operands[0], tmpreg));
5844 (define_expand "vec_widen_<US>mult_lo_<mode>"
5845 [(match_operand:<V_double_width> 0 "register_operand" "")
5846 (SE:<V_double_width> (match_operand:VDI 1 "register_operand" ""))
5847 (SE:<V_double_width> (match_operand:VDI 2 "register_operand" ""))]
5850 rtx tmpreg = gen_reg_rtx (<V_widen>mode);
5851 emit_insn (gen_neon_vec_<US>mult_<mode> (tmpreg, operands[1], operands[2]));
5852 emit_insn (gen_neon_vget_low<V_widen_l> (operands[0], tmpreg));
5859 (define_expand "vec_widen_<US>shiftl_hi_<mode>"
5860 [(match_operand:<V_double_width> 0 "register_operand" "")
5861 (SE:<V_double_width> (match_operand:VDI 1 "register_operand" ""))
5862 (match_operand:SI 2 "immediate_operand" "i")]
5865 rtx tmpreg = gen_reg_rtx (<V_widen>mode);
5866 emit_insn (gen_neon_vec_<US>shiftl_<mode> (tmpreg, operands[1], operands[2]));
5867 emit_insn (gen_neon_vget_high<V_widen_l> (operands[0], tmpreg));
5873 (define_expand "vec_widen_<US>shiftl_lo_<mode>"
5874 [(match_operand:<V_double_width> 0 "register_operand" "")
5875 (SE:<V_double_width> (match_operand:VDI 1 "register_operand" ""))
5876 (match_operand:SI 2 "immediate_operand" "i")]
5879 rtx tmpreg = gen_reg_rtx (<V_widen>mode);
5880 emit_insn (gen_neon_vec_<US>shiftl_<mode> (tmpreg, operands[1], operands[2]));
5881 emit_insn (gen_neon_vget_low<V_widen_l> (operands[0], tmpreg));
5887 ; FIXME: These instruction patterns can't be used safely in big-endian mode
5888 ; because the ordering of vector elements in Q registers is different from what
5889 ; the semantics of the instructions require.
5891 (define_insn "vec_pack_trunc_<mode>"
5892 [(set (match_operand:<V_narrow_pack> 0 "register_operand" "=&w")
5893 (vec_concat:<V_narrow_pack>
5894 (truncate:<V_narrow>
5895 (match_operand:VN 1 "register_operand" "w"))
5896 (truncate:<V_narrow>
5897 (match_operand:VN 2 "register_operand" "w"))))]
5898 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5899 "vmovn.i<V_sz_elem>\t%e0, %q1\;vmovn.i<V_sz_elem>\t%f0, %q2"
5900 [(set_attr "neon_type" "neon_shift_1")
5901 (set_attr "length" "8")]
5904 ;; For the non-quad case.
5905 (define_insn "neon_vec_pack_trunc_<mode>"
5906 [(set (match_operand:<V_narrow> 0 "register_operand" "=w")
5907 (truncate:<V_narrow> (match_operand:VN 1 "register_operand" "w")))]
5908 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5909 "vmovn.i<V_sz_elem>\t%P0, %q1"
5910 [(set_attr "neon_type" "neon_shift_1")]
5913 (define_expand "vec_pack_trunc_<mode>"
5914 [(match_operand:<V_narrow_pack> 0 "register_operand" "")
5915 (match_operand:VSHFT 1 "register_operand" "")
5916 (match_operand:VSHFT 2 "register_operand")]
5917 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5919 rtx tempreg = gen_reg_rtx (<V_DOUBLE>mode);
5921 emit_insn (gen_move_lo_quad_<V_double> (tempreg, operands[1]));
5922 emit_insn (gen_move_hi_quad_<V_double> (tempreg, operands[2]));
5923 emit_insn (gen_neon_vec_pack_trunc_<V_double> (operands[0], tempreg));
5927 (define_insn "neon_vabd<mode>_2"
5928 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
5929 (abs:VDQ (minus:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
5930 (match_operand:VDQ 2 "s_register_operand" "w"))))]
5931 "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
5932 "vabd.<V_s_elem> %<V_reg>0, %<V_reg>1, %<V_reg>2"
5933 [(set (attr "neon_type")
5934 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
5935 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
5936 (const_string "neon_fp_vadd_ddd_vabs_dd")
5937 (const_string "neon_fp_vadd_qqq_vabs_qq"))
5938 (const_string "neon_int_5")))]
5941 (define_insn "neon_vabd<mode>_3"
5942 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
5943 (abs:VDQ (unspec:VDQ [(match_operand:VDQ 1 "s_register_operand" "w")
5944 (match_operand:VDQ 2 "s_register_operand" "w")]
5946 "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
5947 "vabd.<V_if_elem> %<V_reg>0, %<V_reg>1, %<V_reg>2"
5948 [(set (attr "neon_type")
5949 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
5950 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
5951 (const_string "neon_fp_vadd_ddd_vabs_dd")
5952 (const_string "neon_fp_vadd_qqq_vabs_qq"))
5953 (const_string "neon_int_5")))]
5956 ;; Copy from core-to-neon regs, then extend, not vice-versa
5959 [(set (match_operand:DI 0 "s_register_operand" "")
5960 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
5961 "TARGET_NEON && reload_completed && IS_VFP_REGNUM (REGNO (operands[0]))"
5962 [(set (match_dup 2) (vec_duplicate:V2SI (match_dup 1)))
5963 (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 32)))]
5965 operands[2] = gen_rtx_REG (V2SImode, REGNO (operands[0]));
5969 [(set (match_operand:DI 0 "s_register_operand" "")
5970 (sign_extend:DI (match_operand:HI 1 "s_register_operand" "")))]
5971 "TARGET_NEON && reload_completed && IS_VFP_REGNUM (REGNO (operands[0]))"
5972 [(set (match_dup 2) (vec_duplicate:V4HI (match_dup 1)))
5973 (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))]
5975 operands[2] = gen_rtx_REG (V4HImode, REGNO (operands[0]));
5979 [(set (match_operand:DI 0 "s_register_operand" "")
5980 (sign_extend:DI (match_operand:QI 1 "s_register_operand" "")))]
5981 "TARGET_NEON && reload_completed && IS_VFP_REGNUM (REGNO (operands[0]))"
5982 [(set (match_dup 2) (vec_duplicate:V8QI (match_dup 1)))
5983 (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))]
5985 operands[2] = gen_rtx_REG (V8QImode, REGNO (operands[0]));
5989 [(set (match_operand:DI 0 "s_register_operand" "")
5990 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
5991 "TARGET_NEON && reload_completed && IS_VFP_REGNUM (REGNO (operands[0]))"
5992 [(set (match_dup 2) (vec_duplicate:V2SI (match_dup 1)))
5993 (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 32)))]
5995 operands[2] = gen_rtx_REG (V2SImode, REGNO (operands[0]));
5999 [(set (match_operand:DI 0 "s_register_operand" "")
6000 (zero_extend:DI (match_operand:HI 1 "s_register_operand" "")))]
6001 "TARGET_NEON && reload_completed && IS_VFP_REGNUM (REGNO (operands[0]))"
6002 [(set (match_dup 2) (vec_duplicate:V4HI (match_dup 1)))
6003 (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))]
6005 operands[2] = gen_rtx_REG (V4HImode, REGNO (operands[0]));
6009 [(set (match_operand:DI 0 "s_register_operand" "")
6010 (zero_extend:DI (match_operand:QI 1 "s_register_operand" "")))]
6011 "TARGET_NEON && reload_completed && IS_VFP_REGNUM (REGNO (operands[0]))"
6012 [(set (match_dup 2) (vec_duplicate:V8QI (match_dup 1)))
6013 (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 56)))]
6015 operands[2] = gen_rtx_REG (V8QImode, REGNO (operands[0]));