OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [config/] [arm/] [neon.md] - Blame information for rev 709

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 709 jeremybenn
;; ARM NEON coprocessor Machine Description
2
;; Copyright (C) 2006, 2007, 2008, 2009, 2010, 2012
3
;;   Free Software Foundation, Inc.
4
;; Written by CodeSourcery.
5
;;
6
;; This file is part of GCC.
7
;;
8
;; GCC is free software; you can redistribute it and/or modify it
9
;; under the terms of the GNU General Public License as published by
10
;; the Free Software Foundation; either version 3, or (at your option)
11
;; any later version.
12
;;
13
;; GCC is distributed in the hope that it will be useful, but
14
;; WITHOUT ANY WARRANTY; without even the implied warranty of
15
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
;; General Public License for more details.
17
;;
18
;; You should have received a copy of the GNU General Public License
19
;; along with GCC; see the file COPYING3.  If not see
20
;; .
21
 
22
;; Enumerators for unspecs.
23
(define_c_enum "unspec" [
24
  UNSPEC_ASHIFT_SIGNED
25
  UNSPEC_ASHIFT_UNSIGNED
26
  UNSPEC_VABD
27
  UNSPEC_VABDL
28
  UNSPEC_VADD
29
  UNSPEC_VADDHN
30
  UNSPEC_VADDL
31
  UNSPEC_VADDW
32
  UNSPEC_VBSL
33
  UNSPEC_VCAGE
34
  UNSPEC_VCAGT
35
  UNSPEC_VCEQ
36
  UNSPEC_VCGE
37
  UNSPEC_VCGEU
38
  UNSPEC_VCGT
39
  UNSPEC_VCGTU
40
  UNSPEC_VCLS
41
  UNSPEC_VCONCAT
42
  UNSPEC_VCVT
43
  UNSPEC_VCVT_N
44
  UNSPEC_VEXT
45
  UNSPEC_VHADD
46
  UNSPEC_VHSUB
47
  UNSPEC_VLD1
48
  UNSPEC_VLD1_DUP
49
  UNSPEC_VLD1_LANE
50
  UNSPEC_VLD2
51
  UNSPEC_VLD2_DUP
52
  UNSPEC_VLD2_LANE
53
  UNSPEC_VLD3
54
  UNSPEC_VLD3A
55
  UNSPEC_VLD3B
56
  UNSPEC_VLD3_DUP
57
  UNSPEC_VLD3_LANE
58
  UNSPEC_VLD4
59
  UNSPEC_VLD4A
60
  UNSPEC_VLD4B
61
  UNSPEC_VLD4_DUP
62
  UNSPEC_VLD4_LANE
63
  UNSPEC_VMAX
64
  UNSPEC_VMIN
65
  UNSPEC_VMLA
66
  UNSPEC_VMLAL
67
  UNSPEC_VMLA_LANE
68
  UNSPEC_VMLAL_LANE
69
  UNSPEC_VMLS
70
  UNSPEC_VMLSL
71
  UNSPEC_VMLS_LANE
72
  UNSPEC_VMLSL_LANE
73
  UNSPEC_VMOVL
74
  UNSPEC_VMOVN
75
  UNSPEC_VMUL
76
  UNSPEC_VMULL
77
  UNSPEC_VMUL_LANE
78
  UNSPEC_VMULL_LANE
79
  UNSPEC_VPADAL
80
  UNSPEC_VPADD
81
  UNSPEC_VPADDL
82
  UNSPEC_VPMAX
83
  UNSPEC_VPMIN
84
  UNSPEC_VPSMAX
85
  UNSPEC_VPSMIN
86
  UNSPEC_VPUMAX
87
  UNSPEC_VPUMIN
88
  UNSPEC_VQABS
89
  UNSPEC_VQADD
90
  UNSPEC_VQDMLAL
91
  UNSPEC_VQDMLAL_LANE
92
  UNSPEC_VQDMLSL
93
  UNSPEC_VQDMLSL_LANE
94
  UNSPEC_VQDMULH
95
  UNSPEC_VQDMULH_LANE
96
  UNSPEC_VQDMULL
97
  UNSPEC_VQDMULL_LANE
98
  UNSPEC_VQMOVN
99
  UNSPEC_VQMOVUN
100
  UNSPEC_VQNEG
101
  UNSPEC_VQSHL
102
  UNSPEC_VQSHL_N
103
  UNSPEC_VQSHLU_N
104
  UNSPEC_VQSHRN_N
105
  UNSPEC_VQSHRUN_N
106
  UNSPEC_VQSUB
107
  UNSPEC_VRECPE
108
  UNSPEC_VRECPS
109
  UNSPEC_VREV16
110
  UNSPEC_VREV32
111
  UNSPEC_VREV64
112
  UNSPEC_VRSQRTE
113
  UNSPEC_VRSQRTS
114
  UNSPEC_VSHL
115
  UNSPEC_VSHLL_N
116
  UNSPEC_VSHL_N
117
  UNSPEC_VSHR_N
118
  UNSPEC_VSHRN_N
119
  UNSPEC_VSLI
120
  UNSPEC_VSRA_N
121
  UNSPEC_VSRI
122
  UNSPEC_VST1
123
  UNSPEC_VST1_LANE
124
  UNSPEC_VST2
125
  UNSPEC_VST2_LANE
126
  UNSPEC_VST3
127
  UNSPEC_VST3A
128
  UNSPEC_VST3B
129
  UNSPEC_VST3_LANE
130
  UNSPEC_VST4
131
  UNSPEC_VST4A
132
  UNSPEC_VST4B
133
  UNSPEC_VST4_LANE
134
  UNSPEC_VSTRUCTDUMMY
135
  UNSPEC_VSUB
136
  UNSPEC_VSUBHN
137
  UNSPEC_VSUBL
138
  UNSPEC_VSUBW
139
  UNSPEC_VTBL
140
  UNSPEC_VTBX
141
  UNSPEC_VTRN1
142
  UNSPEC_VTRN2
143
  UNSPEC_VTST
144
  UNSPEC_VUZP1
145
  UNSPEC_VUZP2
146
  UNSPEC_VZIP1
147
  UNSPEC_VZIP2
148
  UNSPEC_MISALIGNED_ACCESS
149
  UNSPEC_VCLE
150
  UNSPEC_VCLT
151
])
152
 
153
 
154
;; Attribute used to permit string comparisons against  in
155
;; neon_type attribute definitions.
156
(define_attr "vqh_mnem" "vadd,vmin,vmax" (const_string "vadd"))
157
 
158
(define_insn "*neon_mov"
159
  [(set (match_operand:VD 0 "nonimmediate_operand"
160
          "=w,Uv,w, w,  ?r,?w,?r,?r, ?Us")
161
        (match_operand:VD 1 "general_operand"
162
          " w,w, Dn,Uvi, w, r, r, Usi,r"))]
163
  "TARGET_NEON
164
   && (register_operand (operands[0], mode)
165
       || register_operand (operands[1], mode))"
166
{
167
  if (which_alternative == 2)
168
    {
169
      int width, is_valid;
170
      static char templ[40];
171
 
172
      is_valid = neon_immediate_valid_for_move (operands[1], mode,
173
        &operands[1], &width);
174
 
175
      gcc_assert (is_valid != 0);
176
 
177
      if (width == 0)
178
        return "vmov.f32\t%P0, %1  @ ";
179
      else
180
        sprintf (templ, "vmov.i%d\t%%P0, %%1  @ ", width);
181
 
182
      return templ;
183
    }
184
 
185
  /* FIXME: If the memory layout is changed in big-endian mode, output_move_vfp
186
     below must be changed to output_move_neon (which will use the
187
     element/structure loads/stores), and the constraint changed to 'Um' instead
188
     of 'Uv'.  */
189
 
190
  switch (which_alternative)
191
    {
192
    case 0: return "vmov\t%P0, %P1  @ ";
193
    case 1: case 3: return output_move_vfp (operands);
194
    case 2: gcc_unreachable ();
195
    case 4: return "vmov\t%Q0, %R0, %P1  @ ";
196
    case 5: return "vmov\t%P0, %Q1, %R1  @ ";
197
    default: return output_move_double (operands, true, NULL);
198
    }
199
}
200
 [(set_attr "neon_type" "neon_int_1,*,neon_vmov,*,neon_mrrc,neon_mcr_2_mcrr,*,*,*")
201
  (set_attr "type" "*,f_stored,*,f_loadd,*,*,alu,load2,store2")
202
  (set_attr "insn" "*,*,*,*,*,*,mov,*,*")
203
  (set_attr "length" "4,4,4,4,4,4,8,8,8")
204
  (set_attr "pool_range"     "*,*,*,1020,*,*,*,1020,*")
205
  (set_attr "neg_pool_range" "*,*,*,1004,*,*,*,1004,*")])
206
 
207
(define_insn "*neon_mov"
208
  [(set (match_operand:VQXMOV 0 "nonimmediate_operand"
209
          "=w,Un,w, w,  ?r,?w,?r,?r,  ?Us")
210
        (match_operand:VQXMOV 1 "general_operand"
211
          " w,w, Dn,Uni, w, r, r, Usi, r"))]
212
  "TARGET_NEON
213
   && (register_operand (operands[0], mode)
214
       || register_operand (operands[1], mode))"
215
{
216
  if (which_alternative == 2)
217
    {
218
      int width, is_valid;
219
      static char templ[40];
220
 
221
      is_valid = neon_immediate_valid_for_move (operands[1], mode,
222
        &operands[1], &width);
223
 
224
      gcc_assert (is_valid != 0);
225
 
226
      if (width == 0)
227
        return "vmov.f32\t%q0, %1  @ ";
228
      else
229
        sprintf (templ, "vmov.i%d\t%%q0, %%1  @ ", width);
230
 
231
      return templ;
232
    }
233
 
234
  switch (which_alternative)
235
    {
236
    case 0: return "vmov\t%q0, %q1  @ ";
237
    case 1: case 3: return output_move_neon (operands);
238
    case 2: gcc_unreachable ();
239
    case 4: return "vmov\t%Q0, %R0, %e1  @ \;vmov\t%J0, %K0, %f1";
240
    case 5: return "vmov\t%e0, %Q1, %R1  @ \;vmov\t%f0, %J1, %K1";
241
    default: return output_move_quad (operands);
242
    }
243
}
244
  [(set_attr "neon_type" "neon_int_1,neon_stm_2,neon_vmov,neon_ldm_2,\
245
                          neon_mrrc,neon_mcr_2_mcrr,*,*,*")
246
   (set_attr "type" "*,*,*,*,*,*,alu,load4,store4")
247
   (set_attr "insn" "*,*,*,*,*,*,mov,*,*")
248
   (set_attr "length" "4,8,4,8,8,8,16,8,16")
249
   (set_attr "pool_range" "*,*,*,1020,*,*,*,1020,*")
250
   (set_attr "neg_pool_range" "*,*,*,996,*,*,*,996,*")])
251
 
252
(define_expand "movti"
253
  [(set (match_operand:TI 0 "nonimmediate_operand" "")
254
        (match_operand:TI 1 "general_operand" ""))]
255
  "TARGET_NEON"
256
{
257
  if (can_create_pseudo_p ())
258
    {
259
      if (GET_CODE (operands[0]) != REG)
260
        operands[1] = force_reg (TImode, operands[1]);
261
    }
262
})
263
 
264
(define_expand "mov"
265
  [(set (match_operand:VSTRUCT 0 "nonimmediate_operand" "")
266
        (match_operand:VSTRUCT 1 "general_operand" ""))]
267
  "TARGET_NEON"
268
{
269
  if (can_create_pseudo_p ())
270
    {
271
      if (GET_CODE (operands[0]) != REG)
272
        operands[1] = force_reg (mode, operands[1]);
273
    }
274
})
275
 
276
(define_insn "*neon_mov"
277
  [(set (match_operand:VSTRUCT 0 "nonimmediate_operand" "=w,Ut,w")
278
        (match_operand:VSTRUCT 1 "general_operand"      " w,w, Ut"))]
279
  "TARGET_NEON
280
   && (register_operand (operands[0], mode)
281
       || register_operand (operands[1], mode))"
282
{
283
  switch (which_alternative)
284
    {
285
    case 0: return "#";
286
    case 1: case 2: return output_move_neon (operands);
287
    default: gcc_unreachable ();
288
    }
289
}
290
  [(set_attr "neon_type" "neon_int_1,neon_stm_2,neon_ldm_2")
291
   (set (attr "length") (symbol_ref "arm_attr_length_move_neon (insn)"))])
292
 
293
(define_split
294
  [(set (match_operand:EI 0 "s_register_operand" "")
295
        (match_operand:EI 1 "s_register_operand" ""))]
296
  "TARGET_NEON && reload_completed"
297
  [(set (match_dup 0) (match_dup 1))
298
   (set (match_dup 2) (match_dup 3))]
299
{
300
  int rdest = REGNO (operands[0]);
301
  int rsrc = REGNO (operands[1]);
302
  rtx dest[2], src[2];
303
 
304
  dest[0] = gen_rtx_REG (TImode, rdest);
305
  src[0] = gen_rtx_REG (TImode, rsrc);
306
  dest[1] = gen_rtx_REG (DImode, rdest + 4);
307
  src[1] = gen_rtx_REG (DImode, rsrc + 4);
308
 
309
  neon_disambiguate_copy (operands, dest, src, 2);
310
})
311
 
312
(define_split
313
  [(set (match_operand:OI 0 "s_register_operand" "")
314
        (match_operand:OI 1 "s_register_operand" ""))]
315
  "TARGET_NEON && reload_completed"
316
  [(set (match_dup 0) (match_dup 1))
317
   (set (match_dup 2) (match_dup 3))]
318
{
319
  int rdest = REGNO (operands[0]);
320
  int rsrc = REGNO (operands[1]);
321
  rtx dest[2], src[2];
322
 
323
  dest[0] = gen_rtx_REG (TImode, rdest);
324
  src[0] = gen_rtx_REG (TImode, rsrc);
325
  dest[1] = gen_rtx_REG (TImode, rdest + 4);
326
  src[1] = gen_rtx_REG (TImode, rsrc + 4);
327
 
328
  neon_disambiguate_copy (operands, dest, src, 2);
329
})
330
 
331
(define_split
332
  [(set (match_operand:CI 0 "s_register_operand" "")
333
        (match_operand:CI 1 "s_register_operand" ""))]
334
  "TARGET_NEON && reload_completed"
335
  [(set (match_dup 0) (match_dup 1))
336
   (set (match_dup 2) (match_dup 3))
337
   (set (match_dup 4) (match_dup 5))]
338
{
339
  int rdest = REGNO (operands[0]);
340
  int rsrc = REGNO (operands[1]);
341
  rtx dest[3], src[3];
342
 
343
  dest[0] = gen_rtx_REG (TImode, rdest);
344
  src[0] = gen_rtx_REG (TImode, rsrc);
345
  dest[1] = gen_rtx_REG (TImode, rdest + 4);
346
  src[1] = gen_rtx_REG (TImode, rsrc + 4);
347
  dest[2] = gen_rtx_REG (TImode, rdest + 8);
348
  src[2] = gen_rtx_REG (TImode, rsrc + 8);
349
 
350
  neon_disambiguate_copy (operands, dest, src, 3);
351
})
352
 
353
(define_split
354
  [(set (match_operand:XI 0 "s_register_operand" "")
355
        (match_operand:XI 1 "s_register_operand" ""))]
356
  "TARGET_NEON && reload_completed"
357
  [(set (match_dup 0) (match_dup 1))
358
   (set (match_dup 2) (match_dup 3))
359
   (set (match_dup 4) (match_dup 5))
360
   (set (match_dup 6) (match_dup 7))]
361
{
362
  int rdest = REGNO (operands[0]);
363
  int rsrc = REGNO (operands[1]);
364
  rtx dest[4], src[4];
365
 
366
  dest[0] = gen_rtx_REG (TImode, rdest);
367
  src[0] = gen_rtx_REG (TImode, rsrc);
368
  dest[1] = gen_rtx_REG (TImode, rdest + 4);
369
  src[1] = gen_rtx_REG (TImode, rsrc + 4);
370
  dest[2] = gen_rtx_REG (TImode, rdest + 8);
371
  src[2] = gen_rtx_REG (TImode, rsrc + 8);
372
  dest[3] = gen_rtx_REG (TImode, rdest + 12);
373
  src[3] = gen_rtx_REG (TImode, rsrc + 12);
374
 
375
  neon_disambiguate_copy (operands, dest, src, 4);
376
})
377
 
378
(define_expand "movmisalign"
379
  [(set (match_operand:VDQX 0 "neon_struct_or_register_operand")
380
        (unspec:VDQX [(match_operand:VDQX 1 "neon_struct_or_register_operand")]
381
                     UNSPEC_MISALIGNED_ACCESS))]
382
  "TARGET_NEON && !BYTES_BIG_ENDIAN"
383
{
384
  /* This pattern is not permitted to fail during expansion: if both arguments
385
     are non-registers (e.g. memory := constant, which can be created by the
386
     auto-vectorizer), force operand 1 into a register.  */
387
  if (!s_register_operand (operands[0], mode)
388
      && !s_register_operand (operands[1], mode))
389
    operands[1] = force_reg (mode, operands[1]);
390
})
391
 
392
(define_insn "*movmisalign_neon_store"
393
  [(set (match_operand:VDX 0 "neon_struct_operand"             "=Um")
394
        (unspec:VDX [(match_operand:VDX 1 "s_register_operand" " w")]
395
                    UNSPEC_MISALIGNED_ACCESS))]
396
  "TARGET_NEON && !BYTES_BIG_ENDIAN"
397
  "vst1.\t{%P1}, %A0"
398
  [(set_attr "neon_type" "neon_vst1_1_2_regs_vst2_2_regs")])
399
 
400
(define_insn "*movmisalign_neon_load"
401
  [(set (match_operand:VDX 0 "s_register_operand"               "=w")
402
        (unspec:VDX [(match_operand:VDX 1 "neon_struct_operand" " Um")]
403
                    UNSPEC_MISALIGNED_ACCESS))]
404
  "TARGET_NEON && !BYTES_BIG_ENDIAN"
405
  "vld1.\t{%P0}, %A1"
406
  [(set_attr "neon_type" "neon_vld1_1_2_regs")])
407
 
408
(define_insn "*movmisalign_neon_store"
409
  [(set (match_operand:VQX 0 "neon_struct_operand"             "=Um")
410
        (unspec:VQX [(match_operand:VQX 1 "s_register_operand" " w")]
411
                    UNSPEC_MISALIGNED_ACCESS))]
412
  "TARGET_NEON && !BYTES_BIG_ENDIAN"
413
  "vst1.\t{%q1}, %A0"
414
  [(set_attr "neon_type" "neon_vst1_1_2_regs_vst2_2_regs")])
415
 
416
(define_insn "*movmisalign_neon_load"
417
  [(set (match_operand:VQX 0 "s_register_operand"                "=w")
418
        (unspec:VQX [(match_operand:VQX 1 "neon_struct_operand" " Um")]
419
                    UNSPEC_MISALIGNED_ACCESS))]
420
  "TARGET_NEON && !BYTES_BIG_ENDIAN"
421
  "vld1.\t{%q0}, %A1"
422
  [(set_attr "neon_type" "neon_vld1_1_2_regs")])
423
 
424
(define_insn "vec_set_internal"
425
  [(set (match_operand:VD 0 "s_register_operand" "=w")
426
        (vec_merge:VD
427
          (vec_duplicate:VD
428
            (match_operand: 1 "s_register_operand" "r"))
429
          (match_operand:VD 3 "s_register_operand" "0")
430
          (match_operand:SI 2 "immediate_operand" "i")))]
431
  "TARGET_NEON"
432
{
433
  int elt = ffs ((int) INTVAL (operands[2])) - 1;
434
  if (BYTES_BIG_ENDIAN)
435
    elt = GET_MODE_NUNITS (mode) - 1 - elt;
436
  operands[2] = GEN_INT (elt);
437
 
438
  return "vmov%?.\t%P0[%c2], %1";
439
}
440
  [(set_attr "predicable" "yes")
441
   (set_attr "neon_type" "neon_mcr")])
442
 
443
(define_insn "vec_set_internal"
444
  [(set (match_operand:VQ 0 "s_register_operand" "=w")
445
        (vec_merge:VQ
446
          (vec_duplicate:VQ
447
            (match_operand: 1 "s_register_operand" "r"))
448
          (match_operand:VQ 3 "s_register_operand" "0")
449
          (match_operand:SI 2 "immediate_operand" "i")))]
450
  "TARGET_NEON"
451
{
452
  HOST_WIDE_INT elem = ffs ((int) INTVAL (operands[2])) - 1;
453
  int half_elts = GET_MODE_NUNITS (mode) / 2;
454
  int elt = elem % half_elts;
455
  int hi = (elem / half_elts) * 2;
456
  int regno = REGNO (operands[0]);
457
 
458
  if (BYTES_BIG_ENDIAN)
459
    elt = half_elts - 1 - elt;
460
 
461
  operands[0] = gen_rtx_REG (mode, regno + hi);
462
  operands[2] = GEN_INT (elt);
463
 
464
  return "vmov%?.\t%P0[%c2], %1";
465
}
466
  [(set_attr "predicable" "yes")
467
   (set_attr "neon_type" "neon_mcr")]
468
)
469
 
470
(define_insn "vec_setv2di_internal"
471
  [(set (match_operand:V2DI 0 "s_register_operand" "=w")
472
        (vec_merge:V2DI
473
          (vec_duplicate:V2DI
474
            (match_operand:DI 1 "s_register_operand" "r"))
475
          (match_operand:V2DI 3 "s_register_operand" "0")
476
          (match_operand:SI 2 "immediate_operand" "i")))]
477
  "TARGET_NEON"
478
{
479
  HOST_WIDE_INT elem = ffs ((int) INTVAL (operands[2])) - 1;
480
  int regno = REGNO (operands[0]) + 2 * elem;
481
 
482
  operands[0] = gen_rtx_REG (DImode, regno);
483
 
484
  return "vmov%?\t%P0, %Q1, %R1";
485
}
486
  [(set_attr "predicable" "yes")
487
   (set_attr "neon_type" "neon_mcr_2_mcrr")]
488
)
489
 
490
(define_expand "vec_set"
491
  [(match_operand:VDQ 0 "s_register_operand" "")
492
   (match_operand: 1 "s_register_operand" "")
493
   (match_operand:SI 2 "immediate_operand" "")]
494
  "TARGET_NEON"
495
{
496
  HOST_WIDE_INT elem = (HOST_WIDE_INT) 1 << INTVAL (operands[2]);
497
  emit_insn (gen_vec_set_internal (operands[0], operands[1],
498
                                         GEN_INT (elem), operands[0]));
499
  DONE;
500
})
501
 
502
(define_insn "vec_extract"
503
  [(set (match_operand: 0 "s_register_operand" "=r")
504
        (vec_select:
505
          (match_operand:VD 1 "s_register_operand" "w")
506
          (parallel [(match_operand:SI 2 "immediate_operand" "i")])))]
507
  "TARGET_NEON"
508
{
509
  if (BYTES_BIG_ENDIAN)
510
    {
511
      int elt = INTVAL (operands[2]);
512
      elt = GET_MODE_NUNITS (mode) - 1 - elt;
513
      operands[2] = GEN_INT (elt);
514
    }
515
  return "vmov%?.\t%0, %P1[%c2]";
516
}
517
  [(set_attr "predicable" "yes")
518
   (set_attr "neon_type" "neon_bp_simple")]
519
)
520
 
521
(define_insn "vec_extract"
522
  [(set (match_operand: 0 "s_register_operand" "=r")
523
        (vec_select:
524
          (match_operand:VQ 1 "s_register_operand" "w")
525
          (parallel [(match_operand:SI 2 "immediate_operand" "i")])))]
526
  "TARGET_NEON"
527
{
528
  int half_elts = GET_MODE_NUNITS (mode) / 2;
529
  int elt = INTVAL (operands[2]) % half_elts;
530
  int hi = (INTVAL (operands[2]) / half_elts) * 2;
531
  int regno = REGNO (operands[1]);
532
 
533
  if (BYTES_BIG_ENDIAN)
534
    elt = half_elts - 1 - elt;
535
 
536
  operands[1] = gen_rtx_REG (mode, regno + hi);
537
  operands[2] = GEN_INT (elt);
538
 
539
  return "vmov%?.\t%0, %P1[%c2]";
540
}
541
  [(set_attr "predicable" "yes")
542
   (set_attr "neon_type" "neon_bp_simple")]
543
)
544
 
545
(define_insn "vec_extractv2di"
546
  [(set (match_operand:DI 0 "s_register_operand" "=r")
547
        (vec_select:DI
548
          (match_operand:V2DI 1 "s_register_operand" "w")
549
          (parallel [(match_operand:SI 2 "immediate_operand" "i")])))]
550
  "TARGET_NEON"
551
{
552
  int regno = REGNO (operands[1]) + 2 * INTVAL (operands[2]);
553
 
554
  operands[1] = gen_rtx_REG (DImode, regno);
555
 
556
  return "vmov%?\t%Q0, %R0, %P1  @ v2di";
557
}
558
  [(set_attr "predicable" "yes")
559
   (set_attr "neon_type" "neon_int_1")]
560
)
561
 
562
(define_expand "vec_init"
563
  [(match_operand:VDQ 0 "s_register_operand" "")
564
   (match_operand 1 "" "")]
565
  "TARGET_NEON"
566
{
567
  neon_expand_vector_init (operands[0], operands[1]);
568
  DONE;
569
})
570
 
571
;; Doubleword and quadword arithmetic.
572
 
573
;; NOTE: some other instructions also support 64-bit integer
574
;; element size, which we could potentially use for "long long" operations.
575
 
576
(define_insn "*add3_neon"
577
  [(set (match_operand:VDQ 0 "s_register_operand" "=w")
578
        (plus:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
579
                  (match_operand:VDQ 2 "s_register_operand" "w")))]
580
  "TARGET_NEON && (! || flag_unsafe_math_optimizations)"
581
  "vadd.\t%0, %1, %2"
582
  [(set (attr "neon_type")
583
      (if_then_else (match_test "")
584
                    (if_then_else (match_test "")
585
                                  (const_string "neon_fp_vadd_ddd_vabs_dd")
586
                                  (const_string "neon_fp_vadd_qqq_vabs_qq"))
587
                    (const_string "neon_int_1")))]
588
)
589
 
590
(define_insn "adddi3_neon"
591
  [(set (match_operand:DI 0 "s_register_operand" "=w,?&r,?&r,?w")
592
        (plus:DI (match_operand:DI 1 "s_register_operand" "%w,0,0,w")
593
                 (match_operand:DI 2 "s_register_operand" "w,r,0,w")))
594
   (clobber (reg:CC CC_REGNUM))]
595
  "TARGET_NEON"
596
{
597
  switch (which_alternative)
598
    {
599
    case 0: /* fall through */
600
    case 3: return "vadd.i64\t%P0, %P1, %P2";
601
    case 1: return "#";
602
    case 2: return "#";
603
    default: gcc_unreachable ();
604
    }
605
}
606
  [(set_attr "neon_type" "neon_int_1,*,*,neon_int_1")
607
   (set_attr "conds" "*,clob,clob,*")
608
   (set_attr "length" "*,8,8,*")
609
   (set_attr "arch" "nota8,*,*,onlya8")]
610
)
611
 
612
(define_insn "*sub3_neon"
613
  [(set (match_operand:VDQ 0 "s_register_operand" "=w")
614
        (minus:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
615
                   (match_operand:VDQ 2 "s_register_operand" "w")))]
616
  "TARGET_NEON && (! || flag_unsafe_math_optimizations)"
617
  "vsub.\t%0, %1, %2"
618
  [(set (attr "neon_type")
619
      (if_then_else (match_test "")
620
                    (if_then_else (match_test "")
621
                                  (const_string "neon_fp_vadd_ddd_vabs_dd")
622
                                  (const_string "neon_fp_vadd_qqq_vabs_qq"))
623
                    (const_string "neon_int_2")))]
624
)
625
 
626
(define_insn "subdi3_neon"
627
  [(set (match_operand:DI 0 "s_register_operand" "=w,?&r,?&r,?&r,?w")
628
        (minus:DI (match_operand:DI 1 "s_register_operand" "w,0,r,0,w")
629
                  (match_operand:DI 2 "s_register_operand" "w,r,0,0,w")))
630
   (clobber (reg:CC CC_REGNUM))]
631
  "TARGET_NEON"
632
{
633
  switch (which_alternative)
634
    {
635
    case 0: /* fall through */
636
    case 4: return "vsub.i64\t%P0, %P1, %P2";
637
    case 1: /* fall through */
638
    case 2: /* fall through */
639
    case 3: return  "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2";
640
    default: gcc_unreachable ();
641
    }
642
}
643
  [(set_attr "neon_type" "neon_int_2,*,*,*,neon_int_2")
644
   (set_attr "conds" "*,clob,clob,clob,*")
645
   (set_attr "length" "*,8,8,8,*")
646
   (set_attr "arch" "nota8,*,*,*,onlya8")]
647
)
648
 
649
(define_insn "*mul3_neon"
650
  [(set (match_operand:VDQ 0 "s_register_operand" "=w")
651
        (mult:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
652
                  (match_operand:VDQ 2 "s_register_operand" "w")))]
653
  "TARGET_NEON && (! || flag_unsafe_math_optimizations)"
654
  "vmul.\t%0, %1, %2"
655
  [(set (attr "neon_type")
656
      (if_then_else (match_test "")
657
                    (if_then_else (match_test "")
658
                                  (const_string "neon_fp_vadd_ddd_vabs_dd")
659
                                  (const_string "neon_fp_vadd_qqq_vabs_qq"))
660
                    (if_then_else (match_test "")
661
                                  (if_then_else
662
                                    (match_test "")
663
                                    (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
664
                                    (const_string "neon_mul_qqq_8_16_32_ddd_32"))
665
                                  (if_then_else (match_test "")
666
                                    (const_string "neon_mul_qqq_8_16_32_ddd_32")
667
                                    (const_string "neon_mul_qqq_8_16_32_ddd_32")))))]
668
)
669
 
670
(define_insn "mul3add_neon"
671
  [(set (match_operand:VDQ 0 "s_register_operand" "=w")
672
        (plus:VDQ (mult:VDQ (match_operand:VDQ 2 "s_register_operand" "w")
673
                            (match_operand:VDQ 3 "s_register_operand" "w"))
674
                  (match_operand:VDQ 1 "s_register_operand" "0")))]
675
  "TARGET_NEON && (! || flag_unsafe_math_optimizations)"
676
  "vmla.\t%0, %2, %3"
677
  [(set (attr "neon_type")
678
      (if_then_else (match_test "")
679
                    (if_then_else (match_test "")
680
                                  (const_string "neon_fp_vmla_ddd")
681
                                  (const_string "neon_fp_vmla_qqq"))
682
                    (if_then_else (match_test "")
683
                                  (if_then_else
684
                                    (match_test "")
685
                                    (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
686
                                    (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
687
                                  (if_then_else (match_test "")
688
                                    (const_string "neon_mla_qqq_8_16")
689
                                    (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
690
)
691
 
692
(define_insn "mul3negadd_neon"
693
  [(set (match_operand:VDQ 0 "s_register_operand" "=w")
694
        (minus:VDQ (match_operand:VDQ 1 "s_register_operand" "0")
695
                   (mult:VDQ (match_operand:VDQ 2 "s_register_operand" "w")
696
                             (match_operand:VDQ 3 "s_register_operand" "w"))))]
697
  "TARGET_NEON && (! || flag_unsafe_math_optimizations)"
698
  "vmls.\t%0, %2, %3"
699
  [(set (attr "neon_type")
700
      (if_then_else (match_test "")
701
                    (if_then_else (match_test "")
702
                                  (const_string "neon_fp_vmla_ddd")
703
                                  (const_string "neon_fp_vmla_qqq"))
704
                    (if_then_else (match_test "")
705
                                  (if_then_else
706
                                    (match_test "")
707
                                    (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
708
                                    (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
709
                                  (if_then_else (match_test "")
710
                                    (const_string "neon_mla_qqq_8_16")
711
                                    (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
712
)
713
 
714
(define_insn "ior3"
715
  [(set (match_operand:VDQ 0 "s_register_operand" "=w,w")
716
        (ior:VDQ (match_operand:VDQ 1 "s_register_operand" "w,0")
717
                 (match_operand:VDQ 2 "neon_logic_op2" "w,Dl")))]
718
  "TARGET_NEON"
719
{
720
  switch (which_alternative)
721
    {
722
    case 0: return "vorr\t%0, %1, %2";
723
    case 1: return neon_output_logic_immediate ("vorr", &operands[2],
724
                     mode, 0, VALID_NEON_QREG_MODE (mode));
725
    default: gcc_unreachable ();
726
    }
727
}
728
  [(set_attr "neon_type" "neon_int_1")]
729
)
730
 
731
(define_insn "iordi3_neon"
732
  [(set (match_operand:DI 0 "s_register_operand" "=w,w,?&r,?&r,?w,?w")
733
        (ior:DI (match_operand:DI 1 "s_register_operand" "%w,0,0,r,w,0")
734
                (match_operand:DI 2 "neon_logic_op2" "w,Dl,r,r,w,Dl")))]
735
  "TARGET_NEON"
736
{
737
  switch (which_alternative)
738
    {
739
    case 0: /* fall through */
740
    case 4: return "vorr\t%P0, %P1, %P2";
741
    case 1: /* fall through */
742
    case 5: return neon_output_logic_immediate ("vorr", &operands[2],
743
                     DImode, 0, VALID_NEON_QREG_MODE (DImode));
744
    case 2: return "#";
745
    case 3: return "#";
746
    default: gcc_unreachable ();
747
    }
748
}
749
  [(set_attr "neon_type" "neon_int_1,neon_int_1,*,*,neon_int_1,neon_int_1")
750
   (set_attr "length" "*,*,8,8,*,*")
751
   (set_attr "arch" "nota8,nota8,*,*,onlya8,onlya8")]
752
)
753
 
754
;; The concrete forms of the Neon immediate-logic instructions are vbic and
755
;; vorr. We support the pseudo-instruction vand instead, because that
756
;; corresponds to the canonical form the middle-end expects to use for
757
;; immediate bitwise-ANDs.
758
 
759
(define_insn "and3"
760
  [(set (match_operand:VDQ 0 "s_register_operand" "=w,w")
761
        (and:VDQ (match_operand:VDQ 1 "s_register_operand" "w,0")
762
                 (match_operand:VDQ 2 "neon_inv_logic_op2" "w,DL")))]
763
  "TARGET_NEON"
764
{
765
  switch (which_alternative)
766
    {
767
    case 0: return "vand\t%0, %1, %2";
768
    case 1: return neon_output_logic_immediate ("vand", &operands[2],
769
                     mode, 1, VALID_NEON_QREG_MODE (mode));
770
    default: gcc_unreachable ();
771
    }
772
}
773
  [(set_attr "neon_type" "neon_int_1")]
774
)
775
 
776
(define_insn "anddi3_neon"
777
  [(set (match_operand:DI 0 "s_register_operand" "=w,w,?&r,?&r,?w,?w")
778
        (and:DI (match_operand:DI 1 "s_register_operand" "%w,0,0,r,w,0")
779
                (match_operand:DI 2 "neon_inv_logic_op2" "w,DL,r,r,w,DL")))]
780
  "TARGET_NEON"
781
{
782
  switch (which_alternative)
783
    {
784
    case 0: /* fall through */
785
    case 4: return "vand\t%P0, %P1, %P2";
786
    case 1: /* fall through */
787
    case 5: return neon_output_logic_immediate ("vand", &operands[2],
788
                     DImode, 1, VALID_NEON_QREG_MODE (DImode));
789
    case 2: return "#";
790
    case 3: return "#";
791
    default: gcc_unreachable ();
792
    }
793
}
794
  [(set_attr "neon_type" "neon_int_1,neon_int_1,*,*,neon_int_1,neon_int_1")
795
   (set_attr "length" "*,*,8,8,*,*")
796
   (set_attr "arch" "nota8,nota8,*,*,onlya8,onlya8")]
797
)
798
 
799
(define_insn "orn3_neon"
800
  [(set (match_operand:VDQ 0 "s_register_operand" "=w")
801
        (ior:VDQ (not:VDQ (match_operand:VDQ 2 "s_register_operand" "w"))
802
                 (match_operand:VDQ 1 "s_register_operand" "w")))]
803
  "TARGET_NEON"
804
  "vorn\t%0, %1, %2"
805
  [(set_attr "neon_type" "neon_int_1")]
806
)
807
 
808
;; TODO: investigate whether we should disable
809
;; this and bicdi3_neon for the A8 in line with the other
810
;; changes above.
811
(define_insn_and_split "orndi3_neon"
812
  [(set (match_operand:DI 0 "s_register_operand" "=w,?&r,?&r,?&r")
813
        (ior:DI (not:DI (match_operand:DI 2 "s_register_operand" "w,0,0,r"))
814
                (match_operand:DI 1 "s_register_operand" "w,r,r,0")))]
815
  "TARGET_NEON"
816
  "@
817
   vorn\t%P0, %P1, %P2
818
   #
819
   #
820
   #"
821
  "reload_completed &&
822
   (TARGET_NEON && !(IS_VFP_REGNUM (REGNO (operands[0]))))"
823
  [(set (match_dup 0) (ior:SI (not:SI (match_dup 2)) (match_dup 1)))
824
   (set (match_dup 3) (ior:SI (not:SI (match_dup 4)) (match_dup 5)))]
825
  "
826
  {
827
    if (TARGET_THUMB2)
828
      {
829
        operands[3] = gen_highpart (SImode, operands[0]);
830
        operands[0] = gen_lowpart (SImode, operands[0]);
831
        operands[4] = gen_highpart (SImode, operands[2]);
832
        operands[2] = gen_lowpart (SImode, operands[2]);
833
        operands[5] = gen_highpart (SImode, operands[1]);
834
        operands[1] = gen_lowpart (SImode, operands[1]);
835
      }
836
    else
837
      {
838
        emit_insn (gen_one_cmpldi2 (operands[0], operands[2]));
839
        emit_insn (gen_iordi3 (operands[0], operands[1], operands[0]));
840
        DONE;
841
      }
842
  }"
843
  [(set_attr "neon_type" "neon_int_1,*,*,*")
844
   (set_attr "length" "*,16,8,8")
845
   (set_attr "arch" "any,a,t2,t2")]
846
)
847
 
848
(define_insn "bic3_neon"
849
  [(set (match_operand:VDQ 0 "s_register_operand" "=w")
850
        (and:VDQ (not:VDQ (match_operand:VDQ 2 "s_register_operand" "w"))
851
                 (match_operand:VDQ 1 "s_register_operand" "w")))]
852
  "TARGET_NEON"
853
  "vbic\t%0, %1, %2"
854
  [(set_attr "neon_type" "neon_int_1")]
855
)
856
 
857
;; Compare to *anddi_notdi_di.
858
(define_insn "bicdi3_neon"
859
  [(set (match_operand:DI 0 "s_register_operand" "=w,?=&r,?&r")
860
        (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "w,r,0"))
861
                (match_operand:DI 1 "s_register_operand" "w,0,r")))]
862
  "TARGET_NEON"
863
  "@
864
   vbic\t%P0, %P1, %P2
865
   #
866
   #"
867
  [(set_attr "neon_type" "neon_int_1,*,*")
868
   (set_attr "length" "*,8,8")]
869
)
870
 
871
(define_insn "xor3"
872
  [(set (match_operand:VDQ 0 "s_register_operand" "=w")
873
        (xor:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
874
                 (match_operand:VDQ 2 "s_register_operand" "w")))]
875
  "TARGET_NEON"
876
  "veor\t%0, %1, %2"
877
  [(set_attr "neon_type" "neon_int_1")]
878
)
879
 
880
(define_insn "xordi3_neon"
881
  [(set (match_operand:DI 0 "s_register_operand" "=w,?&r,?&r,?w")
882
        (xor:DI (match_operand:DI 1 "s_register_operand" "%w,0,r,w")
883
                (match_operand:DI 2 "s_register_operand" "w,r,r,w")))]
884
  "TARGET_NEON"
885
  "@
886
   veor\t%P0, %P1, %P2
887
   #
888
   #
889
   veor\t%P0, %P1, %P2"
890
  [(set_attr "neon_type" "neon_int_1,*,*,neon_int_1")
891
   (set_attr "length" "*,8,8,*")
892
   (set_attr "arch" "nota8,*,*,onlya8")]
893
)
894
 
895
(define_insn "one_cmpl2"
896
  [(set (match_operand:VDQ 0 "s_register_operand" "=w")
897
        (not:VDQ (match_operand:VDQ 1 "s_register_operand" "w")))]
898
  "TARGET_NEON"
899
  "vmvn\t%0, %1"
900
  [(set_attr "neon_type" "neon_int_1")]
901
)
902
 
903
(define_insn "abs2"
904
  [(set (match_operand:VDQW 0 "s_register_operand" "=w")
905
        (abs:VDQW (match_operand:VDQW 1 "s_register_operand" "w")))]
906
  "TARGET_NEON"
907
  "vabs.\t%0, %1"
908
  [(set (attr "neon_type")
909
      (if_then_else (match_test "")
910
                    (if_then_else (match_test "")
911
                                  (const_string "neon_fp_vadd_ddd_vabs_dd")
912
                                  (const_string "neon_fp_vadd_qqq_vabs_qq"))
913
                    (const_string "neon_int_3")))]
914
)
915
 
916
(define_insn "neg2"
917
  [(set (match_operand:VDQW 0 "s_register_operand" "=w")
918
        (neg:VDQW (match_operand:VDQW 1 "s_register_operand" "w")))]
919
  "TARGET_NEON"
920
  "vneg.\t%0, %1"
921
  [(set (attr "neon_type")
922
      (if_then_else (match_test "")
923
                    (if_then_else (match_test "")
924
                                  (const_string "neon_fp_vadd_ddd_vabs_dd")
925
                                  (const_string "neon_fp_vadd_qqq_vabs_qq"))
926
                    (const_string "neon_int_3")))]
927
)
928
 
929
(define_insn "*umin3_neon"
930
  [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
931
        (umin:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")
932
                    (match_operand:VDQIW 2 "s_register_operand" "w")))]
933
  "TARGET_NEON"
934
  "vmin.\t%0, %1, %2"
935
  [(set_attr "neon_type" "neon_int_5")]
936
)
937
 
938
(define_insn "*umax3_neon"
939
  [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
940
        (umax:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")
941
                    (match_operand:VDQIW 2 "s_register_operand" "w")))]
942
  "TARGET_NEON"
943
  "vmax.\t%0, %1, %2"
944
  [(set_attr "neon_type" "neon_int_5")]
945
)
946
 
947
(define_insn "*smin3_neon"
948
  [(set (match_operand:VDQW 0 "s_register_operand" "=w")
949
        (smin:VDQW (match_operand:VDQW 1 "s_register_operand" "w")
950
                   (match_operand:VDQW 2 "s_register_operand" "w")))]
951
  "TARGET_NEON"
952
  "vmin.\t%0, %1, %2"
953
  [(set (attr "neon_type")
954
      (if_then_else (match_test "")
955
                    (const_string "neon_fp_vadd_ddd_vabs_dd")
956
                    (const_string "neon_int_5")))]
957
)
958
 
959
(define_insn "*smax3_neon"
960
  [(set (match_operand:VDQW 0 "s_register_operand" "=w")
961
        (smax:VDQW (match_operand:VDQW 1 "s_register_operand" "w")
962
                   (match_operand:VDQW 2 "s_register_operand" "w")))]
963
  "TARGET_NEON"
964
  "vmax.\t%0, %1, %2"
965
  [(set (attr "neon_type")
966
      (if_then_else (match_test "")
967
                    (const_string "neon_fp_vadd_ddd_vabs_dd")
968
                    (const_string "neon_int_5")))]
969
)
970
 
971
; TODO: V2DI shifts are current disabled because there are bugs in the
972
; generic vectorizer code.  It ends up creating a V2DI constructor with
973
; SImode elements.
974
 
975
(define_insn "vashl3"
976
  [(set (match_operand:VDQIW 0 "s_register_operand" "=w,w")
977
        (ashift:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w,w")
978
                      (match_operand:VDQIW 2 "imm_lshift_or_reg_neon" "w,Dn")))]
979
  "TARGET_NEON"
980
  {
981
    switch (which_alternative)
982
      {
983
        case 0: return "vshl.\t%0, %1, %2";
984
        case 1: return neon_output_shift_immediate ("vshl", 'i', &operands[2],
985
                                                    mode,
986
                                                    VALID_NEON_QREG_MODE (mode),
987
                                                    true);
988
        default: gcc_unreachable ();
989
      }
990
  }
991
  [(set (attr "neon_type")
992
      (if_then_else (match_test "")
993
                    (const_string "neon_vshl_ddd")
994
                    (const_string "neon_shift_3")))]
995
)
996
 
997
(define_insn "vashr3_imm"
998
  [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
999
        (ashiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")
1000
                        (match_operand:VDQIW 2 "imm_for_neon_rshift_operand" "Dn")))]
1001
  "TARGET_NEON"
1002
  {
1003
    return neon_output_shift_immediate ("vshr", 's', &operands[2],
1004
                                        mode, VALID_NEON_QREG_MODE (mode),
1005
                                        false);
1006
  }
1007
  [(set (attr "neon_type")
1008
      (if_then_else (match_test "")
1009
                    (const_string "neon_vshl_ddd")
1010
                    (const_string "neon_shift_3")))]
1011
)
1012
 
1013
(define_insn "vlshr3_imm"
1014
  [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
1015
        (lshiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")
1016
                        (match_operand:VDQIW 2 "imm_for_neon_rshift_operand" "Dn")))]
1017
  "TARGET_NEON"
1018
  {
1019
    return neon_output_shift_immediate ("vshr", 'u', &operands[2],
1020
                                        mode, VALID_NEON_QREG_MODE (mode),
1021
                                        false);
1022
  }
1023
  [(set (attr "neon_type")
1024
        (if_then_else (match_test "")
1025
                      (const_string "neon_vshl_ddd")
1026
                      (const_string "neon_shift_3")))]
1027
)
1028
 
1029
; Used for implementing logical shift-right, which is a left-shift by a negative
1030
; amount, with signed operands. This is essentially the same as ashl3
1031
; above, but using an unspec in case GCC tries anything tricky with negative
1032
; shift amounts.
1033
 
1034
(define_insn "ashl3_signed"
1035
  [(set (match_operand:VDQI 0 "s_register_operand" "=w")
1036
        (unspec:VDQI [(match_operand:VDQI 1 "s_register_operand" "w")
1037
                      (match_operand:VDQI 2 "s_register_operand" "w")]
1038
                     UNSPEC_ASHIFT_SIGNED))]
1039
  "TARGET_NEON"
1040
  "vshl.\t%0, %1, %2"
1041
  [(set (attr "neon_type")
1042
      (if_then_else (match_test "")
1043
                    (const_string "neon_vshl_ddd")
1044
                    (const_string "neon_shift_3")))]
1045
)
1046
 
1047
; Used for implementing logical shift-right, which is a left-shift by a negative
1048
; amount, with unsigned operands.
1049
 
1050
(define_insn "ashl3_unsigned"
1051
  [(set (match_operand:VDQI 0 "s_register_operand" "=w")
1052
        (unspec:VDQI [(match_operand:VDQI 1 "s_register_operand" "w")
1053
                      (match_operand:VDQI 2 "s_register_operand" "w")]
1054
                     UNSPEC_ASHIFT_UNSIGNED))]
1055
  "TARGET_NEON"
1056
  "vshl.\t%0, %1, %2"
1057
  [(set (attr "neon_type")
1058
      (if_then_else (match_test "")
1059
                    (const_string "neon_vshl_ddd")
1060
                    (const_string "neon_shift_3")))]
1061
)
1062
 
1063
(define_expand "vashr3"
1064
  [(set (match_operand:VDQIW 0 "s_register_operand" "")
1065
        (ashiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "")
1066
                        (match_operand:VDQIW 2 "imm_rshift_or_reg_neon" "")))]
1067
  "TARGET_NEON"
1068
{
1069
  if (s_register_operand (operands[2], mode))
1070
    {
1071
      rtx neg = gen_reg_rtx (mode);
1072
      emit_insn (gen_neg2 (neg, operands[2]));
1073
      emit_insn (gen_ashl3_signed (operands[0], operands[1], neg));
1074
    }
1075
  else
1076
    emit_insn (gen_vashr3_imm (operands[0], operands[1], operands[2]));
1077
  DONE;
1078
})
1079
 
1080
(define_expand "vlshr3"
1081
  [(set (match_operand:VDQIW 0 "s_register_operand" "")
1082
        (lshiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "")
1083
                        (match_operand:VDQIW 2 "imm_rshift_or_reg_neon" "")))]
1084
  "TARGET_NEON"
1085
{
1086
  if (s_register_operand (operands[2], mode))
1087
    {
1088
      rtx neg = gen_reg_rtx (mode);
1089
      emit_insn (gen_neg2 (neg, operands[2]));
1090
      emit_insn (gen_ashl3_unsigned (operands[0], operands[1], neg));
1091
    }
1092
  else
1093
    emit_insn (gen_vlshr3_imm (operands[0], operands[1], operands[2]));
1094
  DONE;
1095
})
1096
 
1097
;; Widening operations
1098
 
1099
(define_insn "widen_ssum3"
1100
  [(set (match_operand: 0 "s_register_operand" "=w")
1101
        (plus: (sign_extend:
1102
                          (match_operand:VW 1 "s_register_operand" "%w"))
1103
                        (match_operand: 2 "s_register_operand" "w")))]
1104
  "TARGET_NEON"
1105
  "vaddw.\t%q0, %q2, %P1"
1106
  [(set_attr "neon_type" "neon_int_3")]
1107
)
1108
 
1109
(define_insn "widen_usum3"
1110
  [(set (match_operand: 0 "s_register_operand" "=w")
1111
        (plus: (zero_extend:
1112
                          (match_operand:VW 1 "s_register_operand" "%w"))
1113
                        (match_operand: 2 "s_register_operand" "w")))]
1114
  "TARGET_NEON"
1115
  "vaddw.\t%q0, %q2, %P1"
1116
  [(set_attr "neon_type" "neon_int_3")]
1117
)
1118
 
1119
;; VEXT can be used to synthesize coarse whole-vector shifts with 8-bit
1120
;; shift-count granularity. That's good enough for the middle-end's current
1121
;; needs.
1122
 
1123
;; Note that it's not safe to perform such an operation in big-endian mode,
1124
;; due to element-ordering issues.
1125
 
1126
(define_expand "vec_shr_"
1127
  [(match_operand:VDQ 0 "s_register_operand" "")
1128
   (match_operand:VDQ 1 "s_register_operand" "")
1129
   (match_operand:SI 2 "const_multiple_of_8_operand" "")]
1130
  "TARGET_NEON && !BYTES_BIG_ENDIAN"
1131
{
1132
  rtx zero_reg;
1133
  HOST_WIDE_INT num_bits = INTVAL (operands[2]);
1134
  const int width = GET_MODE_BITSIZE (mode);
1135
  const enum machine_mode bvecmode = (width == 128) ? V16QImode : V8QImode;
1136
  rtx (*gen_ext) (rtx, rtx, rtx, rtx) =
1137
    (width == 128) ? gen_neon_vextv16qi : gen_neon_vextv8qi;
1138
 
1139
  if (num_bits == width)
1140
    {
1141
      emit_move_insn (operands[0], operands[1]);
1142
      DONE;
1143
    }
1144
 
1145
  zero_reg = force_reg (bvecmode, CONST0_RTX (bvecmode));
1146
  operands[0] = gen_lowpart (bvecmode, operands[0]);
1147
  operands[1] = gen_lowpart (bvecmode, operands[1]);
1148
 
1149
  emit_insn (gen_ext (operands[0], operands[1], zero_reg,
1150
                      GEN_INT (num_bits / BITS_PER_UNIT)));
1151
  DONE;
1152
})
1153
 
1154
(define_expand "vec_shl_"
1155
  [(match_operand:VDQ 0 "s_register_operand" "")
1156
   (match_operand:VDQ 1 "s_register_operand" "")
1157
   (match_operand:SI 2 "const_multiple_of_8_operand" "")]
1158
  "TARGET_NEON && !BYTES_BIG_ENDIAN"
1159
{
1160
  rtx zero_reg;
1161
  HOST_WIDE_INT num_bits = INTVAL (operands[2]);
1162
  const int width = GET_MODE_BITSIZE (mode);
1163
  const enum machine_mode bvecmode = (width == 128) ? V16QImode : V8QImode;
1164
  rtx (*gen_ext) (rtx, rtx, rtx, rtx) =
1165
    (width == 128) ? gen_neon_vextv16qi : gen_neon_vextv8qi;
1166
 
1167
  if (num_bits == 0)
1168
    {
1169
      emit_move_insn (operands[0], CONST0_RTX (mode));
1170
      DONE;
1171
    }
1172
 
1173
  num_bits = width - num_bits;
1174
 
1175
  zero_reg = force_reg (bvecmode, CONST0_RTX (bvecmode));
1176
  operands[0] = gen_lowpart (bvecmode, operands[0]);
1177
  operands[1] = gen_lowpart (bvecmode, operands[1]);
1178
 
1179
  emit_insn (gen_ext (operands[0], zero_reg, operands[1],
1180
                      GEN_INT (num_bits / BITS_PER_UNIT)));
1181
  DONE;
1182
})
1183
 
1184
;; Helpers for quad-word reduction operations
1185
 
1186
; Add (or smin, smax...) the low N/2 elements of the N-element vector
1187
; operand[1] to the high N/2 elements of same. Put the result in operand[0], an
1188
; N/2-element vector.
1189
 
1190
(define_insn "quad_halves_v4si"
1191
  [(set (match_operand:V2SI 0 "s_register_operand" "=w")
1192
        (vqh_ops:V2SI
1193
          (vec_select:V2SI (match_operand:V4SI 1 "s_register_operand" "w")
1194
                           (parallel [(const_int 0) (const_int 1)]))
1195
          (vec_select:V2SI (match_dup 1)
1196
                           (parallel [(const_int 2) (const_int 3)]))))]
1197
  "TARGET_NEON"
1198
  ".32\t%P0, %e1, %f1"
1199
  [(set_attr "vqh_mnem" "")
1200
   (set (attr "neon_type")
1201
      (if_then_else (eq_attr "vqh_mnem" "vadd")
1202
                    (const_string "neon_int_1") (const_string "neon_int_5")))]
1203
)
1204
 
1205
(define_insn "quad_halves_v4sf"
1206
  [(set (match_operand:V2SF 0 "s_register_operand" "=w")
1207
        (vqhs_ops:V2SF
1208
          (vec_select:V2SF (match_operand:V4SF 1 "s_register_operand" "w")
1209
                           (parallel [(const_int 0) (const_int 1)]))
1210
          (vec_select:V2SF (match_dup 1)
1211
                           (parallel [(const_int 2) (const_int 3)]))))]
1212
  "TARGET_NEON && flag_unsafe_math_optimizations"
1213
  ".f32\t%P0, %e1, %f1"
1214
  [(set_attr "vqh_mnem" "")
1215
   (set (attr "neon_type")
1216
      (if_then_else (eq_attr "vqh_mnem" "vadd")
1217
                    (const_string "neon_int_1") (const_string "neon_int_5")))]
1218
)
1219
 
1220
(define_insn "quad_halves_v8hi"
1221
  [(set (match_operand:V4HI 0 "s_register_operand" "+w")
1222
        (vqh_ops:V4HI
1223
          (vec_select:V4HI (match_operand:V8HI 1 "s_register_operand" "w")
1224
                           (parallel [(const_int 0) (const_int 1)
1225
                                      (const_int 2) (const_int 3)]))
1226
          (vec_select:V4HI (match_dup 1)
1227
                           (parallel [(const_int 4) (const_int 5)
1228
                                      (const_int 6) (const_int 7)]))))]
1229
  "TARGET_NEON"
1230
  ".16\t%P0, %e1, %f1"
1231
  [(set_attr "vqh_mnem" "")
1232
   (set (attr "neon_type")
1233
      (if_then_else (eq_attr "vqh_mnem" "vadd")
1234
                    (const_string "neon_int_1") (const_string "neon_int_5")))]
1235
)
1236
 
1237
(define_insn "quad_halves_v16qi"
1238
  [(set (match_operand:V8QI 0 "s_register_operand" "+w")
1239
        (vqh_ops:V8QI
1240
          (vec_select:V8QI (match_operand:V16QI 1 "s_register_operand" "w")
1241
                           (parallel [(const_int 0) (const_int 1)
1242
                                      (const_int 2) (const_int 3)
1243
                                      (const_int 4) (const_int 5)
1244
                                      (const_int 6) (const_int 7)]))
1245
          (vec_select:V8QI (match_dup 1)
1246
                           (parallel [(const_int 8) (const_int 9)
1247
                                      (const_int 10) (const_int 11)
1248
                                      (const_int 12) (const_int 13)
1249
                                      (const_int 14) (const_int 15)]))))]
1250
  "TARGET_NEON"
1251
  ".8\t%P0, %e1, %f1"
1252
  [(set_attr "vqh_mnem" "")
1253
   (set (attr "neon_type")
1254
      (if_then_else (eq_attr "vqh_mnem" "vadd")
1255
                    (const_string "neon_int_1") (const_string "neon_int_5")))]
1256
)
1257
 
1258
(define_expand "move_hi_quad_"
1259
 [(match_operand:ANY128 0 "s_register_operand" "")
1260
  (match_operand: 1 "s_register_operand" "")]
1261
 "TARGET_NEON"
1262
{
1263
  emit_move_insn (simplify_gen_subreg (mode, operands[0], mode,
1264
                                       GET_MODE_SIZE (mode)),
1265
                  operands[1]);
1266
  DONE;
1267
})
1268
 
1269
(define_expand "move_lo_quad_"
1270
 [(match_operand:ANY128 0 "s_register_operand" "")
1271
  (match_operand: 1 "s_register_operand" "")]
1272
 "TARGET_NEON"
1273
{
1274
  emit_move_insn (simplify_gen_subreg (mode, operands[0],
1275
                                       mode, 0),
1276
                  operands[1]);
1277
  DONE;
1278
})
1279
 
1280
;; Reduction operations
1281
 
1282
(define_expand "reduc_splus_"
1283
  [(match_operand:VD 0 "s_register_operand" "")
1284
   (match_operand:VD 1 "s_register_operand" "")]
1285
  "TARGET_NEON && (! || flag_unsafe_math_optimizations)"
1286
{
1287
  neon_pairwise_reduce (operands[0], operands[1], mode,
1288
                        &gen_neon_vpadd_internal);
1289
  DONE;
1290
})
1291
 
1292
(define_expand "reduc_splus_"
1293
  [(match_operand:VQ 0 "s_register_operand" "")
1294
   (match_operand:VQ 1 "s_register_operand" "")]
1295
  "TARGET_NEON && (! || flag_unsafe_math_optimizations)
1296
   && !BYTES_BIG_ENDIAN"
1297
{
1298
  rtx step1 = gen_reg_rtx (mode);
1299
  rtx res_d = gen_reg_rtx (mode);
1300
 
1301
  emit_insn (gen_quad_halves_plus (step1, operands[1]));
1302
  emit_insn (gen_reduc_splus_ (res_d, step1));
1303
  emit_insn (gen_move_lo_quad_ (operands[0], res_d));
1304
 
1305
  DONE;
1306
})
1307
 
1308
(define_insn "reduc_splus_v2di"
1309
  [(set (match_operand:V2DI 0 "s_register_operand" "=w")
1310
        (unspec:V2DI [(match_operand:V2DI 1 "s_register_operand" "w")]
1311
                     UNSPEC_VPADD))]
1312
  "TARGET_NEON && !BYTES_BIG_ENDIAN"
1313
  "vadd.i64\t%e0, %e1, %f1"
1314
  [(set_attr "neon_type" "neon_int_1")]
1315
)
1316
 
1317
;; NEON does not distinguish between signed and unsigned addition except on
1318
;; widening operations.
1319
(define_expand "reduc_uplus_"
1320
  [(match_operand:VDQI 0 "s_register_operand" "")
1321
   (match_operand:VDQI 1 "s_register_operand" "")]
1322
  "TARGET_NEON && ( || !BYTES_BIG_ENDIAN)"
1323
{
1324
  emit_insn (gen_reduc_splus_ (operands[0], operands[1]));
1325
  DONE;
1326
})
1327
 
1328
(define_expand "reduc_smin_"
1329
  [(match_operand:VD 0 "s_register_operand" "")
1330
   (match_operand:VD 1 "s_register_operand" "")]
1331
  "TARGET_NEON && (! || flag_unsafe_math_optimizations)"
1332
{
1333
  neon_pairwise_reduce (operands[0], operands[1], mode,
1334
                        &gen_neon_vpsmin);
1335
  DONE;
1336
})
1337
 
1338
(define_expand "reduc_smin_"
1339
  [(match_operand:VQ 0 "s_register_operand" "")
1340
   (match_operand:VQ 1 "s_register_operand" "")]
1341
  "TARGET_NEON && (! || flag_unsafe_math_optimizations)
1342
   && !BYTES_BIG_ENDIAN"
1343
{
1344
  rtx step1 = gen_reg_rtx (mode);
1345
  rtx res_d = gen_reg_rtx (mode);
1346
 
1347
  emit_insn (gen_quad_halves_smin (step1, operands[1]));
1348
  emit_insn (gen_reduc_smin_ (res_d, step1));
1349
  emit_insn (gen_move_lo_quad_ (operands[0], res_d));
1350
 
1351
  DONE;
1352
})
1353
 
1354
(define_expand "reduc_smax_"
1355
  [(match_operand:VD 0 "s_register_operand" "")
1356
   (match_operand:VD 1 "s_register_operand" "")]
1357
  "TARGET_NEON && (! || flag_unsafe_math_optimizations)"
1358
{
1359
  neon_pairwise_reduce (operands[0], operands[1], mode,
1360
                        &gen_neon_vpsmax);
1361
  DONE;
1362
})
1363
 
1364
(define_expand "reduc_smax_"
1365
  [(match_operand:VQ 0 "s_register_operand" "")
1366
   (match_operand:VQ 1 "s_register_operand" "")]
1367
  "TARGET_NEON && (! || flag_unsafe_math_optimizations)
1368
   && !BYTES_BIG_ENDIAN"
1369
{
1370
  rtx step1 = gen_reg_rtx (mode);
1371
  rtx res_d = gen_reg_rtx (mode);
1372
 
1373
  emit_insn (gen_quad_halves_smax (step1, operands[1]));
1374
  emit_insn (gen_reduc_smax_ (res_d, step1));
1375
  emit_insn (gen_move_lo_quad_ (operands[0], res_d));
1376
 
1377
  DONE;
1378
})
1379
 
1380
(define_expand "reduc_umin_"
1381
  [(match_operand:VDI 0 "s_register_operand" "")
1382
   (match_operand:VDI 1 "s_register_operand" "")]
1383
  "TARGET_NEON"
1384
{
1385
  neon_pairwise_reduce (operands[0], operands[1], mode,
1386
                        &gen_neon_vpumin);
1387
  DONE;
1388
})
1389
 
1390
(define_expand "reduc_umin_"
1391
  [(match_operand:VQI 0 "s_register_operand" "")
1392
   (match_operand:VQI 1 "s_register_operand" "")]
1393
  "TARGET_NEON && !BYTES_BIG_ENDIAN"
1394
{
1395
  rtx step1 = gen_reg_rtx (mode);
1396
  rtx res_d = gen_reg_rtx (mode);
1397
 
1398
  emit_insn (gen_quad_halves_umin (step1, operands[1]));
1399
  emit_insn (gen_reduc_umin_ (res_d, step1));
1400
  emit_insn (gen_move_lo_quad_ (operands[0], res_d));
1401
 
1402
  DONE;
1403
})
1404
 
1405
(define_expand "reduc_umax_"
1406
  [(match_operand:VDI 0 "s_register_operand" "")
1407
   (match_operand:VDI 1 "s_register_operand" "")]
1408
  "TARGET_NEON"
1409
{
1410
  neon_pairwise_reduce (operands[0], operands[1], mode,
1411
                        &gen_neon_vpumax);
1412
  DONE;
1413
})
1414
 
1415
(define_expand "reduc_umax_"
1416
  [(match_operand:VQI 0 "s_register_operand" "")
1417
   (match_operand:VQI 1 "s_register_operand" "")]
1418
  "TARGET_NEON && !BYTES_BIG_ENDIAN"
1419
{
1420
  rtx step1 = gen_reg_rtx (mode);
1421
  rtx res_d = gen_reg_rtx (mode);
1422
 
1423
  emit_insn (gen_quad_halves_umax (step1, operands[1]));
1424
  emit_insn (gen_reduc_umax_ (res_d, step1));
1425
  emit_insn (gen_move_lo_quad_ (operands[0], res_d));
1426
 
1427
  DONE;
1428
})
1429
 
1430
(define_insn "neon_vpadd_internal"
1431
  [(set (match_operand:VD 0 "s_register_operand" "=w")
1432
        (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
1433
                    (match_operand:VD 2 "s_register_operand" "w")]
1434
                   UNSPEC_VPADD))]
1435
  "TARGET_NEON"
1436
  "vpadd.\t%P0, %P1, %P2"
1437
  ;; Assume this schedules like vadd.
1438
  [(set (attr "neon_type")
1439
      (if_then_else (match_test "")
1440
                    (if_then_else (match_test "")
1441
                                  (const_string "neon_fp_vadd_ddd_vabs_dd")
1442
                                  (const_string "neon_fp_vadd_qqq_vabs_qq"))
1443
                    (const_string "neon_int_1")))]
1444
)
1445
 
1446
(define_insn "neon_vpsmin"
1447
  [(set (match_operand:VD 0 "s_register_operand" "=w")
1448
        (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
1449
                    (match_operand:VD 2 "s_register_operand" "w")]
1450
                   UNSPEC_VPSMIN))]
1451
  "TARGET_NEON"
1452
  "vpmin.\t%P0, %P1, %P2"
1453
  ;; Assume this schedules like vmin.
1454
  [(set (attr "neon_type")
1455
      (if_then_else (match_test "")
1456
                    (const_string "neon_fp_vadd_ddd_vabs_dd")
1457
                    (const_string "neon_int_5")))]
1458
)
1459
 
1460
(define_insn "neon_vpsmax"
1461
  [(set (match_operand:VD 0 "s_register_operand" "=w")
1462
        (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
1463
                    (match_operand:VD 2 "s_register_operand" "w")]
1464
                   UNSPEC_VPSMAX))]
1465
  "TARGET_NEON"
1466
  "vpmax.\t%P0, %P1, %P2"
1467
  ;; Assume this schedules like vmax.
1468
  [(set (attr "neon_type")
1469
      (if_then_else (match_test "")
1470
                    (const_string "neon_fp_vadd_ddd_vabs_dd")
1471
                    (const_string "neon_int_5")))]
1472
)
1473
 
1474
(define_insn "neon_vpumin"
1475
  [(set (match_operand:VDI 0 "s_register_operand" "=w")
1476
        (unspec:VDI [(match_operand:VDI 1 "s_register_operand" "w")
1477
                     (match_operand:VDI 2 "s_register_operand" "w")]
1478
                   UNSPEC_VPUMIN))]
1479
  "TARGET_NEON"
1480
  "vpmin.\t%P0, %P1, %P2"
1481
  ;; Assume this schedules like umin.
1482
  [(set_attr "neon_type" "neon_int_5")]
1483
)
1484
 
1485
(define_insn "neon_vpumax"
1486
  [(set (match_operand:VDI 0 "s_register_operand" "=w")
1487
        (unspec:VDI [(match_operand:VDI 1 "s_register_operand" "w")
1488
                     (match_operand:VDI 2 "s_register_operand" "w")]
1489
                   UNSPEC_VPUMAX))]
1490
  "TARGET_NEON"
1491
  "vpmax.\t%P0, %P1, %P2"
1492
  ;; Assume this schedules like umax.
1493
  [(set_attr "neon_type" "neon_int_5")]
1494
)
1495
 
1496
;; Saturating arithmetic
1497
 
1498
; NOTE: Neon supports many more saturating variants of instructions than the
1499
; following, but these are all GCC currently understands.
1500
; FIXME: Actually, GCC doesn't know how to create saturating add/sub by itself
1501
; yet either, although these patterns may be used by intrinsics when they're
1502
; added.
1503
 
1504
(define_insn "*ss_add_neon"
1505
  [(set (match_operand:VD 0 "s_register_operand" "=w")
1506
       (ss_plus:VD (match_operand:VD 1 "s_register_operand" "w")
1507
                   (match_operand:VD 2 "s_register_operand" "w")))]
1508
  "TARGET_NEON"
1509
  "vqadd.\t%P0, %P1, %P2"
1510
  [(set_attr "neon_type" "neon_int_4")]
1511
)
1512
 
1513
(define_insn "*us_add_neon"
1514
  [(set (match_operand:VD 0 "s_register_operand" "=w")
1515
       (us_plus:VD (match_operand:VD 1 "s_register_operand" "w")
1516
                   (match_operand:VD 2 "s_register_operand" "w")))]
1517
  "TARGET_NEON"
1518
  "vqadd.\t%P0, %P1, %P2"
1519
  [(set_attr "neon_type" "neon_int_4")]
1520
)
1521
 
1522
(define_insn "*ss_sub_neon"
1523
  [(set (match_operand:VD 0 "s_register_operand" "=w")
1524
       (ss_minus:VD (match_operand:VD 1 "s_register_operand" "w")
1525
                    (match_operand:VD 2 "s_register_operand" "w")))]
1526
  "TARGET_NEON"
1527
  "vqsub.\t%P0, %P1, %P2"
1528
  [(set_attr "neon_type" "neon_int_5")]
1529
)
1530
 
1531
(define_insn "*us_sub_neon"
1532
  [(set (match_operand:VD 0 "s_register_operand" "=w")
1533
       (us_minus:VD (match_operand:VD 1 "s_register_operand" "w")
1534
                    (match_operand:VD 2 "s_register_operand" "w")))]
1535
  "TARGET_NEON"
1536
  "vqsub.\t%P0, %P1, %P2"
1537
  [(set_attr "neon_type" "neon_int_5")]
1538
)
1539
 
1540
;; Conditional instructions.  These are comparisons with conditional moves for
1541
;; vectors.  They perform the assignment:
1542
;;
1543
;;     Vop0 = (Vop4  Vop5) ? Vop1 : Vop2;
1544
;;
1545
;; where op3 is <, <=, ==, !=, >= or >.  Operations are performed
1546
;; element-wise.
1547
 
1548
(define_expand "vcond"
1549
  [(set (match_operand:VDQW 0 "s_register_operand" "")
1550
        (if_then_else:VDQW
1551
          (match_operator 3 "arm_comparison_operator"
1552
            [(match_operand:VDQW 4 "s_register_operand" "")
1553
             (match_operand:VDQW 5 "nonmemory_operand" "")])
1554
          (match_operand:VDQW 1 "s_register_operand" "")
1555
          (match_operand:VDQW 2 "s_register_operand" "")))]
1556
  "TARGET_NEON && (! || flag_unsafe_math_optimizations)"
1557
{
1558
  rtx mask;
1559
  int inverse = 0, immediate_zero = 0;
1560
  /* See the description of "magic" bits in the 'T' case of
1561
     arm_print_operand.  */
1562
  HOST_WIDE_INT magic_word = (mode == V2SFmode || mode == V4SFmode)
1563
                             ? 3 : 1;
1564
  rtx magic_rtx = GEN_INT (magic_word);
1565
 
1566
  mask = gen_reg_rtx (mode);
1567
 
1568
  if (operands[5] == CONST0_RTX (mode))
1569
    immediate_zero = 1;
1570
  else if (!REG_P (operands[5]))
1571
    operands[5] = force_reg (mode, operands[5]);
1572
 
1573
  switch (GET_CODE (operands[3]))
1574
    {
1575
    case GE:
1576
      emit_insn (gen_neon_vcge (mask, operands[4], operands[5],
1577
                                      magic_rtx));
1578
      break;
1579
 
1580
    case GT:
1581
      emit_insn (gen_neon_vcgt (mask, operands[4], operands[5],
1582
                                      magic_rtx));
1583
      break;
1584
 
1585
    case EQ:
1586
      emit_insn (gen_neon_vceq (mask, operands[4], operands[5],
1587
                                      magic_rtx));
1588
      break;
1589
 
1590
    case LE:
1591
      if (immediate_zero)
1592
        emit_insn (gen_neon_vcle (mask, operands[4], operands[5],
1593
                                        magic_rtx));
1594
      else
1595
        emit_insn (gen_neon_vcge (mask, operands[5], operands[4],
1596
                                        magic_rtx));
1597
      break;
1598
 
1599
    case LT:
1600
      if (immediate_zero)
1601
        emit_insn (gen_neon_vclt (mask, operands[4], operands[5],
1602
                                        magic_rtx));
1603
      else
1604
        emit_insn (gen_neon_vcgt (mask, operands[5], operands[4],
1605
                                        magic_rtx));
1606
      break;
1607
 
1608
    case NE:
1609
      emit_insn (gen_neon_vceq (mask, operands[4], operands[5],
1610
                                      magic_rtx));
1611
      inverse = 1;
1612
      break;
1613
 
1614
    default:
1615
      gcc_unreachable ();
1616
    }
1617
 
1618
  if (inverse)
1619
    emit_insn (gen_neon_vbsl (operands[0], mask, operands[2],
1620
                                    operands[1]));
1621
  else
1622
    emit_insn (gen_neon_vbsl (operands[0], mask, operands[1],
1623
                                    operands[2]));
1624
 
1625
  DONE;
1626
})
1627
 
1628
(define_expand "vcondu"
1629
  [(set (match_operand:VDQIW 0 "s_register_operand" "")
1630
        (if_then_else:VDQIW
1631
          (match_operator 3 "arm_comparison_operator"
1632
            [(match_operand:VDQIW 4 "s_register_operand" "")
1633
             (match_operand:VDQIW 5 "s_register_operand" "")])
1634
          (match_operand:VDQIW 1 "s_register_operand" "")
1635
          (match_operand:VDQIW 2 "s_register_operand" "")))]
1636
  "TARGET_NEON"
1637
{
1638
  rtx mask;
1639
  int inverse = 0, immediate_zero = 0;
1640
 
1641
  mask = gen_reg_rtx (mode);
1642
 
1643
  if (operands[5] == CONST0_RTX (mode))
1644
    immediate_zero = 1;
1645
  else if (!REG_P (operands[5]))
1646
    operands[5] = force_reg (mode, operands[5]);
1647
 
1648
  switch (GET_CODE (operands[3]))
1649
    {
1650
    case GEU:
1651
      emit_insn (gen_neon_vcge (mask, operands[4], operands[5],
1652
                                      const0_rtx));
1653
      break;
1654
 
1655
    case GTU:
1656
      emit_insn (gen_neon_vcgt (mask, operands[4], operands[5],
1657
                                      const0_rtx));
1658
      break;
1659
 
1660
    case EQ:
1661
      emit_insn (gen_neon_vceq (mask, operands[4], operands[5],
1662
                                      const0_rtx));
1663
      break;
1664
 
1665
    case LEU:
1666
      if (immediate_zero)
1667
        emit_insn (gen_neon_vcle (mask, operands[4], operands[5],
1668
                                        const0_rtx));
1669
      else
1670
        emit_insn (gen_neon_vcge (mask, operands[5], operands[4],
1671
                                        const0_rtx));
1672
      break;
1673
 
1674
    case LTU:
1675
      if (immediate_zero)
1676
        emit_insn (gen_neon_vclt (mask, operands[4], operands[5],
1677
                                        const0_rtx));
1678
      else
1679
        emit_insn (gen_neon_vcgt (mask, operands[5], operands[4],
1680
                                        const0_rtx));
1681
      break;
1682
 
1683
    case NE:
1684
      emit_insn (gen_neon_vceq (mask, operands[4], operands[5],
1685
                                      const0_rtx));
1686
      inverse = 1;
1687
      break;
1688
 
1689
    default:
1690
      gcc_unreachable ();
1691
    }
1692
 
1693
  if (inverse)
1694
    emit_insn (gen_neon_vbsl (operands[0], mask, operands[2],
1695
                                    operands[1]));
1696
  else
1697
    emit_insn (gen_neon_vbsl (operands[0], mask, operands[1],
1698
                                    operands[2]));
1699
 
1700
  DONE;
1701
})
1702
 
1703
;; Patterns for builtins.
1704
 
1705
; good for plain vadd, vaddq.
1706
 
1707
(define_expand "neon_vadd"
1708
  [(match_operand:VDQX 0 "s_register_operand" "=w")
1709
   (match_operand:VDQX 1 "s_register_operand" "w")
1710
   (match_operand:VDQX 2 "s_register_operand" "w")
1711
   (match_operand:SI 3 "immediate_operand" "i")]
1712
  "TARGET_NEON"
1713
{
1714
  if (! || flag_unsafe_math_optimizations)
1715
    emit_insn (gen_add3 (operands[0], operands[1], operands[2]));
1716
  else
1717
    emit_insn (gen_neon_vadd_unspec (operands[0], operands[1],
1718
                                           operands[2]));
1719
  DONE;
1720
})
1721
 
1722
; Note that NEON operations don't support the full IEEE 754 standard: in
1723
; particular, denormal values are flushed to zero.  This means that GCC cannot
1724
; use those instructions for autovectorization, etc. unless
1725
; -funsafe-math-optimizations is in effect (in which case flush-to-zero
1726
; behaviour is permissible).  Intrinsic operations (provided by the arm_neon.h
1727
; header) must work in either case: if -funsafe-math-optimizations is given,
1728
; intrinsics expand to "canonical" RTL where possible, otherwise intrinsics
1729
; expand to unspecs (which may potentially limit the extent to which they might
1730
; be optimized by generic code).
1731
 
1732
; Used for intrinsics when flag_unsafe_math_optimizations is false.
1733
 
1734
(define_insn "neon_vadd_unspec"
1735
  [(set (match_operand:VDQX 0 "s_register_operand" "=w")
1736
        (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w")
1737
                      (match_operand:VDQX 2 "s_register_operand" "w")]
1738
                     UNSPEC_VADD))]
1739
  "TARGET_NEON"
1740
  "vadd.\t%0, %1, %2"
1741
  [(set (attr "neon_type")
1742
      (if_then_else (match_test "")
1743
                    (if_then_else (match_test "")
1744
                                  (const_string "neon_fp_vadd_ddd_vabs_dd")
1745
                                  (const_string "neon_fp_vadd_qqq_vabs_qq"))
1746
                    (const_string "neon_int_1")))]
1747
)
1748
 
1749
; operand 3 represents in bits:
1750
;  bit 0: signed (vs unsigned).
1751
;  bit 1: rounding (vs none).
1752
 
1753
(define_insn "neon_vaddl"
1754
  [(set (match_operand: 0 "s_register_operand" "=w")
1755
        (unspec: [(match_operand:VDI 1 "s_register_operand" "w")
1756
                           (match_operand:VDI 2 "s_register_operand" "w")
1757
                           (match_operand:SI 3 "immediate_operand" "i")]
1758
                          UNSPEC_VADDL))]
1759
  "TARGET_NEON"
1760
  "vaddl.%T3%#\t%q0, %P1, %P2"
1761
  [(set_attr "neon_type" "neon_int_3")]
1762
)
1763
 
1764
(define_insn "neon_vaddw"
1765
  [(set (match_operand: 0 "s_register_operand" "=w")
1766
        (unspec: [(match_operand: 1 "s_register_operand" "w")
1767
                           (match_operand:VDI 2 "s_register_operand" "w")
1768
                           (match_operand:SI 3 "immediate_operand" "i")]
1769
                          UNSPEC_VADDW))]
1770
  "TARGET_NEON"
1771
  "vaddw.%T3%#\t%q0, %q1, %P2"
1772
  [(set_attr "neon_type" "neon_int_2")]
1773
)
1774
 
1775
; vhadd and vrhadd.
1776
 
1777
(define_insn "neon_vhadd"
1778
  [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
1779
        (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
1780
                       (match_operand:VDQIW 2 "s_register_operand" "w")
1781
                       (match_operand:SI 3 "immediate_operand" "i")]
1782
                      UNSPEC_VHADD))]
1783
  "TARGET_NEON"
1784
  "v%O3hadd.%T3%#\t%0, %1, %2"
1785
  [(set_attr "neon_type" "neon_int_4")]
1786
)
1787
 
1788
(define_insn "neon_vqadd"
1789
  [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
1790
        (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
1791
                       (match_operand:VDQIX 2 "s_register_operand" "w")
1792
                       (match_operand:SI 3 "immediate_operand" "i")]
1793
                     UNSPEC_VQADD))]
1794
  "TARGET_NEON"
1795
  "vqadd.%T3%#\t%0, %1, %2"
1796
  [(set_attr "neon_type" "neon_int_4")]
1797
)
1798
 
1799
(define_insn "neon_vaddhn"
1800
  [(set (match_operand: 0 "s_register_operand" "=w")
1801
        (unspec: [(match_operand:VN 1 "s_register_operand" "w")
1802
                            (match_operand:VN 2 "s_register_operand" "w")
1803
                            (match_operand:SI 3 "immediate_operand" "i")]
1804
                           UNSPEC_VADDHN))]
1805
  "TARGET_NEON"
1806
  "v%O3addhn.\t%P0, %q1, %q2"
1807
  [(set_attr "neon_type" "neon_int_4")]
1808
)
1809
 
1810
;; We cannot replace this unspec with mul3 because of the odd
1811
;; polynomial multiplication case that can specified by operand 3.
1812
(define_insn "neon_vmul"
1813
  [(set (match_operand:VDQW 0 "s_register_operand" "=w")
1814
        (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w")
1815
                      (match_operand:VDQW 2 "s_register_operand" "w")
1816
                      (match_operand:SI 3 "immediate_operand" "i")]
1817
                     UNSPEC_VMUL))]
1818
  "TARGET_NEON"
1819
  "vmul.%F3%#\t%0, %1, %2"
1820
  [(set (attr "neon_type")
1821
      (if_then_else (match_test "")
1822
                    (if_then_else (match_test "")
1823
                                  (const_string "neon_fp_vadd_ddd_vabs_dd")
1824
                                  (const_string "neon_fp_vadd_qqq_vabs_qq"))
1825
                    (if_then_else (match_test "")
1826
                                  (if_then_else
1827
                                    (match_test "")
1828
                                    (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
1829
                                    (const_string "neon_mul_qqq_8_16_32_ddd_32"))
1830
                                  (if_then_else (match_test "")
1831
                                    (const_string "neon_mul_qqq_8_16_32_ddd_32")
1832
                                    (const_string "neon_mul_qqq_8_16_32_ddd_32")))))]
1833
)
1834
 
1835
(define_expand "neon_vmla"
1836
  [(match_operand:VDQW 0 "s_register_operand" "=w")
1837
   (match_operand:VDQW 1 "s_register_operand" "0")
1838
   (match_operand:VDQW 2 "s_register_operand" "w")
1839
   (match_operand:VDQW 3 "s_register_operand" "w")
1840
   (match_operand:SI 4 "immediate_operand" "i")]
1841
  "TARGET_NEON"
1842
{
1843
  if (! || flag_unsafe_math_optimizations)
1844
    emit_insn (gen_mul3add_neon (operands[0], operands[1],
1845
                                             operands[2], operands[3]));
1846
  else
1847
    emit_insn (gen_neon_vmla_unspec (operands[0], operands[1],
1848
                                           operands[2], operands[3]));
1849
  DONE;
1850
})
1851
 
1852
; Used for intrinsics when flag_unsafe_math_optimizations is false.
1853
 
1854
(define_insn "neon_vmla_unspec"
1855
  [(set (match_operand:VDQ 0 "s_register_operand" "=w")
1856
        (unspec:VDQ [(match_operand:VDQ 1 "s_register_operand" "0")
1857
                     (match_operand:VDQ 2 "s_register_operand" "w")
1858
                     (match_operand:VDQ 3 "s_register_operand" "w")]
1859
                    UNSPEC_VMLA))]
1860
  "TARGET_NEON"
1861
  "vmla.\t%0, %2, %3"
1862
  [(set (attr "neon_type")
1863
      (if_then_else (match_test "")
1864
                    (if_then_else (match_test "")
1865
                                  (const_string "neon_fp_vmla_ddd")
1866
                                  (const_string "neon_fp_vmla_qqq"))
1867
                    (if_then_else (match_test "")
1868
                                  (if_then_else
1869
                                    (match_test "")
1870
                                    (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
1871
                                    (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
1872
                                  (if_then_else (match_test "")
1873
                                    (const_string "neon_mla_qqq_8_16")
1874
                                    (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
1875
)
1876
 
1877
(define_insn "neon_vmlal"
1878
  [(set (match_operand: 0 "s_register_operand" "=w")
1879
        (unspec: [(match_operand: 1 "s_register_operand" "0")
1880
                           (match_operand:VW 2 "s_register_operand" "w")
1881
                           (match_operand:VW 3 "s_register_operand" "w")
1882
                           (match_operand:SI 4 "immediate_operand" "i")]
1883
                          UNSPEC_VMLAL))]
1884
  "TARGET_NEON"
1885
  "vmlal.%T4%#\t%q0, %P2, %P3"
1886
  [(set (attr "neon_type")
1887
     (if_then_else (match_test "")
1888
                   (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
1889
                   (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
1890
)
1891
 
1892
(define_expand "neon_vmls"
1893
  [(match_operand:VDQW 0 "s_register_operand" "=w")
1894
   (match_operand:VDQW 1 "s_register_operand" "0")
1895
   (match_operand:VDQW 2 "s_register_operand" "w")
1896
   (match_operand:VDQW 3 "s_register_operand" "w")
1897
   (match_operand:SI 4 "immediate_operand" "i")]
1898
  "TARGET_NEON"
1899
{
1900
  if (! || flag_unsafe_math_optimizations)
1901
    emit_insn (gen_mul3negadd_neon (operands[0],
1902
                 operands[1], operands[2], operands[3]));
1903
  else
1904
    emit_insn (gen_neon_vmls_unspec (operands[0], operands[1],
1905
                                           operands[2], operands[3]));
1906
  DONE;
1907
})
1908
 
1909
; Used for intrinsics when flag_unsafe_math_optimizations is false.
1910
 
1911
(define_insn "neon_vmls_unspec"
1912
  [(set (match_operand:VDQ 0 "s_register_operand" "=w")
1913
        (unspec:VDQ [(match_operand:VDQ 1 "s_register_operand" "0")
1914
                     (match_operand:VDQ 2 "s_register_operand" "w")
1915
                     (match_operand:VDQ 3 "s_register_operand" "w")]
1916
                    UNSPEC_VMLS))]
1917
  "TARGET_NEON"
1918
  "vmls.\t%0, %2, %3"
1919
  [(set (attr "neon_type")
1920
      (if_then_else (match_test "")
1921
                    (if_then_else (match_test "")
1922
                                  (const_string "neon_fp_vmla_ddd")
1923
                                  (const_string "neon_fp_vmla_qqq"))
1924
                    (if_then_else (match_test "")
1925
                                  (if_then_else
1926
                                    (match_test "")
1927
                                    (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
1928
                                    (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
1929
                                  (if_then_else
1930
                                    (match_test "")
1931
                                    (const_string "neon_mla_qqq_8_16")
1932
                                    (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
1933
)
1934
 
1935
(define_insn "neon_vmlsl"
1936
  [(set (match_operand: 0 "s_register_operand" "=w")
1937
        (unspec: [(match_operand: 1 "s_register_operand" "0")
1938
                           (match_operand:VW 2 "s_register_operand" "w")
1939
                           (match_operand:VW 3 "s_register_operand" "w")
1940
                           (match_operand:SI 4 "immediate_operand" "i")]
1941
                          UNSPEC_VMLSL))]
1942
  "TARGET_NEON"
1943
  "vmlsl.%T4%#\t%q0, %P2, %P3"
1944
  [(set (attr "neon_type")
1945
     (if_then_else (match_test "")
1946
                   (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
1947
                   (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
1948
)
1949
 
1950
(define_insn "neon_vqdmulh"
1951
  [(set (match_operand:VMDQI 0 "s_register_operand" "=w")
1952
        (unspec:VMDQI [(match_operand:VMDQI 1 "s_register_operand" "w")
1953
                       (match_operand:VMDQI 2 "s_register_operand" "w")
1954
                       (match_operand:SI 3 "immediate_operand" "i")]
1955
                      UNSPEC_VQDMULH))]
1956
  "TARGET_NEON"
1957
  "vq%O3dmulh.\t%0, %1, %2"
1958
  [(set (attr "neon_type")
1959
     (if_then_else (match_test "")
1960
        (if_then_else (match_test "")
1961
                      (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
1962
                      (const_string "neon_mul_qqq_8_16_32_ddd_32"))
1963
        (if_then_else (match_test "")
1964
                      (const_string "neon_mul_qqq_8_16_32_ddd_32")
1965
                      (const_string "neon_mul_qqq_8_16_32_ddd_32"))))]
1966
)
1967
 
1968
(define_insn "neon_vqdmlal"
1969
  [(set (match_operand: 0 "s_register_operand" "=w")
1970
        (unspec: [(match_operand: 1 "s_register_operand" "0")
1971
                           (match_operand:VMDI 2 "s_register_operand" "w")
1972
                           (match_operand:VMDI 3 "s_register_operand" "w")
1973
                           (match_operand:SI 4 "immediate_operand" "i")]
1974
                          UNSPEC_VQDMLAL))]
1975
  "TARGET_NEON"
1976
  "vqdmlal.\t%q0, %P2, %P3"
1977
  [(set (attr "neon_type")
1978
     (if_then_else (match_test "")
1979
                   (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
1980
                   (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
1981
)
1982
 
1983
(define_insn "neon_vqdmlsl"
1984
  [(set (match_operand: 0 "s_register_operand" "=w")
1985
        (unspec: [(match_operand: 1 "s_register_operand" "0")
1986
                           (match_operand:VMDI 2 "s_register_operand" "w")
1987
                           (match_operand:VMDI 3 "s_register_operand" "w")
1988
                           (match_operand:SI 4 "immediate_operand" "i")]
1989
                          UNSPEC_VQDMLSL))]
1990
  "TARGET_NEON"
1991
  "vqdmlsl.\t%q0, %P2, %P3"
1992
  [(set (attr "neon_type")
1993
     (if_then_else (match_test "")
1994
                   (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
1995
                   (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
1996
)
1997
 
1998
(define_insn "neon_vmull"
1999
  [(set (match_operand: 0 "s_register_operand" "=w")
2000
        (unspec: [(match_operand:VW 1 "s_register_operand" "w")
2001
                           (match_operand:VW 2 "s_register_operand" "w")
2002
                           (match_operand:SI 3 "immediate_operand" "i")]
2003
                          UNSPEC_VMULL))]
2004
  "TARGET_NEON"
2005
  "vmull.%T3%#\t%q0, %P1, %P2"
2006
  [(set (attr "neon_type")
2007
     (if_then_else (match_test "")
2008
                   (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
2009
                   (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
2010
)
2011
 
2012
(define_insn "neon_vqdmull"
2013
  [(set (match_operand: 0 "s_register_operand" "=w")
2014
        (unspec: [(match_operand:VMDI 1 "s_register_operand" "w")
2015
                           (match_operand:VMDI 2 "s_register_operand" "w")
2016
                           (match_operand:SI 3 "immediate_operand" "i")]
2017
                          UNSPEC_VQDMULL))]
2018
  "TARGET_NEON"
2019
  "vqdmull.\t%q0, %P1, %P2"
2020
  [(set (attr "neon_type")
2021
     (if_then_else (match_test "")
2022
                   (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
2023
                   (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
2024
)
2025
 
2026
(define_expand "neon_vsub"
2027
  [(match_operand:VDQX 0 "s_register_operand" "=w")
2028
   (match_operand:VDQX 1 "s_register_operand" "w")
2029
   (match_operand:VDQX 2 "s_register_operand" "w")
2030
   (match_operand:SI 3 "immediate_operand" "i")]
2031
  "TARGET_NEON"
2032
{
2033
  if (! || flag_unsafe_math_optimizations)
2034
    emit_insn (gen_sub3 (operands[0], operands[1], operands[2]));
2035
  else
2036
    emit_insn (gen_neon_vsub_unspec (operands[0], operands[1],
2037
                                           operands[2]));
2038
  DONE;
2039
})
2040
 
2041
; Used for intrinsics when flag_unsafe_math_optimizations is false.
2042
 
2043
(define_insn "neon_vsub_unspec"
2044
  [(set (match_operand:VDQX 0 "s_register_operand" "=w")
2045
        (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w")
2046
                      (match_operand:VDQX 2 "s_register_operand" "w")]
2047
                     UNSPEC_VSUB))]
2048
  "TARGET_NEON"
2049
  "vsub.\t%0, %1, %2"
2050
  [(set (attr "neon_type")
2051
      (if_then_else (match_test "")
2052
                    (if_then_else (match_test "")
2053
                                  (const_string "neon_fp_vadd_ddd_vabs_dd")
2054
                                  (const_string "neon_fp_vadd_qqq_vabs_qq"))
2055
                    (const_string "neon_int_2")))]
2056
)
2057
 
2058
(define_insn "neon_vsubl"
2059
  [(set (match_operand: 0 "s_register_operand" "=w")
2060
        (unspec: [(match_operand:VDI 1 "s_register_operand" "w")
2061
                           (match_operand:VDI 2 "s_register_operand" "w")
2062
                           (match_operand:SI 3 "immediate_operand" "i")]
2063
                          UNSPEC_VSUBL))]
2064
  "TARGET_NEON"
2065
  "vsubl.%T3%#\t%q0, %P1, %P2"
2066
  [(set_attr "neon_type" "neon_int_2")]
2067
)
2068
 
2069
(define_insn "neon_vsubw"
2070
  [(set (match_operand: 0 "s_register_operand" "=w")
2071
        (unspec: [(match_operand: 1 "s_register_operand" "w")
2072
                           (match_operand:VDI 2 "s_register_operand" "w")
2073
                           (match_operand:SI 3 "immediate_operand" "i")]
2074
                          UNSPEC_VSUBW))]
2075
  "TARGET_NEON"
2076
  "vsubw.%T3%#\t%q0, %q1, %P2"
2077
  [(set_attr "neon_type" "neon_int_2")]
2078
)
2079
 
2080
(define_insn "neon_vqsub"
2081
  [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
2082
        (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
2083
                       (match_operand:VDQIX 2 "s_register_operand" "w")
2084
                       (match_operand:SI 3 "immediate_operand" "i")]
2085
                      UNSPEC_VQSUB))]
2086
  "TARGET_NEON"
2087
  "vqsub.%T3%#\t%0, %1, %2"
2088
  [(set_attr "neon_type" "neon_int_5")]
2089
)
2090
 
2091
(define_insn "neon_vhsub"
2092
  [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2093
        (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2094
                       (match_operand:VDQIW 2 "s_register_operand" "w")
2095
                       (match_operand:SI 3 "immediate_operand" "i")]
2096
                      UNSPEC_VHSUB))]
2097
  "TARGET_NEON"
2098
  "vhsub.%T3%#\t%0, %1, %2"
2099
  [(set_attr "neon_type" "neon_int_5")]
2100
)
2101
 
2102
(define_insn "neon_vsubhn"
2103
  [(set (match_operand: 0 "s_register_operand" "=w")
2104
        (unspec: [(match_operand:VN 1 "s_register_operand" "w")
2105
                            (match_operand:VN 2 "s_register_operand" "w")
2106
                            (match_operand:SI 3 "immediate_operand" "i")]
2107
                           UNSPEC_VSUBHN))]
2108
  "TARGET_NEON"
2109
  "v%O3subhn.\t%P0, %q1, %q2"
2110
  [(set_attr "neon_type" "neon_int_4")]
2111
)
2112
 
2113
(define_insn "neon_vceq"
2114
  [(set (match_operand: 0 "s_register_operand" "=w,w")
2115
        (unspec:
2116
          [(match_operand:VDQW 1 "s_register_operand" "w,w")
2117
           (match_operand:VDQW 2 "nonmemory_operand" "w,Dz")
2118
           (match_operand:SI 3 "immediate_operand" "i,i")]
2119
          UNSPEC_VCEQ))]
2120
  "TARGET_NEON"
2121
  "@
2122
  vceq.\t%0, %1, %2
2123
  vceq.\t%0, %1, #0"
2124
  [(set (attr "neon_type")
2125
      (if_then_else (match_test "")
2126
                    (if_then_else (match_test "")
2127
                                  (const_string "neon_fp_vadd_ddd_vabs_dd")
2128
                                  (const_string "neon_fp_vadd_qqq_vabs_qq"))
2129
                    (const_string "neon_int_5")))]
2130
)
2131
 
2132
(define_insn "neon_vcge"
2133
  [(set (match_operand: 0 "s_register_operand" "=w,w")
2134
        (unspec:
2135
          [(match_operand:VDQW 1 "s_register_operand" "w,w")
2136
           (match_operand:VDQW 2 "nonmemory_operand" "w,Dz")
2137
           (match_operand:SI 3 "immediate_operand" "i,i")]
2138
          UNSPEC_VCGE))]
2139
  "TARGET_NEON"
2140
  "@
2141
  vcge.%T3%#\t%0, %1, %2
2142
  vcge.%T3%#\t%0, %1, #0"
2143
  [(set (attr "neon_type")
2144
     (if_then_else (match_test "")
2145
                   (if_then_else (match_test "")
2146
                                 (const_string "neon_fp_vadd_ddd_vabs_dd")
2147
                                 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2148
                   (const_string "neon_int_5")))]
2149
)
2150
 
2151
(define_insn "neon_vcgeu"
2152
  [(set (match_operand: 0 "s_register_operand" "=w")
2153
        (unspec:
2154
          [(match_operand:VDQIW 1 "s_register_operand" "w")
2155
           (match_operand:VDQIW 2 "s_register_operand" "w")
2156
           (match_operand:SI 3 "immediate_operand" "i")]
2157
          UNSPEC_VCGEU))]
2158
  "TARGET_NEON"
2159
  "vcge.%T3%#\t%0, %1, %2"
2160
  [(set_attr "neon_type" "neon_int_5")]
2161
)
2162
 
2163
(define_insn "neon_vcgt"
2164
  [(set (match_operand: 0 "s_register_operand" "=w,w")
2165
        (unspec:
2166
          [(match_operand:VDQW 1 "s_register_operand" "w,w")
2167
           (match_operand:VDQW 2 "nonmemory_operand" "w,Dz")
2168
           (match_operand:SI 3 "immediate_operand" "i,i")]
2169
          UNSPEC_VCGT))]
2170
  "TARGET_NEON"
2171
  "@
2172
  vcgt.%T3%#\t%0, %1, %2
2173
  vcgt.%T3%#\t%0, %1, #0"
2174
  [(set (attr "neon_type")
2175
     (if_then_else (match_test "")
2176
                   (if_then_else (match_test "")
2177
                                 (const_string "neon_fp_vadd_ddd_vabs_dd")
2178
                                 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2179
                   (const_string "neon_int_5")))]
2180
)
2181
 
2182
(define_insn "neon_vcgtu"
2183
  [(set (match_operand: 0 "s_register_operand" "=w")
2184
        (unspec:
2185
          [(match_operand:VDQIW 1 "s_register_operand" "w")
2186
           (match_operand:VDQIW 2 "s_register_operand" "w")
2187
           (match_operand:SI 3 "immediate_operand" "i")]
2188
          UNSPEC_VCGTU))]
2189
  "TARGET_NEON"
2190
  "vcgt.%T3%#\t%0, %1, %2"
2191
  [(set_attr "neon_type" "neon_int_5")]
2192
)
2193
 
2194
;; VCLE and VCLT only support comparisons with immediate zero (register
2195
;; variants are VCGE and VCGT with operands reversed).
2196
 
2197
(define_insn "neon_vcle"
2198
  [(set (match_operand: 0 "s_register_operand" "=w")
2199
        (unspec:
2200
          [(match_operand:VDQW 1 "s_register_operand" "w")
2201
           (match_operand:VDQW 2 "nonmemory_operand" "Dz")
2202
           (match_operand:SI 3 "immediate_operand" "i")]
2203
          UNSPEC_VCLE))]
2204
  "TARGET_NEON"
2205
  "vcle.%T3%#\t%0, %1, #0"
2206
  [(set (attr "neon_type")
2207
      (if_then_else (match_test "")
2208
                    (if_then_else (match_test "")
2209
                                  (const_string "neon_fp_vadd_ddd_vabs_dd")
2210
                                  (const_string "neon_fp_vadd_qqq_vabs_qq"))
2211
                    (const_string "neon_int_5")))]
2212
)
2213
 
2214
(define_insn "neon_vclt"
2215
  [(set (match_operand: 0 "s_register_operand" "=w")
2216
        (unspec:
2217
          [(match_operand:VDQW 1 "s_register_operand" "w")
2218
           (match_operand:VDQW 2 "nonmemory_operand" "Dz")
2219
           (match_operand:SI 3 "immediate_operand" "i")]
2220
          UNSPEC_VCLT))]
2221
  "TARGET_NEON"
2222
  "vclt.%T3%#\t%0, %1, #0"
2223
  [(set (attr "neon_type")
2224
      (if_then_else (match_test "")
2225
                    (if_then_else (match_test "")
2226
                                  (const_string "neon_fp_vadd_ddd_vabs_dd")
2227
                                  (const_string "neon_fp_vadd_qqq_vabs_qq"))
2228
                    (const_string "neon_int_5")))]
2229
)
2230
 
2231
(define_insn "neon_vcage"
2232
  [(set (match_operand: 0 "s_register_operand" "=w")
2233
        (unspec: [(match_operand:VCVTF 1 "s_register_operand" "w")
2234
                                (match_operand:VCVTF 2 "s_register_operand" "w")
2235
                                (match_operand:SI 3 "immediate_operand" "i")]
2236
                               UNSPEC_VCAGE))]
2237
  "TARGET_NEON"
2238
  "vacge.\t%0, %1, %2"
2239
  [(set (attr "neon_type")
2240
     (if_then_else (match_test "")
2241
                   (const_string "neon_fp_vadd_ddd_vabs_dd")
2242
                   (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2243
)
2244
 
2245
(define_insn "neon_vcagt"
2246
  [(set (match_operand: 0 "s_register_operand" "=w")
2247
        (unspec: [(match_operand:VCVTF 1 "s_register_operand" "w")
2248
                                (match_operand:VCVTF 2 "s_register_operand" "w")
2249
                                (match_operand:SI 3 "immediate_operand" "i")]
2250
                               UNSPEC_VCAGT))]
2251
  "TARGET_NEON"
2252
  "vacgt.\t%0, %1, %2"
2253
  [(set (attr "neon_type")
2254
     (if_then_else (match_test "")
2255
                   (const_string "neon_fp_vadd_ddd_vabs_dd")
2256
                   (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2257
)
2258
 
2259
(define_insn "neon_vtst"
2260
  [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2261
        (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2262
                       (match_operand:VDQIW 2 "s_register_operand" "w")
2263
                       (match_operand:SI 3 "immediate_operand" "i")]
2264
                      UNSPEC_VTST))]
2265
  "TARGET_NEON"
2266
  "vtst.\t%0, %1, %2"
2267
  [(set_attr "neon_type" "neon_int_4")]
2268
)
2269
 
2270
(define_insn "neon_vabd"
2271
  [(set (match_operand:VDQW 0 "s_register_operand" "=w")
2272
        (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w")
2273
                      (match_operand:VDQW 2 "s_register_operand" "w")
2274
                      (match_operand:SI 3 "immediate_operand" "i")]
2275
                     UNSPEC_VABD))]
2276
  "TARGET_NEON"
2277
  "vabd.%T3%#\t%0, %1, %2"
2278
  [(set (attr "neon_type")
2279
     (if_then_else (match_test "")
2280
                   (if_then_else (match_test "")
2281
                                 (const_string "neon_fp_vadd_ddd_vabs_dd")
2282
                                 (const_string "neon_fp_vadd_qqq_vabs_qq"))
2283
                   (const_string "neon_int_5")))]
2284
)
2285
 
2286
(define_insn "neon_vabdl"
2287
  [(set (match_operand: 0 "s_register_operand" "=w")
2288
        (unspec: [(match_operand:VW 1 "s_register_operand" "w")
2289
                           (match_operand:VW 2 "s_register_operand" "w")
2290
                           (match_operand:SI 3 "immediate_operand" "i")]
2291
                          UNSPEC_VABDL))]
2292
  "TARGET_NEON"
2293
  "vabdl.%T3%#\t%q0, %P1, %P2"
2294
  [(set_attr "neon_type" "neon_int_5")]
2295
)
2296
 
2297
(define_insn "neon_vaba"
2298
  [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2299
        (plus:VDQIW (match_operand:VDQIW 1 "s_register_operand" "0")
2300
                    (unspec:VDQIW [(match_operand:VDQIW 2 "s_register_operand" "w")
2301
                                   (match_operand:VDQIW 3 "s_register_operand" "w")
2302
                                   (match_operand:SI 4 "immediate_operand" "i")]
2303
                                  UNSPEC_VABD)))]
2304
  "TARGET_NEON"
2305
  "vaba.%T4%#\t%0, %2, %3"
2306
  [(set (attr "neon_type")
2307
     (if_then_else (match_test "")
2308
                   (const_string "neon_vaba") (const_string "neon_vaba_qqq")))]
2309
)
2310
 
2311
(define_insn "neon_vabal"
2312
  [(set (match_operand: 0 "s_register_operand" "=w")
2313
        (plus: (match_operand: 1 "s_register_operand" "0")
2314
                        (unspec: [(match_operand:VW 2 "s_register_operand" "w")
2315
                                           (match_operand:VW 3 "s_register_operand" "w")
2316
                                           (match_operand:SI 4 "immediate_operand" "i")]
2317
                          UNSPEC_VABDL)))]
2318
  "TARGET_NEON"
2319
  "vabal.%T4%#\t%q0, %P2, %P3"
2320
  [(set_attr "neon_type" "neon_vaba")]
2321
)
2322
 
2323
(define_insn "neon_vmax"
2324
  [(set (match_operand:VDQW 0 "s_register_operand" "=w")
2325
        (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w")
2326
                      (match_operand:VDQW 2 "s_register_operand" "w")
2327
                      (match_operand:SI 3 "immediate_operand" "i")]
2328
                     UNSPEC_VMAX))]
2329
  "TARGET_NEON"
2330
  "vmax.%T3%#\t%0, %1, %2"
2331
  [(set (attr "neon_type")
2332
    (if_then_else (match_test "")
2333
                  (if_then_else (match_test "")
2334
                                (const_string "neon_fp_vadd_ddd_vabs_dd")
2335
                                (const_string "neon_fp_vadd_qqq_vabs_qq"))
2336
                  (const_string "neon_int_5")))]
2337
)
2338
 
2339
(define_insn "neon_vmin"
2340
  [(set (match_operand:VDQW 0 "s_register_operand" "=w")
2341
        (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w")
2342
                      (match_operand:VDQW 2 "s_register_operand" "w")
2343
                      (match_operand:SI 3 "immediate_operand" "i")]
2344
                     UNSPEC_VMIN))]
2345
  "TARGET_NEON"
2346
  "vmin.%T3%#\t%0, %1, %2"
2347
  [(set (attr "neon_type")
2348
    (if_then_else (match_test "")
2349
                  (if_then_else (match_test "")
2350
                                (const_string "neon_fp_vadd_ddd_vabs_dd")
2351
                                (const_string "neon_fp_vadd_qqq_vabs_qq"))
2352
                  (const_string "neon_int_5")))]
2353
)
2354
 
2355
(define_expand "neon_vpadd"
2356
  [(match_operand:VD 0 "s_register_operand" "=w")
2357
   (match_operand:VD 1 "s_register_operand" "w")
2358
   (match_operand:VD 2 "s_register_operand" "w")
2359
   (match_operand:SI 3 "immediate_operand" "i")]
2360
  "TARGET_NEON"
2361
{
2362
  emit_insn (gen_neon_vpadd_internal (operands[0], operands[1],
2363
                                            operands[2]));
2364
  DONE;
2365
})
2366
 
2367
(define_insn "neon_vpaddl"
2368
  [(set (match_operand: 0 "s_register_operand" "=w")
2369
        (unspec: [(match_operand:VDQIW 1 "s_register_operand" "w")
2370
                                  (match_operand:SI 2 "immediate_operand" "i")]
2371
                                 UNSPEC_VPADDL))]
2372
  "TARGET_NEON"
2373
  "vpaddl.%T2%#\t%0, %1"
2374
  ;; Assume this schedules like vaddl.
2375
  [(set_attr "neon_type" "neon_int_3")]
2376
)
2377
 
2378
(define_insn "neon_vpadal"
2379
  [(set (match_operand: 0 "s_register_operand" "=w")
2380
        (unspec: [(match_operand: 1 "s_register_operand" "0")
2381
                                  (match_operand:VDQIW 2 "s_register_operand" "w")
2382
                                  (match_operand:SI 3 "immediate_operand" "i")]
2383
                                 UNSPEC_VPADAL))]
2384
  "TARGET_NEON"
2385
  "vpadal.%T3%#\t%0, %2"
2386
  ;; Assume this schedules like vpadd.
2387
  [(set_attr "neon_type" "neon_int_1")]
2388
)
2389
 
2390
(define_insn "neon_vpmax"
2391
  [(set (match_operand:VD 0 "s_register_operand" "=w")
2392
        (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
2393
                    (match_operand:VD 2 "s_register_operand" "w")
2394
                    (match_operand:SI 3 "immediate_operand" "i")]
2395
                   UNSPEC_VPMAX))]
2396
  "TARGET_NEON"
2397
  "vpmax.%T3%#\t%0, %1, %2"
2398
  ;; Assume this schedules like vmax.
2399
  [(set (attr "neon_type")
2400
    (if_then_else (match_test "")
2401
                  (const_string "neon_fp_vadd_ddd_vabs_dd")
2402
                  (const_string "neon_int_5")))]
2403
)
2404
 
2405
(define_insn "neon_vpmin"
2406
  [(set (match_operand:VD 0 "s_register_operand" "=w")
2407
        (unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
2408
                    (match_operand:VD 2 "s_register_operand" "w")
2409
                    (match_operand:SI 3 "immediate_operand" "i")]
2410
                   UNSPEC_VPMIN))]
2411
  "TARGET_NEON"
2412
  "vpmin.%T3%#\t%0, %1, %2"
2413
  ;; Assume this schedules like vmin.
2414
  [(set (attr "neon_type")
2415
    (if_then_else (match_test "")
2416
                  (const_string "neon_fp_vadd_ddd_vabs_dd")
2417
                  (const_string "neon_int_5")))]
2418
)
2419
 
2420
(define_insn "neon_vrecps"
2421
  [(set (match_operand:VCVTF 0 "s_register_operand" "=w")
2422
        (unspec:VCVTF [(match_operand:VCVTF 1 "s_register_operand" "w")
2423
                       (match_operand:VCVTF 2 "s_register_operand" "w")
2424
                       (match_operand:SI 3 "immediate_operand" "i")]
2425
                      UNSPEC_VRECPS))]
2426
  "TARGET_NEON"
2427
  "vrecps.\t%0, %1, %2"
2428
  [(set (attr "neon_type")
2429
      (if_then_else (match_test "")
2430
                    (const_string "neon_fp_vrecps_vrsqrts_ddd")
2431
                    (const_string "neon_fp_vrecps_vrsqrts_qqq")))]
2432
)
2433
 
2434
(define_insn "neon_vrsqrts"
2435
  [(set (match_operand:VCVTF 0 "s_register_operand" "=w")
2436
        (unspec:VCVTF [(match_operand:VCVTF 1 "s_register_operand" "w")
2437
                       (match_operand:VCVTF 2 "s_register_operand" "w")
2438
                       (match_operand:SI 3 "immediate_operand" "i")]
2439
                      UNSPEC_VRSQRTS))]
2440
  "TARGET_NEON"
2441
  "vrsqrts.\t%0, %1, %2"
2442
  [(set (attr "neon_type")
2443
      (if_then_else (match_test "")
2444
                    (const_string "neon_fp_vrecps_vrsqrts_ddd")
2445
                    (const_string "neon_fp_vrecps_vrsqrts_qqq")))]
2446
)
2447
 
2448
(define_expand "neon_vabs"
2449
  [(match_operand:VDQW 0 "s_register_operand" "")
2450
   (match_operand:VDQW 1 "s_register_operand" "")
2451
   (match_operand:SI 2 "immediate_operand" "")]
2452
  "TARGET_NEON"
2453
{
2454
  emit_insn (gen_abs2 (operands[0], operands[1]));
2455
  DONE;
2456
})
2457
 
2458
(define_insn "neon_vqabs"
2459
  [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2460
        (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2461
                       (match_operand:SI 2 "immediate_operand" "i")]
2462
                      UNSPEC_VQABS))]
2463
  "TARGET_NEON"
2464
  "vqabs.\t%0, %1"
2465
  [(set_attr "neon_type" "neon_vqneg_vqabs")]
2466
)
2467
 
2468
(define_expand "neon_vneg"
2469
  [(match_operand:VDQW 0 "s_register_operand" "")
2470
   (match_operand:VDQW 1 "s_register_operand" "")
2471
   (match_operand:SI 2 "immediate_operand" "")]
2472
  "TARGET_NEON"
2473
{
2474
  emit_insn (gen_neg2 (operands[0], operands[1]));
2475
  DONE;
2476
})
2477
 
2478
(define_insn "neon_vqneg"
2479
  [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2480
        (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2481
                       (match_operand:SI 2 "immediate_operand" "i")]
2482
                      UNSPEC_VQNEG))]
2483
  "TARGET_NEON"
2484
  "vqneg.\t%0, %1"
2485
  [(set_attr "neon_type" "neon_vqneg_vqabs")]
2486
)
2487
 
2488
(define_insn "neon_vcls"
2489
  [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2490
        (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
2491
                       (match_operand:SI 2 "immediate_operand" "i")]
2492
                      UNSPEC_VCLS))]
2493
  "TARGET_NEON"
2494
  "vcls.\t%0, %1"
2495
  [(set_attr "neon_type" "neon_int_1")]
2496
)
2497
 
2498
(define_insn "clz2"
2499
  [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
2500
        (clz:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")))]
2501
  "TARGET_NEON"
2502
  "vclz.\t%0, %1"
2503
  [(set_attr "neon_type" "neon_int_1")]
2504
)
2505
 
2506
(define_expand "neon_vclz"
2507
  [(match_operand:VDQIW 0 "s_register_operand" "")
2508
   (match_operand:VDQIW 1 "s_register_operand" "")
2509
   (match_operand:SI 2 "immediate_operand" "")]
2510
  "TARGET_NEON"
2511
{
2512
  emit_insn (gen_clz2 (operands[0], operands[1]));
2513
  DONE;
2514
})
2515
 
2516
(define_insn "popcount2"
2517
  [(set (match_operand:VE 0 "s_register_operand" "=w")
2518
        (popcount:VE (match_operand:VE 1 "s_register_operand" "w")))]
2519
  "TARGET_NEON"
2520
  "vcnt.\t%0, %1"
2521
  [(set_attr "neon_type" "neon_int_1")]
2522
)
2523
 
2524
(define_expand "neon_vcnt"
2525
  [(match_operand:VE 0 "s_register_operand" "=w")
2526
   (match_operand:VE 1 "s_register_operand" "w")
2527
   (match_operand:SI 2 "immediate_operand" "i")]
2528
  "TARGET_NEON"
2529
{
2530
  emit_insn (gen_popcount2 (operands[0], operands[1]));
2531
  DONE;
2532
})
2533
 
2534
(define_insn "neon_vrecpe"
2535
  [(set (match_operand:V32 0 "s_register_operand" "=w")
2536
        (unspec:V32 [(match_operand:V32 1 "s_register_operand" "w")
2537
                     (match_operand:SI 2 "immediate_operand" "i")]
2538
                    UNSPEC_VRECPE))]
2539
  "TARGET_NEON"
2540
  "vrecpe.\t%0, %1"
2541
  [(set (attr "neon_type")
2542
      (if_then_else (match_test "")
2543
                    (const_string "neon_fp_vadd_ddd_vabs_dd")
2544
                    (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2545
)
2546
 
2547
(define_insn "neon_vrsqrte"
2548
  [(set (match_operand:V32 0 "s_register_operand" "=w")
2549
        (unspec:V32 [(match_operand:V32 1 "s_register_operand" "w")
2550
                     (match_operand:SI 2 "immediate_operand" "i")]
2551
                    UNSPEC_VRSQRTE))]
2552
  "TARGET_NEON"
2553
  "vrsqrte.\t%0, %1"
2554
  [(set (attr "neon_type")
2555
      (if_then_else (match_test "")
2556
                    (const_string "neon_fp_vadd_ddd_vabs_dd")
2557
                    (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2558
)
2559
 
2560
(define_expand "neon_vmvn"
2561
  [(match_operand:VDQIW 0 "s_register_operand" "")
2562
   (match_operand:VDQIW 1 "s_register_operand" "")
2563
   (match_operand:SI 2 "immediate_operand" "")]
2564
  "TARGET_NEON"
2565
{
2566
  emit_insn (gen_one_cmpl2 (operands[0], operands[1]));
2567
  DONE;
2568
})
2569
 
2570
(define_insn "neon_vget_lane_sext_internal"
2571
  [(set (match_operand:SI 0 "s_register_operand" "=r")
2572
        (sign_extend:SI
2573
          (vec_select:
2574
            (match_operand:VD 1 "s_register_operand" "w")
2575
            (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2576
  "TARGET_NEON"
2577
{
2578
  if (BYTES_BIG_ENDIAN)
2579
    {
2580
      int elt = INTVAL (operands[2]);
2581
      elt = GET_MODE_NUNITS (mode) - 1 - elt;
2582
      operands[2] = GEN_INT (elt);
2583
    }
2584
  return "vmov%?.s\t%0, %P1[%c2]";
2585
}
2586
  [(set_attr "predicable" "yes")
2587
   (set_attr "neon_type" "neon_bp_simple")]
2588
)
2589
 
2590
(define_insn "neon_vget_lane_zext_internal"
2591
  [(set (match_operand:SI 0 "s_register_operand" "=r")
2592
        (zero_extend:SI
2593
          (vec_select:
2594
            (match_operand:VD 1 "s_register_operand" "w")
2595
            (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2596
  "TARGET_NEON"
2597
{
2598
  if (BYTES_BIG_ENDIAN)
2599
    {
2600
      int elt = INTVAL (operands[2]);
2601
      elt = GET_MODE_NUNITS (mode) - 1 - elt;
2602
      operands[2] = GEN_INT (elt);
2603
    }
2604
  return "vmov%?.u\t%0, %P1[%c2]";
2605
}
2606
  [(set_attr "predicable" "yes")
2607
   (set_attr "neon_type" "neon_bp_simple")]
2608
)
2609
 
2610
(define_insn "neon_vget_lane_sext_internal"
2611
  [(set (match_operand:SI 0 "s_register_operand" "=r")
2612
        (sign_extend:SI
2613
          (vec_select:
2614
            (match_operand:VQ 1 "s_register_operand" "w")
2615
            (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2616
  "TARGET_NEON"
2617
{
2618
  rtx ops[3];
2619
  int regno = REGNO (operands[1]);
2620
  unsigned int halfelts = GET_MODE_NUNITS (mode) / 2;
2621
  unsigned int elt = INTVAL (operands[2]);
2622
  unsigned int elt_adj = elt % halfelts;
2623
 
2624
  if (BYTES_BIG_ENDIAN)
2625
    elt_adj = halfelts - 1 - elt_adj;
2626
 
2627
  ops[0] = operands[0];
2628
  ops[1] = gen_rtx_REG (mode, regno + 2 * (elt / halfelts));
2629
  ops[2] = GEN_INT (elt_adj);
2630
  output_asm_insn ("vmov%?.s\t%0, %P1[%c2]", ops);
2631
 
2632
  return "";
2633
}
2634
  [(set_attr "predicable" "yes")
2635
   (set_attr "neon_type" "neon_bp_simple")]
2636
)
2637
 
2638
(define_insn "neon_vget_lane_zext_internal"
2639
  [(set (match_operand:SI 0 "s_register_operand" "=r")
2640
        (zero_extend:SI
2641
          (vec_select:
2642
            (match_operand:VQ 1 "s_register_operand" "w")
2643
            (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2644
  "TARGET_NEON"
2645
{
2646
  rtx ops[3];
2647
  int regno = REGNO (operands[1]);
2648
  unsigned int halfelts = GET_MODE_NUNITS (mode) / 2;
2649
  unsigned int elt = INTVAL (operands[2]);
2650
  unsigned int elt_adj = elt % halfelts;
2651
 
2652
  if (BYTES_BIG_ENDIAN)
2653
    elt_adj = halfelts - 1 - elt_adj;
2654
 
2655
  ops[0] = operands[0];
2656
  ops[1] = gen_rtx_REG (mode, regno + 2 * (elt / halfelts));
2657
  ops[2] = GEN_INT (elt_adj);
2658
  output_asm_insn ("vmov%?.u\t%0, %P1[%c2]", ops);
2659
 
2660
  return "";
2661
}
2662
  [(set_attr "predicable" "yes")
2663
   (set_attr "neon_type" "neon_bp_simple")]
2664
)
2665
 
2666
(define_expand "neon_vget_lane"
2667
  [(match_operand: 0 "s_register_operand" "")
2668
   (match_operand:VDQW 1 "s_register_operand" "")
2669
   (match_operand:SI 2 "immediate_operand" "")
2670
   (match_operand:SI 3 "immediate_operand" "")]
2671
  "TARGET_NEON"
2672
{
2673
  HOST_WIDE_INT magic = INTVAL (operands[3]);
2674
  rtx insn;
2675
 
2676
  neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (mode));
2677
 
2678
  if (BYTES_BIG_ENDIAN)
2679
    {
2680
      /* The intrinsics are defined in terms of a model where the
2681
         element ordering in memory is vldm order, whereas the generic
2682
         RTL is defined in terms of a model where the element ordering
2683
         in memory is array order.  Convert the lane number to conform
2684
         to this model.  */
2685
      unsigned int elt = INTVAL (operands[2]);
2686
      unsigned int reg_nelts
2687
        = 64 / GET_MODE_BITSIZE (GET_MODE_INNER (mode));
2688
      elt ^= reg_nelts - 1;
2689
      operands[2] = GEN_INT (elt);
2690
    }
2691
 
2692
  if ((magic & 3) == 3 || GET_MODE_BITSIZE (GET_MODE_INNER (mode)) == 32)
2693
    insn = gen_vec_extract (operands[0], operands[1], operands[2]);
2694
  else
2695
    {
2696
      if ((magic & 1) != 0)
2697
        insn = gen_neon_vget_lane_sext_internal (operands[0], operands[1],
2698
                                                       operands[2]);
2699
      else
2700
        insn = gen_neon_vget_lane_zext_internal (operands[0], operands[1],
2701
                                                       operands[2]);
2702
    }
2703
  emit_insn (insn);
2704
  DONE;
2705
})
2706
 
2707
; Operand 3 (info word) is ignored because it does nothing useful with 64-bit
2708
; elements.
2709
 
2710
(define_expand "neon_vget_lanedi"
2711
  [(match_operand:DI 0 "s_register_operand" "=r")
2712
   (match_operand:DI 1 "s_register_operand" "w")
2713
   (match_operand:SI 2 "immediate_operand" "i")
2714
   (match_operand:SI 3 "immediate_operand" "i")]
2715
  "TARGET_NEON"
2716
{
2717
  neon_lane_bounds (operands[2], 0, 1);
2718
  emit_move_insn (operands[0], operands[1]);
2719
  DONE;
2720
})
2721
 
2722
(define_expand "neon_vget_lanev2di"
2723
  [(match_operand:DI 0 "s_register_operand" "=r")
2724
   (match_operand:V2DI 1 "s_register_operand" "w")
2725
   (match_operand:SI 2 "immediate_operand" "i")
2726
   (match_operand:SI 3 "immediate_operand" "i")]
2727
  "TARGET_NEON"
2728
{
2729
  neon_lane_bounds (operands[2], 0, 2);
2730
  emit_insn (gen_vec_extractv2di (operands[0], operands[1], operands[2]));
2731
  DONE;
2732
})
2733
 
2734
(define_expand "neon_vset_lane"
2735
  [(match_operand:VDQ 0 "s_register_operand" "=w")
2736
   (match_operand: 1 "s_register_operand" "r")
2737
   (match_operand:VDQ 2 "s_register_operand" "0")
2738
   (match_operand:SI 3 "immediate_operand" "i")]
2739
  "TARGET_NEON"
2740
{
2741
  unsigned int elt = INTVAL (operands[3]);
2742
  neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (mode));
2743
 
2744
  if (BYTES_BIG_ENDIAN)
2745
    {
2746
      unsigned int reg_nelts
2747
        = 64 / GET_MODE_BITSIZE (GET_MODE_INNER (mode));
2748
      elt ^= reg_nelts - 1;
2749
    }
2750
 
2751
  emit_insn (gen_vec_set_internal (operands[0], operands[1],
2752
                                         GEN_INT (1 << elt), operands[2]));
2753
  DONE;
2754
})
2755
 
2756
; See neon_vget_lanedi comment for reasons operands 2 & 3 are ignored.
2757
 
2758
(define_expand "neon_vset_lanedi"
2759
  [(match_operand:DI 0 "s_register_operand" "=w")
2760
   (match_operand:DI 1 "s_register_operand" "r")
2761
   (match_operand:DI 2 "s_register_operand" "0")
2762
   (match_operand:SI 3 "immediate_operand" "i")]
2763
  "TARGET_NEON"
2764
{
2765
  neon_lane_bounds (operands[3], 0, 1);
2766
  emit_move_insn (operands[0], operands[1]);
2767
  DONE;
2768
})
2769
 
2770
(define_expand "neon_vcreate"
2771
  [(match_operand:VDX 0 "s_register_operand" "")
2772
   (match_operand:DI 1 "general_operand" "")]
2773
  "TARGET_NEON"
2774
{
2775
  rtx src = gen_lowpart (mode, operands[1]);
2776
  emit_move_insn (operands[0], src);
2777
  DONE;
2778
})
2779
 
2780
(define_insn "neon_vdup_n"
2781
  [(set (match_operand:VX 0 "s_register_operand" "=w")
2782
        (vec_duplicate:VX (match_operand: 1 "s_register_operand" "r")))]
2783
  "TARGET_NEON"
2784
  "vdup%?.\t%0, %1"
2785
  ;; Assume this schedules like vmov.
2786
  [(set_attr "predicable" "yes")
2787
   (set_attr "neon_type" "neon_bp_simple")]
2788
)
2789
 
2790
(define_insn "neon_vdup_n"
2791
  [(set (match_operand:V32 0 "s_register_operand" "=w,w")
2792
        (vec_duplicate:V32 (match_operand: 1 "s_register_operand" "r,t")))]
2793
  "TARGET_NEON"
2794
  "@
2795
  vdup%?.\t%0, %1
2796
  vdup%?.\t%0, %y1"
2797
  ;; Assume this schedules like vmov.
2798
  [(set_attr "predicable" "yes")
2799
   (set_attr "neon_type" "neon_bp_simple")]
2800
)
2801
 
2802
(define_expand "neon_vdup_ndi"
2803
  [(match_operand:DI 0 "s_register_operand" "=w")
2804
   (match_operand:DI 1 "s_register_operand" "r")]
2805
  "TARGET_NEON"
2806
{
2807
  emit_move_insn (operands[0], operands[1]);
2808
  DONE;
2809
}
2810
)
2811
 
2812
(define_insn "neon_vdup_nv2di"
2813
  [(set (match_operand:V2DI 0 "s_register_operand" "=w,w")
2814
        (vec_duplicate:V2DI (match_operand:DI 1 "s_register_operand" "r,w")))]
2815
  "TARGET_NEON"
2816
  "@
2817
  vmov%?\t%e0, %Q1, %R1\;vmov%?\t%f0, %Q1, %R1
2818
  vmov%?\t%e0, %P1\;vmov%?\t%f0, %P1"
2819
  [(set_attr "predicable" "yes")
2820
   (set_attr "length" "8")
2821
   (set_attr "neon_type" "neon_bp_simple")]
2822
)
2823
 
2824
(define_insn "neon_vdup_lane_internal"
2825
  [(set (match_operand:VDQW 0 "s_register_operand" "=w")
2826
        (vec_duplicate:VDQW
2827
          (vec_select:
2828
            (match_operand: 1 "s_register_operand" "w")
2829
            (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2830
  "TARGET_NEON"
2831
{
2832
  if (BYTES_BIG_ENDIAN)
2833
    {
2834
      int elt = INTVAL (operands[2]);
2835
      elt = GET_MODE_NUNITS (mode) - 1 - elt;
2836
      operands[2] = GEN_INT (elt);
2837
    }
2838
  if ()
2839
    return "vdup.\t%P0, %P1[%c2]";
2840
  else
2841
    return "vdup.\t%q0, %P1[%c2]";
2842
}
2843
  ;; Assume this schedules like vmov.
2844
  [(set_attr "neon_type" "neon_bp_simple")]
2845
)
2846
 
2847
(define_expand "neon_vdup_lane"
2848
  [(match_operand:VDQW 0 "s_register_operand" "=w")
2849
   (match_operand: 1 "s_register_operand" "w")
2850
   (match_operand:SI 2 "immediate_operand" "i")]
2851
  "TARGET_NEON"
2852
{
2853
  neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (mode));
2854
  if (BYTES_BIG_ENDIAN)
2855
    {
2856
      unsigned int elt = INTVAL (operands[2]);
2857
      unsigned int reg_nelts
2858
        = 64 / GET_MODE_BITSIZE (GET_MODE_INNER (mode));
2859
      elt ^= reg_nelts - 1;
2860
      operands[2] = GEN_INT (elt);
2861
    }
2862
    emit_insn (gen_neon_vdup_lane_internal (operands[0], operands[1],
2863
                                                  operands[2]));
2864
    DONE;
2865
})
2866
 
2867
; Scalar index is ignored, since only zero is valid here.
2868
(define_expand "neon_vdup_lanedi"
2869
  [(match_operand:DI 0 "s_register_operand" "=w")
2870
   (match_operand:DI 1 "s_register_operand" "w")
2871
   (match_operand:SI 2 "immediate_operand" "i")]
2872
  "TARGET_NEON"
2873
{
2874
  neon_lane_bounds (operands[2], 0, 1);
2875
  emit_move_insn (operands[0], operands[1]);
2876
  DONE;
2877
})
2878
 
2879
; Likewise for v2di, as the DImode second operand has only a single element.
2880
(define_expand "neon_vdup_lanev2di"
2881
  [(match_operand:V2DI 0 "s_register_operand" "=w")
2882
   (match_operand:DI 1 "s_register_operand" "w")
2883
   (match_operand:SI 2 "immediate_operand" "i")]
2884
  "TARGET_NEON"
2885
{
2886
  neon_lane_bounds (operands[2], 0, 1);
2887
  emit_insn (gen_neon_vdup_nv2di (operands[0], operands[1]));
2888
  DONE;
2889
})
2890
 
2891
; Disabled before reload because we don't want combine doing something silly,
2892
; but used by the post-reload expansion of neon_vcombine.
2893
(define_insn "*neon_vswp"
2894
  [(set (match_operand:VDQX 0 "s_register_operand" "+w")
2895
        (match_operand:VDQX 1 "s_register_operand" "+w"))
2896
   (set (match_dup 1) (match_dup 0))]
2897
  "TARGET_NEON && reload_completed"
2898
  "vswp\t%0, %1"
2899
  [(set (attr "neon_type")
2900
        (if_then_else (match_test "")
2901
                      (const_string "neon_bp_simple")
2902
                      (const_string "neon_bp_2cycle")))]
2903
)
2904
 
2905
;; In this insn, operand 1 should be low, and operand 2 the high part of the
2906
;; dest vector.
2907
;; FIXME: A different implementation of this builtin could make it much
2908
;; more likely that we wouldn't actually need to output anything (we could make
2909
;; it so that the reg allocator puts things in the right places magically
2910
;; instead). Lack of subregs for vectors makes that tricky though, I think.
2911
 
2912
(define_insn_and_split "neon_vcombine"
2913
  [(set (match_operand: 0 "s_register_operand" "=w")
2914
        (vec_concat:
2915
          (match_operand:VDX 1 "s_register_operand" "w")
2916
          (match_operand:VDX 2 "s_register_operand" "w")))]
2917
  "TARGET_NEON"
2918
  "#"
2919
  "&& reload_completed"
2920
  [(const_int 0)]
2921
{
2922
  neon_split_vcombine (operands);
2923
  DONE;
2924
})
2925
 
2926
(define_expand "neon_vget_high"
2927
  [(match_operand: 0 "s_register_operand")
2928
   (match_operand:VQX 1 "s_register_operand")]
2929
  "TARGET_NEON"
2930
{
2931
  emit_move_insn (operands[0],
2932
                  simplify_gen_subreg (mode, operands[1], mode,
2933
                                       GET_MODE_SIZE (mode)));
2934
  DONE;
2935
})
2936
 
2937
(define_expand "neon_vget_low"
2938
  [(match_operand: 0 "s_register_operand")
2939
   (match_operand:VQX 1 "s_register_operand")]
2940
  "TARGET_NEON"
2941
{
2942
  emit_move_insn (operands[0],
2943
                  simplify_gen_subreg (mode, operands[1],
2944
                                       mode, 0));
2945
  DONE;
2946
})
2947
 
2948
(define_insn "float2"
2949
  [(set (match_operand: 0 "s_register_operand" "=w")
2950
        (float: (match_operand:VCVTI 1 "s_register_operand" "w")))]
2951
  "TARGET_NEON && !flag_rounding_math"
2952
  "vcvt.f32.s32\t%0, %1"
2953
  [(set (attr "neon_type")
2954
     (if_then_else (match_test "")
2955
                   (const_string "neon_fp_vadd_ddd_vabs_dd")
2956
                   (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2957
)
2958
 
2959
(define_insn "floatuns2"
2960
  [(set (match_operand: 0 "s_register_operand" "=w")
2961
        (unsigned_float: (match_operand:VCVTI 1 "s_register_operand" "w")))]
2962
  "TARGET_NEON && !flag_rounding_math"
2963
  "vcvt.f32.u32\t%0, %1"
2964
  [(set (attr "neon_type")
2965
     (if_then_else (match_test "")
2966
                   (const_string "neon_fp_vadd_ddd_vabs_dd")
2967
                   (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2968
)
2969
 
2970
(define_insn "fix_trunc2"
2971
  [(set (match_operand: 0 "s_register_operand" "=w")
2972
        (fix: (match_operand:VCVTF 1 "s_register_operand" "w")))]
2973
  "TARGET_NEON"
2974
  "vcvt.s32.f32\t%0, %1"
2975
  [(set (attr "neon_type")
2976
     (if_then_else (match_test "")
2977
                   (const_string "neon_fp_vadd_ddd_vabs_dd")
2978
                   (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2979
)
2980
 
2981
(define_insn "fixuns_trunc2"
2982
  [(set (match_operand: 0 "s_register_operand" "=w")
2983
        (unsigned_fix: (match_operand:VCVTF 1 "s_register_operand" "w")))]
2984
  "TARGET_NEON"
2985
  "vcvt.u32.f32\t%0, %1"
2986
  [(set (attr "neon_type")
2987
     (if_then_else (match_test "")
2988
                   (const_string "neon_fp_vadd_ddd_vabs_dd")
2989
                   (const_string "neon_fp_vadd_qqq_vabs_qq")))]
2990
)
2991
 
2992
(define_insn "neon_vcvt"
2993
  [(set (match_operand: 0 "s_register_operand" "=w")
2994
        (unspec: [(match_operand:VCVTF 1 "s_register_operand" "w")
2995
                           (match_operand:SI 2 "immediate_operand" "i")]
2996
                          UNSPEC_VCVT))]
2997
  "TARGET_NEON"
2998
  "vcvt.%T2%#32.f32\t%0, %1"
2999
  [(set (attr "neon_type")
3000
     (if_then_else (match_test "")
3001
                   (const_string "neon_fp_vadd_ddd_vabs_dd")
3002
                   (const_string "neon_fp_vadd_qqq_vabs_qq")))]
3003
)
3004
 
3005
(define_insn "neon_vcvt"
3006
  [(set (match_operand: 0 "s_register_operand" "=w")
3007
        (unspec: [(match_operand:VCVTI 1 "s_register_operand" "w")
3008
                           (match_operand:SI 2 "immediate_operand" "i")]
3009
                          UNSPEC_VCVT))]
3010
  "TARGET_NEON"
3011
  "vcvt.f32.%T2%#32\t%0, %1"
3012
  [(set (attr "neon_type")
3013
     (if_then_else (match_test "")
3014
                   (const_string "neon_fp_vadd_ddd_vabs_dd")
3015
                   (const_string "neon_fp_vadd_qqq_vabs_qq")))]
3016
)
3017
 
3018
(define_insn "neon_vcvt_n"
3019
  [(set (match_operand: 0 "s_register_operand" "=w")
3020
        (unspec: [(match_operand:VCVTF 1 "s_register_operand" "w")
3021
                           (match_operand:SI 2 "immediate_operand" "i")
3022
                           (match_operand:SI 3 "immediate_operand" "i")]
3023
                          UNSPEC_VCVT_N))]
3024
  "TARGET_NEON"
3025
{
3026
  neon_const_bounds (operands[2], 1, 33);
3027
  return "vcvt.%T3%#32.f32\t%0, %1, %2";
3028
}
3029
  [(set (attr "neon_type")
3030
     (if_then_else (match_test "")
3031
                   (const_string "neon_fp_vadd_ddd_vabs_dd")
3032
                   (const_string "neon_fp_vadd_qqq_vabs_qq")))]
3033
)
3034
 
3035
(define_insn "neon_vcvt_n"
3036
  [(set (match_operand: 0 "s_register_operand" "=w")
3037
        (unspec: [(match_operand:VCVTI 1 "s_register_operand" "w")
3038
                           (match_operand:SI 2 "immediate_operand" "i")
3039
                           (match_operand:SI 3 "immediate_operand" "i")]
3040
                          UNSPEC_VCVT_N))]
3041
  "TARGET_NEON"
3042
{
3043
  neon_const_bounds (operands[2], 1, 33);
3044
  return "vcvt.f32.%T3%#32\t%0, %1, %2";
3045
}
3046
  [(set (attr "neon_type")
3047
     (if_then_else (match_test "")
3048
                   (const_string "neon_fp_vadd_ddd_vabs_dd")
3049
                   (const_string "neon_fp_vadd_qqq_vabs_qq")))]
3050
)
3051
 
3052
(define_insn "neon_vmovn"
3053
  [(set (match_operand: 0 "s_register_operand" "=w")
3054
        (unspec: [(match_operand:VN 1 "s_register_operand" "w")
3055
                            (match_operand:SI 2 "immediate_operand" "i")]
3056
                           UNSPEC_VMOVN))]
3057
  "TARGET_NEON"
3058
  "vmovn.\t%P0, %q1"
3059
  [(set_attr "neon_type" "neon_bp_simple")]
3060
)
3061
 
3062
(define_insn "neon_vqmovn"
3063
  [(set (match_operand: 0 "s_register_operand" "=w")
3064
        (unspec: [(match_operand:VN 1 "s_register_operand" "w")
3065
                            (match_operand:SI 2 "immediate_operand" "i")]
3066
                           UNSPEC_VQMOVN))]
3067
  "TARGET_NEON"
3068
  "vqmovn.%T2%#\t%P0, %q1"
3069
  [(set_attr "neon_type" "neon_shift_2")]
3070
)
3071
 
3072
(define_insn "neon_vqmovun"
3073
  [(set (match_operand: 0 "s_register_operand" "=w")
3074
        (unspec: [(match_operand:VN 1 "s_register_operand" "w")
3075
                            (match_operand:SI 2 "immediate_operand" "i")]
3076
                           UNSPEC_VQMOVUN))]
3077
  "TARGET_NEON"
3078
  "vqmovun.\t%P0, %q1"
3079
  [(set_attr "neon_type" "neon_shift_2")]
3080
)
3081
 
3082
(define_insn "neon_vmovl"
3083
  [(set (match_operand: 0 "s_register_operand" "=w")
3084
        (unspec: [(match_operand:VW 1 "s_register_operand" "w")
3085
                           (match_operand:SI 2 "immediate_operand" "i")]
3086
                          UNSPEC_VMOVL))]
3087
  "TARGET_NEON"
3088
  "vmovl.%T2%#\t%q0, %P1"
3089
  [(set_attr "neon_type" "neon_shift_1")]
3090
)
3091
 
3092
(define_insn "neon_vmul_lane"
3093
  [(set (match_operand:VMD 0 "s_register_operand" "=w")
3094
        (unspec:VMD [(match_operand:VMD 1 "s_register_operand" "w")
3095
                     (match_operand:VMD 2 "s_register_operand"
3096
                                        "")
3097
                     (match_operand:SI 3 "immediate_operand" "i")
3098
                     (match_operand:SI 4 "immediate_operand" "i")]
3099
                    UNSPEC_VMUL_LANE))]
3100
  "TARGET_NEON"
3101
{
3102
  neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (mode));
3103
  return "vmul.\t%P0, %P1, %P2[%c3]";
3104
}
3105
  [(set (attr "neon_type")
3106
     (if_then_else (match_test "")
3107
                   (const_string "neon_fp_vmul_ddd")
3108
                   (if_then_else (match_test "")
3109
                                 (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
3110
                                 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar"))))]
3111
)
3112
 
3113
(define_insn "neon_vmul_lane"
3114
  [(set (match_operand:VMQ 0 "s_register_operand" "=w")
3115
        (unspec:VMQ [(match_operand:VMQ 1 "s_register_operand" "w")
3116
                     (match_operand: 2 "s_register_operand"
3117
                                             "")
3118
                     (match_operand:SI 3 "immediate_operand" "i")
3119
                     (match_operand:SI 4 "immediate_operand" "i")]
3120
                    UNSPEC_VMUL_LANE))]
3121
  "TARGET_NEON"
3122
{
3123
  neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (mode));
3124
  return "vmul.\t%q0, %q1, %P2[%c3]";
3125
}
3126
  [(set (attr "neon_type")
3127
     (if_then_else (match_test "")
3128
                   (const_string "neon_fp_vmul_qqd")
3129
                   (if_then_else (match_test "")
3130
                                 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")
3131
                                 (const_string "neon_mul_qqd_32_scalar"))))]
3132
)
3133
 
3134
(define_insn "neon_vmull_lane"
3135
  [(set (match_operand: 0 "s_register_operand" "=w")
3136
        (unspec: [(match_operand:VMDI 1 "s_register_operand" "w")
3137
                           (match_operand:VMDI 2 "s_register_operand"
3138
                                               "")
3139
                           (match_operand:SI 3 "immediate_operand" "i")
3140
                           (match_operand:SI 4 "immediate_operand" "i")]
3141
                          UNSPEC_VMULL_LANE))]
3142
  "TARGET_NEON"
3143
{
3144
  neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (mode));
3145
  return "vmull.%T4%#\t%q0, %P1, %P2[%c3]";
3146
}
3147
  [(set (attr "neon_type")
3148
     (if_then_else (match_test "")
3149
                   (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
3150
                   (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
3151
)
3152
 
3153
(define_insn "neon_vqdmull_lane"
3154
  [(set (match_operand: 0 "s_register_operand" "=w")
3155
        (unspec: [(match_operand:VMDI 1 "s_register_operand" "w")
3156
                           (match_operand:VMDI 2 "s_register_operand"
3157
                                               "")
3158
                           (match_operand:SI 3 "immediate_operand" "i")
3159
                           (match_operand:SI 4 "immediate_operand" "i")]
3160
                          UNSPEC_VQDMULL_LANE))]
3161
  "TARGET_NEON"
3162
{
3163
  neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (mode));
3164
  return "vqdmull.\t%q0, %P1, %P2[%c3]";
3165
}
3166
  [(set (attr "neon_type")
3167
     (if_then_else (match_test "")
3168
                   (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
3169
                   (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
3170
)
3171
 
3172
(define_insn "neon_vqdmulh_lane"
3173
  [(set (match_operand:VMQI 0 "s_register_operand" "=w")
3174
        (unspec:VMQI [(match_operand:VMQI 1 "s_register_operand" "w")
3175
                      (match_operand: 2 "s_register_operand"
3176
                                              "")
3177
                      (match_operand:SI 3 "immediate_operand" "i")
3178
                      (match_operand:SI 4 "immediate_operand" "i")]
3179
                      UNSPEC_VQDMULH_LANE))]
3180
  "TARGET_NEON"
3181
{
3182
  neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (mode));
3183
  return "vq%O4dmulh.%T4%#\t%q0, %q1, %P2[%c3]";
3184
}
3185
  [(set (attr "neon_type")
3186
     (if_then_else (match_test "")
3187
                   (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")
3188
                   (const_string "neon_mul_qqd_32_scalar")))]
3189
)
3190
 
3191
(define_insn "neon_vqdmulh_lane"
3192
  [(set (match_operand:VMDI 0 "s_register_operand" "=w")
3193
        (unspec:VMDI [(match_operand:VMDI 1 "s_register_operand" "w")
3194
                      (match_operand:VMDI 2 "s_register_operand"
3195
                                          "")
3196
                      (match_operand:SI 3 "immediate_operand" "i")
3197
                      (match_operand:SI 4 "immediate_operand" "i")]
3198
                      UNSPEC_VQDMULH_LANE))]
3199
  "TARGET_NEON"
3200
{
3201
  neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (mode));
3202
  return "vq%O4dmulh.%T4%#\t%P0, %P1, %P2[%c3]";
3203
}
3204
  [(set (attr "neon_type")
3205
     (if_then_else (match_test "")
3206
                   (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
3207
                   (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
3208
)
3209
 
3210
(define_insn "neon_vmla_lane"
3211
  [(set (match_operand:VMD 0 "s_register_operand" "=w")
3212
        (unspec:VMD [(match_operand:VMD 1 "s_register_operand" "0")
3213
                     (match_operand:VMD 2 "s_register_operand" "w")
3214
                     (match_operand:VMD 3 "s_register_operand"
3215
                                        "")
3216
                     (match_operand:SI 4 "immediate_operand" "i")
3217
                     (match_operand:SI 5 "immediate_operand" "i")]
3218
                     UNSPEC_VMLA_LANE))]
3219
  "TARGET_NEON"
3220
{
3221
  neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (mode));
3222
  return "vmla.\t%P0, %P2, %P3[%c4]";
3223
}
3224
  [(set (attr "neon_type")
3225
     (if_then_else (match_test "")
3226
                   (const_string "neon_fp_vmla_ddd_scalar")
3227
                   (if_then_else (match_test "")
3228
                                 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3229
                                 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))))]
3230
)
3231
 
3232
(define_insn "neon_vmla_lane"
3233
  [(set (match_operand:VMQ 0 "s_register_operand" "=w")
3234
        (unspec:VMQ [(match_operand:VMQ 1 "s_register_operand" "0")
3235
                     (match_operand:VMQ 2 "s_register_operand" "w")
3236
                     (match_operand: 3 "s_register_operand"
3237
                                             "")
3238
                     (match_operand:SI 4 "immediate_operand" "i")
3239
                     (match_operand:SI 5 "immediate_operand" "i")]
3240
                     UNSPEC_VMLA_LANE))]
3241
  "TARGET_NEON"
3242
{
3243
  neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (mode));
3244
  return "vmla.\t%q0, %q2, %P3[%c4]";
3245
}
3246
  [(set (attr "neon_type")
3247
     (if_then_else (match_test "")
3248
                   (const_string "neon_fp_vmla_qqq_scalar")
3249
                   (if_then_else (match_test "")
3250
                                 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")
3251
                                 (const_string "neon_mla_qqq_32_qqd_32_scalar"))))]
3252
)
3253
 
3254
(define_insn "neon_vmlal_lane"
3255
  [(set (match_operand: 0 "s_register_operand" "=w")
3256
        (unspec: [(match_operand: 1 "s_register_operand" "0")
3257
                           (match_operand:VMDI 2 "s_register_operand" "w")
3258
                           (match_operand:VMDI 3 "s_register_operand"
3259
                                               "")
3260
                           (match_operand:SI 4 "immediate_operand" "i")
3261
                           (match_operand:SI 5 "immediate_operand" "i")]
3262
                          UNSPEC_VMLAL_LANE))]
3263
  "TARGET_NEON"
3264
{
3265
  neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (mode));
3266
  return "vmlal.%T5%#\t%q0, %P2, %P3[%c4]";
3267
}
3268
  [(set (attr "neon_type")
3269
     (if_then_else (match_test "")
3270
                   (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3271
                   (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
3272
)
3273
 
3274
(define_insn "neon_vqdmlal_lane"
3275
  [(set (match_operand: 0 "s_register_operand" "=w")
3276
        (unspec: [(match_operand: 1 "s_register_operand" "0")
3277
                           (match_operand:VMDI 2 "s_register_operand" "w")
3278
                           (match_operand:VMDI 3 "s_register_operand"
3279
                                               "")
3280
                           (match_operand:SI 4 "immediate_operand" "i")
3281
                           (match_operand:SI 5 "immediate_operand" "i")]
3282
                          UNSPEC_VQDMLAL_LANE))]
3283
  "TARGET_NEON"
3284
{
3285
  neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (mode));
3286
  return "vqdmlal.\t%q0, %P2, %P3[%c4]";
3287
}
3288
  [(set (attr "neon_type")
3289
     (if_then_else (match_test "")
3290
                   (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3291
                   (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
3292
)
3293
 
3294
(define_insn "neon_vmls_lane"
3295
  [(set (match_operand:VMD 0 "s_register_operand" "=w")
3296
        (unspec:VMD [(match_operand:VMD 1 "s_register_operand" "0")
3297
                     (match_operand:VMD 2 "s_register_operand" "w")
3298
                     (match_operand:VMD 3 "s_register_operand"
3299
                                        "")
3300
                     (match_operand:SI 4 "immediate_operand" "i")
3301
                     (match_operand:SI 5 "immediate_operand" "i")]
3302
                    UNSPEC_VMLS_LANE))]
3303
  "TARGET_NEON"
3304
{
3305
  neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (mode));
3306
  return "vmls.\t%P0, %P2, %P3[%c4]";
3307
}
3308
  [(set (attr "neon_type")
3309
     (if_then_else (match_test "")
3310
                   (const_string "neon_fp_vmla_ddd_scalar")
3311
                   (if_then_else (match_test "")
3312
                                 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3313
                                 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))))]
3314
)
3315
 
3316
(define_insn "neon_vmls_lane"
3317
  [(set (match_operand:VMQ 0 "s_register_operand" "=w")
3318
        (unspec:VMQ [(match_operand:VMQ 1 "s_register_operand" "0")
3319
                     (match_operand:VMQ 2 "s_register_operand" "w")
3320
                     (match_operand: 3 "s_register_operand"
3321
                                             "")
3322
                     (match_operand:SI 4 "immediate_operand" "i")
3323
                     (match_operand:SI 5 "immediate_operand" "i")]
3324
                    UNSPEC_VMLS_LANE))]
3325
  "TARGET_NEON"
3326
{
3327
  neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (mode));
3328
  return "vmls.\t%q0, %q2, %P3[%c4]";
3329
}
3330
  [(set (attr "neon_type")
3331
     (if_then_else (match_test "")
3332
                   (const_string "neon_fp_vmla_qqq_scalar")
3333
                   (if_then_else (match_test "")
3334
                                 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")
3335
                                 (const_string "neon_mla_qqq_32_qqd_32_scalar"))))]
3336
)
3337
 
3338
(define_insn "neon_vmlsl_lane"
3339
  [(set (match_operand: 0 "s_register_operand" "=w")
3340
        (unspec: [(match_operand: 1 "s_register_operand" "0")
3341
                           (match_operand:VMDI 2 "s_register_operand" "w")
3342
                           (match_operand:VMDI 3 "s_register_operand"
3343
                                               "")
3344
                           (match_operand:SI 4 "immediate_operand" "i")
3345
                           (match_operand:SI 5 "immediate_operand" "i")]
3346
                          UNSPEC_VMLSL_LANE))]
3347
  "TARGET_NEON"
3348
{
3349
  neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (mode));
3350
  return "vmlsl.%T5%#\t%q0, %P2, %P3[%c4]";
3351
}
3352
  [(set (attr "neon_type")
3353
     (if_then_else (match_test "")
3354
                   (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3355
                   (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
3356
)
3357
 
3358
(define_insn "neon_vqdmlsl_lane"
3359
  [(set (match_operand: 0 "s_register_operand" "=w")
3360
        (unspec: [(match_operand: 1 "s_register_operand" "0")
3361
                           (match_operand:VMDI 2 "s_register_operand" "w")
3362
                           (match_operand:VMDI 3 "s_register_operand"
3363
                                               "")
3364
                           (match_operand:SI 4 "immediate_operand" "i")
3365
                           (match_operand:SI 5 "immediate_operand" "i")]
3366
                          UNSPEC_VQDMLSL_LANE))]
3367
  "TARGET_NEON"
3368
{
3369
  neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (mode));
3370
  return "vqdmlsl.\t%q0, %P2, %P3[%c4]";
3371
}
3372
  [(set (attr "neon_type")
3373
     (if_then_else (match_test "")
3374
                   (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
3375
                   (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
3376
)
3377
 
3378
; FIXME: For the "_n" multiply/multiply-accumulate insns, we copy a value in a
3379
; core register into a temp register, then use a scalar taken from that. This
3380
; isn't an optimal solution if e.g. the scalar has just been read from memory
3381
; or extracted from another vector. The latter case it's currently better to
3382
; use the "_lane" variant, and the former case can probably be implemented
3383
; using vld1_lane, but that hasn't been done yet.
3384
 
3385
(define_expand "neon_vmul_n"
3386
  [(match_operand:VMD 0 "s_register_operand" "")
3387
   (match_operand:VMD 1 "s_register_operand" "")
3388
   (match_operand: 2 "s_register_operand" "")
3389
   (match_operand:SI 3 "immediate_operand" "")]
3390
  "TARGET_NEON"
3391
{
3392
  rtx tmp = gen_reg_rtx (mode);
3393
  emit_insn (gen_neon_vset_lane (tmp, operands[2], tmp, const0_rtx));
3394
  emit_insn (gen_neon_vmul_lane (operands[0], operands[1], tmp,
3395
                                       const0_rtx, const0_rtx));
3396
  DONE;
3397
})
3398
 
3399
(define_expand "neon_vmul_n"
3400
  [(match_operand:VMQ 0 "s_register_operand" "")
3401
   (match_operand:VMQ 1 "s_register_operand" "")
3402
   (match_operand: 2 "s_register_operand" "")
3403
   (match_operand:SI 3 "immediate_operand" "")]
3404
  "TARGET_NEON"
3405
{
3406
  rtx tmp = gen_reg_rtx (mode);
3407
  emit_insn (gen_neon_vset_lane (tmp, operands[2], tmp, const0_rtx));
3408
  emit_insn (gen_neon_vmul_lane (operands[0], operands[1], tmp,
3409
                                       const0_rtx, const0_rtx));
3410
  DONE;
3411
})
3412
 
3413
(define_expand "neon_vmull_n"
3414
  [(match_operand: 0 "s_register_operand" "")
3415
   (match_operand:VMDI 1 "s_register_operand" "")
3416
   (match_operand: 2 "s_register_operand" "")
3417
   (match_operand:SI 3 "immediate_operand" "")]
3418
  "TARGET_NEON"
3419
{
3420
  rtx tmp = gen_reg_rtx (mode);
3421
  emit_insn (gen_neon_vset_lane (tmp, operands[2], tmp, const0_rtx));
3422
  emit_insn (gen_neon_vmull_lane (operands[0], operands[1], tmp,
3423
                                        const0_rtx, operands[3]));
3424
  DONE;
3425
})
3426
 
3427
(define_expand "neon_vqdmull_n"
3428
  [(match_operand: 0 "s_register_operand" "")
3429
   (match_operand:VMDI 1 "s_register_operand" "")
3430
   (match_operand: 2 "s_register_operand" "")
3431
   (match_operand:SI 3 "immediate_operand" "")]
3432
  "TARGET_NEON"
3433
{
3434
  rtx tmp = gen_reg_rtx (mode);
3435
  emit_insn (gen_neon_vset_lane (tmp, operands[2], tmp, const0_rtx));
3436
  emit_insn (gen_neon_vqdmull_lane (operands[0], operands[1], tmp,
3437
                                          const0_rtx, const0_rtx));
3438
  DONE;
3439
})
3440
 
3441
(define_expand "neon_vqdmulh_n"
3442
  [(match_operand:VMDI 0 "s_register_operand" "")
3443
   (match_operand:VMDI 1 "s_register_operand" "")
3444
   (match_operand: 2 "s_register_operand" "")
3445
   (match_operand:SI 3 "immediate_operand" "")]
3446
  "TARGET_NEON"
3447
{
3448
  rtx tmp = gen_reg_rtx (mode);
3449
  emit_insn (gen_neon_vset_lane (tmp, operands[2], tmp, const0_rtx));
3450
  emit_insn (gen_neon_vqdmulh_lane (operands[0], operands[1], tmp,
3451
                                          const0_rtx, operands[3]));
3452
  DONE;
3453
})
3454
 
3455
(define_expand "neon_vqdmulh_n"
3456
  [(match_operand:VMQI 0 "s_register_operand" "")
3457
   (match_operand:VMQI 1 "s_register_operand" "")
3458
   (match_operand: 2 "s_register_operand" "")
3459
   (match_operand:SI 3 "immediate_operand" "")]
3460
  "TARGET_NEON"
3461
{
3462
  rtx tmp = gen_reg_rtx (mode);
3463
  emit_insn (gen_neon_vset_lane (tmp, operands[2], tmp, const0_rtx));
3464
  emit_insn (gen_neon_vqdmulh_lane (operands[0], operands[1], tmp,
3465
                                          const0_rtx, operands[3]));
3466
  DONE;
3467
})
3468
 
3469
(define_expand "neon_vmla_n"
3470
  [(match_operand:VMD 0 "s_register_operand" "")
3471
   (match_operand:VMD 1 "s_register_operand" "")
3472
   (match_operand:VMD 2 "s_register_operand" "")
3473
   (match_operand: 3 "s_register_operand" "")
3474
   (match_operand:SI 4 "immediate_operand" "")]
3475
  "TARGET_NEON"
3476
{
3477
  rtx tmp = gen_reg_rtx (mode);
3478
  emit_insn (gen_neon_vset_lane (tmp, operands[3], tmp, const0_rtx));
3479
  emit_insn (gen_neon_vmla_lane (operands[0], operands[1], operands[2],
3480
                                       tmp, const0_rtx, operands[4]));
3481
  DONE;
3482
})
3483
 
3484
(define_expand "neon_vmla_n"
3485
  [(match_operand:VMQ 0 "s_register_operand" "")
3486
   (match_operand:VMQ 1 "s_register_operand" "")
3487
   (match_operand:VMQ 2 "s_register_operand" "")
3488
   (match_operand: 3 "s_register_operand" "")
3489
   (match_operand:SI 4 "immediate_operand" "")]
3490
  "TARGET_NEON"
3491
{
3492
  rtx tmp = gen_reg_rtx (mode);
3493
  emit_insn (gen_neon_vset_lane (tmp, operands[3], tmp, const0_rtx));
3494
  emit_insn (gen_neon_vmla_lane (operands[0], operands[1], operands[2],
3495
                                       tmp, const0_rtx, operands[4]));
3496
  DONE;
3497
})
3498
 
3499
(define_expand "neon_vmlal_n"
3500
  [(match_operand: 0 "s_register_operand" "")
3501
   (match_operand: 1 "s_register_operand" "")
3502
   (match_operand:VMDI 2 "s_register_operand" "")
3503
   (match_operand: 3 "s_register_operand" "")
3504
   (match_operand:SI 4 "immediate_operand" "")]
3505
  "TARGET_NEON"
3506
{
3507
  rtx tmp = gen_reg_rtx (mode);
3508
  emit_insn (gen_neon_vset_lane (tmp, operands[3], tmp, const0_rtx));
3509
  emit_insn (gen_neon_vmlal_lane (operands[0], operands[1], operands[2],
3510
                                        tmp, const0_rtx, operands[4]));
3511
  DONE;
3512
})
3513
 
3514
(define_expand "neon_vqdmlal_n"
3515
  [(match_operand: 0 "s_register_operand" "")
3516
   (match_operand: 1 "s_register_operand" "")
3517
   (match_operand:VMDI 2 "s_register_operand" "")
3518
   (match_operand: 3 "s_register_operand" "")
3519
   (match_operand:SI 4 "immediate_operand" "")]
3520
  "TARGET_NEON"
3521
{
3522
  rtx tmp = gen_reg_rtx (mode);
3523
  emit_insn (gen_neon_vset_lane (tmp, operands[3], tmp, const0_rtx));
3524
  emit_insn (gen_neon_vqdmlal_lane (operands[0], operands[1], operands[2],
3525
                                          tmp, const0_rtx, operands[4]));
3526
  DONE;
3527
})
3528
 
3529
(define_expand "neon_vmls_n"
3530
  [(match_operand:VMD 0 "s_register_operand" "")
3531
   (match_operand:VMD 1 "s_register_operand" "")
3532
   (match_operand:VMD 2 "s_register_operand" "")
3533
   (match_operand: 3 "s_register_operand" "")
3534
   (match_operand:SI 4 "immediate_operand" "")]
3535
  "TARGET_NEON"
3536
{
3537
  rtx tmp = gen_reg_rtx (mode);
3538
  emit_insn (gen_neon_vset_lane (tmp, operands[3], tmp, const0_rtx));
3539
  emit_insn (gen_neon_vmls_lane (operands[0], operands[1], operands[2],
3540
                                       tmp, const0_rtx, operands[4]));
3541
  DONE;
3542
})
3543
 
3544
(define_expand "neon_vmls_n"
3545
  [(match_operand:VMQ 0 "s_register_operand" "")
3546
   (match_operand:VMQ 1 "s_register_operand" "")
3547
   (match_operand:VMQ 2 "s_register_operand" "")
3548
   (match_operand: 3 "s_register_operand" "")
3549
   (match_operand:SI 4 "immediate_operand" "")]
3550
  "TARGET_NEON"
3551
{
3552
  rtx tmp = gen_reg_rtx (mode);
3553
  emit_insn (gen_neon_vset_lane (tmp, operands[3], tmp, const0_rtx));
3554
  emit_insn (gen_neon_vmls_lane (operands[0], operands[1], operands[2],
3555
                                       tmp, const0_rtx, operands[4]));
3556
  DONE;
3557
})
3558
 
3559
(define_expand "neon_vmlsl_n"
3560
  [(match_operand: 0 "s_register_operand" "")
3561
   (match_operand: 1 "s_register_operand" "")
3562
   (match_operand:VMDI 2 "s_register_operand" "")
3563
   (match_operand: 3 "s_register_operand" "")
3564
   (match_operand:SI 4 "immediate_operand" "")]
3565
  "TARGET_NEON"
3566
{
3567
  rtx tmp = gen_reg_rtx (mode);
3568
  emit_insn (gen_neon_vset_lane (tmp, operands[3], tmp, const0_rtx));
3569
  emit_insn (gen_neon_vmlsl_lane (operands[0], operands[1], operands[2],
3570
                                        tmp, const0_rtx, operands[4]));
3571
  DONE;
3572
})
3573
 
3574
(define_expand "neon_vqdmlsl_n"
3575
  [(match_operand: 0 "s_register_operand" "")
3576
   (match_operand: 1 "s_register_operand" "")
3577
   (match_operand:VMDI 2 "s_register_operand" "")
3578
   (match_operand: 3 "s_register_operand" "")
3579
   (match_operand:SI 4 "immediate_operand" "")]
3580
  "TARGET_NEON"
3581
{
3582
  rtx tmp = gen_reg_rtx (mode);
3583
  emit_insn (gen_neon_vset_lane (tmp, operands[3], tmp, const0_rtx));
3584
  emit_insn (gen_neon_vqdmlsl_lane (operands[0], operands[1], operands[2],
3585
                                          tmp, const0_rtx, operands[4]));
3586
  DONE;
3587
})
3588
 
3589
(define_insn "neon_vext"
3590
  [(set (match_operand:VDQX 0 "s_register_operand" "=w")
3591
        (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w")
3592
                      (match_operand:VDQX 2 "s_register_operand" "w")
3593
                      (match_operand:SI 3 "immediate_operand" "i")]
3594
                     UNSPEC_VEXT))]
3595
  "TARGET_NEON"
3596
{
3597
  neon_const_bounds (operands[3], 0, GET_MODE_NUNITS (mode));
3598
  return "vext.\t%0, %1, %2, %3";
3599
}
3600
  [(set (attr "neon_type")
3601
      (if_then_else (match_test "")
3602
                    (const_string "neon_bp_simple")
3603
                    (const_string "neon_bp_2cycle")))]
3604
)
3605
 
3606
(define_insn "neon_vrev64"
3607
  [(set (match_operand:VDQ 0 "s_register_operand" "=w")
3608
        (unspec:VDQ [(match_operand:VDQ 1 "s_register_operand" "w")
3609
                     (match_operand:SI 2 "immediate_operand" "i")]
3610
                    UNSPEC_VREV64))]
3611
  "TARGET_NEON"
3612
  "vrev64.\t%0, %1"
3613
  [(set_attr "neon_type" "neon_bp_simple")]
3614
)
3615
 
3616
(define_insn "neon_vrev32"
3617
  [(set (match_operand:VX 0 "s_register_operand" "=w")
3618
        (unspec:VX [(match_operand:VX 1 "s_register_operand" "w")
3619
                    (match_operand:SI 2 "immediate_operand" "i")]
3620
                   UNSPEC_VREV32))]
3621
  "TARGET_NEON"
3622
  "vrev32.\t%0, %1"
3623
  [(set_attr "neon_type" "neon_bp_simple")]
3624
)
3625
 
3626
(define_insn "neon_vrev16"
3627
  [(set (match_operand:VE 0 "s_register_operand" "=w")
3628
        (unspec:VE [(match_operand:VE 1 "s_register_operand" "w")
3629
                    (match_operand:SI 2 "immediate_operand" "i")]
3630
                   UNSPEC_VREV16))]
3631
  "TARGET_NEON"
3632
  "vrev16.\t%0, %1"
3633
  [(set_attr "neon_type" "neon_bp_simple")]
3634
)
3635
 
3636
; vbsl_* intrinsics may compile to any of vbsl/vbif/vbit depending on register
3637
; allocation. For an intrinsic of form:
3638
;   rD = vbsl_* (rS, rN, rM)
3639
; We can use any of:
3640
;   vbsl rS, rN, rM  (if D = S)
3641
;   vbit rD, rN, rS  (if D = M, so 1-bits in rS choose bits from rN, else rM)
3642
;   vbif rD, rM, rS  (if D = N, so 0-bits in rS choose bits from rM, else rN)
3643
 
3644
(define_insn "neon_vbsl_internal"
3645
  [(set (match_operand:VDQX 0 "s_register_operand"               "=w,w,w")
3646
        (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" " 0,w,w")
3647
                      (match_operand:VDQX 2 "s_register_operand" " w,w,0")
3648
                      (match_operand:VDQX 3 "s_register_operand" " w,0,w")]
3649
                     UNSPEC_VBSL))]
3650
  "TARGET_NEON"
3651
  "@
3652
  vbsl\t%0, %2, %3
3653
  vbit\t%0, %2, %1
3654
  vbif\t%0, %3, %1"
3655
  [(set_attr "neon_type" "neon_int_1")]
3656
)
3657
 
3658
(define_expand "neon_vbsl"
3659
  [(set (match_operand:VDQX 0 "s_register_operand" "")
3660
        (unspec:VDQX [(match_operand: 1 "s_register_operand" "")
3661
                      (match_operand:VDQX 2 "s_register_operand" "")
3662
                      (match_operand:VDQX 3 "s_register_operand" "")]
3663
                     UNSPEC_VBSL))]
3664
  "TARGET_NEON"
3665
{
3666
  /* We can't alias operands together if they have different modes.  */
3667
  operands[1] = gen_lowpart (mode, operands[1]);
3668
})
3669
 
3670
(define_insn "neon_vshl"
3671
  [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
3672
        (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
3673
                       (match_operand:VDQIX 2 "s_register_operand" "w")
3674
                       (match_operand:SI 3 "immediate_operand" "i")]
3675
                      UNSPEC_VSHL))]
3676
  "TARGET_NEON"
3677
  "v%O3shl.%T3%#\t%0, %1, %2"
3678
  [(set (attr "neon_type")
3679
      (if_then_else (match_test "")
3680
                    (const_string "neon_vshl_ddd")
3681
                    (const_string "neon_shift_3")))]
3682
)
3683
 
3684
(define_insn "neon_vqshl"
3685
  [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
3686
        (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
3687
                       (match_operand:VDQIX 2 "s_register_operand" "w")
3688
                       (match_operand:SI 3 "immediate_operand" "i")]
3689
                      UNSPEC_VQSHL))]
3690
  "TARGET_NEON"
3691
  "vq%O3shl.%T3%#\t%0, %1, %2"
3692
  [(set (attr "neon_type")
3693
      (if_then_else (match_test "")
3694
                    (const_string "neon_shift_2")
3695
                    (const_string "neon_vqshl_vrshl_vqrshl_qqq")))]
3696
)
3697
 
3698
(define_insn "neon_vshr_n"
3699
  [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
3700
        (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
3701
                       (match_operand:SI 2 "immediate_operand" "i")
3702
                       (match_operand:SI 3 "immediate_operand" "i")]
3703
                      UNSPEC_VSHR_N))]
3704
  "TARGET_NEON"
3705
{
3706
  neon_const_bounds (operands[2], 1, neon_element_bits (mode) + 1);
3707
  return "v%O3shr.%T3%#\t%0, %1, %2";
3708
}
3709
  [(set_attr "neon_type" "neon_shift_1")]
3710
)
3711
 
3712
(define_insn "neon_vshrn_n"
3713
  [(set (match_operand: 0 "s_register_operand" "=w")
3714
        (unspec: [(match_operand:VN 1 "s_register_operand" "w")
3715
                            (match_operand:SI 2 "immediate_operand" "i")
3716
                            (match_operand:SI 3 "immediate_operand" "i")]
3717
                           UNSPEC_VSHRN_N))]
3718
  "TARGET_NEON"
3719
{
3720
  neon_const_bounds (operands[2], 1, neon_element_bits (mode) / 2 + 1);
3721
  return "v%O3shrn.\t%P0, %q1, %2";
3722
}
3723
  [(set_attr "neon_type" "neon_shift_1")]
3724
)
3725
 
3726
(define_insn "neon_vqshrn_n"
3727
  [(set (match_operand: 0 "s_register_operand" "=w")
3728
        (unspec: [(match_operand:VN 1 "s_register_operand" "w")
3729
                            (match_operand:SI 2 "immediate_operand" "i")
3730
                            (match_operand:SI 3 "immediate_operand" "i")]
3731
                           UNSPEC_VQSHRN_N))]
3732
  "TARGET_NEON"
3733
{
3734
  neon_const_bounds (operands[2], 1, neon_element_bits (mode) / 2 + 1);
3735
  return "vq%O3shrn.%T3%#\t%P0, %q1, %2";
3736
}
3737
  [(set_attr "neon_type" "neon_shift_2")]
3738
)
3739
 
3740
(define_insn "neon_vqshrun_n"
3741
  [(set (match_operand: 0 "s_register_operand" "=w")
3742
        (unspec: [(match_operand:VN 1 "s_register_operand" "w")
3743
                            (match_operand:SI 2 "immediate_operand" "i")
3744
                            (match_operand:SI 3 "immediate_operand" "i")]
3745
                           UNSPEC_VQSHRUN_N))]
3746
  "TARGET_NEON"
3747
{
3748
  neon_const_bounds (operands[2], 1, neon_element_bits (mode) / 2 + 1);
3749
  return "vq%O3shrun.%T3%#\t%P0, %q1, %2";
3750
}
3751
  [(set_attr "neon_type" "neon_shift_2")]
3752
)
3753
 
3754
(define_insn "neon_vshl_n"
3755
  [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
3756
        (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
3757
                       (match_operand:SI 2 "immediate_operand" "i")
3758
                       (match_operand:SI 3 "immediate_operand" "i")]
3759
                      UNSPEC_VSHL_N))]
3760
  "TARGET_NEON"
3761
{
3762
  neon_const_bounds (operands[2], 0, neon_element_bits (mode));
3763
  return "vshl.\t%0, %1, %2";
3764
}
3765
  [(set_attr "neon_type" "neon_shift_1")]
3766
)
3767
 
3768
(define_insn "neon_vqshl_n"
3769
  [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
3770
        (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
3771
                       (match_operand:SI 2 "immediate_operand" "i")
3772
                       (match_operand:SI 3 "immediate_operand" "i")]
3773
                      UNSPEC_VQSHL_N))]
3774
  "TARGET_NEON"
3775
{
3776
  neon_const_bounds (operands[2], 0, neon_element_bits (mode));
3777
  return "vqshl.%T3%#\t%0, %1, %2";
3778
}
3779
  [(set_attr "neon_type" "neon_shift_2")]
3780
)
3781
 
3782
(define_insn "neon_vqshlu_n"
3783
  [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
3784
        (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w")
3785
                       (match_operand:SI 2 "immediate_operand" "i")
3786
                       (match_operand:SI 3 "immediate_operand" "i")]
3787
                      UNSPEC_VQSHLU_N))]
3788
  "TARGET_NEON"
3789
{
3790
  neon_const_bounds (operands[2], 0, neon_element_bits (mode));
3791
  return "vqshlu.%T3%#\t%0, %1, %2";
3792
}
3793
  [(set_attr "neon_type" "neon_shift_2")]
3794
)
3795
 
3796
(define_insn "neon_vshll_n"
3797
  [(set (match_operand: 0 "s_register_operand" "=w")
3798
        (unspec: [(match_operand:VW 1 "s_register_operand" "w")
3799
                           (match_operand:SI 2 "immediate_operand" "i")
3800
                           (match_operand:SI 3 "immediate_operand" "i")]
3801
                          UNSPEC_VSHLL_N))]
3802
  "TARGET_NEON"
3803
{
3804
  /* The boundaries are: 0 < imm <= size.  */
3805
  neon_const_bounds (operands[2], 0, neon_element_bits (mode) + 1);
3806
  return "vshll.%T3%#\t%q0, %P1, %2";
3807
}
3808
  [(set_attr "neon_type" "neon_shift_1")]
3809
)
3810
 
3811
(define_insn "neon_vsra_n"
3812
  [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
3813
        (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "0")
3814
                       (match_operand:VDQIX 2 "s_register_operand" "w")
3815
                       (match_operand:SI 3 "immediate_operand" "i")
3816
                       (match_operand:SI 4 "immediate_operand" "i")]
3817
                      UNSPEC_VSRA_N))]
3818
  "TARGET_NEON"
3819
{
3820
  neon_const_bounds (operands[3], 1, neon_element_bits (mode) + 1);
3821
  return "v%O4sra.%T4%#\t%0, %2, %3";
3822
}
3823
  [(set_attr "neon_type" "neon_vsra_vrsra")]
3824
)
3825
 
3826
(define_insn "neon_vsri_n"
3827
  [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
3828
        (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "0")
3829
                       (match_operand:VDQIX 2 "s_register_operand" "w")
3830
                       (match_operand:SI 3 "immediate_operand" "i")]
3831
                      UNSPEC_VSRI))]
3832
  "TARGET_NEON"
3833
{
3834
  neon_const_bounds (operands[3], 1, neon_element_bits (mode) + 1);
3835
  return "vsri.\t%0, %2, %3";
3836
}
3837
  [(set (attr "neon_type")
3838
      (if_then_else (match_test "")
3839
                    (const_string "neon_shift_1")
3840
                    (const_string "neon_shift_3")))]
3841
)
3842
 
3843
(define_insn "neon_vsli_n"
3844
  [(set (match_operand:VDQIX 0 "s_register_operand" "=w")
3845
        (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "0")
3846
                       (match_operand:VDQIX 2 "s_register_operand" "w")
3847
                       (match_operand:SI 3 "immediate_operand" "i")]
3848
                      UNSPEC_VSLI))]
3849
  "TARGET_NEON"
3850
{
3851
  neon_const_bounds (operands[3], 0, neon_element_bits (mode));
3852
  return "vsli.\t%0, %2, %3";
3853
}
3854
  [(set (attr "neon_type")
3855
      (if_then_else (match_test "")
3856
                    (const_string "neon_shift_1")
3857
                    (const_string "neon_shift_3")))]
3858
)
3859
 
3860
(define_insn "neon_vtbl1v8qi"
3861
  [(set (match_operand:V8QI 0 "s_register_operand" "=w")
3862
        (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "w")
3863
                      (match_operand:V8QI 2 "s_register_operand" "w")]
3864
                     UNSPEC_VTBL))]
3865
  "TARGET_NEON"
3866
  "vtbl.8\t%P0, {%P1}, %P2"
3867
  [(set_attr "neon_type" "neon_bp_2cycle")]
3868
)
3869
 
3870
(define_insn "neon_vtbl2v8qi"
3871
  [(set (match_operand:V8QI 0 "s_register_operand" "=w")
3872
        (unspec:V8QI [(match_operand:TI 1 "s_register_operand" "w")
3873
                      (match_operand:V8QI 2 "s_register_operand" "w")]
3874
                     UNSPEC_VTBL))]
3875
  "TARGET_NEON"
3876
{
3877
  rtx ops[4];
3878
  int tabbase = REGNO (operands[1]);
3879
 
3880
  ops[0] = operands[0];
3881
  ops[1] = gen_rtx_REG (V8QImode, tabbase);
3882
  ops[2] = gen_rtx_REG (V8QImode, tabbase + 2);
3883
  ops[3] = operands[2];
3884
  output_asm_insn ("vtbl.8\t%P0, {%P1, %P2}, %P3", ops);
3885
 
3886
  return "";
3887
}
3888
  [(set_attr "neon_type" "neon_bp_2cycle")]
3889
)
3890
 
3891
(define_insn "neon_vtbl3v8qi"
3892
  [(set (match_operand:V8QI 0 "s_register_operand" "=w")
3893
        (unspec:V8QI [(match_operand:EI 1 "s_register_operand" "w")
3894
                      (match_operand:V8QI 2 "s_register_operand" "w")]
3895
                     UNSPEC_VTBL))]
3896
  "TARGET_NEON"
3897
{
3898
  rtx ops[5];
3899
  int tabbase = REGNO (operands[1]);
3900
 
3901
  ops[0] = operands[0];
3902
  ops[1] = gen_rtx_REG (V8QImode, tabbase);
3903
  ops[2] = gen_rtx_REG (V8QImode, tabbase + 2);
3904
  ops[3] = gen_rtx_REG (V8QImode, tabbase + 4);
3905
  ops[4] = operands[2];
3906
  output_asm_insn ("vtbl.8\t%P0, {%P1, %P2, %P3}, %P4", ops);
3907
 
3908
  return "";
3909
}
3910
  [(set_attr "neon_type" "neon_bp_3cycle")]
3911
)
3912
 
3913
(define_insn "neon_vtbl4v8qi"
3914
  [(set (match_operand:V8QI 0 "s_register_operand" "=w")
3915
        (unspec:V8QI [(match_operand:OI 1 "s_register_operand" "w")
3916
                      (match_operand:V8QI 2 "s_register_operand" "w")]
3917
                     UNSPEC_VTBL))]
3918
  "TARGET_NEON"
3919
{
3920
  rtx ops[6];
3921
  int tabbase = REGNO (operands[1]);
3922
 
3923
  ops[0] = operands[0];
3924
  ops[1] = gen_rtx_REG (V8QImode, tabbase);
3925
  ops[2] = gen_rtx_REG (V8QImode, tabbase + 2);
3926
  ops[3] = gen_rtx_REG (V8QImode, tabbase + 4);
3927
  ops[4] = gen_rtx_REG (V8QImode, tabbase + 6);
3928
  ops[5] = operands[2];
3929
  output_asm_insn ("vtbl.8\t%P0, {%P1, %P2, %P3, %P4}, %P5", ops);
3930
 
3931
  return "";
3932
}
3933
  [(set_attr "neon_type" "neon_bp_3cycle")]
3934
)
3935
 
3936
;; These three are used by the vec_perm infrastructure for V16QImode.
3937
(define_insn_and_split "neon_vtbl1v16qi"
3938
  [(set (match_operand:V16QI 0 "s_register_operand" "=&w")
3939
        (unspec:V16QI [(match_operand:V16QI 1 "s_register_operand" "w")
3940
                       (match_operand:V16QI 2 "s_register_operand" "w")]
3941
                      UNSPEC_VTBL))]
3942
  "TARGET_NEON"
3943
  "#"
3944
  "&& reload_completed"
3945
  [(const_int 0)]
3946
{
3947
  rtx op0, op1, op2, part0, part2;
3948
  unsigned ofs;
3949
 
3950
  op0 = operands[0];
3951
  op1 = gen_lowpart (TImode, operands[1]);
3952
  op2 = operands[2];
3953
 
3954
  ofs = subreg_lowpart_offset (V8QImode, V16QImode);
3955
  part0 = simplify_subreg (V8QImode, op0, V16QImode, ofs);
3956
  part2 = simplify_subreg (V8QImode, op2, V16QImode, ofs);
3957
  emit_insn (gen_neon_vtbl2v8qi (part0, op1, part2));
3958
 
3959
  ofs = subreg_highpart_offset (V8QImode, V16QImode);
3960
  part0 = simplify_subreg (V8QImode, op0, V16QImode, ofs);
3961
  part2 = simplify_subreg (V8QImode, op2, V16QImode, ofs);
3962
  emit_insn (gen_neon_vtbl2v8qi (part0, op1, part2));
3963
  DONE;
3964
})
3965
 
3966
(define_insn_and_split "neon_vtbl2v16qi"
3967
  [(set (match_operand:V16QI 0 "s_register_operand" "=&w")
3968
        (unspec:V16QI [(match_operand:OI 1 "s_register_operand" "w")
3969
                       (match_operand:V16QI 2 "s_register_operand" "w")]
3970
                      UNSPEC_VTBL))]
3971
  "TARGET_NEON"
3972
  "#"
3973
  "&& reload_completed"
3974
  [(const_int 0)]
3975
{
3976
  rtx op0, op1, op2, part0, part2;
3977
  unsigned ofs;
3978
 
3979
  op0 = operands[0];
3980
  op1 = operands[1];
3981
  op2 = operands[2];
3982
 
3983
  ofs = subreg_lowpart_offset (V8QImode, V16QImode);
3984
  part0 = simplify_subreg (V8QImode, op0, V16QImode, ofs);
3985
  part2 = simplify_subreg (V8QImode, op2, V16QImode, ofs);
3986
  emit_insn (gen_neon_vtbl2v8qi (part0, op1, part2));
3987
 
3988
  ofs = subreg_highpart_offset (V8QImode, V16QImode);
3989
  part0 = simplify_subreg (V8QImode, op0, V16QImode, ofs);
3990
  part2 = simplify_subreg (V8QImode, op2, V16QImode, ofs);
3991
  emit_insn (gen_neon_vtbl2v8qi (part0, op1, part2));
3992
  DONE;
3993
})
3994
 
3995
;; ??? Logically we should extend the regular neon_vcombine pattern to
3996
;; handle quad-word input modes, producing octa-word output modes.  But
3997
;; that requires us to add support for octa-word vector modes in moves.
3998
;; That seems overkill for this one use in vec_perm.
3999
(define_insn_and_split "neon_vcombinev16qi"
4000
  [(set (match_operand:OI 0 "s_register_operand" "=w")
4001
        (unspec:OI [(match_operand:V16QI 1 "s_register_operand" "w")
4002
                    (match_operand:V16QI 2 "s_register_operand" "w")]
4003
                   UNSPEC_VCONCAT))]
4004
  "TARGET_NEON"
4005
  "#"
4006
  "&& reload_completed"
4007
  [(const_int 0)]
4008
{
4009
  neon_split_vcombine (operands);
4010
  DONE;
4011
})
4012
 
4013
(define_insn "neon_vtbx1v8qi"
4014
  [(set (match_operand:V8QI 0 "s_register_operand" "=w")
4015
        (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "0")
4016
                      (match_operand:V8QI 2 "s_register_operand" "w")
4017
                      (match_operand:V8QI 3 "s_register_operand" "w")]
4018
                     UNSPEC_VTBX))]
4019
  "TARGET_NEON"
4020
  "vtbx.8\t%P0, {%P2}, %P3"
4021
  [(set_attr "neon_type" "neon_bp_2cycle")]
4022
)
4023
 
4024
(define_insn "neon_vtbx2v8qi"
4025
  [(set (match_operand:V8QI 0 "s_register_operand" "=w")
4026
        (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "0")
4027
                      (match_operand:TI 2 "s_register_operand" "w")
4028
                      (match_operand:V8QI 3 "s_register_operand" "w")]
4029
                     UNSPEC_VTBX))]
4030
  "TARGET_NEON"
4031
{
4032
  rtx ops[4];
4033
  int tabbase = REGNO (operands[2]);
4034
 
4035
  ops[0] = operands[0];
4036
  ops[1] = gen_rtx_REG (V8QImode, tabbase);
4037
  ops[2] = gen_rtx_REG (V8QImode, tabbase + 2);
4038
  ops[3] = operands[3];
4039
  output_asm_insn ("vtbx.8\t%P0, {%P1, %P2}, %P3", ops);
4040
 
4041
  return "";
4042
}
4043
  [(set_attr "neon_type" "neon_bp_2cycle")]
4044
)
4045
 
4046
(define_insn "neon_vtbx3v8qi"
4047
  [(set (match_operand:V8QI 0 "s_register_operand" "=w")
4048
        (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "0")
4049
                      (match_operand:EI 2 "s_register_operand" "w")
4050
                      (match_operand:V8QI 3 "s_register_operand" "w")]
4051
                     UNSPEC_VTBX))]
4052
  "TARGET_NEON"
4053
{
4054
  rtx ops[5];
4055
  int tabbase = REGNO (operands[2]);
4056
 
4057
  ops[0] = operands[0];
4058
  ops[1] = gen_rtx_REG (V8QImode, tabbase);
4059
  ops[2] = gen_rtx_REG (V8QImode, tabbase + 2);
4060
  ops[3] = gen_rtx_REG (V8QImode, tabbase + 4);
4061
  ops[4] = operands[3];
4062
  output_asm_insn ("vtbx.8\t%P0, {%P1, %P2, %P3}, %P4", ops);
4063
 
4064
  return "";
4065
}
4066
  [(set_attr "neon_type" "neon_bp_3cycle")]
4067
)
4068
 
4069
(define_insn "neon_vtbx4v8qi"
4070
  [(set (match_operand:V8QI 0 "s_register_operand" "=w")
4071
        (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "0")
4072
                      (match_operand:OI 2 "s_register_operand" "w")
4073
                      (match_operand:V8QI 3 "s_register_operand" "w")]
4074
                     UNSPEC_VTBX))]
4075
  "TARGET_NEON"
4076
{
4077
  rtx ops[6];
4078
  int tabbase = REGNO (operands[2]);
4079
 
4080
  ops[0] = operands[0];
4081
  ops[1] = gen_rtx_REG (V8QImode, tabbase);
4082
  ops[2] = gen_rtx_REG (V8QImode, tabbase + 2);
4083
  ops[3] = gen_rtx_REG (V8QImode, tabbase + 4);
4084
  ops[4] = gen_rtx_REG (V8QImode, tabbase + 6);
4085
  ops[5] = operands[3];
4086
  output_asm_insn ("vtbx.8\t%P0, {%P1, %P2, %P3, %P4}, %P5", ops);
4087
 
4088
  return "";
4089
}
4090
  [(set_attr "neon_type" "neon_bp_3cycle")]
4091
)
4092
 
4093
(define_insn "neon_vtrn_internal"
4094
  [(set (match_operand:VDQW 0 "s_register_operand" "=w")
4095
        (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0")
4096
                      (match_operand:VDQW 2 "s_register_operand" "w")]
4097
                     UNSPEC_VTRN1))
4098
   (set (match_operand:VDQW 3 "s_register_operand" "=2")
4099
         (unspec:VDQW [(match_dup 1) (match_dup 2)]
4100
                     UNSPEC_VTRN2))]
4101
  "TARGET_NEON"
4102
  "vtrn.\t%0, %3"
4103
  [(set (attr "neon_type")
4104
      (if_then_else (match_test "")
4105
                    (const_string "neon_bp_simple")
4106
                    (const_string "neon_bp_3cycle")))]
4107
)
4108
 
4109
(define_expand "neon_vtrn"
4110
  [(match_operand:SI 0 "s_register_operand" "r")
4111
   (match_operand:VDQW 1 "s_register_operand" "w")
4112
   (match_operand:VDQW 2 "s_register_operand" "w")]
4113
  "TARGET_NEON"
4114
{
4115
  neon_emit_pair_result_insn (mode, gen_neon_vtrn_internal,
4116
                              operands[0], operands[1], operands[2]);
4117
  DONE;
4118
})
4119
 
4120
(define_insn "neon_vzip_internal"
4121
  [(set (match_operand:VDQW 0 "s_register_operand" "=w")
4122
        (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0")
4123
                      (match_operand:VDQW 2 "s_register_operand" "w")]
4124
                     UNSPEC_VZIP1))
4125
   (set (match_operand:VDQW 3 "s_register_operand" "=2")
4126
        (unspec:VDQW [(match_dup 1) (match_dup 2)]
4127
                     UNSPEC_VZIP2))]
4128
  "TARGET_NEON"
4129
  "vzip.\t%0, %3"
4130
  [(set (attr "neon_type")
4131
      (if_then_else (match_test "")
4132
                    (const_string "neon_bp_simple")
4133
                    (const_string "neon_bp_3cycle")))]
4134
)
4135
 
4136
(define_expand "neon_vzip"
4137
  [(match_operand:SI 0 "s_register_operand" "r")
4138
   (match_operand:VDQW 1 "s_register_operand" "w")
4139
   (match_operand:VDQW 2 "s_register_operand" "w")]
4140
  "TARGET_NEON"
4141
{
4142
  neon_emit_pair_result_insn (mode, gen_neon_vzip_internal,
4143
                              operands[0], operands[1], operands[2]);
4144
  DONE;
4145
})
4146
 
4147
(define_insn "neon_vuzp_internal"
4148
  [(set (match_operand:VDQW 0 "s_register_operand" "=w")
4149
        (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0")
4150
                      (match_operand:VDQW 2 "s_register_operand" "w")]
4151
                     UNSPEC_VUZP1))
4152
   (set (match_operand:VDQW 3 "s_register_operand" "=2")
4153
        (unspec:VDQW [(match_dup 1) (match_dup 2)]
4154
                     UNSPEC_VUZP2))]
4155
  "TARGET_NEON"
4156
  "vuzp.\t%0, %3"
4157
  [(set (attr "neon_type")
4158
      (if_then_else (match_test "")
4159
                    (const_string "neon_bp_simple")
4160
                    (const_string "neon_bp_3cycle")))]
4161
)
4162
 
4163
(define_expand "neon_vuzp"
4164
  [(match_operand:SI 0 "s_register_operand" "r")
4165
   (match_operand:VDQW 1 "s_register_operand" "w")
4166
   (match_operand:VDQW 2 "s_register_operand" "w")]
4167
  "TARGET_NEON"
4168
{
4169
  neon_emit_pair_result_insn (mode, gen_neon_vuzp_internal,
4170
                              operands[0], operands[1], operands[2]);
4171
  DONE;
4172
})
4173
 
4174
(define_expand "neon_vreinterpretv8qi"
4175
  [(match_operand:V8QI 0 "s_register_operand" "")
4176
   (match_operand:VDX 1 "s_register_operand" "")]
4177
  "TARGET_NEON"
4178
{
4179
  neon_reinterpret (operands[0], operands[1]);
4180
  DONE;
4181
})
4182
 
4183
(define_expand "neon_vreinterpretv4hi"
4184
  [(match_operand:V4HI 0 "s_register_operand" "")
4185
   (match_operand:VDX 1 "s_register_operand" "")]
4186
  "TARGET_NEON"
4187
{
4188
  neon_reinterpret (operands[0], operands[1]);
4189
  DONE;
4190
})
4191
 
4192
(define_expand "neon_vreinterpretv2si"
4193
  [(match_operand:V2SI 0 "s_register_operand" "")
4194
   (match_operand:VDX 1 "s_register_operand" "")]
4195
  "TARGET_NEON"
4196
{
4197
  neon_reinterpret (operands[0], operands[1]);
4198
  DONE;
4199
})
4200
 
4201
(define_expand "neon_vreinterpretv2sf"
4202
  [(match_operand:V2SF 0 "s_register_operand" "")
4203
   (match_operand:VDX 1 "s_register_operand" "")]
4204
  "TARGET_NEON"
4205
{
4206
  neon_reinterpret (operands[0], operands[1]);
4207
  DONE;
4208
})
4209
 
4210
(define_expand "neon_vreinterpretdi"
4211
  [(match_operand:DI 0 "s_register_operand" "")
4212
   (match_operand:VDX 1 "s_register_operand" "")]
4213
  "TARGET_NEON"
4214
{
4215
  neon_reinterpret (operands[0], operands[1]);
4216
  DONE;
4217
})
4218
 
4219
(define_expand "neon_vreinterpretv16qi"
4220
  [(match_operand:V16QI 0 "s_register_operand" "")
4221
   (match_operand:VQX 1 "s_register_operand" "")]
4222
  "TARGET_NEON"
4223
{
4224
  neon_reinterpret (operands[0], operands[1]);
4225
  DONE;
4226
})
4227
 
4228
(define_expand "neon_vreinterpretv8hi"
4229
  [(match_operand:V8HI 0 "s_register_operand" "")
4230
   (match_operand:VQX 1 "s_register_operand" "")]
4231
  "TARGET_NEON"
4232
{
4233
  neon_reinterpret (operands[0], operands[1]);
4234
  DONE;
4235
})
4236
 
4237
(define_expand "neon_vreinterpretv4si"
4238
  [(match_operand:V4SI 0 "s_register_operand" "")
4239
   (match_operand:VQX 1 "s_register_operand" "")]
4240
  "TARGET_NEON"
4241
{
4242
  neon_reinterpret (operands[0], operands[1]);
4243
  DONE;
4244
})
4245
 
4246
(define_expand "neon_vreinterpretv4sf"
4247
  [(match_operand:V4SF 0 "s_register_operand" "")
4248
   (match_operand:VQX 1 "s_register_operand" "")]
4249
  "TARGET_NEON"
4250
{
4251
  neon_reinterpret (operands[0], operands[1]);
4252
  DONE;
4253
})
4254
 
4255
(define_expand "neon_vreinterpretv2di"
4256
  [(match_operand:V2DI 0 "s_register_operand" "")
4257
   (match_operand:VQX 1 "s_register_operand" "")]
4258
  "TARGET_NEON"
4259
{
4260
  neon_reinterpret (operands[0], operands[1]);
4261
  DONE;
4262
})
4263
 
4264
(define_expand "vec_load_lanes"
4265
  [(set (match_operand:VDQX 0 "s_register_operand")
4266
        (unspec:VDQX [(match_operand:VDQX 1 "neon_struct_operand")]
4267
                     UNSPEC_VLD1))]
4268
  "TARGET_NEON")
4269
 
4270
(define_insn "neon_vld1"
4271
  [(set (match_operand:VDQX 0 "s_register_operand" "=w")
4272
        (unspec:VDQX [(match_operand:VDQX 1 "neon_struct_operand" "Um")]
4273
                    UNSPEC_VLD1))]
4274
  "TARGET_NEON"
4275
  "vld1.\t%h0, %A1"
4276
  [(set_attr "neon_type" "neon_vld1_1_2_regs")]
4277
)
4278
 
4279
(define_insn "neon_vld1_lane"
4280
  [(set (match_operand:VDX 0 "s_register_operand" "=w")
4281
        (unspec:VDX [(match_operand: 1 "neon_struct_operand" "Um")
4282
                     (match_operand:VDX 2 "s_register_operand" "0")
4283
                     (match_operand:SI 3 "immediate_operand" "i")]
4284
                    UNSPEC_VLD1_LANE))]
4285
  "TARGET_NEON"
4286
{
4287
  HOST_WIDE_INT lane = INTVAL (operands[3]);
4288
  HOST_WIDE_INT max = GET_MODE_NUNITS (mode);
4289
  if (lane < 0 || lane >= max)
4290
    error ("lane out of range");
4291
  if (max == 1)
4292
    return "vld1.\t%P0, %A1";
4293
  else
4294
    return "vld1.\t{%P0[%c3]}, %A1";
4295
}
4296
  [(set (attr "neon_type")
4297
      (if_then_else (eq (const_string "") (const_int 2))
4298
                    (const_string "neon_vld1_1_2_regs")
4299
                    (const_string "neon_vld1_vld2_lane")))]
4300
)
4301
 
4302
(define_insn "neon_vld1_lane"
4303
  [(set (match_operand:VQX 0 "s_register_operand" "=w")
4304
        (unspec:VQX [(match_operand: 1 "neon_struct_operand" "Um")
4305
                     (match_operand:VQX 2 "s_register_operand" "0")
4306
                     (match_operand:SI 3 "immediate_operand" "i")]
4307
                    UNSPEC_VLD1_LANE))]
4308
  "TARGET_NEON"
4309
{
4310
  HOST_WIDE_INT lane = INTVAL (operands[3]);
4311
  HOST_WIDE_INT max = GET_MODE_NUNITS (mode);
4312
  int regno = REGNO (operands[0]);
4313
  if (lane < 0 || lane >= max)
4314
    error ("lane out of range");
4315
  else if (lane >= max / 2)
4316
    {
4317
      lane -= max / 2;
4318
      regno += 2;
4319
      operands[3] = GEN_INT (lane);
4320
    }
4321
  operands[0] = gen_rtx_REG (mode, regno);
4322
  if (max == 2)
4323
    return "vld1.\t%P0, %A1";
4324
  else
4325
    return "vld1.\t{%P0[%c3]}, %A1";
4326
}
4327
  [(set (attr "neon_type")
4328
      (if_then_else (eq (const_string "") (const_int 2))
4329
                    (const_string "neon_vld1_1_2_regs")
4330
                    (const_string "neon_vld1_vld2_lane")))]
4331
)
4332
 
4333
(define_insn "neon_vld1_dup"
4334
  [(set (match_operand:VDX 0 "s_register_operand" "=w")
4335
        (unspec:VDX [(match_operand: 1 "neon_struct_operand" "Um")]
4336
                    UNSPEC_VLD1_DUP))]
4337
  "TARGET_NEON"
4338
{
4339
  if (GET_MODE_NUNITS (mode) > 1)
4340
    return "vld1.\t{%P0[]}, %A1";
4341
  else
4342
    return "vld1.\t%h0, %A1";
4343
}
4344
  [(set (attr "neon_type")
4345
      (if_then_else (gt (const_string "") (const_string "1"))
4346
                    (const_string "neon_vld2_2_regs_vld1_vld2_all_lanes")
4347
                    (const_string "neon_vld1_1_2_regs")))]
4348
)
4349
 
4350
(define_insn "neon_vld1_dup"
4351
  [(set (match_operand:VQX 0 "s_register_operand" "=w")
4352
        (unspec:VQX [(match_operand: 1 "neon_struct_operand" "Um")]
4353
                    UNSPEC_VLD1_DUP))]
4354
  "TARGET_NEON"
4355
{
4356
  if (GET_MODE_NUNITS (mode) > 2)
4357
    return "vld1.\t{%e0[], %f0[]}, %A1";
4358
  else
4359
    return "vld1.\t%h0, %A1";
4360
}
4361
  [(set (attr "neon_type")
4362
      (if_then_else (gt (const_string "") (const_string "1"))
4363
                    (const_string "neon_vld2_2_regs_vld1_vld2_all_lanes")
4364
                    (const_string "neon_vld1_1_2_regs")))]
4365
)
4366
 
4367
(define_expand "vec_store_lanes"
4368
  [(set (match_operand:VDQX 0 "neon_struct_operand")
4369
        (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand")]
4370
                     UNSPEC_VST1))]
4371
  "TARGET_NEON")
4372
 
4373
(define_insn "neon_vst1"
4374
  [(set (match_operand:VDQX 0 "neon_struct_operand" "=Um")
4375
        (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w")]
4376
                     UNSPEC_VST1))]
4377
  "TARGET_NEON"
4378
  "vst1.\t%h1, %A0"
4379
  [(set_attr "neon_type" "neon_vst1_1_2_regs_vst2_2_regs")])
4380
 
4381
(define_insn "neon_vst1_lane"
4382
  [(set (match_operand: 0 "neon_struct_operand" "=Um")
4383
        (vec_select:
4384
          (match_operand:VDX 1 "s_register_operand" "w")
4385
          (parallel [(match_operand:SI 2 "neon_lane_number" "i")])))]
4386
  "TARGET_NEON"
4387
{
4388
  HOST_WIDE_INT lane = INTVAL (operands[2]);
4389
  HOST_WIDE_INT max = GET_MODE_NUNITS (mode);
4390
  if (lane < 0 || lane >= max)
4391
    error ("lane out of range");
4392
  if (max == 1)
4393
    return "vst1.\t{%P1}, %A0";
4394
  else
4395
    return "vst1.\t{%P1[%c2]}, %A0";
4396
}
4397
  [(set (attr "neon_type")
4398
      (if_then_else (eq (const_string "") (const_int 1))
4399
                    (const_string "neon_vst1_1_2_regs_vst2_2_regs")
4400
                    (const_string "neon_vst1_vst2_lane")))])
4401
 
4402
(define_insn "neon_vst1_lane"
4403
  [(set (match_operand: 0 "neon_struct_operand" "=Um")
4404
        (vec_select:
4405
           (match_operand:VQX 1 "s_register_operand" "w")
4406
           (parallel [(match_operand:SI 2 "neon_lane_number" "i")])))]
4407
  "TARGET_NEON"
4408
{
4409
  HOST_WIDE_INT lane = INTVAL (operands[2]);
4410
  HOST_WIDE_INT max = GET_MODE_NUNITS (mode);
4411
  int regno = REGNO (operands[1]);
4412
  if (lane < 0 || lane >= max)
4413
    error ("lane out of range");
4414
  else if (lane >= max / 2)
4415
    {
4416
      lane -= max / 2;
4417
      regno += 2;
4418
      operands[2] = GEN_INT (lane);
4419
    }
4420
  operands[1] = gen_rtx_REG (mode, regno);
4421
  if (max == 2)
4422
    return "vst1.\t{%P1}, %A0";
4423
  else
4424
    return "vst1.\t{%P1[%c2]}, %A0";
4425
}
4426
  [(set_attr "neon_type" "neon_vst1_vst2_lane")]
4427
)
4428
 
4429
(define_expand "vec_load_lanesti"
4430
  [(set (match_operand:TI 0 "s_register_operand")
4431
        (unspec:TI [(match_operand:TI 1 "neon_struct_operand")
4432
                    (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4433
                   UNSPEC_VLD2))]
4434
  "TARGET_NEON")
4435
 
4436
(define_insn "neon_vld2"
4437
  [(set (match_operand:TI 0 "s_register_operand" "=w")
4438
        (unspec:TI [(match_operand:TI 1 "neon_struct_operand" "Um")
4439
                    (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4440
                   UNSPEC_VLD2))]
4441
  "TARGET_NEON"
4442
{
4443
  if ( == 64)
4444
    return "vld1.64\t%h0, %A1";
4445
  else
4446
    return "vld2.\t%h0, %A1";
4447
}
4448
  [(set (attr "neon_type")
4449
      (if_then_else (eq (const_string "") (const_string "64"))
4450
                    (const_string "neon_vld1_1_2_regs")
4451
                    (const_string "neon_vld2_2_regs_vld1_vld2_all_lanes")))]
4452
)
4453
 
4454
(define_expand "vec_load_lanesoi"
4455
  [(set (match_operand:OI 0 "s_register_operand")
4456
        (unspec:OI [(match_operand:OI 1 "neon_struct_operand")
4457
                    (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4458
                   UNSPEC_VLD2))]
4459
  "TARGET_NEON")
4460
 
4461
(define_insn "neon_vld2"
4462
  [(set (match_operand:OI 0 "s_register_operand" "=w")
4463
        (unspec:OI [(match_operand:OI 1 "neon_struct_operand" "Um")
4464
                    (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4465
                   UNSPEC_VLD2))]
4466
  "TARGET_NEON"
4467
  "vld2.\t%h0, %A1"
4468
  [(set_attr "neon_type" "neon_vld2_2_regs_vld1_vld2_all_lanes")])
4469
 
4470
(define_insn "neon_vld2_lane"
4471
  [(set (match_operand:TI 0 "s_register_operand" "=w")
4472
        (unspec:TI [(match_operand: 1 "neon_struct_operand" "Um")
4473
                    (match_operand:TI 2 "s_register_operand" "0")
4474
                    (match_operand:SI 3 "immediate_operand" "i")
4475
                    (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4476
                   UNSPEC_VLD2_LANE))]
4477
  "TARGET_NEON"
4478
{
4479
  HOST_WIDE_INT lane = INTVAL (operands[3]);
4480
  HOST_WIDE_INT max = GET_MODE_NUNITS (mode);
4481
  int regno = REGNO (operands[0]);
4482
  rtx ops[4];
4483
  if (lane < 0 || lane >= max)
4484
    error ("lane out of range");
4485
  ops[0] = gen_rtx_REG (DImode, regno);
4486
  ops[1] = gen_rtx_REG (DImode, regno + 2);
4487
  ops[2] = operands[1];
4488
  ops[3] = operands[3];
4489
  output_asm_insn ("vld2.\t{%P0[%c3], %P1[%c3]}, %A2", ops);
4490
  return "";
4491
}
4492
  [(set_attr "neon_type" "neon_vld1_vld2_lane")]
4493
)
4494
 
4495
(define_insn "neon_vld2_lane"
4496
  [(set (match_operand:OI 0 "s_register_operand" "=w")
4497
        (unspec:OI [(match_operand: 1 "neon_struct_operand" "Um")
4498
                    (match_operand:OI 2 "s_register_operand" "0")
4499
                    (match_operand:SI 3 "immediate_operand" "i")
4500
                    (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4501
                   UNSPEC_VLD2_LANE))]
4502
  "TARGET_NEON"
4503
{
4504
  HOST_WIDE_INT lane = INTVAL (operands[3]);
4505
  HOST_WIDE_INT max = GET_MODE_NUNITS (mode);
4506
  int regno = REGNO (operands[0]);
4507
  rtx ops[4];
4508
  if (lane < 0 || lane >= max)
4509
    error ("lane out of range");
4510
  else if (lane >= max / 2)
4511
    {
4512
      lane -= max / 2;
4513
      regno += 2;
4514
    }
4515
  ops[0] = gen_rtx_REG (DImode, regno);
4516
  ops[1] = gen_rtx_REG (DImode, regno + 4);
4517
  ops[2] = operands[1];
4518
  ops[3] = GEN_INT (lane);
4519
  output_asm_insn ("vld2.\t{%P0[%c3], %P1[%c3]}, %A2", ops);
4520
  return "";
4521
}
4522
  [(set_attr "neon_type" "neon_vld1_vld2_lane")]
4523
)
4524
 
4525
(define_insn "neon_vld2_dup"
4526
  [(set (match_operand:TI 0 "s_register_operand" "=w")
4527
        (unspec:TI [(match_operand: 1 "neon_struct_operand" "Um")
4528
                    (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4529
                   UNSPEC_VLD2_DUP))]
4530
  "TARGET_NEON"
4531
{
4532
  if (GET_MODE_NUNITS (mode) > 1)
4533
    return "vld2.\t{%e0[], %f0[]}, %A1";
4534
  else
4535
    return "vld1.\t%h0, %A1";
4536
}
4537
  [(set (attr "neon_type")
4538
      (if_then_else (gt (const_string "") (const_string "1"))
4539
                    (const_string "neon_vld2_2_regs_vld1_vld2_all_lanes")
4540
                    (const_string "neon_vld1_1_2_regs")))]
4541
)
4542
 
4543
(define_expand "vec_store_lanesti"
4544
  [(set (match_operand:TI 0 "neon_struct_operand")
4545
        (unspec:TI [(match_operand:TI 1 "s_register_operand")
4546
                    (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4547
                   UNSPEC_VST2))]
4548
  "TARGET_NEON")
4549
 
4550
(define_insn "neon_vst2"
4551
  [(set (match_operand:TI 0 "neon_struct_operand" "=Um")
4552
        (unspec:TI [(match_operand:TI 1 "s_register_operand" "w")
4553
                    (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4554
                   UNSPEC_VST2))]
4555
  "TARGET_NEON"
4556
{
4557
  if ( == 64)
4558
    return "vst1.64\t%h1, %A0";
4559
  else
4560
    return "vst2.\t%h1, %A0";
4561
}
4562
  [(set (attr "neon_type")
4563
      (if_then_else (eq (const_string "") (const_string "64"))
4564
                    (const_string "neon_vst1_1_2_regs_vst2_2_regs")
4565
                    (const_string "neon_vst1_1_2_regs_vst2_2_regs")))]
4566
)
4567
 
4568
(define_expand "vec_store_lanesoi"
4569
  [(set (match_operand:OI 0 "neon_struct_operand")
4570
        (unspec:OI [(match_operand:OI 1 "s_register_operand")
4571
                    (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4572
                   UNSPEC_VST2))]
4573
  "TARGET_NEON")
4574
 
4575
(define_insn "neon_vst2"
4576
  [(set (match_operand:OI 0 "neon_struct_operand" "=Um")
4577
        (unspec:OI [(match_operand:OI 1 "s_register_operand" "w")
4578
                    (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4579
                   UNSPEC_VST2))]
4580
  "TARGET_NEON"
4581
  "vst2.\t%h1, %A0"
4582
  [(set_attr "neon_type" "neon_vst1_1_2_regs_vst2_2_regs")]
4583
)
4584
 
4585
(define_insn "neon_vst2_lane"
4586
  [(set (match_operand: 0 "neon_struct_operand" "=Um")
4587
        (unspec:
4588
          [(match_operand:TI 1 "s_register_operand" "w")
4589
           (match_operand:SI 2 "immediate_operand" "i")
4590
           (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4591
          UNSPEC_VST2_LANE))]
4592
  "TARGET_NEON"
4593
{
4594
  HOST_WIDE_INT lane = INTVAL (operands[2]);
4595
  HOST_WIDE_INT max = GET_MODE_NUNITS (mode);
4596
  int regno = REGNO (operands[1]);
4597
  rtx ops[4];
4598
  if (lane < 0 || lane >= max)
4599
    error ("lane out of range");
4600
  ops[0] = operands[0];
4601
  ops[1] = gen_rtx_REG (DImode, regno);
4602
  ops[2] = gen_rtx_REG (DImode, regno + 2);
4603
  ops[3] = operands[2];
4604
  output_asm_insn ("vst2.\t{%P1[%c3], %P2[%c3]}, %A0", ops);
4605
  return "";
4606
}
4607
  [(set_attr "neon_type" "neon_vst1_vst2_lane")]
4608
)
4609
 
4610
(define_insn "neon_vst2_lane"
4611
  [(set (match_operand: 0 "neon_struct_operand" "=Um")
4612
        (unspec:
4613
           [(match_operand:OI 1 "s_register_operand" "w")
4614
            (match_operand:SI 2 "immediate_operand" "i")
4615
            (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4616
           UNSPEC_VST2_LANE))]
4617
  "TARGET_NEON"
4618
{
4619
  HOST_WIDE_INT lane = INTVAL (operands[2]);
4620
  HOST_WIDE_INT max = GET_MODE_NUNITS (mode);
4621
  int regno = REGNO (operands[1]);
4622
  rtx ops[4];
4623
  if (lane < 0 || lane >= max)
4624
    error ("lane out of range");
4625
  else if (lane >= max / 2)
4626
    {
4627
      lane -= max / 2;
4628
      regno += 2;
4629
    }
4630
  ops[0] = operands[0];
4631
  ops[1] = gen_rtx_REG (DImode, regno);
4632
  ops[2] = gen_rtx_REG (DImode, regno + 4);
4633
  ops[3] = GEN_INT (lane);
4634
  output_asm_insn ("vst2.\t{%P1[%c3], %P2[%c3]}, %A0", ops);
4635
  return "";
4636
}
4637
  [(set_attr "neon_type" "neon_vst1_vst2_lane")]
4638
)
4639
 
4640
(define_expand "vec_load_lanesei"
4641
  [(set (match_operand:EI 0 "s_register_operand")
4642
        (unspec:EI [(match_operand:EI 1 "neon_struct_operand")
4643
                    (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4644
                   UNSPEC_VLD3))]
4645
  "TARGET_NEON")
4646
 
4647
(define_insn "neon_vld3"
4648
  [(set (match_operand:EI 0 "s_register_operand" "=w")
4649
        (unspec:EI [(match_operand:EI 1 "neon_struct_operand" "Um")
4650
                    (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4651
                   UNSPEC_VLD3))]
4652
  "TARGET_NEON"
4653
{
4654
  if ( == 64)
4655
    return "vld1.64\t%h0, %A1";
4656
  else
4657
    return "vld3.\t%h0, %A1";
4658
}
4659
  [(set (attr "neon_type")
4660
      (if_then_else (eq (const_string "") (const_string "64"))
4661
                    (const_string "neon_vld1_1_2_regs")
4662
                    (const_string "neon_vld3_vld4")))]
4663
)
4664
 
4665
(define_expand "vec_load_lanesci"
4666
  [(match_operand:CI 0 "s_register_operand")
4667
   (match_operand:CI 1 "neon_struct_operand")
4668
   (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4669
  "TARGET_NEON"
4670
{
4671
  emit_insn (gen_neon_vld3 (operands[0], operands[1]));
4672
  DONE;
4673
})
4674
 
4675
(define_expand "neon_vld3"
4676
  [(match_operand:CI 0 "s_register_operand")
4677
   (match_operand:CI 1 "neon_struct_operand")
4678
   (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4679
  "TARGET_NEON"
4680
{
4681
  rtx mem;
4682
 
4683
  mem = adjust_address (operands[1], EImode, 0);
4684
  emit_insn (gen_neon_vld3qa (operands[0], mem));
4685
  mem = adjust_address (mem, EImode, GET_MODE_SIZE (EImode));
4686
  emit_insn (gen_neon_vld3qb (operands[0], mem, operands[0]));
4687
  DONE;
4688
})
4689
 
4690
(define_insn "neon_vld3qa"
4691
  [(set (match_operand:CI 0 "s_register_operand" "=w")
4692
        (unspec:CI [(match_operand:EI 1 "neon_struct_operand" "Um")
4693
                    (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4694
                   UNSPEC_VLD3A))]
4695
  "TARGET_NEON"
4696
{
4697
  int regno = REGNO (operands[0]);
4698
  rtx ops[4];
4699
  ops[0] = gen_rtx_REG (DImode, regno);
4700
  ops[1] = gen_rtx_REG (DImode, regno + 4);
4701
  ops[2] = gen_rtx_REG (DImode, regno + 8);
4702
  ops[3] = operands[1];
4703
  output_asm_insn ("vld3.\t{%P0, %P1, %P2}, %A3", ops);
4704
  return "";
4705
}
4706
  [(set_attr "neon_type" "neon_vld3_vld4")]
4707
)
4708
 
4709
(define_insn "neon_vld3qb"
4710
  [(set (match_operand:CI 0 "s_register_operand" "=w")
4711
        (unspec:CI [(match_operand:EI 1 "neon_struct_operand" "Um")
4712
                    (match_operand:CI 2 "s_register_operand" "0")
4713
                    (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4714
                   UNSPEC_VLD3B))]
4715
  "TARGET_NEON"
4716
{
4717
  int regno = REGNO (operands[0]);
4718
  rtx ops[4];
4719
  ops[0] = gen_rtx_REG (DImode, regno + 2);
4720
  ops[1] = gen_rtx_REG (DImode, regno + 6);
4721
  ops[2] = gen_rtx_REG (DImode, regno + 10);
4722
  ops[3] = operands[1];
4723
  output_asm_insn ("vld3.\t{%P0, %P1, %P2}, %A3", ops);
4724
  return "";
4725
}
4726
  [(set_attr "neon_type" "neon_vld3_vld4")]
4727
)
4728
 
4729
(define_insn "neon_vld3_lane"
4730
  [(set (match_operand:EI 0 "s_register_operand" "=w")
4731
        (unspec:EI [(match_operand: 1 "neon_struct_operand" "Um")
4732
                    (match_operand:EI 2 "s_register_operand" "0")
4733
                    (match_operand:SI 3 "immediate_operand" "i")
4734
                    (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4735
                   UNSPEC_VLD3_LANE))]
4736
  "TARGET_NEON"
4737
{
4738
  HOST_WIDE_INT lane = INTVAL (operands[3]);
4739
  HOST_WIDE_INT max = GET_MODE_NUNITS (mode);
4740
  int regno = REGNO (operands[0]);
4741
  rtx ops[5];
4742
  if (lane < 0 || lane >= max)
4743
    error ("lane out of range");
4744
  ops[0] = gen_rtx_REG (DImode, regno);
4745
  ops[1] = gen_rtx_REG (DImode, regno + 2);
4746
  ops[2] = gen_rtx_REG (DImode, regno + 4);
4747
  ops[3] = operands[1];
4748
  ops[4] = operands[3];
4749
  output_asm_insn ("vld3.\t{%P0[%c4], %P1[%c4], %P2[%c4]}, %A3",
4750
                   ops);
4751
  return "";
4752
}
4753
  [(set_attr "neon_type" "neon_vld3_vld4_lane")]
4754
)
4755
 
4756
(define_insn "neon_vld3_lane"
4757
  [(set (match_operand:CI 0 "s_register_operand" "=w")
4758
        (unspec:CI [(match_operand: 1 "neon_struct_operand" "Um")
4759
                    (match_operand:CI 2 "s_register_operand" "0")
4760
                    (match_operand:SI 3 "immediate_operand" "i")
4761
                    (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4762
                   UNSPEC_VLD3_LANE))]
4763
  "TARGET_NEON"
4764
{
4765
  HOST_WIDE_INT lane = INTVAL (operands[3]);
4766
  HOST_WIDE_INT max = GET_MODE_NUNITS (mode);
4767
  int regno = REGNO (operands[0]);
4768
  rtx ops[5];
4769
  if (lane < 0 || lane >= max)
4770
    error ("lane out of range");
4771
  else if (lane >= max / 2)
4772
    {
4773
      lane -= max / 2;
4774
      regno += 2;
4775
    }
4776
  ops[0] = gen_rtx_REG (DImode, regno);
4777
  ops[1] = gen_rtx_REG (DImode, regno + 4);
4778
  ops[2] = gen_rtx_REG (DImode, regno + 8);
4779
  ops[3] = operands[1];
4780
  ops[4] = GEN_INT (lane);
4781
  output_asm_insn ("vld3.\t{%P0[%c4], %P1[%c4], %P2[%c4]}, %A3",
4782
                   ops);
4783
  return "";
4784
}
4785
  [(set_attr "neon_type" "neon_vld3_vld4_lane")]
4786
)
4787
 
4788
(define_insn "neon_vld3_dup"
4789
  [(set (match_operand:EI 0 "s_register_operand" "=w")
4790
        (unspec:EI [(match_operand: 1 "neon_struct_operand" "Um")
4791
                    (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4792
                   UNSPEC_VLD3_DUP))]
4793
  "TARGET_NEON"
4794
{
4795
  if (GET_MODE_NUNITS (mode) > 1)
4796
    {
4797
      int regno = REGNO (operands[0]);
4798
      rtx ops[4];
4799
      ops[0] = gen_rtx_REG (DImode, regno);
4800
      ops[1] = gen_rtx_REG (DImode, regno + 2);
4801
      ops[2] = gen_rtx_REG (DImode, regno + 4);
4802
      ops[3] = operands[1];
4803
      output_asm_insn ("vld3.\t{%P0[], %P1[], %P2[]}, %A3", ops);
4804
      return "";
4805
    }
4806
  else
4807
    return "vld1.\t%h0, %A1";
4808
}
4809
  [(set (attr "neon_type")
4810
      (if_then_else (gt (const_string "") (const_string "1"))
4811
                    (const_string "neon_vld3_vld4_all_lanes")
4812
                    (const_string "neon_vld1_1_2_regs")))])
4813
 
4814
(define_expand "vec_store_lanesei"
4815
  [(set (match_operand:EI 0 "neon_struct_operand")
4816
        (unspec:EI [(match_operand:EI 1 "s_register_operand")
4817
                    (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4818
                   UNSPEC_VST3))]
4819
  "TARGET_NEON")
4820
 
4821
(define_insn "neon_vst3"
4822
  [(set (match_operand:EI 0 "neon_struct_operand" "=Um")
4823
        (unspec:EI [(match_operand:EI 1 "s_register_operand" "w")
4824
                    (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4825
                   UNSPEC_VST3))]
4826
  "TARGET_NEON"
4827
{
4828
  if ( == 64)
4829
    return "vst1.64\t%h1, %A0";
4830
  else
4831
    return "vst3.\t%h1, %A0";
4832
}
4833
  [(set (attr "neon_type")
4834
      (if_then_else (eq (const_string "") (const_string "64"))
4835
                    (const_string "neon_vst1_1_2_regs_vst2_2_regs")
4836
                    (const_string "neon_vst2_4_regs_vst3_vst4")))])
4837
 
4838
(define_expand "vec_store_lanesci"
4839
  [(match_operand:CI 0 "neon_struct_operand")
4840
   (match_operand:CI 1 "s_register_operand")
4841
   (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4842
  "TARGET_NEON"
4843
{
4844
  emit_insn (gen_neon_vst3 (operands[0], operands[1]));
4845
  DONE;
4846
})
4847
 
4848
(define_expand "neon_vst3"
4849
  [(match_operand:CI 0 "neon_struct_operand")
4850
   (match_operand:CI 1 "s_register_operand")
4851
   (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4852
  "TARGET_NEON"
4853
{
4854
  rtx mem;
4855
 
4856
  mem = adjust_address (operands[0], EImode, 0);
4857
  emit_insn (gen_neon_vst3qa (mem, operands[1]));
4858
  mem = adjust_address (mem, EImode, GET_MODE_SIZE (EImode));
4859
  emit_insn (gen_neon_vst3qb (mem, operands[1]));
4860
  DONE;
4861
})
4862
 
4863
(define_insn "neon_vst3qa"
4864
  [(set (match_operand:EI 0 "neon_struct_operand" "=Um")
4865
        (unspec:EI [(match_operand:CI 1 "s_register_operand" "w")
4866
                    (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4867
                   UNSPEC_VST3A))]
4868
  "TARGET_NEON"
4869
{
4870
  int regno = REGNO (operands[1]);
4871
  rtx ops[4];
4872
  ops[0] = operands[0];
4873
  ops[1] = gen_rtx_REG (DImode, regno);
4874
  ops[2] = gen_rtx_REG (DImode, regno + 4);
4875
  ops[3] = gen_rtx_REG (DImode, regno + 8);
4876
  output_asm_insn ("vst3.\t{%P1, %P2, %P3}, %A0", ops);
4877
  return "";
4878
}
4879
  [(set_attr "neon_type" "neon_vst2_4_regs_vst3_vst4")]
4880
)
4881
 
4882
(define_insn "neon_vst3qb"
4883
  [(set (match_operand:EI 0 "neon_struct_operand" "=Um")
4884
        (unspec:EI [(match_operand:CI 1 "s_register_operand" "w")
4885
                    (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4886
                   UNSPEC_VST3B))]
4887
  "TARGET_NEON"
4888
{
4889
  int regno = REGNO (operands[1]);
4890
  rtx ops[4];
4891
  ops[0] = operands[0];
4892
  ops[1] = gen_rtx_REG (DImode, regno + 2);
4893
  ops[2] = gen_rtx_REG (DImode, regno + 6);
4894
  ops[3] = gen_rtx_REG (DImode, regno + 10);
4895
  output_asm_insn ("vst3.\t{%P1, %P2, %P3}, %A0", ops);
4896
  return "";
4897
}
4898
  [(set_attr "neon_type" "neon_vst2_4_regs_vst3_vst4")]
4899
)
4900
 
4901
(define_insn "neon_vst3_lane"
4902
  [(set (match_operand: 0 "neon_struct_operand" "=Um")
4903
        (unspec:
4904
           [(match_operand:EI 1 "s_register_operand" "w")
4905
            (match_operand:SI 2 "immediate_operand" "i")
4906
            (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4907
           UNSPEC_VST3_LANE))]
4908
  "TARGET_NEON"
4909
{
4910
  HOST_WIDE_INT lane = INTVAL (operands[2]);
4911
  HOST_WIDE_INT max = GET_MODE_NUNITS (mode);
4912
  int regno = REGNO (operands[1]);
4913
  rtx ops[5];
4914
  if (lane < 0 || lane >= max)
4915
    error ("lane out of range");
4916
  ops[0] = operands[0];
4917
  ops[1] = gen_rtx_REG (DImode, regno);
4918
  ops[2] = gen_rtx_REG (DImode, regno + 2);
4919
  ops[3] = gen_rtx_REG (DImode, regno + 4);
4920
  ops[4] = operands[2];
4921
  output_asm_insn ("vst3.\t{%P1[%c4], %P2[%c4], %P3[%c4]}, %A0",
4922
                   ops);
4923
  return "";
4924
}
4925
  [(set_attr "neon_type" "neon_vst3_vst4_lane")]
4926
)
4927
 
4928
(define_insn "neon_vst3_lane"
4929
  [(set (match_operand: 0 "neon_struct_operand" "=Um")
4930
        (unspec:
4931
           [(match_operand:CI 1 "s_register_operand" "w")
4932
            (match_operand:SI 2 "immediate_operand" "i")
4933
            (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4934
           UNSPEC_VST3_LANE))]
4935
  "TARGET_NEON"
4936
{
4937
  HOST_WIDE_INT lane = INTVAL (operands[2]);
4938
  HOST_WIDE_INT max = GET_MODE_NUNITS (mode);
4939
  int regno = REGNO (operands[1]);
4940
  rtx ops[5];
4941
  if (lane < 0 || lane >= max)
4942
    error ("lane out of range");
4943
  else if (lane >= max / 2)
4944
    {
4945
      lane -= max / 2;
4946
      regno += 2;
4947
    }
4948
  ops[0] = operands[0];
4949
  ops[1] = gen_rtx_REG (DImode, regno);
4950
  ops[2] = gen_rtx_REG (DImode, regno + 4);
4951
  ops[3] = gen_rtx_REG (DImode, regno + 8);
4952
  ops[4] = GEN_INT (lane);
4953
  output_asm_insn ("vst3.\t{%P1[%c4], %P2[%c4], %P3[%c4]}, %A0",
4954
                   ops);
4955
  return "";
4956
}
4957
[(set_attr "neon_type" "neon_vst3_vst4_lane")])
4958
 
4959
(define_expand "vec_load_lanesoi"
4960
  [(set (match_operand:OI 0 "s_register_operand")
4961
        (unspec:OI [(match_operand:OI 1 "neon_struct_operand")
4962
                    (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4963
                   UNSPEC_VLD4))]
4964
  "TARGET_NEON")
4965
 
4966
(define_insn "neon_vld4"
4967
  [(set (match_operand:OI 0 "s_register_operand" "=w")
4968
        (unspec:OI [(match_operand:OI 1 "neon_struct_operand" "Um")
4969
                    (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4970
                   UNSPEC_VLD4))]
4971
  "TARGET_NEON"
4972
{
4973
  if ( == 64)
4974
    return "vld1.64\t%h0, %A1";
4975
  else
4976
    return "vld4.\t%h0, %A1";
4977
}
4978
  [(set (attr "neon_type")
4979
      (if_then_else (eq (const_string "") (const_string "64"))
4980
                    (const_string "neon_vld1_1_2_regs")
4981
                    (const_string "neon_vld3_vld4")))]
4982
)
4983
 
4984
(define_expand "vec_load_lanesxi"
4985
  [(match_operand:XI 0 "s_register_operand")
4986
   (match_operand:XI 1 "neon_struct_operand")
4987
   (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4988
  "TARGET_NEON"
4989
{
4990
  emit_insn (gen_neon_vld4 (operands[0], operands[1]));
4991
  DONE;
4992
})
4993
 
4994
(define_expand "neon_vld4"
4995
  [(match_operand:XI 0 "s_register_operand")
4996
   (match_operand:XI 1 "neon_struct_operand")
4997
   (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
4998
  "TARGET_NEON"
4999
{
5000
  rtx mem;
5001
 
5002
  mem = adjust_address (operands[1], OImode, 0);
5003
  emit_insn (gen_neon_vld4qa (operands[0], mem));
5004
  mem = adjust_address (mem, OImode, GET_MODE_SIZE (OImode));
5005
  emit_insn (gen_neon_vld4qb (operands[0], mem, operands[0]));
5006
  DONE;
5007
})
5008
 
5009
(define_insn "neon_vld4qa"
5010
  [(set (match_operand:XI 0 "s_register_operand" "=w")
5011
        (unspec:XI [(match_operand:OI 1 "neon_struct_operand" "Um")
5012
                    (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5013
                   UNSPEC_VLD4A))]
5014
  "TARGET_NEON"
5015
{
5016
  int regno = REGNO (operands[0]);
5017
  rtx ops[5];
5018
  ops[0] = gen_rtx_REG (DImode, regno);
5019
  ops[1] = gen_rtx_REG (DImode, regno + 4);
5020
  ops[2] = gen_rtx_REG (DImode, regno + 8);
5021
  ops[3] = gen_rtx_REG (DImode, regno + 12);
5022
  ops[4] = operands[1];
5023
  output_asm_insn ("vld4.\t{%P0, %P1, %P2, %P3}, %A4", ops);
5024
  return "";
5025
}
5026
  [(set_attr "neon_type" "neon_vld3_vld4")]
5027
)
5028
 
5029
(define_insn "neon_vld4qb"
5030
  [(set (match_operand:XI 0 "s_register_operand" "=w")
5031
        (unspec:XI [(match_operand:OI 1 "neon_struct_operand" "Um")
5032
                    (match_operand:XI 2 "s_register_operand" "0")
5033
                    (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5034
                   UNSPEC_VLD4B))]
5035
  "TARGET_NEON"
5036
{
5037
  int regno = REGNO (operands[0]);
5038
  rtx ops[5];
5039
  ops[0] = gen_rtx_REG (DImode, regno + 2);
5040
  ops[1] = gen_rtx_REG (DImode, regno + 6);
5041
  ops[2] = gen_rtx_REG (DImode, regno + 10);
5042
  ops[3] = gen_rtx_REG (DImode, regno + 14);
5043
  ops[4] = operands[1];
5044
  output_asm_insn ("vld4.\t{%P0, %P1, %P2, %P3}, %A4", ops);
5045
  return "";
5046
}
5047
  [(set_attr "neon_type" "neon_vld3_vld4")]
5048
)
5049
 
5050
(define_insn "neon_vld4_lane"
5051
  [(set (match_operand:OI 0 "s_register_operand" "=w")
5052
        (unspec:OI [(match_operand: 1 "neon_struct_operand" "Um")
5053
                    (match_operand:OI 2 "s_register_operand" "0")
5054
                    (match_operand:SI 3 "immediate_operand" "i")
5055
                    (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5056
                   UNSPEC_VLD4_LANE))]
5057
  "TARGET_NEON"
5058
{
5059
  HOST_WIDE_INT lane = INTVAL (operands[3]);
5060
  HOST_WIDE_INT max = GET_MODE_NUNITS (mode);
5061
  int regno = REGNO (operands[0]);
5062
  rtx ops[6];
5063
  if (lane < 0 || lane >= max)
5064
    error ("lane out of range");
5065
  ops[0] = gen_rtx_REG (DImode, regno);
5066
  ops[1] = gen_rtx_REG (DImode, regno + 2);
5067
  ops[2] = gen_rtx_REG (DImode, regno + 4);
5068
  ops[3] = gen_rtx_REG (DImode, regno + 6);
5069
  ops[4] = operands[1];
5070
  ops[5] = operands[3];
5071
  output_asm_insn ("vld4.\t{%P0[%c5], %P1[%c5], %P2[%c5], %P3[%c5]}, %A4",
5072
                   ops);
5073
  return "";
5074
}
5075
  [(set_attr "neon_type" "neon_vld3_vld4_lane")]
5076
)
5077
 
5078
(define_insn "neon_vld4_lane"
5079
  [(set (match_operand:XI 0 "s_register_operand" "=w")
5080
        (unspec:XI [(match_operand: 1 "neon_struct_operand" "Um")
5081
                    (match_operand:XI 2 "s_register_operand" "0")
5082
                    (match_operand:SI 3 "immediate_operand" "i")
5083
                    (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5084
                   UNSPEC_VLD4_LANE))]
5085
  "TARGET_NEON"
5086
{
5087
  HOST_WIDE_INT lane = INTVAL (operands[3]);
5088
  HOST_WIDE_INT max = GET_MODE_NUNITS (mode);
5089
  int regno = REGNO (operands[0]);
5090
  rtx ops[6];
5091
  if (lane < 0 || lane >= max)
5092
    error ("lane out of range");
5093
  else if (lane >= max / 2)
5094
    {
5095
      lane -= max / 2;
5096
      regno += 2;
5097
    }
5098
  ops[0] = gen_rtx_REG (DImode, regno);
5099
  ops[1] = gen_rtx_REG (DImode, regno + 4);
5100
  ops[2] = gen_rtx_REG (DImode, regno + 8);
5101
  ops[3] = gen_rtx_REG (DImode, regno + 12);
5102
  ops[4] = operands[1];
5103
  ops[5] = GEN_INT (lane);
5104
  output_asm_insn ("vld4.\t{%P0[%c5], %P1[%c5], %P2[%c5], %P3[%c5]}, %A4",
5105
                   ops);
5106
  return "";
5107
}
5108
  [(set_attr "neon_type" "neon_vld3_vld4_lane")]
5109
)
5110
 
5111
(define_insn "neon_vld4_dup"
5112
  [(set (match_operand:OI 0 "s_register_operand" "=w")
5113
        (unspec:OI [(match_operand: 1 "neon_struct_operand" "Um")
5114
                    (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5115
                   UNSPEC_VLD4_DUP))]
5116
  "TARGET_NEON"
5117
{
5118
  if (GET_MODE_NUNITS (mode) > 1)
5119
    {
5120
      int regno = REGNO (operands[0]);
5121
      rtx ops[5];
5122
      ops[0] = gen_rtx_REG (DImode, regno);
5123
      ops[1] = gen_rtx_REG (DImode, regno + 2);
5124
      ops[2] = gen_rtx_REG (DImode, regno + 4);
5125
      ops[3] = gen_rtx_REG (DImode, regno + 6);
5126
      ops[4] = operands[1];
5127
      output_asm_insn ("vld4.\t{%P0[], %P1[], %P2[], %P3[]}, %A4",
5128
                       ops);
5129
      return "";
5130
    }
5131
  else
5132
    return "vld1.\t%h0, %A1";
5133
}
5134
  [(set (attr "neon_type")
5135
      (if_then_else (gt (const_string "") (const_string "1"))
5136
                    (const_string "neon_vld3_vld4_all_lanes")
5137
                    (const_string "neon_vld1_1_2_regs")))]
5138
)
5139
 
5140
(define_expand "vec_store_lanesoi"
5141
  [(set (match_operand:OI 0 "neon_struct_operand")
5142
        (unspec:OI [(match_operand:OI 1 "s_register_operand")
5143
                    (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5144
                   UNSPEC_VST4))]
5145
  "TARGET_NEON")
5146
 
5147
(define_insn "neon_vst4"
5148
  [(set (match_operand:OI 0 "neon_struct_operand" "=Um")
5149
        (unspec:OI [(match_operand:OI 1 "s_register_operand" "w")
5150
                    (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5151
                   UNSPEC_VST4))]
5152
  "TARGET_NEON"
5153
{
5154
  if ( == 64)
5155
    return "vst1.64\t%h1, %A0";
5156
  else
5157
    return "vst4.\t%h1, %A0";
5158
}
5159
  [(set (attr "neon_type")
5160
      (if_then_else (eq (const_string "") (const_string "64"))
5161
                    (const_string "neon_vst1_1_2_regs_vst2_2_regs")
5162
                    (const_string "neon_vst2_4_regs_vst3_vst4")))]
5163
)
5164
 
5165
(define_expand "vec_store_lanesxi"
5166
  [(match_operand:XI 0 "neon_struct_operand")
5167
   (match_operand:XI 1 "s_register_operand")
5168
   (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5169
  "TARGET_NEON"
5170
{
5171
  emit_insn (gen_neon_vst4 (operands[0], operands[1]));
5172
  DONE;
5173
})
5174
 
5175
(define_expand "neon_vst4"
5176
  [(match_operand:XI 0 "neon_struct_operand")
5177
   (match_operand:XI 1 "s_register_operand")
5178
   (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5179
  "TARGET_NEON"
5180
{
5181
  rtx mem;
5182
 
5183
  mem = adjust_address (operands[0], OImode, 0);
5184
  emit_insn (gen_neon_vst4qa (mem, operands[1]));
5185
  mem = adjust_address (mem, OImode, GET_MODE_SIZE (OImode));
5186
  emit_insn (gen_neon_vst4qb (mem, operands[1]));
5187
  DONE;
5188
})
5189
 
5190
(define_insn "neon_vst4qa"
5191
  [(set (match_operand:OI 0 "neon_struct_operand" "=Um")
5192
        (unspec:OI [(match_operand:XI 1 "s_register_operand" "w")
5193
                    (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5194
                   UNSPEC_VST4A))]
5195
  "TARGET_NEON"
5196
{
5197
  int regno = REGNO (operands[1]);
5198
  rtx ops[5];
5199
  ops[0] = operands[0];
5200
  ops[1] = gen_rtx_REG (DImode, regno);
5201
  ops[2] = gen_rtx_REG (DImode, regno + 4);
5202
  ops[3] = gen_rtx_REG (DImode, regno + 8);
5203
  ops[4] = gen_rtx_REG (DImode, regno + 12);
5204
  output_asm_insn ("vst4.\t{%P1, %P2, %P3, %P4}, %A0", ops);
5205
  return "";
5206
}
5207
  [(set_attr "neon_type" "neon_vst2_4_regs_vst3_vst4")]
5208
)
5209
 
5210
(define_insn "neon_vst4qb"
5211
  [(set (match_operand:OI 0 "neon_struct_operand" "=Um")
5212
        (unspec:OI [(match_operand:XI 1 "s_register_operand" "w")
5213
                    (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5214
                   UNSPEC_VST4B))]
5215
  "TARGET_NEON"
5216
{
5217
  int regno = REGNO (operands[1]);
5218
  rtx ops[5];
5219
  ops[0] = operands[0];
5220
  ops[1] = gen_rtx_REG (DImode, regno + 2);
5221
  ops[2] = gen_rtx_REG (DImode, regno + 6);
5222
  ops[3] = gen_rtx_REG (DImode, regno + 10);
5223
  ops[4] = gen_rtx_REG (DImode, regno + 14);
5224
  output_asm_insn ("vst4.\t{%P1, %P2, %P3, %P4}, %A0", ops);
5225
  return "";
5226
}
5227
  [(set_attr "neon_type" "neon_vst2_4_regs_vst3_vst4")]
5228
)
5229
 
5230
(define_insn "neon_vst4_lane"
5231
  [(set (match_operand: 0 "neon_struct_operand" "=Um")
5232
        (unspec:
5233
           [(match_operand:OI 1 "s_register_operand" "w")
5234
            (match_operand:SI 2 "immediate_operand" "i")
5235
            (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5236
           UNSPEC_VST4_LANE))]
5237
  "TARGET_NEON"
5238
{
5239
  HOST_WIDE_INT lane = INTVAL (operands[2]);
5240
  HOST_WIDE_INT max = GET_MODE_NUNITS (mode);
5241
  int regno = REGNO (operands[1]);
5242
  rtx ops[6];
5243
  if (lane < 0 || lane >= max)
5244
    error ("lane out of range");
5245
  ops[0] = operands[0];
5246
  ops[1] = gen_rtx_REG (DImode, regno);
5247
  ops[2] = gen_rtx_REG (DImode, regno + 2);
5248
  ops[3] = gen_rtx_REG (DImode, regno + 4);
5249
  ops[4] = gen_rtx_REG (DImode, regno + 6);
5250
  ops[5] = operands[2];
5251
  output_asm_insn ("vst4.\t{%P1[%c5], %P2[%c5], %P3[%c5], %P4[%c5]}, %A0",
5252
                   ops);
5253
  return "";
5254
}
5255
  [(set_attr "neon_type" "neon_vst3_vst4_lane")]
5256
)
5257
 
5258
(define_insn "neon_vst4_lane"
5259
  [(set (match_operand: 0 "neon_struct_operand" "=Um")
5260
        (unspec:
5261
           [(match_operand:XI 1 "s_register_operand" "w")
5262
            (match_operand:SI 2 "immediate_operand" "i")
5263
            (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
5264
           UNSPEC_VST4_LANE))]
5265
  "TARGET_NEON"
5266
{
5267
  HOST_WIDE_INT lane = INTVAL (operands[2]);
5268
  HOST_WIDE_INT max = GET_MODE_NUNITS (mode);
5269
  int regno = REGNO (operands[1]);
5270
  rtx ops[6];
5271
  if (lane < 0 || lane >= max)
5272
    error ("lane out of range");
5273
  else if (lane >= max / 2)
5274
    {
5275
      lane -= max / 2;
5276
      regno += 2;
5277
    }
5278
  ops[0] = operands[0];
5279
  ops[1] = gen_rtx_REG (DImode, regno);
5280
  ops[2] = gen_rtx_REG (DImode, regno + 4);
5281
  ops[3] = gen_rtx_REG (DImode, regno + 8);
5282
  ops[4] = gen_rtx_REG (DImode, regno + 12);
5283
  ops[5] = GEN_INT (lane);
5284
  output_asm_insn ("vst4.\t{%P1[%c5], %P2[%c5], %P3[%c5], %P4[%c5]}, %A0",
5285
                   ops);
5286
  return "";
5287
}
5288
  [(set_attr "neon_type" "neon_vst3_vst4_lane")]
5289
)
5290
 
5291
(define_expand "neon_vand"
5292
  [(match_operand:VDQX 0 "s_register_operand" "")
5293
   (match_operand:VDQX 1 "s_register_operand" "")
5294
   (match_operand:VDQX 2 "neon_inv_logic_op2" "")
5295
   (match_operand:SI 3 "immediate_operand" "")]
5296
  "TARGET_NEON"
5297
{
5298
  emit_insn (gen_and3 (operands[0], operands[1], operands[2]));
5299
  DONE;
5300
})
5301
 
5302
(define_expand "neon_vorr"
5303
  [(match_operand:VDQX 0 "s_register_operand" "")
5304
   (match_operand:VDQX 1 "s_register_operand" "")
5305
   (match_operand:VDQX 2 "neon_logic_op2" "")
5306
   (match_operand:SI 3 "immediate_operand" "")]
5307
  "TARGET_NEON"
5308
{
5309
  emit_insn (gen_ior3 (operands[0], operands[1], operands[2]));
5310
  DONE;
5311
})
5312
 
5313
(define_expand "neon_veor"
5314
  [(match_operand:VDQX 0 "s_register_operand" "")
5315
   (match_operand:VDQX 1 "s_register_operand" "")
5316
   (match_operand:VDQX 2 "s_register_operand" "")
5317
   (match_operand:SI 3 "immediate_operand" "")]
5318
  "TARGET_NEON"
5319
{
5320
  emit_insn (gen_xor3 (operands[0], operands[1], operands[2]));
5321
  DONE;
5322
})
5323
 
5324
(define_expand "neon_vbic"
5325
  [(match_operand:VDQX 0 "s_register_operand" "")
5326
   (match_operand:VDQX 1 "s_register_operand" "")
5327
   (match_operand:VDQX 2 "neon_logic_op2" "")
5328
   (match_operand:SI 3 "immediate_operand" "")]
5329
  "TARGET_NEON"
5330
{
5331
  emit_insn (gen_bic3_neon (operands[0], operands[1], operands[2]));
5332
  DONE;
5333
})
5334
 
5335
(define_expand "neon_vorn"
5336
  [(match_operand:VDQX 0 "s_register_operand" "")
5337
   (match_operand:VDQX 1 "s_register_operand" "")
5338
   (match_operand:VDQX 2 "neon_inv_logic_op2" "")
5339
   (match_operand:SI 3 "immediate_operand" "")]
5340
  "TARGET_NEON"
5341
{
5342
  emit_insn (gen_orn3_neon (operands[0], operands[1], operands[2]));
5343
  DONE;
5344
})
5345
 
5346
(define_insn "neon_vec_unpack_lo_"
5347
  [(set (match_operand: 0 "register_operand" "=w")
5348
        (SE: (vec_select:
5349
                          (match_operand:VU 1 "register_operand" "w")
5350
                          (match_operand:VU 2 "vect_par_constant_low" ""))))]
5351
  "TARGET_NEON && !BYTES_BIG_ENDIAN"
5352
  "vmovl. %q0, %e1"
5353
  [(set_attr "neon_type" "neon_shift_1")]
5354
)
5355
 
5356
(define_insn "neon_vec_unpack_hi_"
5357
  [(set (match_operand: 0 "register_operand" "=w")
5358
        (SE: (vec_select:
5359
                          (match_operand:VU 1 "register_operand" "w")
5360
                          (match_operand:VU 2 "vect_par_constant_high" ""))))]
5361
  "TARGET_NEON && !BYTES_BIG_ENDIAN"
5362
  "vmovl. %q0, %f1"
5363
  [(set_attr "neon_type" "neon_shift_1")]
5364
)
5365
 
5366
(define_expand "vec_unpack_hi_"
5367
  [(match_operand: 0 "register_operand" "")
5368
   (SE: (match_operand:VU 1 "register_operand"))]
5369
 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5370
  {
5371
   rtvec v = rtvec_alloc (/2)  ;
5372
   rtx t1;
5373
   int i;
5374
   for (i = 0; i < (/2); i++)
5375
     RTVEC_ELT (v, i) = GEN_INT ((/2) + i);
5376
 
5377
   t1 = gen_rtx_PARALLEL (mode, v);
5378
   emit_insn (gen_neon_vec_unpack_hi_ (operands[0],
5379
                                                 operands[1],
5380
                                                 t1));
5381
   DONE;
5382
  }
5383
)
5384
 
5385
(define_expand "vec_unpack_lo_"
5386
  [(match_operand: 0 "register_operand" "")
5387
   (SE: (match_operand:VU 1 "register_operand" ""))]
5388
 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5389
  {
5390
   rtvec v = rtvec_alloc (/2)  ;
5391
   rtx t1;
5392
   int i;
5393
   for (i = 0; i < (/2) ; i++)
5394
     RTVEC_ELT (v, i) = GEN_INT (i);
5395
   t1 = gen_rtx_PARALLEL (mode, v);
5396
   emit_insn (gen_neon_vec_unpack_lo_ (operands[0],
5397
                                                 operands[1],
5398
                                                 t1));
5399
   DONE;
5400
  }
5401
)
5402
 
5403
(define_insn "neon_vec_mult_lo_"
5404
 [(set (match_operand: 0 "register_operand" "=w")
5405
       (mult: (SE: (vec_select:
5406
                           (match_operand:VU 1 "register_operand" "w")
5407
                           (match_operand:VU 2 "vect_par_constant_low" "")))
5408
                        (SE: (vec_select:
5409
                           (match_operand:VU 3 "register_operand" "w")
5410
                           (match_dup 2)))))]
5411
  "TARGET_NEON && !BYTES_BIG_ENDIAN"
5412
  "vmull. %q0, %e1, %e3"
5413
  [(set_attr "neon_type" "neon_shift_1")]
5414
)
5415
 
5416
(define_expand "vec_widen_mult_lo_"
5417
  [(match_operand: 0 "register_operand" "")
5418
   (SE: (match_operand:VU 1 "register_operand" ""))
5419
   (SE: (match_operand:VU 2 "register_operand" ""))]
5420
 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5421
 {
5422
   rtvec v = rtvec_alloc (/2)  ;
5423
   rtx t1;
5424
   int i;
5425
   for (i = 0; i < (/2) ; i++)
5426
     RTVEC_ELT (v, i) = GEN_INT (i);
5427
   t1 = gen_rtx_PARALLEL (mode, v);
5428
 
5429
   emit_insn (gen_neon_vec_mult_lo_ (operands[0],
5430
                                               operands[1],
5431
                                               t1,
5432
                                               operands[2]));
5433
   DONE;
5434
 }
5435
)
5436
 
5437
(define_insn "neon_vec_mult_hi_"
5438
 [(set (match_operand: 0 "register_operand" "=w")
5439
      (mult: (SE: (vec_select:
5440
                            (match_operand:VU 1 "register_operand" "w")
5441
                            (match_operand:VU 2 "vect_par_constant_high" "")))
5442
                       (SE: (vec_select:
5443
                            (match_operand:VU 3 "register_operand" "w")
5444
                            (match_dup 2)))))]
5445
  "TARGET_NEON && !BYTES_BIG_ENDIAN"
5446
  "vmull. %q0, %f1, %f3"
5447
  [(set_attr "neon_type" "neon_shift_1")]
5448
)
5449
 
5450
(define_expand "vec_widen_mult_hi_"
5451
  [(match_operand: 0 "register_operand" "")
5452
   (SE: (match_operand:VU 1 "register_operand" ""))
5453
   (SE: (match_operand:VU 2 "register_operand" ""))]
5454
 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5455
 {
5456
   rtvec v = rtvec_alloc (/2)  ;
5457
   rtx t1;
5458
   int i;
5459
   for (i = 0; i < (/2) ; i++)
5460
     RTVEC_ELT (v, i) = GEN_INT (/2 + i);
5461
   t1 = gen_rtx_PARALLEL (mode, v);
5462
 
5463
   emit_insn (gen_neon_vec_mult_hi_ (operands[0],
5464
                                               operands[1],
5465
                                               t1,
5466
                                               operands[2]));
5467
   DONE;
5468
 
5469
 }
5470
)
5471
 
5472
(define_insn "neon_vec_shiftl_"
5473
 [(set (match_operand: 0 "register_operand" "=w")
5474
       (SE: (ashift:VW (match_operand:VW 1 "register_operand" "w")
5475
       (match_operand: 2 "const_neon_scalar_shift_amount_operand" ""))))]
5476
  "TARGET_NEON"
5477
{
5478
  return "vshll. %q0, %P1, %2";
5479
}
5480
  [(set_attr "neon_type" "neon_shift_1")]
5481
)
5482
 
5483
(define_expand "vec_widen_shiftl_lo_"
5484
  [(match_operand: 0 "register_operand" "")
5485
   (SE: (match_operand:VU 1 "register_operand" ""))
5486
   (match_operand:SI 2 "immediate_operand" "i")]
5487
 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5488
 {
5489
  emit_insn (gen_neon_vec_shiftl_ (operands[0],
5490
                simplify_gen_subreg (mode, operands[1], mode, 0),
5491
                operands[2]));
5492
   DONE;
5493
 }
5494
)
5495
 
5496
(define_expand "vec_widen_shiftl_hi_"
5497
  [(match_operand: 0 "register_operand" "")
5498
   (SE: (match_operand:VU 1 "register_operand" ""))
5499
   (match_operand:SI 2 "immediate_operand" "i")]
5500
 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5501
 {
5502
  emit_insn (gen_neon_vec_shiftl_ (operands[0],
5503
                simplify_gen_subreg (mode, operands[1], mode,
5504
                                     GET_MODE_SIZE (mode)),
5505
                operands[2]));
5506
   DONE;
5507
 }
5508
)
5509
 
5510
;; Vectorize for non-neon-quad case
5511
(define_insn "neon_unpack_"
5512
 [(set (match_operand: 0 "register_operand" "=w")
5513
       (SE: (match_operand:VDI 1 "register_operand" "w")))]
5514
 "TARGET_NEON"
5515
 "vmovl. %q0, %P1"
5516
  [(set_attr "neon_type" "neon_shift_1")]
5517
)
5518
 
5519
(define_expand "vec_unpack_lo_"
5520
 [(match_operand: 0 "register_operand" "")
5521
  (SE:(match_operand:VDI 1 "register_operand"))]
5522
 "TARGET_NEON"
5523
{
5524
  rtx tmpreg = gen_reg_rtx (mode);
5525
  emit_insn (gen_neon_unpack_ (tmpreg, operands[1]));
5526
  emit_insn (gen_neon_vget_low (operands[0], tmpreg));
5527
 
5528
  DONE;
5529
}
5530
)
5531
 
5532
(define_expand "vec_unpack_hi_"
5533
 [(match_operand: 0 "register_operand" "")
5534
  (SE:(match_operand:VDI 1 "register_operand"))]
5535
 "TARGET_NEON"
5536
{
5537
  rtx tmpreg = gen_reg_rtx (mode);
5538
  emit_insn (gen_neon_unpack_ (tmpreg, operands[1]));
5539
  emit_insn (gen_neon_vget_high (operands[0], tmpreg));
5540
 
5541
  DONE;
5542
}
5543
)
5544
 
5545
(define_insn "neon_vec_mult_"
5546
 [(set (match_operand: 0 "register_operand" "=w")
5547
       (mult: (SE:
5548
                           (match_operand:VDI 1 "register_operand" "w"))
5549
                       (SE:
5550
                           (match_operand:VDI 2 "register_operand" "w"))))]
5551
  "TARGET_NEON"
5552
  "vmull. %q0, %P1, %P2"
5553
  [(set_attr "neon_type" "neon_shift_1")]
5554
)
5555
 
5556
(define_expand "vec_widen_mult_hi_"
5557
  [(match_operand: 0 "register_operand" "")
5558
   (SE: (match_operand:VDI 1 "register_operand" ""))
5559
   (SE: (match_operand:VDI 2 "register_operand" ""))]
5560
 "TARGET_NEON"
5561
 {
5562
   rtx tmpreg = gen_reg_rtx (mode);
5563
   emit_insn (gen_neon_vec_mult_ (tmpreg, operands[1], operands[2]));
5564
   emit_insn (gen_neon_vget_high (operands[0], tmpreg));
5565
 
5566
   DONE;
5567
 
5568
 }
5569
)
5570
 
5571
(define_expand "vec_widen_mult_lo_"
5572
  [(match_operand: 0 "register_operand" "")
5573
   (SE: (match_operand:VDI 1 "register_operand" ""))
5574
   (SE: (match_operand:VDI 2 "register_operand" ""))]
5575
 "TARGET_NEON"
5576
 {
5577
   rtx tmpreg = gen_reg_rtx (mode);
5578
   emit_insn (gen_neon_vec_mult_ (tmpreg, operands[1], operands[2]));
5579
   emit_insn (gen_neon_vget_low (operands[0], tmpreg));
5580
 
5581
   DONE;
5582
 
5583
 }
5584
)
5585
 
5586
(define_expand "vec_widen_shiftl_hi_"
5587
 [(match_operand: 0 "register_operand" "")
5588
   (SE: (match_operand:VDI 1 "register_operand" ""))
5589
   (match_operand:SI 2 "immediate_operand" "i")]
5590
 "TARGET_NEON"
5591
 {
5592
   rtx tmpreg = gen_reg_rtx (mode);
5593
   emit_insn (gen_neon_vec_shiftl_ (tmpreg, operands[1], operands[2]));
5594
   emit_insn (gen_neon_vget_high (operands[0], tmpreg));
5595
 
5596
   DONE;
5597
 }
5598
)
5599
 
5600
(define_expand "vec_widen_shiftl_lo_"
5601
  [(match_operand: 0 "register_operand" "")
5602
   (SE: (match_operand:VDI 1 "register_operand" ""))
5603
   (match_operand:SI 2 "immediate_operand" "i")]
5604
 "TARGET_NEON"
5605
 {
5606
   rtx tmpreg = gen_reg_rtx (mode);
5607
   emit_insn (gen_neon_vec_shiftl_ (tmpreg, operands[1], operands[2]));
5608
   emit_insn (gen_neon_vget_low (operands[0], tmpreg));
5609
 
5610
   DONE;
5611
 }
5612
)
5613
 
5614
; FIXME: These instruction patterns can't be used safely in big-endian mode
5615
; because the ordering of vector elements in Q registers is different from what
5616
; the semantics of the instructions require.
5617
 
5618
(define_insn "vec_pack_trunc_"
5619
 [(set (match_operand: 0 "register_operand" "=&w")
5620
       (vec_concat:
5621
                (truncate:
5622
                        (match_operand:VN 1 "register_operand" "w"))
5623
                (truncate:
5624
                        (match_operand:VN 2 "register_operand" "w"))))]
5625
 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5626
 "vmovn.i\t%e0, %q1\;vmovn.i\t%f0, %q2"
5627
 [(set_attr "neon_type" "neon_shift_1")
5628
  (set_attr "length" "8")]
5629
)
5630
 
5631
;; For the non-quad case.
5632
(define_insn "neon_vec_pack_trunc_"
5633
 [(set (match_operand: 0 "register_operand" "=w")
5634
       (truncate: (match_operand:VN 1 "register_operand" "w")))]
5635
 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5636
 "vmovn.i\t%P0, %q1"
5637
 [(set_attr "neon_type" "neon_shift_1")]
5638
)
5639
 
5640
(define_expand "vec_pack_trunc_"
5641
 [(match_operand: 0 "register_operand" "")
5642
  (match_operand:VSHFT 1 "register_operand" "")
5643
  (match_operand:VSHFT 2 "register_operand")]
5644
 "TARGET_NEON && !BYTES_BIG_ENDIAN"
5645
{
5646
  rtx tempreg = gen_reg_rtx (mode);
5647
 
5648
  emit_insn (gen_move_lo_quad_ (tempreg, operands[1]));
5649
  emit_insn (gen_move_hi_quad_ (tempreg, operands[2]));
5650
  emit_insn (gen_neon_vec_pack_trunc_ (operands[0], tempreg));
5651
  DONE;
5652
})
5653
 
5654
(define_insn "neon_vabd_2"
5655
 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
5656
       (abs:VDQ (minus:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
5657
                           (match_operand:VDQ 2 "s_register_operand" "w"))))]
5658
 "TARGET_NEON && (! || flag_unsafe_math_optimizations)"
5659
 "vabd. %0, %1, %2"
5660
 [(set (attr "neon_type")
5661
       (if_then_else (ne (symbol_ref "") (const_int 0))
5662
                     (if_then_else (ne (symbol_ref "") (const_int 0))
5663
                                   (const_string "neon_fp_vadd_ddd_vabs_dd")
5664
                                   (const_string "neon_fp_vadd_qqq_vabs_qq"))
5665
                     (const_string "neon_int_5")))]
5666
)
5667
 
5668
(define_insn "neon_vabd_3"
5669
 [(set (match_operand:VDQ 0 "s_register_operand" "=w")
5670
       (abs:VDQ (unspec:VDQ [(match_operand:VDQ 1 "s_register_operand" "w")
5671
                             (match_operand:VDQ 2 "s_register_operand" "w")]
5672
                 UNSPEC_VSUB)))]
5673
 "TARGET_NEON && (! || flag_unsafe_math_optimizations)"
5674
 "vabd. %0, %1, %2"
5675
 [(set (attr "neon_type")
5676
       (if_then_else (ne (symbol_ref "") (const_int 0))
5677
                     (if_then_else (ne (symbol_ref "") (const_int 0))
5678
                                   (const_string "neon_fp_vadd_ddd_vabs_dd")
5679
                                   (const_string "neon_fp_vadd_qqq_vabs_qq"))
5680
                     (const_string "neon_int_5")))]
5681
)

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.