1 ;; ARM NEON coprocessor Machine Description
2 ;; Copyright (C) 2006 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 2, 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 COPYING. If not, write to the Free
19 ;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
22 ;; Constants for unspecs.
24 [(UNSPEC_ASHIFT_SIGNED 65)
25 (UNSPEC_ASHIFT_UNSIGNED 66)
60 (UNSPEC_VLD1_LANE 101)
63 (UNSPEC_VLD2_LANE 104)
68 (UNSPEC_VLD3_LANE 109)
73 (UNSPEC_VLD4_LANE 114)
78 (UNSPEC_VMLA_LANE 119)
79 (UNSPEC_VMLAL_LANE 120)
82 (UNSPEC_VMLS_LANE 123)
83 (UNSPEC_VMLSL_LANE 124)
88 (UNSPEC_VMUL_LANE 129)
89 (UNSPEC_VMULL_LANE 130)
106 (UNSPEC_VQDMLAL_LANE 147)
108 (UNSPEC_VQDMLSL_LANE 149)
110 (UNSPEC_VQDMULH_LANE 151)
112 (UNSPEC_VQDMULL_LANE 153)
118 (UNSPEC_VQSHLU_N 159)
119 (UNSPEC_VQSHRN_N 160)
120 (UNSPEC_VQSHRUN_N 161)
129 (UNSPEC_VSET_LANE 170)
139 (UNSPEC_VST1_LANE 180)
141 (UNSPEC_VST2_LANE 182)
145 (UNSPEC_VST3_LANE 186)
149 (UNSPEC_VST4_LANE 190)
150 (UNSPEC_VSTRUCTDUMMY 191)
165 ;; Double-width vector modes.
166 (define_mode_macro VD [V8QI V4HI V2SI V2SF])
168 ;; Double-width vector modes plus 64-bit elements.
169 (define_mode_macro VDX [V8QI V4HI V2SI V2SF DI])
171 ;; Same, without floating-point elements.
172 (define_mode_macro VDI [V8QI V4HI V2SI])
174 ;; Quad-width vector modes.
175 (define_mode_macro VQ [V16QI V8HI V4SI V4SF])
177 ;; Quad-width vector modes plus 64-bit elements.
178 (define_mode_macro VQX [V16QI V8HI V4SI V4SF V2DI])
180 ;; Same, without floating-point elements.
181 (define_mode_macro VQI [V16QI V8HI V4SI])
183 ;; Same, with TImode added, for moves.
184 (define_mode_macro VQXMOV [V16QI V8HI V4SI V4SF V2DI TI])
186 ;; Opaque structure types wider than TImode.
187 (define_mode_macro VSTRUCT [EI OI CI XI])
189 ;; Number of instructions needed to load/store struct elements. FIXME!
190 (define_mode_attr V_slen [(EI "2") (OI "2") (CI "3") (XI "4")])
192 ;; Opaque structure types used in table lookups (except vtbl1/vtbx1).
193 (define_mode_macro VTAB [TI EI OI])
195 ;; vtbl<n> suffix for above modes.
196 (define_mode_attr VTAB_n [(TI "2") (EI "3") (OI "4")])
199 (define_mode_macro VW [V8QI V4HI V2SI])
202 (define_mode_macro VN [V8HI V4SI V2DI])
204 ;; All supported vector modes (except singleton DImode).
205 (define_mode_macro VDQ [V8QI V16QI V4HI V8HI V2SI V4SI V2SF V4SF V2DI])
207 ;; All supported vector modes (except those with 64-bit integer elements).
208 (define_mode_macro VDQW [V8QI V16QI V4HI V8HI V2SI V4SI V2SF V4SF])
210 ;; Supported integer vector modes (not 64 bit elements).
211 (define_mode_macro VDQIW [V8QI V16QI V4HI V8HI V2SI V4SI])
213 ;; Supported integer vector modes (not singleton DI)
214 (define_mode_macro VDQI [V8QI V16QI V4HI V8HI V2SI V4SI V2DI])
216 ;; Vector modes, including 64-bit integer elements.
217 (define_mode_macro VDQX [V8QI V16QI V4HI V8HI V2SI V4SI V2SF V4SF DI V2DI])
219 ;; Vector modes including 64-bit integer elements, but no floats.
220 (define_mode_macro VDQIX [V8QI V16QI V4HI V8HI V2SI V4SI DI V2DI])
222 ;; Vector modes for float->int conversions.
223 (define_mode_macro VCVTF [V2SF V4SF])
225 ;; Vector modes form int->float conversions.
226 (define_mode_macro VCVTI [V2SI V4SI])
228 ;; Vector modes for doubleword multiply-accumulate, etc. insns.
229 (define_mode_macro VMD [V4HI V2SI V2SF])
231 ;; Vector modes for quadword multiply-accumulate, etc. insns.
232 (define_mode_macro VMQ [V8HI V4SI V4SF])
234 ;; Above modes combined.
235 (define_mode_macro VMDQ [V4HI V2SI V2SF V8HI V4SI V4SF])
237 ;; As VMD, but integer modes only.
238 (define_mode_macro VMDI [V4HI V2SI])
240 ;; As VMQ, but integer modes only.
241 (define_mode_macro VMQI [V8HI V4SI])
243 ;; Above modes combined.
244 (define_mode_macro VMDQI [V4HI V2SI V8HI V4SI])
246 ;; Modes with 8-bit and 16-bit elements.
247 (define_mode_macro VX [V8QI V4HI V16QI V8HI])
249 ;; Modes with 8-bit elements.
250 (define_mode_macro VE [V8QI V16QI])
252 ;; Modes with 64-bit elements only.
253 (define_mode_macro V64 [DI V2DI])
255 ;; Modes with 32-bit elements only.
256 (define_mode_macro V32 [V2SI V2SF V4SI V4SF])
258 ;; (Opposite) mode to convert to/from for above conversions.
259 (define_mode_attr V_CVTTO [(V2SI "V2SF") (V2SF "V2SI")
260 (V4SI "V4SF") (V4SF "V4SI")])
262 ;; Define element mode for each vector mode.
263 (define_mode_attr V_elem [(V8QI "QI") (V16QI "QI")
264 (V4HI "HI") (V8HI "HI")
265 (V2SI "SI") (V4SI "SI")
266 (V2SF "SF") (V4SF "SF")
267 (DI "DI") (V2DI "DI")])
269 ;; Element modes for vector extraction, padded up to register size.
271 (define_mode_attr V_ext [(V8QI "SI") (V16QI "SI")
272 (V4HI "SI") (V8HI "SI")
273 (V2SI "SI") (V4SI "SI")
274 (V2SF "SF") (V4SF "SF")
275 (DI "DI") (V2DI "DI")])
277 ;; Mode of pair of elements for each vector mode, to define transfer
278 ;; size for structure lane/dup loads and stores.
279 (define_mode_attr V_two_elem [(V8QI "HI") (V16QI "HI")
280 (V4HI "SI") (V8HI "SI")
281 (V2SI "V2SI") (V4SI "V2SI")
282 (V2SF "V2SF") (V4SF "V2SF")
283 (DI "V2DI") (V2DI "V2DI")])
285 ;; Similar, for three elements.
286 ;; ??? Should we define extra modes so that sizes of all three-element
287 ;; accesses can be accurately represented?
288 (define_mode_attr V_three_elem [(V8QI "SI") (V16QI "SI")
289 (V4HI "V4HI") (V8HI "V4HI")
290 (V2SI "V4SI") (V4SI "V4SI")
291 (V2SF "V4SF") (V4SF "V4SF")
292 (DI "EI") (V2DI "EI")])
294 ;; Similar, for four elements.
295 (define_mode_attr V_four_elem [(V8QI "SI") (V16QI "SI")
296 (V4HI "V4HI") (V8HI "V4HI")
297 (V2SI "V4SI") (V4SI "V4SI")
298 (V2SF "V4SF") (V4SF "V4SF")
299 (DI "OI") (V2DI "OI")])
301 ;; Register width from element mode
302 (define_mode_attr V_reg [(V8QI "P") (V16QI "q")
303 (V4HI "P") (V8HI "q")
304 (V2SI "P") (V4SI "q")
305 (V2SF "P") (V4SF "q")
306 (DI "P") (V2DI "q")])
308 ;; Wider modes with the same number of elements.
309 (define_mode_attr V_widen [(V8QI "V8HI") (V4HI "V4SI") (V2SI "V2DI")])
311 ;; Narrower modes with the same number of elements.
312 (define_mode_attr V_narrow [(V8HI "V8QI") (V4SI "V4HI") (V2DI "V2SI")])
314 ;; Modes with half the number of equal-sized elements.
315 (define_mode_attr V_HALF [(V16QI "V8QI") (V8HI "V4HI")
316 (V4SI "V2SI") (V4SF "V2SF")
319 ;; Same, but lower-case.
320 (define_mode_attr V_half [(V16QI "v8qi") (V8HI "v4hi")
321 (V4SI "v2si") (V4SF "v2sf")
324 ;; Modes with twice the number of equal-sized elements.
325 (define_mode_attr V_DOUBLE [(V8QI "V16QI") (V4HI "V8HI")
326 (V2SI "V4SI") (V2SF "V4SF")
329 ;; Same, but lower-case.
330 (define_mode_attr V_double [(V8QI "v16qi") (V4HI "v8hi")
331 (V2SI "v4si") (V2SF "v4sf")
334 ;; Modes with double-width elements.
335 (define_mode_attr V_double_width [(V8QI "V4HI") (V16QI "V8HI")
336 (V4HI "V2SI") (V8HI "V4SI")
337 (V2SI "DI") (V4SI "V2DI")])
339 ;; Mode of result of comparison operations (and bit-select operand 1).
340 (define_mode_attr V_cmp_result [(V8QI "V8QI") (V16QI "V16QI")
341 (V4HI "V4HI") (V8HI "V8HI")
342 (V2SI "V2SI") (V4SI "V4SI")
343 (V2SF "V2SI") (V4SF "V4SI")
344 (DI "DI") (V2DI "V2DI")])
346 ;; Get element type from double-width mode, for operations where we don't care
348 (define_mode_attr V_if_elem [(V8QI "i8") (V16QI "i8")
349 (V4HI "i16") (V8HI "i16")
350 (V2SI "i32") (V4SI "i32")
351 (DI "i64") (V2DI "i64")
352 (V2SF "f32") (V4SF "f32")])
354 ;; Same, but for operations which work on signed values.
355 (define_mode_attr V_s_elem [(V8QI "s8") (V16QI "s8")
356 (V4HI "s16") (V8HI "s16")
357 (V2SI "s32") (V4SI "s32")
358 (DI "s64") (V2DI "s64")
359 (V2SF "f32") (V4SF "f32")])
361 ;; Same, but for operations which work on unsigned values.
362 (define_mode_attr V_u_elem [(V8QI "u8") (V16QI "u8")
363 (V4HI "u16") (V8HI "u16")
364 (V2SI "u32") (V4SI "u32")
365 (DI "u64") (V2DI "u64")
366 (V2SF "f32") (V4SF "f32")])
368 ;; Element types for extraction of unsigned scalars.
369 (define_mode_attr V_uf_sclr [(V8QI "u8") (V16QI "u8")
370 (V4HI "u16") (V8HI "u16")
371 (V2SI "32") (V4SI "32")
372 (V2SF "32") (V4SF "32")])
374 (define_mode_attr V_sz_elem [(V8QI "8") (V16QI "8")
375 (V4HI "16") (V8HI "16")
376 (V2SI "32") (V4SI "32")
377 (DI "64") (V2DI "64")
378 (V2SF "32") (V4SF "32")])
380 ;; Element sizes for duplicating ARM registers to all elements of a vector.
381 (define_mode_attr VD_dup [(V8QI "8") (V4HI "16") (V2SI "32") (V2SF "32")])
383 ;; Opaque integer types for results of pair-forming intrinsics (vtrn, etc.)
384 (define_mode_attr V_PAIR [(V8QI "TI") (V16QI "OI")
385 (V4HI "TI") (V8HI "OI")
386 (V2SI "TI") (V4SI "OI")
387 (V2SF "TI") (V4SF "OI")
388 (DI "TI") (V2DI "OI")])
390 ;; Same, but lower-case.
391 (define_mode_attr V_pair [(V8QI "ti") (V16QI "oi")
392 (V4HI "ti") (V8HI "oi")
393 (V2SI "ti") (V4SI "oi")
394 (V2SF "ti") (V4SF "oi")
395 (DI "ti") (V2DI "oi")])
397 ;; Operations on two halves of a quadword vector.
398 (define_code_macro vqh_ops [plus smin smax umin umax])
400 ;; Same, without unsigned variants (for use with *SFmode pattern).
401 (define_code_macro vqhs_ops [plus smin smax])
403 ;; Assembler mnemonics for above codes.
404 (define_code_attr VQH_mnem [(plus "vadd") (smin "vmin") (smax "vmax")
405 (umin "vmin") (umax "vmax")])
407 ;; Signs of above, where relevant.
408 (define_code_attr VQH_sign [(plus "i") (smin "s") (smax "s") (umin "u")
411 ;; Extra suffix on some 64-bit insn names (to avoid collision with standard
412 ;; names which we don't want to define).
413 (define_mode_attr V_suf64 [(V8QI "") (V16QI "")
417 (DI "_neon") (V2DI "")])
419 ;; Scalars to be presented to scalar multiplication instructions
420 ;; must satisfy the following constraints.
421 ;; 1. If the mode specifies 16-bit elements, the scalar must be in D0-D7.
422 ;; 2. If the mode specifies 32-bit elements, the scalar must be in D0-D15.
423 ;; This mode attribute is used to obtain the correct register constraints.
424 (define_mode_attr scalar_mul_constraint [(V4HI "x") (V2SI "t") (V2SF "t")
425 (V8HI "x") (V4SI "t") (V4SF "t")])
427 ;; Attribute used to permit string comparisons against <VQH_mnem> in
428 ;; neon_type attribute definitions.
429 (define_attr "vqh_mnem" "vadd,vmin,vmax" (const_string "vadd"))
431 ;; Classification of NEON instructions for scheduling purposes.
432 ;; Do not set this attribute and the "type" attribute together in
433 ;; any one instruction pattern.
434 (define_attr "neon_type"
445 neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
446 neon_mul_qqq_8_16_32_ddd_32,\
447 neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
448 neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
450 neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
451 neon_mla_qqq_32_qqd_32_scalar,\
452 neon_mul_ddd_16_scalar_32_16_long_scalar,\
453 neon_mul_qqd_32_scalar,\
454 neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
459 neon_vqshl_vrshl_vqrshl_qqq,\
461 neon_fp_vadd_ddd_vabs_dd,\
462 neon_fp_vadd_qqq_vabs_qq,\
468 neon_fp_vmla_ddd_scalar,\
469 neon_fp_vmla_qqq_scalar,\
470 neon_fp_vrecps_vrsqrts_ddd,\
471 neon_fp_vrecps_vrsqrts_qqq,\
479 neon_vld2_2_regs_vld1_vld2_all_lanes,\
482 neon_vst1_1_2_regs_vst2_2_regs,\
484 neon_vst2_4_regs_vst3_vst4,\
486 neon_vld1_vld2_lane,\
487 neon_vld3_vld4_lane,\
488 neon_vst1_vst2_lane,\
489 neon_vst3_vst4_lane,\
490 neon_vld3_vld4_all_lanes,\
498 (const_string "none"))
500 ;; Predicates used for setting the above attribute.
502 (define_mode_attr Is_float_mode [(V8QI "false") (V16QI "false")
503 (V4HI "false") (V8HI "false")
504 (V2SI "false") (V4SI "false")
505 (V2SF "true") (V4SF "true")
506 (DI "false") (V2DI "false")])
508 (define_mode_attr Scalar_mul_8_16 [(V8QI "true") (V16QI "true")
509 (V4HI "true") (V8HI "true")
510 (V2SI "false") (V4SI "false")
511 (V2SF "false") (V4SF "false")
512 (DI "false") (V2DI "false")])
515 (define_mode_attr Is_d_reg [(V8QI "true") (V16QI "false")
516 (V4HI "true") (V8HI "false")
517 (V2SI "true") (V4SI "false")
518 (V2SF "true") (V4SF "false")
519 (DI "true") (V2DI "false")])
521 (define_mode_attr V_mode_nunits [(V8QI "8") (V16QI "16")
522 (V4HI "4") (V8HI "8")
523 (V2SI "2") (V4SI "4")
524 (V2SF "2") (V4SF "4")
525 (DI "1") (V2DI "2")])
527 (define_insn "*neon_mov<mode>"
528 [(set (match_operand:VD 0 "nonimmediate_operand"
529 "=w,Uv,w, w, ?r,?w,?r,?r, ?Us")
530 (match_operand:VD 1 "general_operand"
531 " w,w, Dn,Uvi, w, r, r, Usi,r"))]
534 if (which_alternative == 2)
537 static char templ[40];
539 is_valid = neon_immediate_valid_for_move (operands[1], <MODE>mode,
540 &operands[1], &width);
542 gcc_assert (is_valid != 0);
545 return "vmov.f32\t%P0, %1 @ <mode>";
547 sprintf (templ, "vmov.i%d\t%%P0, %%1 @ <mode>", width);
552 /* FIXME: If the memory layout is changed in big-endian mode, output_move_vfp
553 below must be changed to output_move_neon (which will use the
554 element/structure loads/stores), and the constraint changed to 'Un' instead
557 switch (which_alternative)
559 case 0: return "vmov\t%P0, %P1 @ <mode>";
560 case 1: case 3: return output_move_vfp (operands);
561 case 2: gcc_unreachable ();
562 case 4: return "vmov\t%Q0, %R0, %P1 @ <mode>";
563 case 5: return "vmov\t%P0, %Q1, %R1 @ <mode>";
564 default: return output_move_double (operands);
567 [(set_attr "neon_type" "neon_int_1,*,neon_vmov,*,neon_mrrc,neon_mcr_2_mcrr,*,*,*")
568 (set_attr "type" "*,f_stored,*,f_loadd,*,*,alu,load2,store2")
569 (set_attr "insn" "*,*,*,*,*,*,mov,*,*")
570 (set_attr "length" "4,4,4,4,4,4,8,8,8")
571 (set_attr "pool_range" "*,*,*,1020,*,*,*,1020,*")
572 (set_attr "neg_pool_range" "*,*,*,1008,*,*,*,1008,*")])
574 (define_insn "*neon_mov<mode>"
575 [(set (match_operand:VQXMOV 0 "nonimmediate_operand"
576 "=w,Un,w, w, ?r,?w,?r,?r, ?Us")
577 (match_operand:VQXMOV 1 "general_operand"
578 " w,w, Dn,Uni, w, r, r, Usi, r"))]
581 if (which_alternative == 2)
584 static char templ[40];
586 is_valid = neon_immediate_valid_for_move (operands[1], <MODE>mode,
587 &operands[1], &width);
589 gcc_assert (is_valid != 0);
592 return "vmov.f32\t%q0, %1 @ <mode>";
594 sprintf (templ, "vmov.i%d\t%%q0, %%1 @ <mode>", width);
599 switch (which_alternative)
601 case 0: return "vmov\t%q0, %q1 @ <mode>";
602 case 1: case 3: return output_move_neon (operands);
603 case 2: gcc_unreachable ();
604 case 4: return "vmov\t%Q0, %R0, %e1 @ <mode>\;vmov\t%J0, %K0, %f1";
605 case 5: return "vmov\t%e0, %Q1, %R1 @ <mode>\;vmov\t%f0, %J1, %K1";
606 default: return output_move_quad (operands);
609 [(set_attr "neon_type" "neon_int_1,neon_stm_2,neon_vmov,neon_ldm_2,\
610 neon_mrrc,neon_mcr_2_mcrr,*,*,*")
611 (set_attr "type" "*,*,*,*,*,*,alu,load4,store4")
612 (set_attr "insn" "*,*,*,*,*,*,mov,*,*")
613 (set_attr "length" "4,8,4,8,8,8,16,8,16")
614 (set_attr "pool_range" "*,*,*,1020,*,*,*,1020,*")
615 (set_attr "neg_pool_range" "*,*,*,1008,*,*,*,1008,*")])
617 (define_expand "movti"
618 [(set (match_operand:TI 0 "nonimmediate_operand" "")
619 (match_operand:TI 1 "general_operand" ""))]
624 (define_expand "mov<mode>"
625 [(set (match_operand:VSTRUCT 0 "nonimmediate_operand" "")
626 (match_operand:VSTRUCT 1 "general_operand" ""))]
631 (define_insn "*neon_mov<mode>"
632 [(set (match_operand:VSTRUCT 0 "nonimmediate_operand" "=w,Ut,w")
633 (match_operand:VSTRUCT 1 "general_operand" " w,w, Ut"))]
636 switch (which_alternative)
639 case 1: case 2: return output_move_neon (operands);
640 default: gcc_unreachable ();
643 [(set_attr "length" "<V_slen>,<V_slen>,<V_slen>")])
646 [(set (match_operand:EI 0 "s_register_operand" "")
647 (match_operand:EI 1 "s_register_operand" ""))]
648 "TARGET_NEON && reload_completed"
649 [(set (match_dup 0) (match_dup 1))
650 (set (match_dup 2) (match_dup 3))]
652 int rdest = REGNO (operands[0]);
653 int rsrc = REGNO (operands[1]);
656 dest[0] = gen_rtx_REG (TImode, rdest);
657 src[0] = gen_rtx_REG (TImode, rsrc);
658 dest[1] = gen_rtx_REG (DImode, rdest + 4);
659 src[1] = gen_rtx_REG (DImode, rsrc + 4);
661 neon_disambiguate_copy (operands, dest, src, 2);
665 [(set (match_operand:OI 0 "s_register_operand" "")
666 (match_operand:OI 1 "s_register_operand" ""))]
667 "TARGET_NEON && reload_completed"
668 [(set (match_dup 0) (match_dup 1))
669 (set (match_dup 2) (match_dup 3))]
671 int rdest = REGNO (operands[0]);
672 int rsrc = REGNO (operands[1]);
675 dest[0] = gen_rtx_REG (TImode, rdest);
676 src[0] = gen_rtx_REG (TImode, rsrc);
677 dest[1] = gen_rtx_REG (TImode, rdest + 4);
678 src[1] = gen_rtx_REG (TImode, rsrc + 4);
680 neon_disambiguate_copy (operands, dest, src, 2);
684 [(set (match_operand:CI 0 "s_register_operand" "")
685 (match_operand:CI 1 "s_register_operand" ""))]
686 "TARGET_NEON && reload_completed"
687 [(set (match_dup 0) (match_dup 1))
688 (set (match_dup 2) (match_dup 3))
689 (set (match_dup 4) (match_dup 5))]
691 int rdest = REGNO (operands[0]);
692 int rsrc = REGNO (operands[1]);
695 dest[0] = gen_rtx_REG (TImode, rdest);
696 src[0] = gen_rtx_REG (TImode, rsrc);
697 dest[1] = gen_rtx_REG (TImode, rdest + 4);
698 src[1] = gen_rtx_REG (TImode, rsrc + 4);
699 dest[2] = gen_rtx_REG (TImode, rdest + 8);
700 src[2] = gen_rtx_REG (TImode, rsrc + 8);
702 neon_disambiguate_copy (operands, dest, src, 3);
706 [(set (match_operand:XI 0 "s_register_operand" "")
707 (match_operand:XI 1 "s_register_operand" ""))]
708 "TARGET_NEON && reload_completed"
709 [(set (match_dup 0) (match_dup 1))
710 (set (match_dup 2) (match_dup 3))
711 (set (match_dup 4) (match_dup 5))
712 (set (match_dup 6) (match_dup 7))]
714 int rdest = REGNO (operands[0]);
715 int rsrc = REGNO (operands[1]);
718 dest[0] = gen_rtx_REG (TImode, rdest);
719 src[0] = gen_rtx_REG (TImode, rsrc);
720 dest[1] = gen_rtx_REG (TImode, rdest + 4);
721 src[1] = gen_rtx_REG (TImode, rsrc + 4);
722 dest[2] = gen_rtx_REG (TImode, rdest + 8);
723 src[2] = gen_rtx_REG (TImode, rsrc + 8);
724 dest[3] = gen_rtx_REG (TImode, rdest + 12);
725 src[3] = gen_rtx_REG (TImode, rsrc + 12);
727 neon_disambiguate_copy (operands, dest, src, 4);
730 (define_insn "vec_set<mode>_internal"
731 [(set (match_operand:VD 0 "s_register_operand" "=w")
734 (match_operand:<V_elem> 1 "s_register_operand" "r"))
735 (match_operand:VD 3 "s_register_operand" "0")
736 (match_operand:SI 2 "immediate_operand" "i")))]
739 operands[2] = GEN_INT (ffs ((int) INTVAL (operands[2]) - 1));
741 return "vmov%?.<V_uf_sclr>\t%P0[%c2], %1";
743 [(set_attr "predicable" "yes")
744 (set_attr "neon_type" "neon_mcr")])
746 (define_insn "vec_set<mode>_internal"
747 [(set (match_operand:VQ 0 "s_register_operand" "=w")
750 (match_operand:<V_elem> 1 "s_register_operand" "r"))
751 (match_operand:VQ 3 "s_register_operand" "0")
752 (match_operand:SI 2 "immediate_operand" "i")))]
755 HOST_WIDE_INT elem = ffs (operands[2]) - 1;
756 int half_elts = GET_MODE_NUNITS (<MODE>mode) / 2;
757 int elt = elem % half_elts;
758 int hi = (elem / half_elts) * 2;
759 int regno = REGNO (operands[0]);
761 operands[0] = gen_rtx_REG (<V_HALF>mode, regno + hi);
762 operands[2] = GEN_INT (elt);
764 return "vmov%?.<V_uf_sclr>\t%P0[%c2], %1";
766 [(set_attr "predicable" "yes")
767 (set_attr "neon_type" "neon_mcr")]
770 (define_insn "vec_setv2di_internal"
771 [(set (match_operand:V2DI 0 "s_register_operand" "=w")
774 (match_operand:DI 1 "s_register_operand" "r"))
775 (match_operand:V2DI 3 "s_register_operand" "0")
776 (match_operand:SI 2 "immediate_operand" "i")))]
779 HOST_WIDE_INT elem = ffs (operands[2]) - 1;
780 int regno = REGNO (operands[0]) + 2 * elem;
782 operands[0] = gen_rtx_REG (DImode, regno);
784 return "vmov%?.64\t%P0, %Q1, %R1";
786 [(set_attr "predicable" "yes")
787 (set_attr "neon_type" "neon_mcr_2_mcrr")]
790 (define_expand "vec_set<mode>"
791 [(match_operand:VDQ 0 "s_register_operand" "")
792 (match_operand:<V_elem> 1 "s_register_operand" "")
793 (match_operand:SI 2 "immediate_operand" "")]
796 HOST_WIDE_INT elem = (HOST_WIDE_INT) 1 << INTVAL (operands[2]);
797 emit_insn (gen_vec_set<mode>_internal (operands[0], operands[1],
798 GEN_INT (elem), operands[0]));
802 (define_insn "vec_extract<mode>"
803 [(set (match_operand:<V_elem> 0 "s_register_operand" "=r")
805 (match_operand:VD 1 "s_register_operand" "w")
806 (parallel [(match_operand:SI 2 "immediate_operand" "i")])))]
808 "vmov%?.<V_uf_sclr>\t%0, %P1[%c2]"
809 [(set_attr "predicable" "yes")
810 (set_attr "neon_type" "neon_bp_simple")]
813 (define_insn "vec_extract<mode>"
814 [(set (match_operand:<V_elem> 0 "s_register_operand" "=r")
816 (match_operand:VQ 1 "s_register_operand" "w")
817 (parallel [(match_operand:SI 2 "immediate_operand" "i")])))]
820 int half_elts = GET_MODE_NUNITS (<MODE>mode) / 2;
821 int elt = INTVAL (operands[2]) % half_elts;
822 int hi = (INTVAL (operands[2]) / half_elts) * 2;
823 int regno = REGNO (operands[1]);
825 operands[1] = gen_rtx_REG (<V_HALF>mode, regno + hi);
826 operands[2] = GEN_INT (elt);
828 return "vmov%?.<V_uf_sclr>\t%0, %P1[%c2]";
830 [(set_attr "predicable" "yes")
831 (set_attr "neon_type" "neon_bp_simple")]
834 (define_insn "vec_extractv2di"
835 [(set (match_operand:DI 0 "s_register_operand" "=r")
837 (match_operand:V2DI 1 "s_register_operand" "w")
838 (parallel [(match_operand:SI 2 "immediate_operand" "i")])))]
841 int regno = REGNO (operands[1]) + INTVAL (operands[2]);
843 operands[1] = gen_rtx_REG (DImode, regno);
845 return "vmov%?.64\t%Q0, %R0, %P1";
847 [(set_attr "predicable" "yes")
848 (set_attr "neon_type" "neon_int_1")]
851 (define_expand "vec_init<mode>"
852 [(match_operand:VDQ 0 "s_register_operand" "")
853 (match_operand 1 "" "")]
856 neon_expand_vector_init (operands[0], operands[1]);
860 ;; Doubleword and quadword arithmetic.
862 ;; NOTE: vadd/vsub and some other instructions also support 64-bit integer
863 ;; element size, which we could potentially use for "long long" operations. We
864 ;; don't want to do this at present though, because moving values from the
865 ;; vector unit to the ARM core is currently slow and 64-bit addition (etc.) is
866 ;; easy to do with ARM instructions anyway.
868 (define_insn "*add<mode>3_neon"
869 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
870 (plus:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
871 (match_operand:VDQ 2 "s_register_operand" "w")))]
873 "vadd.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
874 [(set (attr "neon_type")
875 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
876 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
877 (const_string "neon_fp_vadd_ddd_vabs_dd")
878 (const_string "neon_fp_vadd_qqq_vabs_qq"))
879 (const_string "neon_int_1")))]
882 (define_insn "*sub<mode>3_neon"
883 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
884 (minus:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
885 (match_operand:VDQ 2 "s_register_operand" "w")))]
887 "vsub.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
888 [(set (attr "neon_type")
889 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
890 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
891 (const_string "neon_fp_vadd_ddd_vabs_dd")
892 (const_string "neon_fp_vadd_qqq_vabs_qq"))
893 (const_string "neon_int_2")))]
896 (define_insn "*mul<mode>3_neon"
897 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
898 (mult:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
899 (match_operand:VDQ 2 "s_register_operand" "w")))]
901 "vmul.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
902 [(set (attr "neon_type")
903 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
904 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
905 (const_string "neon_fp_vadd_ddd_vabs_dd")
906 (const_string "neon_fp_vadd_qqq_vabs_qq"))
907 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
909 (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
910 (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
911 (const_string "neon_mul_qqq_8_16_32_ddd_32"))
912 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
913 (const_string "neon_mul_qqq_8_16_32_ddd_32")
914 (const_string "neon_mul_qqq_8_16_32_ddd_32")))))]
917 (define_insn "ior<mode>3"
918 [(set (match_operand:VDQ 0 "s_register_operand" "=w,w")
919 (ior:VDQ (match_operand:VDQ 1 "s_register_operand" "w,0")
920 (match_operand:VDQ 2 "neon_logic_op2" "w,Dl")))]
923 switch (which_alternative)
925 case 0: return "vorr\t%<V_reg>0, %<V_reg>1, %<V_reg>2";
926 case 1: return neon_output_logic_immediate ("vorr", &operands[2],
927 <MODE>mode, 0, VALID_NEON_QREG_MODE (<MODE>mode));
928 default: gcc_unreachable ();
931 [(set_attr "neon_type" "neon_int_1")]
934 (define_insn "iordi3_neon"
935 [(set (match_operand:DI 0 "s_register_operand" "=w,w")
936 (unspec:DI [(match_operand:DI 1 "s_register_operand" "w,0")
937 (match_operand:DI 2 "neon_logic_op2" "w,Dl")]
941 switch (which_alternative)
943 case 0: return "vorr\t%P0, %P1, %P2";
944 case 1: return neon_output_logic_immediate ("vorr", &operands[2],
945 DImode, 0, VALID_NEON_QREG_MODE (DImode));
946 default: gcc_unreachable ();
949 [(set_attr "neon_type" "neon_int_1")]
952 ;; The concrete forms of the Neon immediate-logic instructions are vbic and
953 ;; vorr. We support the pseudo-instruction vand instead, because that
954 ;; corresponds to the canonical form the middle-end expects to use for
955 ;; immediate bitwise-ANDs.
957 (define_insn "and<mode>3"
958 [(set (match_operand:VDQ 0 "s_register_operand" "=w,w")
959 (and:VDQ (match_operand:VDQ 1 "s_register_operand" "w,0")
960 (match_operand:VDQ 2 "neon_inv_logic_op2" "w,DL")))]
963 switch (which_alternative)
965 case 0: return "vand\t%<V_reg>0, %<V_reg>1, %<V_reg>2";
966 case 1: return neon_output_logic_immediate ("vand", &operands[2],
967 <MODE>mode, 1, VALID_NEON_QREG_MODE (<MODE>mode));
968 default: gcc_unreachable ();
971 [(set_attr "neon_type" "neon_int_1")]
974 (define_insn "anddi3_neon"
975 [(set (match_operand:DI 0 "s_register_operand" "=w,w")
976 (unspec:DI [(match_operand:DI 1 "s_register_operand" "w,0")
977 (match_operand:DI 2 "neon_inv_logic_op2" "w,DL")]
981 switch (which_alternative)
983 case 0: return "vand\t%P0, %P1, %P2";
984 case 1: return neon_output_logic_immediate ("vand", &operands[2],
985 DImode, 1, VALID_NEON_QREG_MODE (DImode));
986 default: gcc_unreachable ();
989 [(set_attr "neon_type" "neon_int_1")]
992 (define_insn "orn<mode>3_neon"
993 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
994 (ior:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
995 (not:VDQ (match_operand:VDQ 2 "s_register_operand" "w"))))]
997 "vorn\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
998 [(set_attr "neon_type" "neon_int_1")]
1001 (define_insn "orndi3_neon"
1002 [(set (match_operand:DI 0 "s_register_operand" "=w")
1003 (unspec:DI [(match_operand:DI 1 "s_register_operand" "w")
1004 (match_operand:DI 2 "s_register_operand" "w")]
1007 "vorn\t%P0, %P1, %P2"
1008 [(set_attr "neon_type" "neon_int_1")]
1011 (define_insn "bic<mode>3_neon"
1012 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
1013 (and:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
1014 (not:VDQ (match_operand:VDQ 2 "s_register_operand" "w"))))]
1016 "vbic\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1017 [(set_attr "neon_type" "neon_int_1")]
1020 (define_insn "bicdi3_neon"
1021 [(set (match_operand:DI 0 "s_register_operand" "=w")
1022 (unspec:DI [(match_operand:DI 1 "s_register_operand" "w")
1023 (match_operand:DI 2 "s_register_operand" "w")]
1026 "vbic\t%P0, %P1, %P2"
1027 [(set_attr "neon_type" "neon_int_1")]
1030 (define_insn "xor<mode>3"
1031 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
1032 (xor:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
1033 (match_operand:VDQ 2 "s_register_operand" "w")))]
1035 "veor\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1036 [(set_attr "neon_type" "neon_int_1")]
1039 (define_insn "xordi3_neon"
1040 [(set (match_operand:DI 0 "s_register_operand" "=w")
1041 (unspec:DI [(match_operand:DI 1 "s_register_operand" "w")
1042 (match_operand:DI 2 "s_register_operand" "w")]
1045 "veor\t%P0, %P1, %P2"
1046 [(set_attr "neon_type" "neon_int_1")]
1049 (define_insn "one_cmpl<mode>2"
1050 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
1051 (not:VDQ (match_operand:VDQ 1 "s_register_operand" "w")))]
1053 "vmvn\t%<V_reg>0, %<V_reg>1"
1054 [(set_attr "neon_type" "neon_int_1")]
1057 (define_insn "abs<mode>2"
1058 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
1059 (abs:VDQW (match_operand:VDQW 1 "s_register_operand" "w")))]
1061 "vabs.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
1062 [(set (attr "neon_type")
1063 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
1064 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1065 (const_string "neon_fp_vadd_ddd_vabs_dd")
1066 (const_string "neon_fp_vadd_qqq_vabs_qq"))
1067 (const_string "neon_int_3")))]
1070 (define_insn "neg<mode>2"
1071 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
1072 (neg:VDQW (match_operand:VDQW 1 "s_register_operand" "w")))]
1074 "vneg.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
1075 [(set (attr "neon_type")
1076 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
1077 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1078 (const_string "neon_fp_vadd_ddd_vabs_dd")
1079 (const_string "neon_fp_vadd_qqq_vabs_qq"))
1080 (const_string "neon_int_3")))]
1083 (define_insn "*umin<mode>3_neon"
1084 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
1085 (umin:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")
1086 (match_operand:VDQIW 2 "s_register_operand" "w")))]
1088 "vmin.<V_u_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1089 [(set_attr "neon_type" "neon_int_5")]
1092 (define_insn "*umax<mode>3_neon"
1093 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
1094 (umax:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")
1095 (match_operand:VDQIW 2 "s_register_operand" "w")))]
1097 "vmax.<V_u_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1098 [(set_attr "neon_type" "neon_int_5")]
1101 (define_insn "*smin<mode>3_neon"
1102 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
1103 (smin:VDQW (match_operand:VDQW 1 "s_register_operand" "w")
1104 (match_operand:VDQW 2 "s_register_operand" "w")))]
1106 "vmin.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1107 [(set (attr "neon_type")
1108 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
1109 (const_string "neon_fp_vadd_ddd_vabs_dd")
1110 (const_string "neon_int_5")))]
1113 (define_insn "*smax<mode>3_neon"
1114 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
1115 (smax:VDQW (match_operand:VDQW 1 "s_register_operand" "w")
1116 (match_operand:VDQW 2 "s_register_operand" "w")))]
1118 "vmax.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1119 [(set (attr "neon_type")
1120 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
1121 (const_string "neon_fp_vadd_ddd_vabs_dd")
1122 (const_string "neon_int_5")))]
1125 ; TODO: V2DI shifts are current disabled because there are bugs in the
1126 ; generic vectorizer code. It ends up creating a V2DI constructor with
1129 (define_insn "ashl<mode>3"
1130 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
1131 (ashift:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")
1132 (match_operand:VDQIW 2 "s_register_operand" "w")))]
1134 "vshl.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1135 [(set (attr "neon_type")
1136 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1137 (const_string "neon_vshl_ddd")
1138 (const_string "neon_shift_3")))]
1141 ; Used for implementing logical shift-right, which is a left-shift by a negative
1142 ; amount, with signed operands. This is essentially the same as ashl<mode>3
1143 ; above, but using an unspec in case GCC tries anything tricky with negative
1146 (define_insn "ashl<mode>3_signed"
1147 [(set (match_operand:VDQI 0 "s_register_operand" "=w")
1148 (unspec:VDQI [(match_operand:VDQI 1 "s_register_operand" "w")
1149 (match_operand:VDQI 2 "s_register_operand" "w")]
1150 UNSPEC_ASHIFT_SIGNED))]
1152 "vshl.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1153 [(set (attr "neon_type")
1154 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1155 (const_string "neon_vshl_ddd")
1156 (const_string "neon_shift_3")))]
1159 ; Used for implementing logical shift-right, which is a left-shift by a negative
1160 ; amount, with unsigned operands.
1162 (define_insn "ashl<mode>3_unsigned"
1163 [(set (match_operand:VDQI 0 "s_register_operand" "=w")
1164 (unspec:VDQI [(match_operand:VDQI 1 "s_register_operand" "w")
1165 (match_operand:VDQI 2 "s_register_operand" "w")]
1166 UNSPEC_ASHIFT_UNSIGNED))]
1168 "vshl.<V_u_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1169 [(set (attr "neon_type")
1170 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1171 (const_string "neon_vshl_ddd")
1172 (const_string "neon_shift_3")))]
1175 (define_expand "ashr<mode>3"
1176 [(set (match_operand:VDQIW 0 "s_register_operand" "")
1177 (ashiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "")
1178 (match_operand:VDQIW 2 "s_register_operand" "")))]
1181 rtx neg = gen_reg_rtx (<MODE>mode);
1183 emit_insn (gen_neg<mode>2 (neg, operands[2]));
1184 emit_insn (gen_ashl<mode>3_signed (operands[0], operands[1], neg));
1189 (define_expand "lshr<mode>3"
1190 [(set (match_operand:VDQIW 0 "s_register_operand" "")
1191 (lshiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "")
1192 (match_operand:VDQIW 2 "s_register_operand" "")))]
1195 rtx neg = gen_reg_rtx (<MODE>mode);
1197 emit_insn (gen_neg<mode>2 (neg, operands[2]));
1198 emit_insn (gen_ashl<mode>3_unsigned (operands[0], operands[1], neg));
1203 ;; Widening operations
1205 (define_insn "widen_ssum<mode>3"
1206 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1207 (plus:<V_widen> (sign_extend:<V_widen>
1208 (match_operand:VW 1 "s_register_operand" "%w"))
1209 (match_operand:<V_widen> 2 "s_register_operand" "w")))]
1211 "vaddw.<V_s_elem>\t%q0, %q2, %P1"
1212 [(set_attr "neon_type" "neon_int_3")]
1215 (define_insn "widen_usum<mode>3"
1216 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1217 (plus:<V_widen> (zero_extend:<V_widen>
1218 (match_operand:VW 1 "s_register_operand" "%w"))
1219 (match_operand:<V_widen> 2 "s_register_operand" "w")))]
1221 "vaddw.<V_u_elem>\t%q0, %q2, %P1"
1222 [(set_attr "neon_type" "neon_int_3")]
1225 ;; VEXT can be used to synthesize coarse whole-vector shifts with 8-bit
1226 ;; shift-count granularity. That's good enough for the middle-end's current
1229 (define_expand "vec_shr_<mode>"
1230 [(match_operand:VDQ 0 "s_register_operand" "")
1231 (match_operand:VDQ 1 "s_register_operand" "")
1232 (match_operand:SI 2 "const_multiple_of_8_operand" "")]
1236 HOST_WIDE_INT num_bits = INTVAL (operands[2]);
1237 const int width = GET_MODE_BITSIZE (<MODE>mode);
1238 const enum machine_mode bvecmode = (width == 128) ? V16QImode : V8QImode;
1239 rtx (*gen_ext) (rtx, rtx, rtx, rtx) =
1240 (width == 128) ? gen_neon_vextv16qi : gen_neon_vextv8qi;
1242 if (num_bits == width)
1244 emit_move_insn (operands[0], operands[1]);
1248 zero_reg = force_reg (bvecmode, CONST0_RTX (bvecmode));
1249 operands[0] = gen_lowpart (bvecmode, operands[0]);
1250 operands[1] = gen_lowpart (bvecmode, operands[1]);
1252 emit_insn (gen_ext (operands[0], operands[1], zero_reg,
1253 GEN_INT (num_bits / BITS_PER_UNIT)));
1257 (define_expand "vec_shl_<mode>"
1258 [(match_operand:VDQ 0 "s_register_operand" "")
1259 (match_operand:VDQ 1 "s_register_operand" "")
1260 (match_operand:SI 2 "const_multiple_of_8_operand" "")]
1264 HOST_WIDE_INT num_bits = INTVAL (operands[2]);
1265 const int width = GET_MODE_BITSIZE (<MODE>mode);
1266 const enum machine_mode bvecmode = (width == 128) ? V16QImode : V8QImode;
1267 rtx (*gen_ext) (rtx, rtx, rtx, rtx) =
1268 (width == 128) ? gen_neon_vextv16qi : gen_neon_vextv8qi;
1272 emit_move_insn (operands[0], CONST0_RTX (<MODE>mode));
1276 num_bits = width - num_bits;
1278 zero_reg = force_reg (bvecmode, CONST0_RTX (bvecmode));
1279 operands[0] = gen_lowpart (bvecmode, operands[0]);
1280 operands[1] = gen_lowpart (bvecmode, operands[1]);
1282 emit_insn (gen_ext (operands[0], zero_reg, operands[1],
1283 GEN_INT (num_bits / BITS_PER_UNIT)));
1287 ;; Helpers for quad-word reduction operations
1289 ; Add (or smin, smax...) the low N/2 elements of the N-element vector
1290 ; operand[1] to the high N/2 elements of same. Put the result in operand[0], an
1291 ; N/2-element vector.
1293 (define_insn "quad_halves_<code>v4si"
1294 [(set (match_operand:V2SI 0 "s_register_operand" "=w")
1296 (vec_select:V2SI (match_operand:V4SI 1 "s_register_operand" "w")
1297 (parallel [(const_int 0) (const_int 1)]))
1298 (vec_select:V2SI (match_dup 1)
1299 (parallel [(const_int 2) (const_int 3)]))))]
1301 "<VQH_mnem>.<VQH_sign>32\t%P0, %e1, %f1"
1302 [(set_attr "vqh_mnem" "<VQH_mnem>")
1303 (set (attr "neon_type")
1304 (if_then_else (eq_attr "vqh_mnem" "vadd")
1305 (const_string "neon_int_1") (const_string "neon_int_5")))]
1308 (define_insn "quad_halves_<code>v4sf"
1309 [(set (match_operand:V2SF 0 "s_register_operand" "=w")
1311 (vec_select:V2SF (match_operand:V4SF 1 "s_register_operand" "w")
1312 (parallel [(const_int 0) (const_int 1)]))
1313 (vec_select:V2SF (match_dup 1)
1314 (parallel [(const_int 2) (const_int 3)]))))]
1316 "<VQH_mnem>.f32\t%P0, %e1, %f1"
1317 [(set_attr "vqh_mnem" "<VQH_mnem>")
1318 (set (attr "neon_type")
1319 (if_then_else (eq_attr "vqh_mnem" "vadd")
1320 (const_string "neon_int_1") (const_string "neon_int_5")))]
1323 (define_insn "quad_halves_<code>v8hi"
1324 [(set (match_operand:V4HI 0 "s_register_operand" "+w")
1326 (vec_select:V4HI (match_operand:V8HI 1 "s_register_operand" "w")
1327 (parallel [(const_int 0) (const_int 1)
1328 (const_int 2) (const_int 3)]))
1329 (vec_select:V4HI (match_dup 1)
1330 (parallel [(const_int 4) (const_int 5)
1331 (const_int 6) (const_int 7)]))))]
1333 "<VQH_mnem>.<VQH_sign>16\t%P0, %e1, %f1"
1334 [(set_attr "vqh_mnem" "<VQH_mnem>")
1335 (set (attr "neon_type")
1336 (if_then_else (eq_attr "vqh_mnem" "vadd")
1337 (const_string "neon_int_1") (const_string "neon_int_5")))]
1340 (define_insn "quad_halves_<code>v16qi"
1341 [(set (match_operand:V8QI 0 "s_register_operand" "+w")
1343 (vec_select:V8QI (match_operand:V16QI 1 "s_register_operand" "w")
1344 (parallel [(const_int 0) (const_int 1)
1345 (const_int 2) (const_int 3)
1346 (const_int 4) (const_int 5)
1347 (const_int 6) (const_int 7)]))
1348 (vec_select:V8QI (match_dup 1)
1349 (parallel [(const_int 8) (const_int 9)
1350 (const_int 10) (const_int 11)
1351 (const_int 12) (const_int 13)
1352 (const_int 14) (const_int 15)]))))]
1354 "<VQH_mnem>.<VQH_sign>8\t%P0, %e1, %f1"
1355 [(set_attr "vqh_mnem" "<VQH_mnem>")
1356 (set (attr "neon_type")
1357 (if_then_else (eq_attr "vqh_mnem" "vadd")
1358 (const_string "neon_int_1") (const_string "neon_int_5")))]
1361 ; FIXME: We wouldn't need the following insns if we could write subregs of
1362 ; vector registers. Make an attempt at removing unnecessary moves, though
1363 ; we're really at the mercy of the register allocator.
1365 (define_insn "move_lo_quad_v4si"
1366 [(set (match_operand:V4SI 0 "s_register_operand" "+w")
1368 (match_operand:V2SI 1 "s_register_operand" "w")
1369 (vec_select:V2SI (match_dup 0)
1370 (parallel [(const_int 2) (const_int 3)]))))]
1373 int dest = REGNO (operands[0]);
1374 int src = REGNO (operands[1]);
1377 return "vmov\t%e0, %P1";
1381 [(set_attr "neon_type" "neon_bp_simple")]
1384 (define_insn "move_lo_quad_v4sf"
1385 [(set (match_operand:V4SF 0 "s_register_operand" "+w")
1387 (match_operand:V2SF 1 "s_register_operand" "w")
1388 (vec_select:V2SF (match_dup 0)
1389 (parallel [(const_int 2) (const_int 3)]))))]
1392 int dest = REGNO (operands[0]);
1393 int src = REGNO (operands[1]);
1396 return "vmov\t%e0, %P1";
1400 [(set_attr "neon_type" "neon_bp_simple")]
1403 (define_insn "move_lo_quad_v8hi"
1404 [(set (match_operand:V8HI 0 "s_register_operand" "+w")
1406 (match_operand:V4HI 1 "s_register_operand" "w")
1407 (vec_select:V4HI (match_dup 0)
1408 (parallel [(const_int 4) (const_int 5)
1409 (const_int 6) (const_int 7)]))))]
1412 int dest = REGNO (operands[0]);
1413 int src = REGNO (operands[1]);
1416 return "vmov\t%e0, %P1";
1420 [(set_attr "neon_type" "neon_bp_simple")]
1423 (define_insn "move_lo_quad_v16qi"
1424 [(set (match_operand:V16QI 0 "s_register_operand" "+w")
1426 (match_operand:V8QI 1 "s_register_operand" "w")
1427 (vec_select:V8QI (match_dup 0)
1428 (parallel [(const_int 8) (const_int 9)
1429 (const_int 10) (const_int 11)
1430 (const_int 12) (const_int 13)
1431 (const_int 14) (const_int 15)]))))]
1434 int dest = REGNO (operands[0]);
1435 int src = REGNO (operands[1]);
1438 return "vmov\t%e0, %P1";
1442 [(set_attr "neon_type" "neon_bp_simple")]
1445 ;; Reduction operations
1447 (define_expand "reduc_splus_<mode>"
1448 [(match_operand:VD 0 "s_register_operand" "")
1449 (match_operand:VD 1 "s_register_operand" "")]
1452 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1453 &gen_neon_vpadd_internal<mode>);
1457 (define_expand "reduc_splus_<mode>"
1458 [(match_operand:VQ 0 "s_register_operand" "")
1459 (match_operand:VQ 1 "s_register_operand" "")]
1462 rtx step1 = gen_reg_rtx (<V_HALF>mode);
1463 rtx res_d = gen_reg_rtx (<V_HALF>mode);
1465 emit_insn (gen_quad_halves_plus<mode> (step1, operands[1]));
1466 emit_insn (gen_reduc_splus_<V_half> (res_d, step1));
1467 emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d));
1472 (define_insn "reduc_splus_v2di"
1473 [(set (match_operand:V2DI 0 "s_register_operand" "=w")
1474 (unspec:V2DI [(match_operand:V2DI 1 "s_register_operand" "w")]
1477 "vadd.i64\t%e0, %e1, %f1"
1478 [(set_attr "neon_type" "neon_int_1")]
1481 ;; NEON does not distinguish between signed and unsigned addition except on
1482 ;; widening operations.
1483 (define_expand "reduc_uplus_<mode>"
1484 [(match_operand:VDQI 0 "s_register_operand" "")
1485 (match_operand:VDQI 1 "s_register_operand" "")]
1488 emit_insn (gen_reduc_splus_<mode> (operands[0], operands[1]));
1492 (define_expand "reduc_smin_<mode>"
1493 [(match_operand:VD 0 "s_register_operand" "")
1494 (match_operand:VD 1 "s_register_operand" "")]
1497 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1498 &gen_neon_vpsmin<mode>);
1502 (define_expand "reduc_smin_<mode>"
1503 [(match_operand:VQ 0 "s_register_operand" "")
1504 (match_operand:VQ 1 "s_register_operand" "")]
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_smin<mode> (step1, operands[1]));
1511 emit_insn (gen_reduc_smin_<V_half> (res_d, step1));
1512 emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d));
1517 (define_expand "reduc_smax_<mode>"
1518 [(match_operand:VD 0 "s_register_operand" "")
1519 (match_operand:VD 1 "s_register_operand" "")]
1522 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1523 &gen_neon_vpsmax<mode>);
1527 (define_expand "reduc_smax_<mode>"
1528 [(match_operand:VQ 0 "s_register_operand" "")
1529 (match_operand:VQ 1 "s_register_operand" "")]
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_smax<mode> (step1, operands[1]));
1536 emit_insn (gen_reduc_smax_<V_half> (res_d, step1));
1537 emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d));
1542 (define_expand "reduc_umin_<mode>"
1543 [(match_operand:VDI 0 "s_register_operand" "")
1544 (match_operand:VDI 1 "s_register_operand" "")]
1547 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1548 &gen_neon_vpumin<mode>);
1552 (define_expand "reduc_umin_<mode>"
1553 [(match_operand:VQI 0 "s_register_operand" "")
1554 (match_operand:VQI 1 "s_register_operand" "")]
1557 rtx step1 = gen_reg_rtx (<V_HALF>mode);
1558 rtx res_d = gen_reg_rtx (<V_HALF>mode);
1560 emit_insn (gen_quad_halves_umin<mode> (step1, operands[1]));
1561 emit_insn (gen_reduc_umin_<V_half> (res_d, step1));
1562 emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d));
1567 (define_expand "reduc_umax_<mode>"
1568 [(match_operand:VDI 0 "s_register_operand" "")
1569 (match_operand:VDI 1 "s_register_operand" "")]
1572 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode,
1573 &gen_neon_vpumax<mode>);
1577 (define_expand "reduc_umax_<mode>"
1578 [(match_operand:VQI 0 "s_register_operand" "")
1579 (match_operand:VQI 1 "s_register_operand" "")]
1582 rtx step1 = gen_reg_rtx (<V_HALF>mode);
1583 rtx res_d = gen_reg_rtx (<V_HALF>mode);
1585 emit_insn (gen_quad_halves_umax<mode> (step1, operands[1]));
1586 emit_insn (gen_reduc_umax_<V_half> (res_d, step1));
1587 emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d));
1592 (define_insn "neon_vpadd_internal<mode>"
1593 [(set (match_operand:VD 0 "s_register_operand" "=w")
1594 (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
1595 (match_operand:VD 2 "s_register_operand" "w")]
1598 "vpadd.<V_if_elem>\t%P0, %P1, %P2"
1599 ;; Assume this schedules like vadd.
1600 [(set (attr "neon_type")
1601 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
1602 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1603 (const_string "neon_fp_vadd_ddd_vabs_dd")
1604 (const_string "neon_fp_vadd_qqq_vabs_qq"))
1605 (const_string "neon_int_1")))]
1608 (define_insn "neon_vpsmin<mode>"
1609 [(set (match_operand:VD 0 "s_register_operand" "=w")
1610 (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
1611 (match_operand:VD 2 "s_register_operand" "w")]
1614 "vpmin.<V_s_elem>\t%P0, %P1, %P2"
1615 ;; Assume this schedules like vmin.
1616 [(set (attr "neon_type")
1617 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
1618 (const_string "neon_fp_vadd_ddd_vabs_dd")
1619 (const_string "neon_int_5")))]
1622 (define_insn "neon_vpsmax<mode>"
1623 [(set (match_operand:VD 0 "s_register_operand" "=w")
1624 (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
1625 (match_operand:VD 2 "s_register_operand" "w")]
1628 "vpmax.<V_s_elem>\t%P0, %P1, %P2"
1629 ;; Assume this schedules like vmax.
1630 [(set (attr "neon_type")
1631 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
1632 (const_string "neon_fp_vadd_ddd_vabs_dd")
1633 (const_string "neon_int_5")))]
1636 (define_insn "neon_vpumin<mode>"
1637 [(set (match_operand:VDI 0 "s_register_operand" "=w")
1638 (unspec:VDI [(match_operand:VDI 1 "s_register_operand" "w")
1639 (match_operand:VDI 2 "s_register_operand" "w")]
1642 "vpmin.<V_u_elem>\t%P0, %P1, %P2"
1643 ;; Assume this schedules like umin.
1644 [(set_attr "neon_type" "neon_int_5")]
1647 (define_insn "neon_vpumax<mode>"
1648 [(set (match_operand:VDI 0 "s_register_operand" "=w")
1649 (unspec:VDI [(match_operand:VDI 1 "s_register_operand" "w")
1650 (match_operand:VDI 2 "s_register_operand" "w")]
1653 "vpmax.<V_u_elem>\t%P0, %P1, %P2"
1654 ;; Assume this schedules like umax.
1655 [(set_attr "neon_type" "neon_int_5")]
1658 ;; Saturating arithmetic
1660 ; NOTE: Neon supports many more saturating variants of instructions than the
1661 ; following, but these are all GCC currently understands.
1662 ; FIXME: Actually, GCC doesn't know how to create saturating add/sub by itself
1663 ; yet either, although these patterns may be used by intrinsics when they're
1666 (define_insn "*ss_add<mode>_neon"
1667 [(set (match_operand:VD 0 "s_register_operand" "=w")
1668 (ss_plus:VD (match_operand:VD 1 "s_register_operand" "w")
1669 (match_operand:VD 2 "s_register_operand" "w")))]
1671 "vqadd.<V_s_elem>\t%P0, %P1, %P2"
1672 [(set_attr "neon_type" "neon_int_4")]
1675 (define_insn "*us_add<mode>_neon"
1676 [(set (match_operand:VD 0 "s_register_operand" "=w")
1677 (us_plus:VD (match_operand:VD 1 "s_register_operand" "w")
1678 (match_operand:VD 2 "s_register_operand" "w")))]
1680 "vqadd.<V_u_elem>\t%P0, %P1, %P2"
1681 [(set_attr "neon_type" "neon_int_4")]
1684 (define_insn "*ss_sub<mode>_neon"
1685 [(set (match_operand:VD 0 "s_register_operand" "=w")
1686 (ss_minus:VD (match_operand:VD 1 "s_register_operand" "w")
1687 (match_operand:VD 2 "s_register_operand" "w")))]
1689 "vqsub.<V_s_elem>\t%P0, %P1, %P2"
1690 [(set_attr "neon_type" "neon_int_5")]
1693 (define_insn "*us_sub<mode>_neon"
1694 [(set (match_operand:VD 0 "s_register_operand" "=w")
1695 (us_minus:VD (match_operand:VD 1 "s_register_operand" "w")
1696 (match_operand:VD 2 "s_register_operand" "w")))]
1698 "vqsub.<V_u_elem>\t%P0, %P1, %P2"
1699 [(set_attr "neon_type" "neon_int_5")]
1702 ;; Patterns for builtins.
1704 ; good for plain vadd, vaddq.
1706 (define_insn "neon_vadd<mode>"
1707 [(set (match_operand:VDQX 0 "s_register_operand" "=w")
1708 (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w")
1709 (match_operand:VDQX 2 "s_register_operand" "w")
1710 (match_operand:SI 3 "immediate_operand" "i")]
1713 "vadd.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1714 [(set (attr "neon_type")
1715 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
1716 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1717 (const_string "neon_fp_vadd_ddd_vabs_dd")
1718 (const_string "neon_fp_vadd_qqq_vabs_qq"))
1719 (const_string "neon_int_1")))]
1722 ; operand 3 represents in bits:
1723 ; bit 0: signed (vs unsigned).
1724 ; bit 1: rounding (vs none).
1726 (define_insn "neon_vaddl<mode>"
1727 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1728 (unspec:<V_widen> [(match_operand:VDI 1 "s_register_operand" "w")
1729 (match_operand:VDI 2 "s_register_operand" "w")
1730 (match_operand:SI 3 "immediate_operand" "i")]
1733 "vaddl.%T3%#<V_sz_elem>\t%q0, %P1, %P2"
1734 [(set_attr "neon_type" "neon_int_3")]
1737 (define_insn "neon_vaddw<mode>"
1738 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1739 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "w")
1740 (match_operand:VDI 2 "s_register_operand" "w")
1741 (match_operand:SI 3 "immediate_operand" "i")]
1744 "vaddw.%T3%#<V_sz_elem>\t%q0, %q1, %P2"
1745 [(set_attr "neon_type" "neon_int_2")]
1750 (define_insn "neon_vhadd<mode>"
1751 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
1752 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
1753 (match_operand:VDQIW 2 "s_register_operand" "w")
1754 (match_operand:SI 3 "immediate_operand" "i")]
1757 "v%O3hadd.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1758 [(set_attr "neon_type" "neon_int_4")]
1761 (define_insn "neon_vqadd<mode>"
1762 [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
1763 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
1764 (match_operand:VDQIX 2 "s_register_operand" "w")
1765 (match_operand:SI 3 "immediate_operand" "i")]
1768 "vqadd.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1769 [(set_attr "neon_type" "neon_int_4")]
1772 (define_insn "neon_vaddhn<mode>"
1773 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
1774 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
1775 (match_operand:VN 2 "s_register_operand" "w")
1776 (match_operand:SI 3 "immediate_operand" "i")]
1779 "v%O3addhn.<V_if_elem>\t%P0, %q1, %q2"
1780 [(set_attr "neon_type" "neon_int_4")]
1783 (define_insn "neon_vmul<mode>"
1784 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
1785 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w")
1786 (match_operand:VDQW 2 "s_register_operand" "w")
1787 (match_operand:SI 3 "immediate_operand" "i")]
1790 "vmul.%F3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1791 [(set (attr "neon_type")
1792 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
1793 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1794 (const_string "neon_fp_vadd_ddd_vabs_dd")
1795 (const_string "neon_fp_vadd_qqq_vabs_qq"))
1796 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1798 (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
1799 (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
1800 (const_string "neon_mul_qqq_8_16_32_ddd_32"))
1801 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
1802 (const_string "neon_mul_qqq_8_16_32_ddd_32")
1803 (const_string "neon_mul_qqq_8_16_32_ddd_32")))))]
1806 (define_insn "neon_vmla<mode>"
1807 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
1808 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0")
1809 (match_operand:VDQW 2 "s_register_operand" "w")
1810 (match_operand:VDQW 3 "s_register_operand" "w")
1811 (match_operand:SI 4 "immediate_operand" "i")]
1814 "vmla.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
1815 [(set (attr "neon_type")
1816 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
1817 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1818 (const_string "neon_fp_vmla_ddd")
1819 (const_string "neon_fp_vmla_qqq"))
1820 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1822 (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
1823 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
1824 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
1825 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
1826 (const_string "neon_mla_qqq_8_16")
1827 (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
1830 (define_insn "neon_vmlal<mode>"
1831 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1832 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
1833 (match_operand:VW 2 "s_register_operand" "w")
1834 (match_operand:VW 3 "s_register_operand" "w")
1835 (match_operand:SI 4 "immediate_operand" "i")]
1838 "vmlal.%T4%#<V_sz_elem>\t%q0, %P2, %P3"
1839 [(set (attr "neon_type")
1840 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
1841 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
1842 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
1845 (define_insn "neon_vmls<mode>"
1846 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
1847 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0")
1848 (match_operand:VDQW 2 "s_register_operand" "w")
1849 (match_operand:VDQW 3 "s_register_operand" "w")
1850 (match_operand:SI 4 "immediate_operand" "i")]
1853 "vmls.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
1854 [(set (attr "neon_type")
1855 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
1856 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1857 (const_string "neon_fp_vmla_ddd")
1858 (const_string "neon_fp_vmla_qqq"))
1859 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1861 (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
1862 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
1863 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
1865 (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
1866 (const_string "neon_mla_qqq_8_16")
1867 (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
1870 (define_insn "neon_vmlsl<mode>"
1871 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1872 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
1873 (match_operand:VW 2 "s_register_operand" "w")
1874 (match_operand:VW 3 "s_register_operand" "w")
1875 (match_operand:SI 4 "immediate_operand" "i")]
1878 "vmlsl.%T4%#<V_sz_elem>\t%q0, %P2, %P3"
1879 [(set (attr "neon_type")
1880 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
1881 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
1882 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
1885 (define_insn "neon_vqdmulh<mode>"
1886 [(set (match_operand:VMDQI 0 "s_register_operand" "=w")
1887 (unspec:VMDQI [(match_operand:VMDQI 1 "s_register_operand" "w")
1888 (match_operand:VMDQI 2 "s_register_operand" "w")
1889 (match_operand:SI 3 "immediate_operand" "i")]
1892 "vq%O3dmulh.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1893 [(set (attr "neon_type")
1894 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1895 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
1896 (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
1897 (const_string "neon_mul_qqq_8_16_32_ddd_32"))
1898 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
1899 (const_string "neon_mul_qqq_8_16_32_ddd_32")
1900 (const_string "neon_mul_qqq_8_16_32_ddd_32"))))]
1903 (define_insn "neon_vqdmlal<mode>"
1904 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1905 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
1906 (match_operand:VMDI 2 "s_register_operand" "w")
1907 (match_operand:VMDI 3 "s_register_operand" "w")
1908 (match_operand:SI 4 "immediate_operand" "i")]
1911 "vqdmlal.<V_s_elem>\t%q0, %P2, %P3"
1912 [(set (attr "neon_type")
1913 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
1914 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
1915 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
1918 (define_insn "neon_vqdmlsl<mode>"
1919 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1920 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
1921 (match_operand:VMDI 2 "s_register_operand" "w")
1922 (match_operand:VMDI 3 "s_register_operand" "w")
1923 (match_operand:SI 4 "immediate_operand" "i")]
1926 "vqdmlsl.<V_s_elem>\t%q0, %P2, %P3"
1927 [(set (attr "neon_type")
1928 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
1929 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
1930 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
1933 (define_insn "neon_vmull<mode>"
1934 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1935 (unspec:<V_widen> [(match_operand:VW 1 "s_register_operand" "w")
1936 (match_operand:VW 2 "s_register_operand" "w")
1937 (match_operand:SI 3 "immediate_operand" "i")]
1940 "vmull.%T3%#<V_sz_elem>\t%q0, %P1, %P2"
1941 [(set (attr "neon_type")
1942 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
1943 (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
1944 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
1947 (define_insn "neon_vqdmull<mode>"
1948 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1949 (unspec:<V_widen> [(match_operand:VMDI 1 "s_register_operand" "w")
1950 (match_operand:VMDI 2 "s_register_operand" "w")
1951 (match_operand:SI 3 "immediate_operand" "i")]
1954 "vqdmull.<V_s_elem>\t%q0, %P1, %P2"
1955 [(set (attr "neon_type")
1956 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
1957 (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
1958 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
1961 (define_insn "neon_vsub<mode>"
1962 [(set (match_operand:VDQX 0 "s_register_operand" "=w")
1963 (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w")
1964 (match_operand:VDQX 2 "s_register_operand" "w")
1965 (match_operand:SI 3 "immediate_operand" "i")]
1968 "vsub.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
1969 [(set (attr "neon_type")
1970 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
1971 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
1972 (const_string "neon_fp_vadd_ddd_vabs_dd")
1973 (const_string "neon_fp_vadd_qqq_vabs_qq"))
1974 (const_string "neon_int_2")))]
1977 (define_insn "neon_vsubl<mode>"
1978 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1979 (unspec:<V_widen> [(match_operand:VDI 1 "s_register_operand" "w")
1980 (match_operand:VDI 2 "s_register_operand" "w")
1981 (match_operand:SI 3 "immediate_operand" "i")]
1984 "vsubl.%T3%#<V_sz_elem>\t%q0, %P1, %P2"
1985 [(set_attr "neon_type" "neon_int_2")]
1988 (define_insn "neon_vsubw<mode>"
1989 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
1990 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "w")
1991 (match_operand:VDI 2 "s_register_operand" "w")
1992 (match_operand:SI 3 "immediate_operand" "i")]
1995 "vsubw.%T3%#<V_sz_elem>\t%q0, %q1, %P2"
1996 [(set_attr "neon_type" "neon_int_2")]
1999 (define_insn "neon_vqsub<mode>"
2000 [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
2001 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
2002 (match_operand:VDQIX 2 "s_register_operand" "w")
2003 (match_operand:SI 3 "immediate_operand" "i")]
2006 "vqsub.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2007 [(set_attr "neon_type" "neon_int_5")]
2010 (define_insn "neon_vhsub<mode>"
2011 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2012 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2013 (match_operand:VDQIW 2 "s_register_operand" "w")
2014 (match_operand:SI 3 "immediate_operand" "i")]
2017 "vhsub.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2018 [(set_attr "neon_type" "neon_int_5")]
2021 (define_insn "neon_vsubhn<mode>"
2022 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
2023 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
2024 (match_operand:VN 2 "s_register_operand" "w")
2025 (match_operand:SI 3 "immediate_operand" "i")]
2028 "v%O3subhn.<V_if_elem>\t%P0, %q1, %q2"
2029 [(set_attr "neon_type" "neon_int_4")]
2032 (define_insn "neon_vceq<mode>"
2033 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
2034 (unspec:<V_cmp_result> [(match_operand:VDQW 1 "s_register_operand" "w")
2035 (match_operand:VDQW 2 "s_register_operand" "w")
2036 (match_operand:SI 3 "immediate_operand" "i")]
2039 "vceq.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2040 [(set (attr "neon_type")
2041 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
2042 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2043 (const_string "neon_fp_vadd_ddd_vabs_dd")
2044 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2045 (const_string "neon_int_5")))]
2048 (define_insn "neon_vcge<mode>"
2049 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
2050 (unspec:<V_cmp_result> [(match_operand:VDQW 1 "s_register_operand" "w")
2051 (match_operand:VDQW 2 "s_register_operand" "w")
2052 (match_operand:SI 3 "immediate_operand" "i")]
2055 "vcge.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2056 [(set (attr "neon_type")
2057 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
2058 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2059 (const_string "neon_fp_vadd_ddd_vabs_dd")
2060 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2061 (const_string "neon_int_5")))]
2064 (define_insn "neon_vcgt<mode>"
2065 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
2066 (unspec:<V_cmp_result> [(match_operand:VDQW 1 "s_register_operand" "w")
2067 (match_operand:VDQW 2 "s_register_operand" "w")
2068 (match_operand:SI 3 "immediate_operand" "i")]
2071 "vcgt.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2072 [(set (attr "neon_type")
2073 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
2074 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2075 (const_string "neon_fp_vadd_ddd_vabs_dd")
2076 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2077 (const_string "neon_int_5")))]
2080 (define_insn "neon_vcage<mode>"
2081 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
2082 (unspec:<V_cmp_result> [(match_operand:VCVTF 1 "s_register_operand" "w")
2083 (match_operand:VCVTF 2 "s_register_operand" "w")
2084 (match_operand:SI 3 "immediate_operand" "i")]
2087 "vacge.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2088 [(set (attr "neon_type")
2089 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2090 (const_string "neon_fp_vadd_ddd_vabs_dd")
2091 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2094 (define_insn "neon_vcagt<mode>"
2095 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
2096 (unspec:<V_cmp_result> [(match_operand:VCVTF 1 "s_register_operand" "w")
2097 (match_operand:VCVTF 2 "s_register_operand" "w")
2098 (match_operand:SI 3 "immediate_operand" "i")]
2101 "vacgt.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2102 [(set (attr "neon_type")
2103 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2104 (const_string "neon_fp_vadd_ddd_vabs_dd")
2105 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2108 (define_insn "neon_vtst<mode>"
2109 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2110 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2111 (match_operand:VDQIW 2 "s_register_operand" "w")
2112 (match_operand:SI 3 "immediate_operand" "i")]
2115 "vtst.<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2116 [(set_attr "neon_type" "neon_int_4")]
2119 (define_insn "neon_vabd<mode>"
2120 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
2121 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w")
2122 (match_operand:VDQW 2 "s_register_operand" "w")
2123 (match_operand:SI 3 "immediate_operand" "i")]
2126 "vabd.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2127 [(set (attr "neon_type")
2128 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
2129 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2130 (const_string "neon_fp_vadd_ddd_vabs_dd")
2131 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2132 (const_string "neon_int_5")))]
2135 (define_insn "neon_vabdl<mode>"
2136 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2137 (unspec:<V_widen> [(match_operand:VW 1 "s_register_operand" "w")
2138 (match_operand:VW 2 "s_register_operand" "w")
2139 (match_operand:SI 3 "immediate_operand" "i")]
2142 "vabdl.%T3%#<V_sz_elem>\t%q0, %P1, %P2"
2143 [(set_attr "neon_type" "neon_int_5")]
2146 (define_insn "neon_vaba<mode>"
2147 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2148 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "0")
2149 (match_operand:VDQIW 2 "s_register_operand" "w")
2150 (match_operand:VDQIW 3 "s_register_operand" "w")
2151 (match_operand:SI 4 "immediate_operand" "i")]
2154 "vaba.%T4%#<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
2155 [(set (attr "neon_type")
2156 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2157 (const_string "neon_vaba") (const_string "neon_vaba_qqq")))]
2160 (define_insn "neon_vabal<mode>"
2161 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2162 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
2163 (match_operand:VW 2 "s_register_operand" "w")
2164 (match_operand:VW 3 "s_register_operand" "w")
2165 (match_operand:SI 4 "immediate_operand" "i")]
2168 "vabal.%T4%#<V_sz_elem>\t%q0, %P2, %P3"
2169 [(set_attr "neon_type" "neon_vaba")]
2172 (define_insn "neon_vmax<mode>"
2173 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
2174 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w")
2175 (match_operand:VDQW 2 "s_register_operand" "w")
2176 (match_operand:SI 3 "immediate_operand" "i")]
2179 "vmax.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2180 [(set (attr "neon_type")
2181 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
2182 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2183 (const_string "neon_fp_vadd_ddd_vabs_dd")
2184 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2185 (const_string "neon_int_5")))]
2188 (define_insn "neon_vmin<mode>"
2189 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
2190 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w")
2191 (match_operand:VDQW 2 "s_register_operand" "w")
2192 (match_operand:SI 3 "immediate_operand" "i")]
2195 "vmin.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2196 [(set (attr "neon_type")
2197 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
2198 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2199 (const_string "neon_fp_vadd_ddd_vabs_dd")
2200 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2201 (const_string "neon_int_5")))]
2204 (define_expand "neon_vpadd<mode>"
2205 [(match_operand:VD 0 "s_register_operand" "=w")
2206 (match_operand:VD 1 "s_register_operand" "w")
2207 (match_operand:VD 2 "s_register_operand" "w")
2208 (match_operand:SI 3 "immediate_operand" "i")]
2211 emit_insn (gen_neon_vpadd_internal<mode> (operands[0], operands[1],
2216 (define_insn "neon_vpaddl<mode>"
2217 [(set (match_operand:<V_double_width> 0 "s_register_operand" "=w")
2218 (unspec:<V_double_width> [(match_operand:VDQIW 1 "s_register_operand" "w")
2219 (match_operand:SI 2 "immediate_operand" "i")]
2222 "vpaddl.%T2%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
2223 ;; Assume this schedules like vaddl.
2224 [(set_attr "neon_type" "neon_int_3")]
2227 (define_insn "neon_vpadal<mode>"
2228 [(set (match_operand:<V_double_width> 0 "s_register_operand" "=w")
2229 (unspec:<V_double_width> [(match_operand:<V_double_width> 1 "s_register_operand" "0")
2230 (match_operand:VDQIW 2 "s_register_operand" "w")
2231 (match_operand:SI 3 "immediate_operand" "i")]
2234 "vpadal.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>2"
2235 ;; Assume this schedules like vpadd.
2236 [(set_attr "neon_type" "neon_int_1")]
2239 (define_insn "neon_vpmax<mode>"
2240 [(set (match_operand:VD 0 "s_register_operand" "=w")
2241 (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
2242 (match_operand:VD 2 "s_register_operand" "w")
2243 (match_operand:SI 3 "immediate_operand" "i")]
2246 "vpmax.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2247 ;; Assume this schedules like vmax.
2248 [(set (attr "neon_type")
2249 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
2250 (const_string "neon_fp_vadd_ddd_vabs_dd")
2251 (const_string "neon_int_5")))]
2254 (define_insn "neon_vpmin<mode>"
2255 [(set (match_operand:VD 0 "s_register_operand" "=w")
2256 (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
2257 (match_operand:VD 2 "s_register_operand" "w")
2258 (match_operand:SI 3 "immediate_operand" "i")]
2261 "vpmin.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2262 ;; Assume this schedules like vmin.
2263 [(set (attr "neon_type")
2264 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
2265 (const_string "neon_fp_vadd_ddd_vabs_dd")
2266 (const_string "neon_int_5")))]
2269 (define_insn "neon_vrecps<mode>"
2270 [(set (match_operand:VCVTF 0 "s_register_operand" "=w")
2271 (unspec:VCVTF [(match_operand:VCVTF 1 "s_register_operand" "w")
2272 (match_operand:VCVTF 2 "s_register_operand" "w")
2273 (match_operand:SI 3 "immediate_operand" "i")]
2276 "vrecps.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2277 [(set (attr "neon_type")
2278 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2279 (const_string "neon_fp_vrecps_vrsqrts_ddd")
2280 (const_string "neon_fp_vrecps_vrsqrts_qqq")))]
2283 (define_insn "neon_vrsqrts<mode>"
2284 [(set (match_operand:VCVTF 0 "s_register_operand" "=w")
2285 (unspec:VCVTF [(match_operand:VCVTF 1 "s_register_operand" "w")
2286 (match_operand:VCVTF 2 "s_register_operand" "w")
2287 (match_operand:SI 3 "immediate_operand" "i")]
2290 "vrsqrts.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
2291 [(set (attr "neon_type")
2292 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2293 (const_string "neon_fp_vrecps_vrsqrts_ddd")
2294 (const_string "neon_fp_vrecps_vrsqrts_qqq")))]
2297 (define_insn "neon_vabs<mode>"
2298 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
2299 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w")
2300 (match_operand:SI 2 "immediate_operand" "i")]
2303 "vabs.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
2304 [(set (attr "neon_type")
2305 (if_then_else (ior (ne (symbol_ref "<Is_float_mode>") (const_int 0))
2306 (ne (symbol_ref "<Is_float_mode>") (const_int 0)))
2308 (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2309 (const_string "neon_fp_vadd_ddd_vabs_dd")
2310 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2311 (const_string "neon_vqneg_vqabs")))]
2314 (define_insn "neon_vqabs<mode>"
2315 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2316 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2317 (match_operand:SI 2 "immediate_operand" "i")]
2320 "vqabs.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
2321 [(set_attr "neon_type" "neon_vqneg_vqabs")]
2324 (define_expand "neon_vneg<mode>"
2325 [(match_operand:VDQW 0 "s_register_operand" "")
2326 (match_operand:VDQW 1 "s_register_operand" "")
2327 (match_operand:SI 2 "immediate_operand" "")]
2330 emit_insn (gen_neg<mode>2 (operands[0], operands[1]));
2334 (define_insn "neon_vqneg<mode>"
2335 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2336 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2337 (match_operand:SI 2 "immediate_operand" "i")]
2340 "vqneg.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
2341 [(set_attr "neon_type" "neon_vqneg_vqabs")]
2344 (define_insn "neon_vcls<mode>"
2345 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2346 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2347 (match_operand:SI 2 "immediate_operand" "i")]
2350 "vcls.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
2351 [(set_attr "neon_type" "neon_int_1")]
2354 (define_insn "neon_vclz<mode>"
2355 [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2356 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2357 (match_operand:SI 2 "immediate_operand" "i")]
2360 "vclz.<V_if_elem>\t%<V_reg>0, %<V_reg>1"
2361 [(set_attr "neon_type" "neon_int_1")]
2364 (define_insn "neon_vcnt<mode>"
2365 [(set (match_operand:VE 0 "s_register_operand" "=w")
2366 (unspec:VE [(match_operand:VE 1 "s_register_operand" "w")
2367 (match_operand:SI 2 "immediate_operand" "i")]
2370 "vcnt.<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
2371 [(set_attr "neon_type" "neon_int_1")]
2374 (define_insn "neon_vrecpe<mode>"
2375 [(set (match_operand:V32 0 "s_register_operand" "=w")
2376 (unspec:V32 [(match_operand:V32 1 "s_register_operand" "w")
2377 (match_operand:SI 2 "immediate_operand" "i")]
2380 "vrecpe.<V_u_elem>\t%<V_reg>0, %<V_reg>1"
2381 [(set (attr "neon_type")
2382 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2383 (const_string "neon_fp_vadd_ddd_vabs_dd")
2384 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2387 (define_insn "neon_vrsqrte<mode>"
2388 [(set (match_operand:V32 0 "s_register_operand" "=w")
2389 (unspec:V32 [(match_operand:V32 1 "s_register_operand" "w")
2390 (match_operand:SI 2 "immediate_operand" "i")]
2393 "vrsqrte.<V_u_elem>\t%<V_reg>0, %<V_reg>1"
2394 [(set (attr "neon_type")
2395 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2396 (const_string "neon_fp_vadd_ddd_vabs_dd")
2397 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2400 (define_expand "neon_vmvn<mode>"
2401 [(match_operand:VDQIW 0 "s_register_operand" "")
2402 (match_operand:VDQIW 1 "s_register_operand" "")
2403 (match_operand:SI 2 "immediate_operand" "")]
2406 emit_insn (gen_one_cmpl<mode>2 (operands[0], operands[1]));
2410 (define_insn "neon_vget_lane<mode>_sext_internal"
2411 [(set (match_operand:SI 0 "s_register_operand" "=r")
2413 (vec_select:<V_elem>
2414 (match_operand:VD 1 "s_register_operand" "w")
2415 (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2417 "vmov%?.s<V_sz_elem>\t%0, %P1[%c2]"
2418 [(set_attr "predicable" "yes")
2419 (set_attr "neon_type" "neon_bp_simple")]
2422 (define_insn "neon_vget_lane<mode>_zext_internal"
2423 [(set (match_operand:SI 0 "s_register_operand" "=r")
2425 (vec_select:<V_elem>
2426 (match_operand:VD 1 "s_register_operand" "w")
2427 (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2429 "vmov%?.u<V_sz_elem>\t%0, %P1[%c2]"
2430 [(set_attr "predicable" "yes")
2431 (set_attr "neon_type" "neon_bp_simple")]
2434 (define_insn "neon_vget_lane<mode>_sext_internal"
2435 [(set (match_operand:SI 0 "s_register_operand" "=r")
2437 (vec_select:<V_elem>
2438 (match_operand:VQ 1 "s_register_operand" "w")
2439 (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2443 int regno = REGNO (operands[1]);
2444 unsigned int halfelts = GET_MODE_NUNITS (<MODE>mode) / 2;
2445 unsigned int elt = INTVAL (operands[2]);
2447 ops[0] = operands[0];
2448 ops[1] = gen_rtx_REG (<V_HALF>mode, regno + 2 * (elt / halfelts));
2449 ops[2] = GEN_INT (elt % halfelts);
2450 output_asm_insn ("vmov%?.s<V_sz_elem>\t%0, %P1[%c2]", ops);
2454 [(set_attr "predicable" "yes")
2455 (set_attr "neon_type" "neon_bp_simple")]
2458 (define_insn "neon_vget_lane<mode>_zext_internal"
2459 [(set (match_operand:SI 0 "s_register_operand" "=r")
2461 (vec_select:<V_elem>
2462 (match_operand:VQ 1 "s_register_operand" "w")
2463 (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2467 int regno = REGNO (operands[1]);
2468 unsigned int halfelts = GET_MODE_NUNITS (<MODE>mode) / 2;
2469 unsigned int elt = INTVAL (operands[2]);
2471 ops[0] = operands[0];
2472 ops[1] = gen_rtx_REG (<V_HALF>mode, regno + 2 * (elt / halfelts));
2473 ops[2] = GEN_INT (elt % halfelts);
2474 output_asm_insn ("vmov%?.u<V_sz_elem>\t%0, %P1[%c2]", ops);
2478 [(set_attr "predicable" "yes")
2479 (set_attr "neon_type" "neon_bp_simple")]
2482 (define_expand "neon_vget_lane<mode>"
2483 [(match_operand:<V_ext> 0 "s_register_operand" "")
2484 (match_operand:VDQW 1 "s_register_operand" "")
2485 (match_operand:SI 2 "immediate_operand" "")
2486 (match_operand:SI 3 "immediate_operand" "")]
2489 HOST_WIDE_INT magic = INTVAL (operands[3]);
2492 neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<MODE>mode));
2494 if ((magic & 3) == 3 || GET_MODE_BITSIZE (GET_MODE_INNER (<MODE>mode)) == 32)
2495 insn = gen_vec_extract<mode> (operands[0], operands[1], operands[2]);
2498 if ((magic & 1) != 0)
2499 insn = gen_neon_vget_lane<mode>_sext_internal (operands[0], operands[1],
2502 insn = gen_neon_vget_lane<mode>_zext_internal (operands[0], operands[1],
2509 ; Operand 3 (info word) is ignored because it does nothing useful with 64-bit
2512 (define_insn "neon_vget_lanedi"
2513 [(set (match_operand:DI 0 "s_register_operand" "=r")
2514 (unspec:DI [(match_operand:DI 1 "s_register_operand" "w")
2515 (match_operand:SI 2 "immediate_operand" "i")
2516 (match_operand:SI 3 "immediate_operand" "i")]
2520 neon_lane_bounds (operands[2], 0, 1);
2521 return "vmov%?\t%Q0, %R0, %P1 @ di";
2523 [(set_attr "predicable" "yes")
2524 (set_attr "neon_type" "neon_bp_simple")]
2527 (define_insn "neon_vget_lanev2di"
2528 [(set (match_operand:DI 0 "s_register_operand" "=r")
2529 (unspec:DI [(match_operand:V2DI 1 "s_register_operand" "w")
2530 (match_operand:SI 2 "immediate_operand" "i")
2531 (match_operand:SI 3 "immediate_operand" "i")]
2536 unsigned int regno = REGNO (operands[1]);
2537 unsigned int elt = INTVAL (operands[2]);
2539 neon_lane_bounds (operands[2], 0, 2);
2541 ops[0] = operands[0];
2542 ops[1] = gen_rtx_REG (DImode, regno + 2 * elt);
2543 output_asm_insn ("vmov%?\t%Q0, %R0, %P1 @ v2di", ops);
2547 [(set_attr "predicable" "yes")
2548 (set_attr "neon_type" "neon_bp_simple")]
2551 (define_insn "neon_vset_lane<mode>"
2552 [(set (match_operand:VD 0 "s_register_operand" "=w")
2553 (unspec:VD [(match_operand:<V_elem> 1 "s_register_operand" "r")
2554 (match_operand:VD 2 "s_register_operand" "0")
2555 (match_operand:SI 3 "immediate_operand" "i")]
2559 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
2560 return "vmov%?.<V_sz_elem>\t%P0[%c3], %1";
2562 [(set_attr "predicable" "yes")
2563 (set_attr "neon_type" "neon_bp_simple")]
2566 ; See neon_vget_lanedi comment for reasons operands 2 & 3 are ignored.
2568 (define_insn "neon_vset_lanedi"
2569 [(set (match_operand:DI 0 "s_register_operand" "=w")
2570 (unspec:DI [(match_operand:DI 1 "s_register_operand" "r")
2571 (match_operand:DI 2 "s_register_operand" "0")
2572 (match_operand:SI 3 "immediate_operand" "i")]
2576 neon_lane_bounds (operands[3], 0, 1);
2577 return "vmov%?\t%P0, %Q1, %R1 @ di";
2579 [(set_attr "predicable" "yes")
2580 (set_attr "neon_type" "neon_bp_simple")]
2583 (define_insn "neon_vset_lane<mode>"
2584 [(set (match_operand:VQ 0 "s_register_operand" "=w")
2585 (unspec:VQ [(match_operand:<V_elem> 1 "s_register_operand" "r")
2586 (match_operand:VQ 2 "s_register_operand" "0")
2587 (match_operand:SI 3 "immediate_operand" "i")]
2592 unsigned int regno = REGNO (operands[0]);
2593 unsigned int halfelts = GET_MODE_NUNITS (<MODE>mode) / 2;
2594 unsigned int elt = INTVAL (operands[3]);
2596 neon_lane_bounds (operands[3], 0, halfelts * 2);
2598 ops[0] = gen_rtx_REG (<V_HALF>mode, regno + 2 * (elt / halfelts));
2599 ops[1] = operands[1];
2600 ops[2] = GEN_INT (elt % halfelts);
2601 output_asm_insn ("vmov%?.<V_sz_elem>\t%P0[%c2], %1", ops);
2605 [(set_attr "predicable" "yes")
2606 (set_attr "neon_type" "neon_bp_simple")]
2609 (define_insn "neon_vset_lanev2di"
2610 [(set (match_operand:V2DI 0 "s_register_operand" "=w")
2611 (unspec:V2DI [(match_operand:DI 1 "s_register_operand" "r")
2612 (match_operand:V2DI 2 "s_register_operand" "0")
2613 (match_operand:SI 3 "immediate_operand" "i")]
2618 unsigned int regno = REGNO (operands[0]);
2619 unsigned int elt = INTVAL (operands[3]);
2621 neon_lane_bounds (operands[3], 0, 2);
2623 ops[0] = gen_rtx_REG (DImode, regno + 2 * elt);
2624 ops[1] = operands[1];
2625 output_asm_insn ("vmov%?\t%P0, %Q1, %R1 @ v2di", ops);
2629 [(set_attr "predicable" "yes")
2630 (set_attr "neon_type" "neon_bp_simple")]
2633 (define_expand "neon_vcreate<mode>"
2634 [(match_operand:VDX 0 "s_register_operand" "")
2635 (match_operand:DI 1 "general_operand" "")]
2638 rtx src = gen_lowpart (<MODE>mode, operands[1]);
2639 emit_move_insn (operands[0], src);
2643 (define_insn "neon_vdup_n<mode>"
2644 [(set (match_operand:VDQW 0 "s_register_operand" "=w")
2645 (unspec:VDQW [(match_operand:<V_elem> 1 "s_register_operand" "r")]
2648 "vdup%?.<V_sz_elem>\t%<V_reg>0, %1"
2649 ;; Assume this schedules like vmov.
2650 [(set_attr "predicable" "yes")
2651 (set_attr "neon_type" "neon_bp_simple")]
2654 (define_insn "neon_vdup_ndi"
2655 [(set (match_operand:DI 0 "s_register_operand" "=w")
2656 (unspec:DI [(match_operand:DI 1 "s_register_operand" "r")]
2659 "vmov%?\t%P0, %Q1, %R1"
2660 [(set_attr "predicable" "yes")
2661 (set_attr "neon_type" "neon_bp_simple")]
2664 (define_insn "neon_vdup_nv2di"
2665 [(set (match_operand:V2DI 0 "s_register_operand" "=w")
2666 (unspec:V2DI [(match_operand:DI 1 "s_register_operand" "r")]
2669 "vmov%?\t%e0, %Q1, %R1\;vmov%?\t%f0, %Q1, %R1"
2670 [(set_attr "predicable" "yes")
2671 (set_attr "length" "8")
2672 (set_attr "neon_type" "neon_bp_simple")]
2675 (define_insn "neon_vdup_lane<mode>"
2676 [(set (match_operand:VD 0 "s_register_operand" "=w")
2677 (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
2678 (match_operand:SI 2 "immediate_operand" "i")]
2682 neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<MODE>mode));
2683 return "vdup.<V_sz_elem>\t%P0, %P1[%c2]";
2685 ;; Assume this schedules like vmov.
2686 [(set_attr "neon_type" "neon_bp_simple")]
2689 (define_insn "neon_vdup_lane<mode>"
2690 [(set (match_operand:VQ 0 "s_register_operand" "=w")
2691 (unspec:VQ [(match_operand:<V_HALF> 1 "s_register_operand" "w")
2692 (match_operand:SI 2 "immediate_operand" "i")]
2696 neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<V_HALF>mode));
2697 return "vdup.<V_sz_elem>\t%q0, %P1[%c2]";
2699 ;; Assume this schedules like vmov.
2700 [(set_attr "neon_type" "neon_bp_simple")]
2703 ; Scalar index is ignored, since only zero is valid here.
2704 (define_expand "neon_vdup_lanedi"
2705 [(set (match_operand:DI 0 "s_register_operand" "=w")
2706 (unspec:DI [(match_operand:DI 1 "s_register_operand" "w")
2707 (match_operand:SI 2 "immediate_operand" "i")]
2711 neon_lane_bounds (operands[2], 0, 1);
2712 emit_move_insn (operands[0], operands[1]);
2717 (define_insn "neon_vdup_lanev2di"
2718 [(set (match_operand:V2DI 0 "s_register_operand" "=w")
2719 (unspec:V2DI [(match_operand:DI 1 "s_register_operand" "w")
2720 (match_operand:SI 2 "immediate_operand" "i")]
2724 neon_lane_bounds (operands[2], 0, 1);
2725 return "vmov\t%e0, %P1\;vmov\t%f0, %P1";
2727 [(set_attr "length" "8")
2728 (set_attr "neon_type" "neon_bp_simple")]
2731 ;; In this insn, operand 1 should be low, and operand 2 the high part of the
2733 ;; FIXME: A different implementation of this builtin could make it much
2734 ;; more likely that we wouldn't actually need to output anything (we could make
2735 ;; it so that the reg allocator puts things in the right places magically
2736 ;; instead). Lack of subregs for vectors makes that tricky though, I think.
2738 (define_insn "neon_vcombine<mode>"
2739 [(set (match_operand:<V_DOUBLE> 0 "s_register_operand" "=w")
2740 (unspec:<V_DOUBLE> [(match_operand:VDX 1 "s_register_operand" "w")
2741 (match_operand:VDX 2 "s_register_operand" "w")]
2745 int dest = REGNO (operands[0]);
2746 int src1 = REGNO (operands[1]);
2747 int src2 = REGNO (operands[2]);
2750 if (src1 == dest && src2 == dest + 2)
2752 else if (src2 == dest && src1 == dest + 2)
2753 /* Special case of reversed high/low parts. */
2754 return "vswp\t%P1, %P2";
2756 destlo = gen_rtx_REG (<MODE>mode, dest);
2758 if (!reg_overlap_mentioned_p (operands[2], destlo))
2760 /* Try to avoid unnecessary moves if part of the result is in the right
2763 output_asm_insn ("vmov\t%e0, %P1", operands);
2764 if (src2 != dest + 2)
2765 output_asm_insn ("vmov\t%f0, %P2", operands);
2769 if (src2 != dest + 2)
2770 output_asm_insn ("vmov\t%f0, %P2", operands);
2772 output_asm_insn ("vmov\t%e0, %P1", operands);
2777 ;; We set the neon_type attribute based on the vmov instructions above.
2778 [(set_attr "length" "8")
2779 (set_attr "neon_type" "neon_bp_simple")]
2782 (define_insn "neon_vget_high<mode>"
2783 [(set (match_operand:<V_HALF> 0 "s_register_operand" "=w")
2784 (unspec:<V_HALF> [(match_operand:VQX 1 "s_register_operand" "w")]
2788 int dest = REGNO (operands[0]);
2789 int src = REGNO (operands[1]);
2791 if (dest != src + 2)
2792 return "vmov\t%P0, %f1";
2796 [(set_attr "neon_type" "neon_bp_simple")]
2799 (define_insn "neon_vget_low<mode>"
2800 [(set (match_operand:<V_HALF> 0 "s_register_operand" "=w")
2801 (unspec:<V_HALF> [(match_operand:VQX 1 "s_register_operand" "w")]
2805 int dest = REGNO (operands[0]);
2806 int src = REGNO (operands[1]);
2809 return "vmov\t%P0, %e1";
2813 [(set_attr "neon_type" "neon_bp_simple")]
2816 (define_insn "neon_vcvt<mode>"
2817 [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
2818 (unspec:<V_CVTTO> [(match_operand:VCVTF 1 "s_register_operand" "w")
2819 (match_operand:SI 2 "immediate_operand" "i")]
2822 "vcvt.%T2%#32.f32\t%<V_reg>0, %<V_reg>1"
2823 [(set (attr "neon_type")
2824 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2825 (const_string "neon_fp_vadd_ddd_vabs_dd")
2826 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2829 (define_insn "neon_vcvt<mode>"
2830 [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
2831 (unspec:<V_CVTTO> [(match_operand:VCVTI 1 "s_register_operand" "w")
2832 (match_operand:SI 2 "immediate_operand" "i")]
2835 "vcvt.f32.%T2%#32\t%<V_reg>0, %<V_reg>1"
2836 [(set (attr "neon_type")
2837 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2838 (const_string "neon_fp_vadd_ddd_vabs_dd")
2839 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2842 (define_insn "neon_vcvt_n<mode>"
2843 [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
2844 (unspec:<V_CVTTO> [(match_operand:VCVTF 1 "s_register_operand" "w")
2845 (match_operand:SI 2 "immediate_operand" "i")
2846 (match_operand:SI 3 "immediate_operand" "i")]
2850 neon_const_bounds (operands[2], 1, 33);
2851 return "vcvt.%T3%#32.f32\t%<V_reg>0, %<V_reg>1, %2";
2853 [(set (attr "neon_type")
2854 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2855 (const_string "neon_fp_vadd_ddd_vabs_dd")
2856 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2859 (define_insn "neon_vcvt_n<mode>"
2860 [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w")
2861 (unspec:<V_CVTTO> [(match_operand:VCVTI 1 "s_register_operand" "w")
2862 (match_operand:SI 2 "immediate_operand" "i")
2863 (match_operand:SI 3 "immediate_operand" "i")]
2867 neon_const_bounds (operands[2], 1, 33);
2868 return "vcvt.f32.%T3%#32\t%<V_reg>0, %<V_reg>1, %2";
2870 [(set (attr "neon_type")
2871 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
2872 (const_string "neon_fp_vadd_ddd_vabs_dd")
2873 (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2876 (define_insn "neon_vmovn<mode>"
2877 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
2878 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
2879 (match_operand:SI 2 "immediate_operand" "i")]
2882 "vmovn.<V_if_elem>\t%P0, %q1"
2883 [(set_attr "neon_type" "neon_bp_simple")]
2886 (define_insn "neon_vqmovn<mode>"
2887 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
2888 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
2889 (match_operand:SI 2 "immediate_operand" "i")]
2892 "vqmovn.%T2%#<V_sz_elem>\t%P0, %q1"
2893 [(set_attr "neon_type" "neon_shift_2")]
2896 (define_insn "neon_vqmovun<mode>"
2897 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w")
2898 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w")
2899 (match_operand:SI 2 "immediate_operand" "i")]
2902 "vqmovun.<V_s_elem>\t%P0, %q1"
2903 [(set_attr "neon_type" "neon_shift_2")]
2906 (define_insn "neon_vmovl<mode>"
2907 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2908 (unspec:<V_widen> [(match_operand:VW 1 "s_register_operand" "w")
2909 (match_operand:SI 2 "immediate_operand" "i")]
2912 "vmovl.%T2%#<V_sz_elem>\t%q0, %P1"
2913 [(set_attr "neon_type" "neon_shift_1")]
2916 (define_insn "neon_vmul_lane<mode>"
2917 [(set (match_operand:VMD 0 "s_register_operand" "=w")
2918 (unspec:VMD [(match_operand:VMD 1 "s_register_operand" "w")
2919 (match_operand:VMD 2 "s_register_operand"
2920 "<scalar_mul_constraint>")
2921 (match_operand:SI 3 "immediate_operand" "i")
2922 (match_operand:SI 4 "immediate_operand" "i")]
2926 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
2927 return "vmul.<V_if_elem>\t%P0, %P1, %P2[%c3]";
2929 [(set (attr "neon_type")
2930 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
2931 (const_string "neon_fp_vmul_ddd")
2932 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
2933 (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
2934 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar"))))]
2937 (define_insn "neon_vmul_lane<mode>"
2938 [(set (match_operand:VMQ 0 "s_register_operand" "=w")
2939 (unspec:VMQ [(match_operand:VMQ 1 "s_register_operand" "w")
2940 (match_operand:<V_HALF> 2 "s_register_operand"
2941 "<scalar_mul_constraint>")
2942 (match_operand:SI 3 "immediate_operand" "i")
2943 (match_operand:SI 4 "immediate_operand" "i")]
2947 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<V_HALF>mode));
2948 return "vmul.<V_if_elem>\t%q0, %q1, %P2[%c3]";
2950 [(set (attr "neon_type")
2951 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
2952 (const_string "neon_fp_vmul_qqd")
2953 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
2954 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")
2955 (const_string "neon_mul_qqd_32_scalar"))))]
2958 (define_insn "neon_vmull_lane<mode>"
2959 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2960 (unspec:<V_widen> [(match_operand:VMDI 1 "s_register_operand" "w")
2961 (match_operand:VMDI 2 "s_register_operand"
2962 "<scalar_mul_constraint>")
2963 (match_operand:SI 3 "immediate_operand" "i")
2964 (match_operand:SI 4 "immediate_operand" "i")]
2965 UNSPEC_VMULL_LANE))]
2968 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
2969 return "vmull.%T4%#<V_sz_elem>\t%q0, %P1, %P2[%c3]";
2971 [(set (attr "neon_type")
2972 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
2973 (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
2974 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
2977 (define_insn "neon_vqdmull_lane<mode>"
2978 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
2979 (unspec:<V_widen> [(match_operand:VMDI 1 "s_register_operand" "w")
2980 (match_operand:VMDI 2 "s_register_operand"
2981 "<scalar_mul_constraint>")
2982 (match_operand:SI 3 "immediate_operand" "i")
2983 (match_operand:SI 4 "immediate_operand" "i")]
2984 UNSPEC_VQDMULL_LANE))]
2987 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
2988 return "vqdmull.<V_s_elem>\t%q0, %P1, %P2[%c3]";
2990 [(set (attr "neon_type")
2991 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
2992 (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
2993 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
2996 (define_insn "neon_vqdmulh_lane<mode>"
2997 [(set (match_operand:VMQI 0 "s_register_operand" "=w")
2998 (unspec:VMQI [(match_operand:VMQI 1 "s_register_operand" "w")
2999 (match_operand:<V_HALF> 2 "s_register_operand"
3000 "<scalar_mul_constraint>")
3001 (match_operand:SI 3 "immediate_operand" "i")
3002 (match_operand:SI 4 "immediate_operand" "i")]
3003 UNSPEC_VQDMULH_LANE))]
3006 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
3007 return "vq%O4dmulh.%T4%#<V_sz_elem>\t%q0, %q1, %P2[%c3]";
3009 [(set (attr "neon_type")
3010 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
3011 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")
3012 (const_string "neon_mul_qqd_32_scalar")))]
3015 (define_insn "neon_vqdmulh_lane<mode>"
3016 [(set (match_operand:VMDI 0 "s_register_operand" "=w")
3017 (unspec:VMDI [(match_operand:VMDI 1 "s_register_operand" "w")
3018 (match_operand:VMDI 2 "s_register_operand"
3019 "<scalar_mul_constraint>")
3020 (match_operand:SI 3 "immediate_operand" "i")
3021 (match_operand:SI 4 "immediate_operand" "i")]
3022 UNSPEC_VQDMULH_LANE))]
3025 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
3026 return "vq%O4dmulh.%T4%#<V_sz_elem>\t%P0, %P1, %P2[%c3]";
3028 [(set (attr "neon_type")
3029 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
3030 (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
3031 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
3034 (define_insn "neon_vmla_lane<mode>"
3035 [(set (match_operand:VMD 0 "s_register_operand" "=w")
3036 (unspec:VMD [(match_operand:VMD 1 "s_register_operand" "0")
3037 (match_operand:VMD 2 "s_register_operand" "w")
3038 (match_operand:VMD 3 "s_register_operand"
3039 "<scalar_mul_constraint>")
3040 (match_operand:SI 4 "immediate_operand" "i")
3041 (match_operand:SI 5 "immediate_operand" "i")]
3045 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3046 return "vmla.<V_if_elem>\t%P0, %P2, %P3[%c4]";
3048 [(set (attr "neon_type")
3049 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
3050 (const_string "neon_fp_vmla_ddd_scalar")
3051 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
3052 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3053 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))))]
3056 (define_insn "neon_vmla_lane<mode>"
3057 [(set (match_operand:VMQ 0 "s_register_operand" "=w")
3058 (unspec:VMQ [(match_operand:VMQ 1 "s_register_operand" "0")
3059 (match_operand:VMQ 2 "s_register_operand" "w")
3060 (match_operand:<V_HALF> 3 "s_register_operand"
3061 "<scalar_mul_constraint>")
3062 (match_operand:SI 4 "immediate_operand" "i")
3063 (match_operand:SI 5 "immediate_operand" "i")]
3067 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3068 return "vmla.<V_if_elem>\t%q0, %q2, %P3[%c4]";
3070 [(set (attr "neon_type")
3071 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
3072 (const_string "neon_fp_vmla_qqq_scalar")
3073 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
3074 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")
3075 (const_string "neon_mla_qqq_32_qqd_32_scalar"))))]
3078 (define_insn "neon_vmlal_lane<mode>"
3079 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3080 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
3081 (match_operand:VMDI 2 "s_register_operand" "w")
3082 (match_operand:VMDI 3 "s_register_operand"
3083 "<scalar_mul_constraint>")
3084 (match_operand:SI 4 "immediate_operand" "i")
3085 (match_operand:SI 5 "immediate_operand" "i")]
3086 UNSPEC_VMLAL_LANE))]
3089 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3090 return "vmlal.%T5%#<V_sz_elem>\t%q0, %P2, %P3[%c4]";
3092 [(set (attr "neon_type")
3093 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
3094 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3095 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
3098 (define_insn "neon_vqdmlal_lane<mode>"
3099 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3100 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
3101 (match_operand:VMDI 2 "s_register_operand" "w")
3102 (match_operand:VMDI 3 "s_register_operand"
3103 "<scalar_mul_constraint>")
3104 (match_operand:SI 4 "immediate_operand" "i")
3105 (match_operand:SI 5 "immediate_operand" "i")]
3106 UNSPEC_VQDMLAL_LANE))]
3109 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3110 return "vqdmlal.<V_s_elem>\t%q0, %P2, %P3[%c4]";
3112 [(set (attr "neon_type")
3113 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
3114 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3115 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
3118 (define_insn "neon_vmls_lane<mode>"
3119 [(set (match_operand:VMD 0 "s_register_operand" "=w")
3120 (unspec:VMD [(match_operand:VMD 1 "s_register_operand" "0")
3121 (match_operand:VMD 2 "s_register_operand" "w")
3122 (match_operand:VMD 3 "s_register_operand"
3123 "<scalar_mul_constraint>")
3124 (match_operand:SI 4 "immediate_operand" "i")
3125 (match_operand:SI 5 "immediate_operand" "i")]
3129 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3130 return "vmls.<V_if_elem>\t%P0, %P2, %P3[%c4]";
3132 [(set (attr "neon_type")
3133 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
3134 (const_string "neon_fp_vmla_ddd_scalar")
3135 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
3136 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3137 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))))]
3140 (define_insn "neon_vmls_lane<mode>"
3141 [(set (match_operand:VMQ 0 "s_register_operand" "=w")
3142 (unspec:VMQ [(match_operand:VMQ 1 "s_register_operand" "0")
3143 (match_operand:VMQ 2 "s_register_operand" "w")
3144 (match_operand:<V_HALF> 3 "s_register_operand"
3145 "<scalar_mul_constraint>")
3146 (match_operand:SI 4 "immediate_operand" "i")
3147 (match_operand:SI 5 "immediate_operand" "i")]
3151 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3152 return "vmls.<V_if_elem>\t%q0, %q2, %P3[%c4]";
3154 [(set (attr "neon_type")
3155 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
3156 (const_string "neon_fp_vmla_qqq_scalar")
3157 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
3158 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")
3159 (const_string "neon_mla_qqq_32_qqd_32_scalar"))))]
3162 (define_insn "neon_vmlsl_lane<mode>"
3163 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3164 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
3165 (match_operand:VMDI 2 "s_register_operand" "w")
3166 (match_operand:VMDI 3 "s_register_operand"
3167 "<scalar_mul_constraint>")
3168 (match_operand:SI 4 "immediate_operand" "i")
3169 (match_operand:SI 5 "immediate_operand" "i")]
3170 UNSPEC_VMLSL_LANE))]
3173 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3174 return "vmlsl.%T5%#<V_sz_elem>\t%q0, %P2, %P3[%c4]";
3176 [(set (attr "neon_type")
3177 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
3178 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3179 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
3182 (define_insn "neon_vqdmlsl_lane<mode>"
3183 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
3184 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
3185 (match_operand:VMDI 2 "s_register_operand" "w")
3186 (match_operand:VMDI 3 "s_register_operand"
3187 "<scalar_mul_constraint>")
3188 (match_operand:SI 4 "immediate_operand" "i")
3189 (match_operand:SI 5 "immediate_operand" "i")]
3190 UNSPEC_VQDMLSL_LANE))]
3193 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
3194 return "vqdmlsl.<V_s_elem>\t%q0, %P2, %P3[%c4]";
3196 [(set (attr "neon_type")
3197 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
3198 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3199 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
3202 ; FIXME: For the "_n" multiply/multiply-accumulate insns, we copy a value in a
3203 ; core register into a temp register, then use a scalar taken from that. This
3204 ; isn't an optimal solution if e.g. the scalar has just been read from memory
3205 ; or extracted from another vector. The latter case it's currently better to
3206 ; use the "_lane" variant, and the former case can probably be implemented
3207 ; using vld1_lane, but that hasn't been done yet.
3209 (define_expand "neon_vmul_n<mode>"
3210 [(match_operand:VMD 0 "s_register_operand" "")
3211 (match_operand:VMD 1 "s_register_operand" "")
3212 (match_operand:<V_elem> 2 "s_register_operand" "")
3213 (match_operand:SI 3 "immediate_operand" "")]
3216 rtx tmp = gen_reg_rtx (<MODE>mode);
3217 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[2], tmp, const0_rtx));
3218 emit_insn (gen_neon_vmul_lane<mode> (operands[0], operands[1], tmp,
3219 const0_rtx, const0_rtx));
3223 (define_expand "neon_vmul_n<mode>"
3224 [(match_operand:VMQ 0 "s_register_operand" "")
3225 (match_operand:VMQ 1 "s_register_operand" "")
3226 (match_operand:<V_elem> 2 "s_register_operand" "")
3227 (match_operand:SI 3 "immediate_operand" "")]
3230 rtx tmp = gen_reg_rtx (<V_HALF>mode);
3231 emit_insn (gen_neon_vset_lane<V_half> (tmp, operands[2], tmp, const0_rtx));
3232 emit_insn (gen_neon_vmul_lane<mode> (operands[0], operands[1], tmp,
3233 const0_rtx, const0_rtx));