OSDN Git Service

gcc/
[pf3gnuchains/gcc-fork.git] / gcc / config / arm / neon.ml
1 (* Common code for ARM NEON header file, documentation and test case
2    generators.
3
4    Copyright (C) 2006 Free Software Foundation, Inc.
5    Contributed by CodeSourcery.
6
7    This file is part of GCC.
8
9    GCC is free software; you can redistribute it and/or modify it under
10    the terms of the GNU General Public License as published by the Free
11    Software Foundation; either version 2, or (at your option) any later
12    version.
13
14    GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15    WARRANTY; without even the implied warranty of MERCHANTABILITY or
16    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17    for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with GCC; see the file COPYING.  If not, write to the Free
21    Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
22    02110-1301, USA.  *)
23
24 (* Shorthand types for vector elements.  *)
25 type elts = S8 | S16 | S32 | S64 | F32 | U8 | U16 | U32 | U64 | P8 | P16
26           | I8 | I16 | I32 | I64 | B8 | B16 | B32 | B64 | Conv of elts * elts
27           | Cast of elts * elts | NoElts
28
29 type eltclass = Signed | Unsigned | Float | Poly | Int | Bits
30               | ConvClass of eltclass * eltclass | NoType
31
32 (* These vector types correspond directly to C types.  *)
33 type vectype = T_int8x8    | T_int8x16
34              | T_int16x4   | T_int16x8
35              | T_int32x2   | T_int32x4
36              | T_int64x1   | T_int64x2
37              | T_uint8x8   | T_uint8x16
38              | T_uint16x4  | T_uint16x8
39              | T_uint32x2  | T_uint32x4
40              | T_uint64x1  | T_uint64x2
41              | T_float32x2 | T_float32x4
42              | T_poly8x8   | T_poly8x16
43              | T_poly16x4  | T_poly16x8
44              | T_immediate of int * int
45              | T_int8      | T_int16
46              | T_int32     | T_int64
47              | T_uint8     | T_uint16
48              | T_uint32    | T_uint64
49              | T_poly8     | T_poly16
50              | T_float32   | T_arrayof of int * vectype
51              | T_ptrto of vectype | T_const of vectype
52              | T_void      | T_intQI
53              | T_intHI     | T_intSI
54              | T_intDI
55
56 (* The meanings of the following are:
57      TImode : "Tetra", two registers (four words).
58      EImode : "hExa", three registers (six words).
59      OImode : "Octa", four registers (eight words).
60      CImode : "dodeCa", six registers (twelve words).
61      XImode : "heXadeca", eight registers (sixteen words).
62 *)
63
64 type inttype = B_TImode | B_EImode | B_OImode | B_CImode | B_XImode
65
66 type shape_elt = Dreg | Qreg | Corereg | Immed | VecArray of int * shape_elt
67                | PtrTo of shape_elt | CstPtrTo of shape_elt
68                (* These next ones are used only in the test generator.  *)
69                | Element_of_dreg        (* Used for "lane" variants.  *)
70                | Element_of_qreg        (* Likewise.  *)
71                | All_elements_of_dreg   (* Used for "dup" variants.  *)
72
73 type shape_form = All of int * shape_elt
74                 | Long
75                 | Long_noreg of shape_elt
76                 | Wide
77                 | Wide_noreg of shape_elt
78                 | Narrow
79                 | Long_imm
80                 | Narrow_imm
81                 | Binary_imm of shape_elt
82                 | Use_operands of shape_elt array
83                 | By_scalar of shape_elt
84                 | Unary_scalar of shape_elt
85                 | Wide_lane
86                 | Wide_scalar
87                 | Pair_result of shape_elt
88
89 type arity = Arity0 of vectype
90            | Arity1 of vectype * vectype
91            | Arity2 of vectype * vectype * vectype
92            | Arity3 of vectype * vectype * vectype * vectype
93            | Arity4 of vectype * vectype * vectype * vectype * vectype
94
95 type vecmode = V8QI | V4HI | V2SI | V2SF | DI
96              | V16QI | V8HI | V4SI | V4SF | V2DI
97              | QI | HI | SI | SF
98
99 type opcode =
100   (* Binary ops.  *)
101     Vadd
102   | Vmul
103   | Vmla
104   | Vmls
105   | Vsub
106   | Vceq
107   | Vcge
108   | Vcgt
109   | Vcle
110   | Vclt
111   | Vcage
112   | Vcagt
113   | Vcale
114   | Vcalt
115   | Vtst
116   | Vabd
117   | Vaba
118   | Vmax
119   | Vmin
120   | Vpadd
121   | Vpada
122   | Vpmax
123   | Vpmin
124   | Vrecps
125   | Vrsqrts
126   | Vshl
127   | Vshr_n
128   | Vshl_n
129   | Vsra_n
130   | Vsri
131   | Vsli
132   (* Logic binops.  *)
133   | Vand
134   | Vorr
135   | Veor
136   | Vbic
137   | Vorn
138   | Vbsl
139   (* Ops with scalar.  *)
140   | Vmul_lane
141   | Vmla_lane
142   | Vmls_lane
143   | Vmul_n
144   | Vmla_n
145   | Vmls_n
146   | Vmull_n
147   | Vmull_lane
148   | Vqdmull_n
149   | Vqdmull_lane
150   | Vqdmulh_n
151   | Vqdmulh_lane
152   (* Unary ops.  *)
153   | Vabs
154   | Vneg
155   | Vcls
156   | Vclz
157   | Vcnt
158   | Vrecpe
159   | Vrsqrte
160   | Vmvn
161   (* Vector extract.  *)
162   | Vext
163   (* Reverse elements.  *)
164   | Vrev64
165   | Vrev32
166   | Vrev16
167   (* Transposition ops.  *)
168   | Vtrn
169   | Vzip
170   | Vuzp
171   (* Loads and stores (VLD1/VST1/VLD2...), elements and structures.  *)
172   | Vldx of int
173   | Vstx of int
174   | Vldx_lane of int
175   | Vldx_dup of int
176   | Vstx_lane of int
177   (* Set/extract lanes from a vector.  *)
178   | Vget_lane
179   | Vset_lane
180   (* Initialize vector from bit pattern.  *)
181   | Vcreate
182   (* Set all lanes to same value.  *)
183   | Vdup_n
184   | Vmov_n  (* Is this the same?  *)
185   (* Duplicate scalar to all lanes of vector.  *)
186   | Vdup_lane
187   (* Combine vectors.  *)
188   | Vcombine
189   (* Get quadword high/low parts.  *)
190   | Vget_high
191   | Vget_low
192   (* Convert vectors.  *)
193   | Vcvt
194   | Vcvt_n
195   (* Narrow/lengthen vectors.  *)
196   | Vmovn
197   | Vmovl
198   (* Table lookup.  *)
199   | Vtbl of int
200   | Vtbx of int
201   (* Reinterpret casts.  *)
202   | Vreinterp
203
204 (* Features used for documentation, to distinguish between some instruction
205    variants, and to signal special requirements (e.g. swapping arguments).  *)
206
207 type features =
208     Halving
209   | Rounding
210   | Saturating
211   | Dst_unsign
212   | High_half
213   | Doubling
214   | Flipped of string  (* Builtin name to use with flipped arguments.  *)
215   | InfoWord  (* Pass an extra word for signage/rounding etc. (always passed
216                  for All _, Long, Wide, Narrow shape_forms.  *)
217   | ReturnPtr  (* Pass explicit pointer to return value as first argument.  *)
218     (* A specification as to the shape of instruction expected upon
219        disassembly, used if it differs from the shape used to build the
220        intrinsic prototype.  Multiple entries in the constructor's argument
221        indicate that the intrinsic expands to more than one assembly
222        instruction, each with a corresponding shape specified here.  *)
223   | Disassembles_as of shape_form list
224   | Builtin_name of string  (* Override the name of the builtin.  *)
225     (* Override the name of the instruction.  If more than one name
226        is specified, it means that the instruction can have any of those
227        names.  *)
228   | Instruction_name of string list
229     (* Mark that the intrinsic yields no instructions, or expands to yield
230        behavior that the test generator cannot test.  *)
231   | No_op
232     (* Mark that the intrinsic has constant arguments that cannot be set
233        to the defaults (zero for pointers and one otherwise) in the test
234        cases.  The function supplied must return the integer to be written
235        into the testcase for the argument number (0-based) supplied to it.  *)
236   | Const_valuator of (int -> int)
237
238 exception MixedMode of elts * elts
239
240 let rec elt_width = function
241     S8 | U8 | P8 | I8 | B8 -> 8
242   | S16 | U16 | P16 | I16 | B16 -> 16
243   | S32 | F32 | U32 | I32 | B32 -> 32
244   | S64 | U64 | I64 | B64 -> 64
245   | Conv (a, b) ->
246       let wa = elt_width a and wb = elt_width b in
247       if wa = wb then wa else failwith "element width?"
248   | Cast (a, b) -> raise (MixedMode (a, b))
249   | NoElts -> failwith "No elts"
250
251 let rec elt_class = function
252     S8 | S16 | S32 | S64 -> Signed
253   | U8 | U16 | U32 | U64 -> Unsigned
254   | P8 | P16 -> Poly
255   | F32 -> Float
256   | I8 | I16 | I32 | I64 -> Int
257   | B8 | B16 | B32 | B64 -> Bits
258   | Conv (a, b) | Cast (a, b) -> ConvClass (elt_class a, elt_class b)
259   | NoElts -> NoType
260
261 let elt_of_class_width c w =
262   match c, w with
263     Signed, 8 -> S8
264   | Signed, 16 -> S16
265   | Signed, 32 -> S32
266   | Signed, 64 -> S64
267   | Float, 32 -> F32
268   | Unsigned, 8 -> U8
269   | Unsigned, 16 -> U16
270   | Unsigned, 32 -> U32
271   | Unsigned, 64 -> U64
272   | Poly, 8 -> P8
273   | Poly, 16 -> P16
274   | Int, 8 -> I8
275   | Int, 16 -> I16
276   | Int, 32 -> I32
277   | Int, 64 -> I64
278   | Bits, 8 -> B8
279   | Bits, 16 -> B16
280   | Bits, 32 -> B32
281   | Bits, 64 -> B64
282   | _ -> failwith "Bad element type"
283
284 (* Return unsigned integer element the same width as argument.  *)
285 let unsigned_of_elt elt =
286   elt_of_class_width Unsigned (elt_width elt)
287
288 let signed_of_elt elt =
289   elt_of_class_width Signed (elt_width elt)
290
291 (* Return untyped bits element the same width as argument.  *)
292 let bits_of_elt elt =
293   elt_of_class_width Bits (elt_width elt)
294
295 let non_signed_variant = function
296     S8 -> I8
297   | S16 -> I16
298   | S32 -> I32
299   | S64 -> I64
300   | U8 -> I8
301   | U16 -> I16
302   | U32 -> I32
303   | U64 -> I64
304   | x -> x
305
306 let poly_unsigned_variant v =
307   let elclass = match elt_class v with
308     Poly -> Unsigned
309   | x -> x in
310   elt_of_class_width elclass (elt_width v)
311
312 let widen_elt elt =
313   let w = elt_width elt
314   and c = elt_class elt in
315   elt_of_class_width c (w * 2)
316
317 let narrow_elt elt =
318   let w = elt_width elt
319   and c = elt_class elt in
320   elt_of_class_width c (w / 2)
321
322 (* If we're trying to find a mode from a "Use_operands" instruction, use the
323    last vector operand as the dominant mode used to invoke the correct builtin.
324    We must stick to this rule in neon.md.  *)
325 let find_key_operand operands =
326   let rec scan opno =
327     match operands.(opno) with
328       Qreg -> Qreg
329     | Dreg -> Dreg
330     | VecArray (_, Qreg) -> Qreg
331     | VecArray (_, Dreg) -> Dreg
332     | _ -> scan (opno-1)
333   in
334     scan ((Array.length operands) - 1)
335
336 let rec mode_of_elt elt shape =
337   let flt = match elt_class elt with
338     Float | ConvClass(_, Float) -> true | _ -> false in
339   let idx =
340     match elt_width elt with
341       8 -> 0 | 16 -> 1 | 32 -> 2 | 64 -> 3
342     | _ -> failwith "Bad element width"
343   in match shape with
344     All (_, Dreg) | By_scalar Dreg | Pair_result Dreg | Unary_scalar Dreg
345   | Binary_imm Dreg | Long_noreg Dreg | Wide_noreg Dreg ->
346       [| V8QI; V4HI; if flt then V2SF else V2SI; DI |].(idx)
347   | All (_, Qreg) | By_scalar Qreg | Pair_result Qreg | Unary_scalar Qreg
348   | Binary_imm Qreg | Long_noreg Qreg | Wide_noreg Qreg ->
349       [| V16QI; V8HI; if flt then V4SF else V4SI; V2DI |].(idx)
350   | All (_, (Corereg | PtrTo _ | CstPtrTo _)) ->
351       [| QI; HI; if flt then SF else SI; DI |].(idx)
352   | Long | Wide | Wide_lane | Wide_scalar
353   | Long_imm ->
354       [| V8QI; V4HI; V2SI; DI |].(idx)
355   | Narrow | Narrow_imm -> [| V16QI; V8HI; V4SI; V2DI |].(idx)
356   | Use_operands ops -> mode_of_elt elt (All (0, (find_key_operand ops)))
357   | _ -> failwith "invalid shape"
358
359 (* Modify an element type dependent on the shape of the instruction and the
360    operand number.  *)
361
362 let shapemap shape no =
363   let ident = fun x -> x in
364   match shape with
365     All _ | Use_operands _ | By_scalar _ | Pair_result _ | Unary_scalar _
366   | Binary_imm _ -> ident
367   | Long | Long_noreg _ | Wide_scalar | Long_imm ->
368       [| widen_elt; ident; ident |].(no)
369   | Wide | Wide_noreg _ -> [| widen_elt; widen_elt; ident |].(no)
370   | Wide_lane -> [| widen_elt; ident; ident; ident |].(no)
371   | Narrow | Narrow_imm -> [| narrow_elt; ident; ident |].(no)
372
373 (* Register type (D/Q) of an operand, based on shape and operand number.  *)
374
375 let regmap shape no =
376   match shape with
377     All (_, reg) | Long_noreg reg | Wide_noreg reg -> reg
378   | Long -> [| Qreg; Dreg; Dreg |].(no)
379   | Wide -> [| Qreg; Qreg; Dreg |].(no)
380   | Narrow -> [| Dreg; Qreg; Qreg |].(no)
381   | Wide_lane -> [| Qreg; Dreg; Dreg; Immed |].(no)
382   | Wide_scalar -> [| Qreg; Dreg; Corereg |].(no)
383   | By_scalar reg -> [| reg; reg; Dreg; Immed |].(no)
384   | Unary_scalar reg -> [| reg; Dreg; Immed |].(no)
385   | Pair_result reg -> [| VecArray (2, reg); reg; reg |].(no)
386   | Binary_imm reg -> [| reg; reg; Immed |].(no)
387   | Long_imm -> [| Qreg; Dreg; Immed |].(no)
388   | Narrow_imm -> [| Dreg; Qreg; Immed |].(no)
389   | Use_operands these -> these.(no)
390
391 let type_for_elt shape elt no =
392   let elt = (shapemap shape no) elt in
393   let reg = regmap shape no in
394   let rec type_for_reg_elt reg elt =
395     match reg with
396       Dreg ->
397         begin match elt with
398           S8 -> T_int8x8
399         | S16 -> T_int16x4
400         | S32 -> T_int32x2
401         | S64 -> T_int64x1
402         | U8 -> T_uint8x8
403         | U16 -> T_uint16x4
404         | U32 -> T_uint32x2
405         | U64 -> T_uint64x1
406         | F32 -> T_float32x2
407         | P8 -> T_poly8x8
408         | P16 -> T_poly16x4
409         | _ -> failwith "Bad elt type"
410         end
411     | Qreg ->
412         begin match elt with
413           S8 -> T_int8x16
414         | S16 -> T_int16x8
415         | S32 -> T_int32x4
416         | S64 -> T_int64x2
417         | U8 -> T_uint8x16
418         | U16 -> T_uint16x8
419         | U32 -> T_uint32x4
420         | U64 -> T_uint64x2
421         | F32 -> T_float32x4
422         | P8 -> T_poly8x16
423         | P16 -> T_poly16x8
424         | _ -> failwith "Bad elt type"
425         end
426     | Corereg ->
427         begin match elt with
428           S8 -> T_int8
429         | S16 -> T_int16
430         | S32 -> T_int32
431         | S64 -> T_int64
432         | U8 -> T_uint8
433         | U16 -> T_uint16
434         | U32 -> T_uint32
435         | U64 -> T_uint64
436         | P8 -> T_poly8
437         | P16 -> T_poly16
438         | F32 -> T_float32
439         | _ -> failwith "Bad elt type"
440         end
441     | Immed ->
442         T_immediate (0, 0)
443     | VecArray (num, sub) ->
444         T_arrayof (num, type_for_reg_elt sub elt)
445     | PtrTo x ->
446         T_ptrto (type_for_reg_elt x elt)
447     | CstPtrTo x ->
448         T_ptrto (T_const (type_for_reg_elt x elt))
449     (* Anything else is solely for the use of the test generator.  *)
450     | _ -> assert false
451   in
452     type_for_reg_elt reg elt
453
454 (* Return size of a vector type, in bits.  *)
455 let vectype_size = function
456     T_int8x8 | T_int16x4 | T_int32x2 | T_int64x1
457   | T_uint8x8 | T_uint16x4 | T_uint32x2 | T_uint64x1
458   | T_float32x2 | T_poly8x8 | T_poly16x4 -> 64
459   | T_int8x16 | T_int16x8 | T_int32x4 | T_int64x2
460   | T_uint8x16 | T_uint16x8  | T_uint32x4  | T_uint64x2
461   | T_float32x4 | T_poly8x16 | T_poly16x8 -> 128
462   | _ -> raise Not_found
463
464 let inttype_for_array num elttype =
465   let eltsize = vectype_size elttype in
466   let numwords = (num * eltsize) / 32 in
467   match numwords with
468     4 -> B_TImode
469   | 6 -> B_EImode
470   | 8 -> B_OImode
471   | 12 -> B_CImode
472   | 16 -> B_XImode
473   | _ -> failwith ("no int type for size " ^ string_of_int numwords)
474
475 (* These functions return pairs of (internal, external) types, where "internal"
476    types are those seen by GCC, and "external" are those seen by the assembler.
477    These types aren't necessarily the same, since the intrinsics can munge more
478    than one C type into each assembler opcode.  *)
479
480 let make_sign_invariant func shape elt =
481   let arity, elt' = func shape elt in
482   arity, non_signed_variant elt'
483
484 (* Don't restrict any types.  *)
485
486 let elts_same make_arity shape elt =
487   let vtype = type_for_elt shape elt in
488   make_arity vtype, elt
489
490 (* As sign_invar_*, but when sign matters.  *)
491 let elts_same_io_lane =
492   elts_same (fun vtype -> Arity4 (vtype 0, vtype 0, vtype 1, vtype 2, vtype 3))
493
494 let elts_same_io =
495   elts_same (fun vtype -> Arity3 (vtype 0, vtype 0, vtype 1, vtype 2))
496
497 let elts_same_2_lane =
498   elts_same (fun vtype -> Arity3 (vtype 0, vtype 1, vtype 2, vtype 3))
499
500 let elts_same_3 = elts_same_2_lane
501
502 let elts_same_2 =
503   elts_same (fun vtype -> Arity2 (vtype 0, vtype 1, vtype 2))
504
505 let elts_same_1 =
506   elts_same (fun vtype -> Arity1 (vtype 0, vtype 1))
507
508 (* Use for signed/unsigned invariant operations (i.e. where the operation
509    doesn't depend on the sign of the data.  *)
510
511 let sign_invar_io_lane = make_sign_invariant elts_same_io_lane
512 let sign_invar_io = make_sign_invariant elts_same_io
513 let sign_invar_2_lane = make_sign_invariant elts_same_2_lane
514 let sign_invar_2 = make_sign_invariant elts_same_2
515 let sign_invar_1 = make_sign_invariant elts_same_1
516
517 (* Sign-sensitive comparison.  *)
518
519 let cmp_sign_matters shape elt =
520   let vtype = type_for_elt shape elt
521   and rtype = type_for_elt shape (unsigned_of_elt elt) 0 in
522   Arity2 (rtype, vtype 1, vtype 2), elt
523
524 (* Signed/unsigned invariant comparison.  *)
525
526 let cmp_sign_invar shape elt =
527   let shape', elt' = cmp_sign_matters shape elt in
528   let elt'' =
529     match non_signed_variant elt' with
530       P8 -> I8
531     | x -> x
532   in
533     shape', elt''
534
535 (* Comparison (VTST) where only the element width matters.  *)
536
537 let cmp_bits shape elt =
538   let vtype = type_for_elt shape elt
539   and rtype = type_for_elt shape (unsigned_of_elt elt) 0
540   and bits_only = bits_of_elt elt in
541   Arity2 (rtype, vtype 1, vtype 2), bits_only
542
543 let reg_shift shape elt =
544   let vtype = type_for_elt shape elt
545   and op2type = type_for_elt shape (signed_of_elt elt) 2 in
546   Arity2 (vtype 0, vtype 1, op2type), elt
547
548 (* Genericised constant-shift type-generating function.  *)
549
550 let const_shift mkimm ?arity ?result shape elt =
551   let op2type = (shapemap shape 2) elt in
552   let op2width = elt_width op2type in
553   let op2 = mkimm op2width
554   and op1 = type_for_elt shape elt 1
555   and r_elt =
556     match result with
557       None -> elt
558     | Some restriction -> restriction elt in
559   let rtype = type_for_elt shape r_elt 0 in
560   match arity with
561     None -> Arity2 (rtype, op1, op2), elt
562   | Some mkarity -> mkarity rtype op1 op2, elt
563
564 (* Use for immediate right-shifts.  *)
565
566 let shift_right shape elt =
567   const_shift (fun imm -> T_immediate (1, imm)) shape elt
568
569 let shift_right_acc shape elt =
570   const_shift (fun imm -> T_immediate (1, imm))
571     ~arity:(fun dst op1 op2 -> Arity3 (dst, dst, op1, op2)) shape elt
572
573 (* Use for immediate right-shifts when the operation doesn't care about
574    signedness.  *)
575
576 let shift_right_sign_invar =
577   make_sign_invariant shift_right
578
579 (* Immediate right-shift; result is unsigned even when operand is signed.  *)
580
581 let shift_right_to_uns shape elt =
582   const_shift (fun imm -> T_immediate (1, imm)) ~result:unsigned_of_elt
583     shape elt
584
585 (* Immediate left-shift.  *)
586
587 let shift_left shape elt =
588   const_shift (fun imm -> T_immediate (0, imm - 1)) shape elt
589
590 (* Immediate left-shift, unsigned result.  *)
591
592 let shift_left_to_uns shape elt =
593   const_shift (fun imm -> T_immediate (0, imm - 1)) ~result:unsigned_of_elt
594     shape elt
595
596 (* Immediate left-shift, don't care about signs.  *)
597
598 let shift_left_sign_invar =
599   make_sign_invariant shift_left
600
601 (* Shift left/right and insert: only element size matters.  *)
602
603 let shift_insert shape elt =
604   let arity, elt =
605     const_shift (fun imm -> T_immediate (1, imm))
606     ~arity:(fun dst op1 op2 -> Arity3 (dst, dst, op1, op2)) shape elt in
607   arity, bits_of_elt elt
608
609 (* Get/set lane.  *)
610
611 let get_lane shape elt =
612   let vtype = type_for_elt shape elt in
613   Arity2 (vtype 0, vtype 1, vtype 2),
614     (match elt with P8 -> U8 | P16 -> U16 | S32 | U32 | F32 -> B32 | x -> x)
615
616 let set_lane shape elt =
617   let vtype = type_for_elt shape elt in
618   Arity3 (vtype 0, vtype 1, vtype 2, vtype 3), bits_of_elt elt
619
620 let set_lane_notype shape elt =
621   let vtype = type_for_elt shape elt in
622   Arity3 (vtype 0, vtype 1, vtype 2, vtype 3), NoElts
623
624 let create_vector shape elt =
625   let vtype = type_for_elt shape U64 1
626   and rtype = type_for_elt shape elt 0 in
627   Arity1 (rtype, vtype), elt
628
629 let conv make_arity shape elt =
630   let edest, esrc = match elt with
631     Conv (edest, esrc) | Cast (edest, esrc) -> edest, esrc
632   | _ -> failwith "Non-conversion element in conversion" in
633   let vtype = type_for_elt shape esrc
634   and rtype = type_for_elt shape edest 0 in
635   make_arity rtype vtype, elt
636
637 let conv_1 = conv (fun rtype vtype -> Arity1 (rtype, vtype 1))
638 let conv_2 = conv (fun rtype vtype -> Arity2 (rtype, vtype 1, vtype 2))
639
640 (* Operation has an unsigned result even if operands are signed.  *)
641
642 let dst_unsign make_arity shape elt =
643   let vtype = type_for_elt shape elt
644   and rtype = type_for_elt shape (unsigned_of_elt elt) 0 in
645   make_arity rtype vtype, elt
646
647 let dst_unsign_1 = dst_unsign (fun rtype vtype -> Arity1 (rtype, vtype 1))
648
649 let make_bits_only func shape elt =
650   let arity, elt' = func shape elt in
651   arity, bits_of_elt elt'
652
653 (* Extend operation.  *)
654
655 let extend shape elt =
656   let vtype = type_for_elt shape elt in
657   Arity3 (vtype 0, vtype 1, vtype 2, vtype 3), bits_of_elt elt
658
659 (* Table look-up operations. Operand 2 is signed/unsigned for signed/unsigned
660    integer ops respectively, or unsigned for polynomial ops.  *)
661
662 let table mkarity shape elt =
663   let vtype = type_for_elt shape elt in
664   let op2 = type_for_elt shape (poly_unsigned_variant elt) 2 in
665   mkarity vtype op2, bits_of_elt elt
666
667 let table_2 = table (fun vtype op2 -> Arity2 (vtype 0, vtype 1, op2))
668 let table_io = table (fun vtype op2 -> Arity3 (vtype 0, vtype 0, vtype 1, op2))
669
670 (* Operations where only bits matter.  *)
671
672 let bits_1 = make_bits_only elts_same_1
673 let bits_2 = make_bits_only elts_same_2
674 let bits_3 = make_bits_only elts_same_3
675
676 (* Store insns.  *)
677 let store_1 shape elt =
678   let vtype = type_for_elt shape elt in
679   Arity2 (T_void, vtype 0, vtype 1), bits_of_elt elt
680
681 let store_3 shape elt =
682   let vtype = type_for_elt shape elt in
683   Arity3 (T_void, vtype 0, vtype 1, vtype 2), bits_of_elt elt
684
685 let make_notype func shape elt =
686   let arity, _ = func shape elt in
687   arity, NoElts
688
689 let notype_1 = make_notype elts_same_1
690 let notype_2 = make_notype elts_same_2
691 let notype_3 = make_notype elts_same_3
692
693 (* Bit-select operations (first operand is unsigned int).  *)
694
695 let bit_select shape elt =
696   let vtype = type_for_elt shape elt
697   and itype = type_for_elt shape (unsigned_of_elt elt) in
698   Arity3 (vtype 0, itype 1, vtype 2, vtype 3), NoElts
699
700 (* Common lists of supported element types.  *)
701
702 let su_8_32 = [S8; S16; S32; U8; U16; U32]
703 let su_8_64 = S64 :: U64 :: su_8_32
704 let su_16_64 = [S16; S32; S64; U16; U32; U64]
705 let pf_su_8_32 = P8 :: P16 :: F32 :: su_8_32
706 let pf_su_8_64 = P8 :: P16 :: F32 :: su_8_64
707
708 let ops =
709   [
710     (* Addition.  *)
711     Vadd, [], All (3, Dreg), "vadd", sign_invar_2, F32 :: su_8_64;
712     Vadd, [], All (3, Qreg), "vaddQ", sign_invar_2, F32 :: su_8_64;
713     Vadd, [], Long, "vaddl", elts_same_2, su_8_32;
714     Vadd, [], Wide, "vaddw", elts_same_2, su_8_32;
715     Vadd, [Halving], All (3, Dreg), "vhadd", elts_same_2, su_8_32;
716     Vadd, [Halving], All (3, Qreg), "vhaddQ", elts_same_2, su_8_32;
717     Vadd, [Instruction_name ["vrhadd"]; Rounding; Halving],
718       All (3, Dreg), "vRhadd", elts_same_2, su_8_32;
719     Vadd, [Instruction_name ["vrhadd"]; Rounding; Halving],
720       All (3, Qreg), "vRhaddQ", elts_same_2, su_8_32;
721     Vadd, [Saturating], All (3, Dreg), "vqadd", elts_same_2, su_8_64;
722     Vadd, [Saturating], All (3, Qreg), "vqaddQ", elts_same_2, su_8_64;
723     Vadd, [High_half], Narrow, "vaddhn", sign_invar_2, su_16_64;
724     Vadd, [Instruction_name ["vraddhn"]; Rounding; High_half],
725       Narrow, "vRaddhn", sign_invar_2, su_16_64;
726
727     (* Multiplication.  *)
728     Vmul, [], All (3, Dreg), "vmul", sign_invar_2, P8 :: F32 :: su_8_32;
729     Vmul, [], All (3, Qreg), "vmulQ", sign_invar_2, P8 :: F32 :: su_8_32;
730     Vmul, [Saturating; Doubling; High_half], All (3, Dreg), "vqdmulh",
731       elts_same_2, [S16; S32];
732     Vmul, [Saturating; Doubling; High_half], All (3, Qreg), "vqdmulhQ",
733       elts_same_2, [S16; S32];
734     Vmul,
735       [Saturating; Rounding; Doubling; High_half;
736        Instruction_name ["vqrdmulh"]],
737       All (3, Dreg), "vqRdmulh",
738       elts_same_2, [S16; S32];
739     Vmul,
740       [Saturating; Rounding; Doubling; High_half;
741        Instruction_name ["vqrdmulh"]],
742       All (3, Qreg), "vqRdmulhQ",
743       elts_same_2, [S16; S32];
744     Vmul, [], Long, "vmull", elts_same_2, P8 :: su_8_32;
745     Vmul, [Saturating; Doubling], Long, "vqdmull", elts_same_2, [S16; S32];
746
747     (* Multiply-accumulate. *)
748     Vmla, [], All (3, Dreg), "vmla", sign_invar_io, F32 :: su_8_32;
749     Vmla, [], All (3, Qreg), "vmlaQ", sign_invar_io, F32 :: su_8_32;
750     Vmla, [], Long, "vmlal", elts_same_io, su_8_32;
751     Vmla, [Saturating; Doubling], Long, "vqdmlal", elts_same_io, [S16; S32];
752
753     (* Multiply-subtract.  *)
754     Vmls, [], All (3, Dreg), "vmls", sign_invar_io, F32 :: su_8_32;
755     Vmls, [], All (3, Qreg), "vmlsQ", sign_invar_io, F32 :: su_8_32;
756     Vmls, [], Long, "vmlsl", elts_same_io, su_8_32;
757     Vmls, [Saturating; Doubling], Long, "vqdmlsl", elts_same_io, [S16; S32];
758
759     (* Subtraction.  *)
760     Vsub, [], All (3, Dreg), "vsub", sign_invar_2, F32 :: su_8_64;
761     Vsub, [], All (3, Qreg), "vsubQ", sign_invar_2, F32 :: su_8_64;
762     Vsub, [], Long, "vsubl", elts_same_2, su_8_32;
763     Vsub, [], Wide, "vsubw", elts_same_2, su_8_32;
764     Vsub, [Halving], All (3, Dreg), "vhsub", elts_same_2, su_8_32;
765     Vsub, [Halving], All (3, Qreg), "vhsubQ", elts_same_2, su_8_32;
766     Vsub, [Saturating], All (3, Dreg), "vqsub", elts_same_2, su_8_64;
767     Vsub, [Saturating], All (3, Qreg), "vqsubQ", elts_same_2, su_8_64;
768     Vsub, [High_half], Narrow, "vsubhn", sign_invar_2, su_16_64;
769     Vsub, [Instruction_name ["vrsubhn"]; Rounding; High_half],
770       Narrow, "vRsubhn", sign_invar_2, su_16_64;
771
772     (* Comparison, equal.  *)
773     Vceq, [], All (3, Dreg), "vceq", cmp_sign_invar, P8 :: F32 :: su_8_32;
774     Vceq, [], All (3, Qreg), "vceqQ", cmp_sign_invar, P8 :: F32 :: su_8_32;
775
776     (* Comparison, greater-than or equal.  *)
777     Vcge, [], All (3, Dreg), "vcge", cmp_sign_matters, F32 :: su_8_32;
778     Vcge, [], All (3, Qreg), "vcgeQ", cmp_sign_matters, F32 :: su_8_32;
779
780     (* Comparison, less-than or equal.  *)
781     Vcle, [Flipped "vcge"], All (3, Dreg), "vcle", cmp_sign_matters,
782       F32 :: su_8_32;
783     Vcle, [Instruction_name ["vcge"]; Flipped "vcgeQ"],
784       All (3, Qreg), "vcleQ", cmp_sign_matters,
785       F32 :: su_8_32;
786
787     (* Comparison, greater-than.  *)
788     Vcgt, [], All (3, Dreg), "vcgt", cmp_sign_matters, F32 :: su_8_32;
789     Vcgt, [], All (3, Qreg), "vcgtQ", cmp_sign_matters, F32 :: su_8_32;
790
791     (* Comparison, less-than.  *)
792     Vclt, [Flipped "vcgt"], All (3, Dreg), "vclt", cmp_sign_matters,
793       F32 :: su_8_32;
794     Vclt, [Instruction_name ["vcgt"]; Flipped "vcgtQ"],
795       All (3, Qreg), "vcltQ", cmp_sign_matters,
796       F32 :: su_8_32;
797
798     (* Compare absolute greater-than or equal.  *)
799     Vcage, [Instruction_name ["vacge"]],
800       All (3, Dreg), "vcage", cmp_sign_matters, [F32];
801     Vcage, [Instruction_name ["vacge"]],
802       All (3, Qreg), "vcageQ", cmp_sign_matters, [F32];
803
804     (* Compare absolute less-than or equal.  *)
805     Vcale, [Instruction_name ["vacge"]; Flipped "vcage"],
806       All (3, Dreg), "vcale", cmp_sign_matters, [F32];
807     Vcale, [Instruction_name ["vacge"]; Flipped "vcageQ"],
808       All (3, Qreg), "vcaleQ", cmp_sign_matters, [F32];
809
810     (* Compare absolute greater-than or equal.  *)
811     Vcagt, [Instruction_name ["vacgt"]],
812       All (3, Dreg), "vcagt", cmp_sign_matters, [F32];
813     Vcagt, [Instruction_name ["vacgt"]],
814       All (3, Qreg), "vcagtQ", cmp_sign_matters, [F32];
815
816     (* Compare absolute less-than or equal.  *)
817     Vcalt, [Instruction_name ["vacgt"]; Flipped "vcagt"],
818       All (3, Dreg), "vcalt", cmp_sign_matters, [F32];
819     Vcalt, [Instruction_name ["vacgt"]; Flipped "vcagtQ"],
820       All (3, Qreg), "vcaltQ", cmp_sign_matters, [F32];
821
822     (* Test bits.  *)
823     Vtst, [], All (3, Dreg), "vtst", cmp_bits, P8 :: su_8_32;
824     Vtst, [], All (3, Qreg), "vtstQ", cmp_bits, P8 :: su_8_32;
825
826     (* Absolute difference.  *)
827     Vabd, [], All (3, Dreg), "vabd", elts_same_2, F32 :: su_8_32;
828     Vabd, [], All (3, Qreg), "vabdQ", elts_same_2, F32 :: su_8_32;
829     Vabd, [], Long, "vabdl", elts_same_2, su_8_32;
830
831     (* Absolute difference and accumulate.  *)
832     Vaba, [], All (3, Dreg), "vaba", elts_same_io, su_8_32;
833     Vaba, [], All (3, Qreg), "vabaQ", elts_same_io, su_8_32;
834     Vaba, [], Long, "vabal", elts_same_io, su_8_32;
835
836     (* Max.  *)
837     Vmax, [], All (3, Dreg), "vmax", elts_same_2, F32 :: su_8_32;
838     Vmax, [], All (3, Qreg), "vmaxQ", elts_same_2, F32 :: su_8_32;
839
840     (* Min.  *)
841     Vmin, [], All (3, Dreg), "vmin", elts_same_2, F32 :: su_8_32;
842     Vmin, [], All (3, Qreg), "vminQ", elts_same_2, F32 :: su_8_32;
843
844     (* Pairwise add.  *)
845     Vpadd, [], All (3, Dreg), "vpadd", sign_invar_2, F32 :: su_8_32;
846     Vpadd, [], Long_noreg Dreg, "vpaddl", elts_same_1, su_8_32;
847     Vpadd, [], Long_noreg Qreg, "vpaddlQ", elts_same_1, su_8_32;
848
849     (* Pairwise add, widen and accumulate.  *)
850     Vpada, [], Wide_noreg Dreg, "vpadal", elts_same_2, su_8_32;
851     Vpada, [], Wide_noreg Qreg, "vpadalQ", elts_same_2, su_8_32;
852
853     (* Folding maximum, minimum.  *)
854     Vpmax, [], All (3, Dreg), "vpmax", elts_same_2, F32 :: su_8_32;
855     Vpmin, [], All (3, Dreg), "vpmin", elts_same_2, F32 :: su_8_32;
856
857     (* Reciprocal step.  *)
858     Vrecps, [], All (3, Dreg), "vrecps", elts_same_2, [F32];
859     Vrecps, [], All (3, Qreg), "vrecpsQ", elts_same_2, [F32];
860     Vrsqrts, [], All (3, Dreg), "vrsqrts", elts_same_2, [F32];
861     Vrsqrts, [], All (3, Qreg), "vrsqrtsQ", elts_same_2, [F32];
862
863     (* Vector shift left.  *)
864     Vshl, [], All (3, Dreg), "vshl", reg_shift, su_8_64;
865     Vshl, [], All (3, Qreg), "vshlQ", reg_shift, su_8_64;
866     Vshl, [Instruction_name ["vrshl"]; Rounding],
867       All (3, Dreg), "vRshl", reg_shift, su_8_64;
868     Vshl, [Instruction_name ["vrshl"]; Rounding],
869       All (3, Qreg), "vRshlQ", reg_shift, su_8_64;
870     Vshl, [Saturating], All (3, Dreg), "vqshl", reg_shift, su_8_64;
871     Vshl, [Saturating], All (3, Qreg), "vqshlQ", reg_shift, su_8_64;
872     Vshl, [Instruction_name ["vqrshl"]; Saturating; Rounding],
873       All (3, Dreg), "vqRshl", reg_shift, su_8_64;
874     Vshl, [Instruction_name ["vqrshl"]; Saturating; Rounding],
875       All (3, Qreg), "vqRshlQ", reg_shift, su_8_64;
876
877     (* Vector shift right by constant.  *)
878     Vshr_n, [], Binary_imm Dreg, "vshr_n", shift_right, su_8_64;
879     Vshr_n, [], Binary_imm Qreg, "vshrQ_n", shift_right, su_8_64;
880     Vshr_n, [Instruction_name ["vrshr"]; Rounding], Binary_imm Dreg,
881       "vRshr_n", shift_right, su_8_64;
882     Vshr_n, [Instruction_name ["vrshr"]; Rounding], Binary_imm Qreg,
883       "vRshrQ_n", shift_right, su_8_64;
884     Vshr_n, [], Narrow_imm, "vshrn_n", shift_right_sign_invar, su_16_64;
885     Vshr_n, [Instruction_name ["vrshrn"]; Rounding], Narrow_imm, "vRshrn_n",
886       shift_right_sign_invar, su_16_64;
887     Vshr_n, [Saturating], Narrow_imm, "vqshrn_n", shift_right, su_16_64;
888     Vshr_n, [Instruction_name ["vqrshrn"]; Saturating; Rounding], Narrow_imm,
889       "vqRshrn_n", shift_right, su_16_64;
890     Vshr_n, [Saturating; Dst_unsign], Narrow_imm, "vqshrun_n",
891       shift_right_to_uns, [S16; S32; S64];
892     Vshr_n, [Instruction_name ["vqrshrun"]; Saturating; Dst_unsign; Rounding],
893       Narrow_imm, "vqRshrun_n", shift_right_to_uns, [S16; S32; S64];
894
895     (* Vector shift left by constant.  *)
896     Vshl_n, [], Binary_imm Dreg, "vshl_n", shift_left_sign_invar, su_8_64;
897     Vshl_n, [], Binary_imm Qreg, "vshlQ_n", shift_left_sign_invar, su_8_64;
898     Vshl_n, [Saturating], Binary_imm Dreg, "vqshl_n", shift_left, su_8_64;
899     Vshl_n, [Saturating], Binary_imm Qreg, "vqshlQ_n", shift_left, su_8_64;
900     Vshl_n, [Saturating; Dst_unsign], Binary_imm Dreg, "vqshlu_n",
901       shift_left_to_uns, [S8; S16; S32; S64];
902     Vshl_n, [Saturating; Dst_unsign], Binary_imm Qreg, "vqshluQ_n",
903       shift_left_to_uns, [S8; S16; S32; S64];
904     Vshl_n, [], Long_imm, "vshll_n", shift_left, su_8_32;
905
906     (* Vector shift right by constant and accumulate.  *)
907     Vsra_n, [], Binary_imm Dreg, "vsra_n", shift_right_acc, su_8_64;
908     Vsra_n, [], Binary_imm Qreg, "vsraQ_n", shift_right_acc, su_8_64;
909     Vsra_n, [Instruction_name ["vrsra"]; Rounding], Binary_imm Dreg,
910       "vRsra_n", shift_right_acc, su_8_64;
911     Vsra_n, [Instruction_name ["vrsra"]; Rounding], Binary_imm Qreg,
912       "vRsraQ_n", shift_right_acc, su_8_64;
913
914     (* Vector shift right and insert.  *)
915     Vsri, [], Use_operands [| Dreg; Dreg; Immed |], "vsri_n", shift_insert,
916       P8 :: P16 :: su_8_64;
917     Vsri, [], Use_operands [| Qreg; Qreg; Immed |], "vsriQ_n", shift_insert,
918       P8 :: P16 :: su_8_64;
919
920     (* Vector shift left and insert.  *)
921     Vsli, [], Use_operands [| Dreg; Dreg; Immed |], "vsli_n", shift_insert,
922       P8 :: P16 :: su_8_64;
923     Vsli, [], Use_operands [| Qreg; Qreg; Immed |], "vsliQ_n", shift_insert,
924       P8 :: P16 :: su_8_64;
925
926     (* Absolute value.  *)
927     Vabs, [], All (2, Dreg), "vabs", elts_same_1, [S8; S16; S32; F32];
928     Vabs, [], All (2, Qreg), "vabsQ", elts_same_1, [S8; S16; S32; F32];
929     Vabs, [Saturating], All (2, Dreg), "vqabs", elts_same_1, [S8; S16; S32];
930     Vabs, [Saturating], All (2, Qreg), "vqabsQ", elts_same_1, [S8; S16; S32];
931
932     (* Negate.  *)
933     Vneg, [], All (2, Dreg), "vneg", elts_same_1, [S8; S16; S32; F32];
934     Vneg, [], All (2, Qreg), "vnegQ", elts_same_1, [S8; S16; S32; F32];
935     Vneg, [Saturating], All (2, Dreg), "vqneg", elts_same_1, [S8; S16; S32];
936     Vneg, [Saturating], All (2, Qreg), "vqnegQ", elts_same_1, [S8; S16; S32];
937
938     (* Bitwise not.  *)
939     Vmvn, [], All (2, Dreg), "vmvn", notype_1, P8 :: su_8_32;
940     Vmvn, [], All (2, Qreg), "vmvnQ", notype_1, P8 :: su_8_32;
941
942     (* Count leading sign bits.  *)
943     Vcls, [], All (2, Dreg), "vcls", elts_same_1, [S8; S16; S32];
944     Vcls, [], All (2, Qreg), "vclsQ", elts_same_1, [S8; S16; S32];
945
946     (* Count leading zeros.  *)
947     Vclz, [], All (2, Dreg), "vclz", sign_invar_1, su_8_32;
948     Vclz, [], All (2, Qreg), "vclzQ", sign_invar_1, su_8_32;
949
950     (* Count number of set bits.  *)
951     Vcnt, [], All (2, Dreg), "vcnt", bits_1, [P8; S8; U8];
952     Vcnt, [], All (2, Qreg), "vcntQ", bits_1, [P8; S8; U8];
953
954     (* Reciprocal estimate.  *)
955     Vrecpe, [], All (2, Dreg), "vrecpe", elts_same_1, [U32; F32];
956     Vrecpe, [], All (2, Qreg), "vrecpeQ", elts_same_1, [U32; F32];
957
958     (* Reciprocal square-root estimate.  *)
959     Vrsqrte, [], All (2, Dreg), "vrsqrte", elts_same_1, [U32; F32];
960     Vrsqrte, [], All (2, Qreg), "vrsqrteQ", elts_same_1, [U32; F32];
961
962     (* Get lanes from a vector.  *)
963     Vget_lane,
964       [InfoWord; Disassembles_as [Use_operands [| Corereg; Element_of_dreg |]];
965        Instruction_name ["vmov"]],
966       Use_operands [| Corereg; Dreg; Immed |],
967       "vget_lane", get_lane, pf_su_8_32;
968     Vget_lane,
969       [InfoWord;
970        Disassembles_as [Use_operands [| Corereg; Corereg; Dreg |]];
971        Instruction_name ["vmov"]; Const_valuator (fun _ -> 0)],
972       Use_operands [| Corereg; Dreg; Immed |],
973       "vget_lane", notype_2, [S64; U64];
974     Vget_lane,
975       [InfoWord; Disassembles_as [Use_operands [| Corereg; Element_of_dreg |]];
976        Instruction_name ["vmov"]],
977       Use_operands [| Corereg; Qreg; Immed |],
978       "vgetQ_lane", get_lane, pf_su_8_32;
979     Vget_lane,
980       [InfoWord;
981        Disassembles_as [Use_operands [| Corereg; Corereg; Dreg |]];
982        Instruction_name ["vmov"]; Const_valuator (fun _ -> 0)],
983       Use_operands [| Corereg; Qreg; Immed |],
984       "vgetQ_lane", notype_2, [S64; U64];
985
986     (* Set lanes in a vector.  *)
987     Vset_lane, [Disassembles_as [Use_operands [| Element_of_dreg; Corereg |]];
988                 Instruction_name ["vmov"]],
989       Use_operands [| Dreg; Corereg; Dreg; Immed |], "vset_lane",
990       set_lane, pf_su_8_32;
991     Vset_lane, [Disassembles_as [Use_operands [| Dreg; Corereg; Corereg |]];
992                 Instruction_name ["vmov"]; Const_valuator (fun _ -> 0)],
993       Use_operands [| Dreg; Corereg; Dreg; Immed |], "vset_lane",
994       set_lane_notype, [S64; U64];
995     Vset_lane, [Disassembles_as [Use_operands [| Element_of_dreg; Corereg |]];
996                 Instruction_name ["vmov"]],
997       Use_operands [| Qreg; Corereg; Qreg; Immed |], "vsetQ_lane",
998       set_lane, pf_su_8_32;
999     Vset_lane, [Disassembles_as [Use_operands [| Dreg; Corereg; Corereg |]];
1000                 Instruction_name ["vmov"]; Const_valuator (fun _ -> 0)],
1001       Use_operands [| Qreg; Corereg; Qreg; Immed |], "vsetQ_lane",
1002       set_lane_notype, [S64; U64];
1003
1004     (* Create vector from literal bit pattern.  *)
1005     Vcreate,
1006       [No_op], (* Not really, but it can yield various things that are too
1007                   hard for the test generator at this time.  *)
1008       Use_operands [| Dreg; Corereg |], "vcreate", create_vector,
1009       pf_su_8_64;
1010
1011     (* Set all lanes to the same value.  *)
1012     Vdup_n, [],
1013       Use_operands [| Dreg; Corereg |], "vdup_n", bits_1,
1014       pf_su_8_32;
1015     Vdup_n,
1016       [Instruction_name ["vmov"];
1017        Disassembles_as [Use_operands [| Dreg; Corereg; Corereg |]]],
1018       Use_operands [| Dreg; Corereg |], "vdup_n", notype_1,
1019       [S64; U64];
1020     Vdup_n, [],
1021       Use_operands [| Qreg; Corereg |], "vdupQ_n", bits_1,
1022       pf_su_8_32;
1023     Vdup_n,
1024       [Instruction_name ["vmov"];
1025        Disassembles_as [Use_operands [| Dreg; Corereg; Corereg |];
1026                         Use_operands [| Dreg; Corereg; Corereg |]]],
1027       Use_operands [| Qreg; Corereg |], "vdupQ_n", notype_1,
1028       [S64; U64];
1029
1030     (* These are just aliases for the above.  *)
1031     Vmov_n,
1032       [Builtin_name "vdup_n"],
1033       Use_operands [| Dreg; Corereg |],
1034       "vmov_n", bits_1, pf_su_8_32;
1035     Vmov_n,
1036       [Builtin_name "vdup_n";
1037        Instruction_name ["vmov"];
1038        Disassembles_as [Use_operands [| Dreg; Corereg; Corereg |]]],
1039       Use_operands [| Dreg; Corereg |],
1040       "vmov_n", notype_1, [S64; U64];
1041     Vmov_n,
1042       [Builtin_name "vdupQ_n"],
1043       Use_operands [| Qreg; Corereg |],
1044       "vmovQ_n", bits_1, pf_su_8_32;
1045     Vmov_n,
1046       [Builtin_name "vdupQ_n";
1047        Instruction_name ["vmov"];
1048        Disassembles_as [Use_operands [| Dreg; Corereg; Corereg |];
1049                         Use_operands [| Dreg; Corereg; Corereg |]]],
1050       Use_operands [| Qreg; Corereg |],
1051       "vmovQ_n", notype_1, [S64; U64];
1052
1053     (* Duplicate, lane version.  We can't use Use_operands here because the
1054        rightmost register (always Dreg) would be picked up by find_key_operand,
1055        when we want the leftmost register to be used in this case (otherwise
1056        the modes are indistinguishable in neon.md, etc.  *)
1057     Vdup_lane,
1058       [Disassembles_as [Use_operands [| Dreg; Element_of_dreg |]]],
1059       Unary_scalar Dreg, "vdup_lane", bits_2, pf_su_8_32;
1060     Vdup_lane,
1061       [No_op; Const_valuator (fun _ -> 0)],
1062       Unary_scalar Dreg, "vdup_lane", bits_2, [S64; U64];
1063     Vdup_lane,
1064       [Disassembles_as [Use_operands [| Qreg; Element_of_dreg |]]],
1065       Unary_scalar Qreg, "vdupQ_lane", bits_2, pf_su_8_32;
1066     Vdup_lane,
1067       [No_op; Const_valuator (fun _ -> 0)],
1068       Unary_scalar Qreg, "vdupQ_lane", bits_2, [S64; U64];
1069
1070     (* Combining vectors.  *)
1071     Vcombine, [No_op],
1072       Use_operands [| Qreg; Dreg; Dreg |], "vcombine", notype_2,
1073       pf_su_8_64;
1074
1075     (* Splitting vectors.  *)
1076     Vget_high, [No_op],
1077       Use_operands [| Dreg; Qreg |], "vget_high",
1078       notype_1, pf_su_8_64;
1079     Vget_low, [Instruction_name ["vmov"];
1080                Disassembles_as [Use_operands [| Dreg; Dreg |]]],
1081       Use_operands [| Dreg; Qreg |], "vget_low",
1082       notype_1, pf_su_8_64;
1083
1084     (* Conversions.  *)
1085     Vcvt, [InfoWord], All (2, Dreg), "vcvt", conv_1,
1086       [Conv (S32, F32); Conv (U32, F32); Conv (F32, S32); Conv (F32, U32)];
1087     Vcvt, [InfoWord], All (2, Qreg), "vcvtQ", conv_1,
1088       [Conv (S32, F32); Conv (U32, F32); Conv (F32, S32); Conv (F32, U32)];
1089     Vcvt_n, [InfoWord], Use_operands [| Dreg; Dreg; Immed |], "vcvt_n", conv_2,
1090       [Conv (S32, F32); Conv (U32, F32); Conv (F32, S32); Conv (F32, U32)];
1091     Vcvt_n, [InfoWord], Use_operands [| Qreg; Qreg; Immed |], "vcvtQ_n", conv_2,
1092       [Conv (S32, F32); Conv (U32, F32); Conv (F32, S32); Conv (F32, U32)];
1093
1094     (* Move, narrowing.  *)
1095     Vmovn, [Disassembles_as [Use_operands [| Dreg; Qreg |]]],
1096       Narrow, "vmovn", sign_invar_1, su_16_64;
1097     Vmovn, [Disassembles_as [Use_operands [| Dreg; Qreg |]]; Saturating],
1098       Narrow, "vqmovn", elts_same_1, su_16_64;
1099     Vmovn,
1100       [Disassembles_as [Use_operands [| Dreg; Qreg |]]; Saturating; Dst_unsign],
1101       Narrow, "vqmovun", dst_unsign_1,
1102       [S16; S32; S64];
1103
1104     (* Move, long.  *)
1105     Vmovl, [Disassembles_as [Use_operands [| Qreg; Dreg |]]],
1106       Long, "vmovl", elts_same_1, su_8_32;
1107
1108     (* Table lookup.  *)
1109     Vtbl 1,
1110       [Instruction_name ["vtbl"];
1111        Disassembles_as [Use_operands [| Dreg; VecArray (1, Dreg); Dreg |]]],
1112       Use_operands [| Dreg; Dreg; Dreg |], "vtbl1", table_2, [U8; S8; P8];
1113     Vtbl 2, [Instruction_name ["vtbl"]],
1114       Use_operands [| Dreg; VecArray (2, Dreg); Dreg |], "vtbl2", table_2,
1115       [U8; S8; P8];
1116     Vtbl 3, [Instruction_name ["vtbl"]],
1117       Use_operands [| Dreg; VecArray (3, Dreg); Dreg |], "vtbl3", table_2,
1118       [U8; S8; P8];
1119     Vtbl 4, [Instruction_name ["vtbl"]],
1120       Use_operands [| Dreg; VecArray (4, Dreg); Dreg |], "vtbl4", table_2,
1121       [U8; S8; P8];
1122
1123     (* Extended table lookup.  *)
1124     Vtbx 1,
1125       [Instruction_name ["vtbx"];
1126        Disassembles_as [Use_operands [| Dreg; VecArray (1, Dreg); Dreg |]]],
1127       Use_operands [| Dreg; Dreg; Dreg |], "vtbx1", table_io, [U8; S8; P8];
1128     Vtbx 2, [Instruction_name ["vtbx"]],
1129       Use_operands [| Dreg; VecArray (2, Dreg); Dreg |], "vtbx2", table_io,
1130       [U8; S8; P8];
1131     Vtbx 3, [Instruction_name ["vtbx"]],
1132       Use_operands [| Dreg; VecArray (3, Dreg); Dreg |], "vtbx3", table_io,
1133       [U8; S8; P8];
1134     Vtbx 4, [Instruction_name ["vtbx"]],
1135       Use_operands [| Dreg; VecArray (4, Dreg); Dreg |], "vtbx4", table_io,
1136       [U8; S8; P8];
1137
1138     (* Multiply, lane.  (note: these were undocumented at the time of
1139        writing).  *)
1140     Vmul_lane, [], By_scalar Dreg, "vmul_lane", sign_invar_2_lane,
1141       [S16; S32; U16; U32; F32];
1142     Vmul_lane, [], By_scalar Qreg, "vmulQ_lane", sign_invar_2_lane,
1143       [S16; S32; U16; U32; F32];
1144
1145     (* Multiply-accumulate, lane.  *)
1146     Vmla_lane, [], By_scalar Dreg, "vmla_lane", sign_invar_io_lane,
1147       [S16; S32; U16; U32; F32];
1148     Vmla_lane, [], By_scalar Qreg, "vmlaQ_lane", sign_invar_io_lane,
1149       [S16; S32; U16; U32; F32];
1150     Vmla_lane, [], Wide_lane, "vmlal_lane", elts_same_io_lane,
1151       [S16; S32; U16; U32];
1152     Vmla_lane, [Saturating; Doubling], Wide_lane, "vqdmlal_lane",
1153       elts_same_io_lane, [S16; S32];
1154
1155     (* Multiply-subtract, lane.  *)
1156     Vmls_lane, [], By_scalar Dreg, "vmls_lane", sign_invar_io_lane,
1157       [S16; S32; U16; U32; F32];
1158     Vmls_lane, [], By_scalar Qreg, "vmlsQ_lane", sign_invar_io_lane,
1159       [S16; S32; U16; U32; F32];
1160     Vmls_lane, [], Wide_lane, "vmlsl_lane", elts_same_io_lane,
1161       [S16; S32; U16; U32];
1162     Vmls_lane, [Saturating; Doubling], Wide_lane, "vqdmlsl_lane",
1163       elts_same_io_lane, [S16; S32];
1164
1165     (* Long multiply, lane.  *)
1166     Vmull_lane, [],
1167       Wide_lane, "vmull_lane", elts_same_2_lane, [S16; S32; U16; U32];
1168
1169     (* Saturating doubling long multiply, lane.  *)
1170     Vqdmull_lane, [Saturating; Doubling],
1171       Wide_lane, "vqdmull_lane", elts_same_2_lane, [S16; S32];
1172
1173     (* Saturating doubling long multiply high, lane.  *)
1174     Vqdmulh_lane, [Saturating; Halving],
1175       By_scalar Qreg, "vqdmulhQ_lane", elts_same_2_lane, [S16; S32];
1176     Vqdmulh_lane, [Saturating; Halving],
1177       By_scalar Dreg, "vqdmulh_lane", elts_same_2_lane, [S16; S32];
1178     Vqdmulh_lane, [Saturating; Halving; Rounding;
1179                    Instruction_name ["vqrdmulh"]],
1180       By_scalar Qreg, "vqRdmulhQ_lane", elts_same_2_lane, [S16; S32];
1181     Vqdmulh_lane, [Saturating; Halving; Rounding;
1182                    Instruction_name ["vqrdmulh"]],
1183       By_scalar Dreg, "vqRdmulh_lane", elts_same_2_lane, [S16; S32];
1184
1185     (* Vector multiply by scalar.  *)
1186     Vmul_n, [InfoWord;
1187              Disassembles_as [Use_operands [| Dreg; Dreg; Element_of_dreg |]]],
1188              Use_operands [| Dreg; Dreg; Corereg |], "vmul_n",
1189       sign_invar_2, [S16; S32; U16; U32; F32];
1190     Vmul_n, [InfoWord;
1191              Disassembles_as [Use_operands [| Qreg; Qreg; Element_of_dreg |]]],
1192              Use_operands [| Qreg; Qreg; Corereg |], "vmulQ_n",
1193       sign_invar_2, [S16; S32; U16; U32; F32];
1194
1195     (* Vector long multiply by scalar.  *)
1196     Vmull_n, [Instruction_name ["vmull"];
1197               Disassembles_as [Use_operands [| Qreg; Dreg; Element_of_dreg |]]],
1198               Wide_scalar, "vmull_n",
1199       elts_same_2, [S16; S32; U16; U32];
1200
1201     (* Vector saturating doubling long multiply by scalar.  *)
1202     Vqdmull_n, [Saturating; Doubling;
1203                 Disassembles_as [Use_operands [| Qreg; Dreg;
1204                                                  Element_of_dreg |]]],
1205                 Wide_scalar, "vqdmull_n",
1206       elts_same_2, [S16; S32];
1207
1208     (* Vector saturating doubling long multiply high by scalar.  *)
1209     Vqdmulh_n,
1210       [Saturating; Halving; InfoWord;
1211        Disassembles_as [Use_operands [| Qreg; Qreg; Element_of_dreg |]]],
1212       Use_operands [| Qreg; Qreg; Corereg |],
1213       "vqdmulhQ_n", elts_same_2, [S16; S32];
1214     Vqdmulh_n,
1215       [Saturating; Halving; InfoWord;
1216        Disassembles_as [Use_operands [| Dreg; Dreg; Element_of_dreg |]]],
1217       Use_operands [| Dreg; Dreg; Corereg |],
1218       "vqdmulh_n", elts_same_2, [S16; S32];
1219     Vqdmulh_n,
1220       [Saturating; Halving; Rounding; InfoWord;
1221        Instruction_name ["vqrdmulh"];
1222        Disassembles_as [Use_operands [| Qreg; Qreg; Element_of_dreg |]]],
1223       Use_operands [| Qreg; Qreg; Corereg |],
1224       "vqRdmulhQ_n", elts_same_2, [S16; S32];
1225     Vqdmulh_n,
1226       [Saturating; Halving; Rounding; InfoWord;
1227        Instruction_name ["vqrdmulh"];
1228        Disassembles_as [Use_operands [| Dreg; Dreg; Element_of_dreg |]]],
1229       Use_operands [| Dreg; Dreg; Corereg |],
1230       "vqRdmulh_n", elts_same_2, [S16; S32];
1231
1232     (* Vector multiply-accumulate by scalar.  *)
1233     Vmla_n, [InfoWord;
1234              Disassembles_as [Use_operands [| Dreg; Dreg; Element_of_dreg |]]],
1235       Use_operands [| Dreg; Dreg; Corereg |], "vmla_n",
1236       sign_invar_io, [S16; S32; U16; U32; F32];
1237     Vmla_n, [InfoWord;
1238              Disassembles_as [Use_operands [| Qreg; Qreg; Element_of_dreg |]]],
1239       Use_operands [| Qreg; Qreg; Corereg |], "vmlaQ_n",
1240       sign_invar_io, [S16; S32; U16; U32; F32];
1241     Vmla_n, [], Wide_scalar, "vmlal_n", elts_same_io, [S16; S32; U16; U32];
1242     Vmla_n, [Saturating; Doubling], Wide_scalar, "vqdmlal_n", elts_same_io,
1243       [S16; S32];
1244
1245     (* Vector multiply subtract by scalar.  *)
1246     Vmls_n, [InfoWord;
1247              Disassembles_as [Use_operands [| Dreg; Dreg; Element_of_dreg |]]],
1248       Use_operands [| Dreg; Dreg; Corereg |], "vmls_n",
1249       sign_invar_io, [S16; S32; U16; U32; F32];
1250     Vmls_n, [InfoWord;
1251              Disassembles_as [Use_operands [| Qreg; Qreg; Element_of_dreg |]]],
1252       Use_operands [| Qreg; Qreg; Corereg |], "vmlsQ_n",
1253       sign_invar_io, [S16; S32; U16; U32; F32];
1254     Vmls_n, [], Wide_scalar, "vmlsl_n", elts_same_io, [S16; S32; U16; U32];
1255     Vmls_n, [Saturating; Doubling], Wide_scalar, "vqdmlsl_n", elts_same_io,
1256       [S16; S32];
1257
1258     (* Vector extract.  *)
1259     Vext, [Const_valuator (fun _ -> 0)],
1260       Use_operands [| Dreg; Dreg; Dreg; Immed |], "vext", extend,
1261       pf_su_8_64;
1262     Vext, [Const_valuator (fun _ -> 0)],
1263       Use_operands [| Qreg; Qreg; Qreg; Immed |], "vextQ", extend,
1264       pf_su_8_64;
1265
1266     (* Reverse elements.  *)
1267     Vrev64, [], All (2, Dreg), "vrev64", bits_1, P8 :: P16 :: F32 :: su_8_32;
1268     Vrev64, [], All (2, Qreg), "vrev64Q", bits_1, P8 :: P16 :: F32 :: su_8_32;
1269     Vrev32, [], All (2, Dreg), "vrev32", bits_1, [P8; P16; S8; U8; S16; U16];
1270     Vrev32, [], All (2, Qreg), "vrev32Q", bits_1, [P8; P16; S8; U8; S16; U16];
1271     Vrev16, [], All (2, Dreg), "vrev16", bits_1, [P8; S8; U8];
1272     Vrev16, [], All (2, Qreg), "vrev16Q", bits_1, [P8; S8; U8];
1273
1274     (* Bit selection.  *)
1275     Vbsl,
1276       [Instruction_name ["vbsl"; "vbit"; "vbif"];
1277        Disassembles_as [Use_operands [| Dreg; Dreg; Dreg |]]],
1278       Use_operands [| Dreg; Dreg; Dreg; Dreg |], "vbsl", bit_select,
1279       pf_su_8_64;
1280     Vbsl,
1281       [Instruction_name ["vbsl"; "vbit"; "vbif"];
1282        Disassembles_as [Use_operands [| Qreg; Qreg; Qreg |]]],
1283       Use_operands [| Qreg; Qreg; Qreg; Qreg |], "vbslQ", bit_select,
1284       pf_su_8_64;
1285
1286     (* Transpose elements.  **NOTE** ReturnPtr goes some of the way towards
1287        generating good code for intrinsics which return structure types --
1288        builtins work well by themselves (and understand that the values being
1289        stored on e.g. the stack also reside in registers, so can optimise the
1290        stores away entirely if the results are used immediately), but
1291        intrinsics are very much less efficient. Maybe something can be improved
1292        re: inlining, or tweaking the ABI used for intrinsics (a special call
1293        attribute?).
1294     *)
1295     Vtrn, [ReturnPtr], Pair_result Dreg, "vtrn", bits_2, pf_su_8_32;
1296     Vtrn, [ReturnPtr], Pair_result Qreg, "vtrnQ", bits_2, pf_su_8_32;
1297
1298     (* Zip elements.  *)
1299     Vzip, [ReturnPtr], Pair_result Dreg, "vzip", bits_2, pf_su_8_32;
1300     Vzip, [ReturnPtr], Pair_result Qreg, "vzipQ", bits_2, pf_su_8_32;
1301
1302     (* Unzip elements.  *)
1303     Vuzp, [ReturnPtr], Pair_result Dreg, "vuzp", bits_2, pf_su_8_32;
1304     Vuzp, [ReturnPtr], Pair_result Qreg, "vuzpQ", bits_2, pf_su_8_32;
1305
1306     (* Element/structure loads.  VLD1 variants.  *)
1307     Vldx 1,
1308       [Disassembles_as [Use_operands [| VecArray (1, Dreg);
1309                                         CstPtrTo Corereg |]]],
1310       Use_operands [| Dreg; CstPtrTo Corereg |], "vld1", bits_1,
1311       pf_su_8_64;
1312     Vldx 1, [Disassembles_as [Use_operands [| VecArray (2, Dreg);
1313                                               CstPtrTo Corereg |]]],
1314       Use_operands [| Qreg; CstPtrTo Corereg |], "vld1Q", bits_1,
1315       pf_su_8_64;
1316
1317     Vldx_lane 1,
1318       [Disassembles_as [Use_operands [| VecArray (1, Element_of_dreg);
1319                                         CstPtrTo Corereg |]]],
1320       Use_operands [| Dreg; CstPtrTo Corereg; Dreg; Immed |],
1321       "vld1_lane", bits_3, pf_su_8_32;
1322     Vldx_lane 1,
1323       [Disassembles_as [Use_operands [| VecArray (1, Dreg);
1324                                         CstPtrTo Corereg |]];
1325        Const_valuator (fun _ -> 0)],
1326       Use_operands [| Dreg; CstPtrTo Corereg; Dreg; Immed |],
1327       "vld1_lane", bits_3, [S64; U64];
1328     Vldx_lane 1,
1329       [Disassembles_as [Use_operands [| VecArray (1, Element_of_dreg);
1330                                         CstPtrTo Corereg |]]],
1331       Use_operands [| Qreg; CstPtrTo Corereg; Qreg; Immed |],
1332       "vld1Q_lane", bits_3, pf_su_8_32;
1333     Vldx_lane 1,
1334       [Disassembles_as [Use_operands [| VecArray (1, Dreg);
1335                                         CstPtrTo Corereg |]]],
1336       Use_operands [| Qreg; CstPtrTo Corereg; Qreg; Immed |],
1337       "vld1Q_lane", bits_3, [S64; U64];
1338
1339     Vldx_dup 1,
1340       [Disassembles_as [Use_operands [| VecArray (1, All_elements_of_dreg);
1341                                         CstPtrTo Corereg |]]],
1342       Use_operands [| Dreg; CstPtrTo Corereg |], "vld1_dup",
1343       bits_1, pf_su_8_32;
1344     Vldx_dup 1,
1345       [Disassembles_as [Use_operands [| VecArray (1, Dreg);
1346                                         CstPtrTo Corereg |]]],
1347       Use_operands [| Dreg; CstPtrTo Corereg |], "vld1_dup",
1348       bits_1, [S64; U64];
1349     Vldx_dup 1,
1350       [Disassembles_as [Use_operands [| VecArray (2, All_elements_of_dreg);
1351                                         CstPtrTo Corereg |]]],
1352       Use_operands [| Qreg; CstPtrTo Corereg |], "vld1Q_dup",
1353       bits_1, pf_su_8_32;
1354     Vldx_dup 1,
1355       [Disassembles_as [Use_operands [| VecArray (2, Dreg);
1356                                         CstPtrTo Corereg |]]],
1357       Use_operands [| Qreg; CstPtrTo Corereg |], "vld1Q_dup",
1358       bits_1, [S64; U64];
1359
1360     (* VST1 variants.  *)
1361     Vstx 1, [Disassembles_as [Use_operands [| VecArray (1, Dreg);
1362                                               PtrTo Corereg |]]],
1363       Use_operands [| PtrTo Corereg; Dreg |], "vst1",
1364       store_1, pf_su_8_64;
1365     Vstx 1, [Disassembles_as [Use_operands [| VecArray (2, Dreg);
1366                                               PtrTo Corereg |]]],
1367       Use_operands [| PtrTo Corereg; Qreg |], "vst1Q",
1368       store_1, pf_su_8_64;
1369
1370     Vstx_lane 1,
1371       [Disassembles_as [Use_operands [| VecArray (1, Element_of_dreg);
1372                                         CstPtrTo Corereg |]]],
1373       Use_operands [| PtrTo Corereg; Dreg; Immed |],
1374       "vst1_lane", store_3, pf_su_8_32;
1375     Vstx_lane 1,
1376       [Disassembles_as [Use_operands [| VecArray (1, Dreg);
1377                                         CstPtrTo Corereg |]];
1378        Const_valuator (fun _ -> 0)],
1379       Use_operands [| PtrTo Corereg; Dreg; Immed |],
1380       "vst1_lane", store_3, [U64; S64];
1381     Vstx_lane 1,
1382       [Disassembles_as [Use_operands [| VecArray (1, Element_of_dreg);
1383                                         CstPtrTo Corereg |]]],
1384       Use_operands [| PtrTo Corereg; Qreg; Immed |],
1385       "vst1Q_lane", store_3, pf_su_8_32;
1386     Vstx_lane 1,
1387       [Disassembles_as [Use_operands [| VecArray (1, Dreg);
1388                                         CstPtrTo Corereg |]]],
1389       Use_operands [| PtrTo Corereg; Qreg; Immed |],
1390       "vst1Q_lane", store_3, [U64; S64];
1391
1392     (* VLD2 variants.  *)
1393     Vldx 2, [], Use_operands [| VecArray (2, Dreg); CstPtrTo Corereg |],
1394       "vld2", bits_1, pf_su_8_32;
1395     Vldx 2, [Instruction_name ["vld1"]],
1396        Use_operands [| VecArray (2, Dreg); CstPtrTo Corereg |],
1397       "vld2", bits_1, [S64; U64];
1398     Vldx 2, [Disassembles_as [Use_operands [| VecArray (2, Dreg);
1399                                               CstPtrTo Corereg |];
1400                               Use_operands [| VecArray (2, Dreg);
1401                                               CstPtrTo Corereg |]]],
1402       Use_operands [| VecArray (2, Qreg); CstPtrTo Corereg |],
1403       "vld2Q", bits_1, pf_su_8_32;
1404
1405     Vldx_lane 2,
1406       [Disassembles_as [Use_operands
1407         [| VecArray (2, Element_of_dreg);
1408            CstPtrTo Corereg |]]],
1409       Use_operands [| VecArray (2, Dreg); CstPtrTo Corereg;
1410                       VecArray (2, Dreg); Immed |],
1411       "vld2_lane", bits_3, P8 :: P16 :: F32 :: su_8_32;
1412     Vldx_lane 2,
1413       [Disassembles_as [Use_operands
1414         [| VecArray (2, Element_of_dreg);
1415            CstPtrTo Corereg |]]],
1416       Use_operands [| VecArray (2, Qreg); CstPtrTo Corereg;
1417                       VecArray (2, Qreg); Immed |],
1418       "vld2Q_lane", bits_3, [P16; F32; U16; U32; S16; S32];
1419
1420     Vldx_dup 2,
1421       [Disassembles_as [Use_operands
1422         [| VecArray (2, All_elements_of_dreg); CstPtrTo Corereg |]]],
1423       Use_operands [| VecArray (2, Dreg); CstPtrTo Corereg |],
1424       "vld2_dup", bits_1, pf_su_8_32;
1425     Vldx_dup 2,
1426       [Instruction_name ["vld1"]; Disassembles_as [Use_operands
1427         [| VecArray (2, Dreg); CstPtrTo Corereg |]]],
1428       Use_operands [| VecArray (2, Dreg); CstPtrTo Corereg |],
1429       "vld2_dup", bits_1, [S64; U64];
1430
1431     (* VST2 variants.  *)
1432     Vstx 2, [Disassembles_as [Use_operands [| VecArray (2, Dreg);
1433                                               PtrTo Corereg |]]],
1434       Use_operands [| PtrTo Corereg; VecArray (2, Dreg) |], "vst2",
1435       store_1, pf_su_8_32;
1436     Vstx 2, [Disassembles_as [Use_operands [| VecArray (2, Dreg);
1437                                               PtrTo Corereg |]];
1438              Instruction_name ["vst1"]],
1439       Use_operands [| PtrTo Corereg; VecArray (2, Dreg) |], "vst2",
1440       store_1, [S64; U64];
1441     Vstx 2, [Disassembles_as [Use_operands [| VecArray (2, Dreg);
1442                                               PtrTo Corereg |];
1443                               Use_operands [| VecArray (2, Dreg);
1444                                               PtrTo Corereg |]]],
1445       Use_operands [| PtrTo Corereg; VecArray (2, Qreg) |], "vst2Q",
1446       store_1, pf_su_8_32;
1447
1448     Vstx_lane 2,
1449       [Disassembles_as [Use_operands
1450         [| VecArray (2, Element_of_dreg);
1451            CstPtrTo Corereg |]]],
1452       Use_operands [| PtrTo Corereg; VecArray (2, Dreg); Immed |], "vst2_lane",
1453       store_3, P8 :: P16 :: F32 :: su_8_32;
1454     Vstx_lane 2,
1455       [Disassembles_as [Use_operands
1456         [| VecArray (2, Element_of_dreg);
1457            CstPtrTo Corereg |]]],
1458       Use_operands [| PtrTo Corereg; VecArray (2, Qreg); Immed |], "vst2Q_lane",
1459       store_3, [P16; F32; U16; U32; S16; S32];
1460
1461     (* VLD3 variants.  *)
1462     Vldx 3, [], Use_operands [| VecArray (3, Dreg); CstPtrTo Corereg |],
1463       "vld3", bits_1, pf_su_8_32;
1464     Vldx 3, [Instruction_name ["vld1"]],
1465       Use_operands [| VecArray (3, Dreg); CstPtrTo Corereg |],
1466       "vld3", bits_1, [S64; U64];
1467     Vldx 3, [Disassembles_as [Use_operands [| VecArray (3, Dreg);
1468                                               CstPtrTo Corereg |];
1469                               Use_operands [| VecArray (3, Dreg);
1470                                               CstPtrTo Corereg |]]],
1471       Use_operands [| VecArray (3, Qreg); CstPtrTo Corereg |],
1472       "vld3Q", bits_1, P8 :: P16 :: F32 :: su_8_32;
1473
1474     Vldx_lane 3,
1475       [Disassembles_as [Use_operands
1476         [| VecArray (3, Element_of_dreg);
1477            CstPtrTo Corereg |]]],
1478       Use_operands [| VecArray (3, Dreg); CstPtrTo Corereg;
1479                                      VecArray (3, Dreg); Immed |],
1480       "vld3_lane", bits_3, P8 :: P16 :: F32 :: su_8_32;
1481     Vldx_lane 3,
1482       [Disassembles_as [Use_operands
1483         [| VecArray (3, Element_of_dreg);
1484            CstPtrTo Corereg |]]],
1485       Use_operands [| VecArray (3, Qreg); CstPtrTo Corereg;
1486                                      VecArray (3, Qreg); Immed |],
1487       "vld3Q_lane", bits_3, [P16; F32; U16; U32; S16; S32];
1488
1489     Vldx_dup 3,
1490       [Disassembles_as [Use_operands
1491         [| VecArray (3, All_elements_of_dreg); CstPtrTo Corereg |]]],
1492       Use_operands [| VecArray (3, Dreg); CstPtrTo Corereg |],
1493       "vld3_dup", bits_1, pf_su_8_32;
1494     Vldx_dup 3,
1495       [Instruction_name ["vld1"]; Disassembles_as [Use_operands
1496         [| VecArray (3, Dreg); CstPtrTo Corereg |]]],
1497       Use_operands [| VecArray (3, Dreg); CstPtrTo Corereg |],
1498       "vld3_dup", bits_1, [S64; U64];
1499
1500     (* VST3 variants.  *)
1501     Vstx 3, [Disassembles_as [Use_operands [| VecArray (4, Dreg);
1502                                               PtrTo Corereg |]]],
1503       Use_operands [| PtrTo Corereg; VecArray (3, Dreg) |], "vst3",
1504       store_1, pf_su_8_32;
1505     Vstx 3, [Disassembles_as [Use_operands [| VecArray (4, Dreg);
1506                                               PtrTo Corereg |]];
1507              Instruction_name ["vst1"]],
1508       Use_operands [| PtrTo Corereg; VecArray (3, Dreg) |], "vst3",
1509       store_1, [S64; U64];
1510     Vstx 3, [Disassembles_as [Use_operands [| VecArray (3, Dreg);
1511                                               PtrTo Corereg |];
1512                               Use_operands [| VecArray (3, Dreg);
1513                                               PtrTo Corereg |]]],
1514       Use_operands [| PtrTo Corereg; VecArray (3, Qreg) |], "vst3Q",
1515       store_1, pf_su_8_32;
1516
1517     Vstx_lane 3,
1518       [Disassembles_as [Use_operands
1519         [| VecArray (3, Element_of_dreg);
1520            CstPtrTo Corereg |]]],
1521       Use_operands [| PtrTo Corereg; VecArray (3, Dreg); Immed |], "vst3_lane",
1522       store_3, P8 :: P16 :: F32 :: su_8_32;
1523     Vstx_lane 3,
1524       [Disassembles_as [Use_operands
1525         [| VecArray (3, Element_of_dreg);
1526            CstPtrTo Corereg |]]],
1527       Use_operands [| PtrTo Corereg; VecArray (3, Qreg); Immed |], "vst3Q_lane",
1528       store_3, [P16; F32; U16; U32; S16; S32];
1529
1530     (* VLD4/VST4 variants.  *)
1531     Vldx 4, [], Use_operands [| VecArray (4, Dreg); CstPtrTo Corereg |],
1532       "vld4", bits_1, pf_su_8_32;
1533     Vldx 4, [Instruction_name ["vld1"]],
1534       Use_operands [| VecArray (4, Dreg); CstPtrTo Corereg |],
1535       "vld4", bits_1, [S64; U64];
1536     Vldx 4, [Disassembles_as [Use_operands [| VecArray (4, Dreg);
1537                                               CstPtrTo Corereg |];
1538                               Use_operands [| VecArray (4, Dreg);
1539                                               CstPtrTo Corereg |]]],
1540       Use_operands [| VecArray (4, Qreg); CstPtrTo Corereg |],
1541       "vld4Q", bits_1, P8 :: P16 :: F32 :: su_8_32;
1542
1543     Vldx_lane 4,
1544       [Disassembles_as [Use_operands
1545         [| VecArray (4, Element_of_dreg);
1546            CstPtrTo Corereg |]]],
1547       Use_operands [| VecArray (4, Dreg); CstPtrTo Corereg;
1548                                      VecArray (4, Dreg); Immed |],
1549       "vld4_lane", bits_3, P8 :: P16 :: F32 :: su_8_32;
1550     Vldx_lane 4,
1551       [Disassembles_as [Use_operands
1552         [| VecArray (4, Element_of_dreg);
1553            CstPtrTo Corereg |]]],
1554       Use_operands [| VecArray (4, Qreg); CstPtrTo Corereg;
1555                       VecArray (4, Qreg); Immed |],
1556       "vld4Q_lane", bits_3, [P16; F32; U16; U32; S16; S32];
1557
1558     Vldx_dup 4,
1559       [Disassembles_as [Use_operands
1560         [| VecArray (4, All_elements_of_dreg); CstPtrTo Corereg |]]],
1561       Use_operands [| VecArray (4, Dreg); CstPtrTo Corereg |],
1562       "vld4_dup", bits_1, pf_su_8_32;
1563     Vldx_dup 4,
1564       [Instruction_name ["vld1"]; Disassembles_as [Use_operands
1565         [| VecArray (4, Dreg); CstPtrTo Corereg |]]],
1566       Use_operands [| VecArray (4, Dreg); CstPtrTo Corereg |],
1567       "vld4_dup", bits_1, [S64; U64];
1568
1569     Vstx 4, [Disassembles_as [Use_operands [| VecArray (4, Dreg);
1570                                               PtrTo Corereg |]]],
1571       Use_operands [| PtrTo Corereg; VecArray (4, Dreg) |], "vst4",
1572       store_1, pf_su_8_32;
1573     Vstx 4, [Disassembles_as [Use_operands [| VecArray (4, Dreg);
1574                                               PtrTo Corereg |]];
1575              Instruction_name ["vst1"]],
1576       Use_operands [| PtrTo Corereg; VecArray (4, Dreg) |], "vst4",
1577       store_1, [S64; U64];
1578     Vstx 4, [Disassembles_as [Use_operands [| VecArray (4, Dreg);
1579                                               PtrTo Corereg |];
1580                               Use_operands [| VecArray (4, Dreg);
1581                                               PtrTo Corereg |]]],
1582      Use_operands [| PtrTo Corereg; VecArray (4, Qreg) |], "vst4Q",
1583       store_1, pf_su_8_32;
1584
1585     Vstx_lane 4,
1586       [Disassembles_as [Use_operands
1587         [| VecArray (4, Element_of_dreg);
1588            CstPtrTo Corereg |]]],
1589       Use_operands [| PtrTo Corereg; VecArray (4, Dreg); Immed |], "vst4_lane",
1590       store_3, P8 :: P16 :: F32 :: su_8_32;
1591     Vstx_lane 4,
1592       [Disassembles_as [Use_operands
1593         [| VecArray (4, Element_of_dreg);
1594            CstPtrTo Corereg |]]],
1595       Use_operands [| PtrTo Corereg; VecArray (4, Qreg); Immed |], "vst4Q_lane",
1596       store_3, [P16; F32; U16; U32; S16; S32];
1597
1598     (* Logical operations. And.  *)
1599     Vand, [], All (3, Dreg), "vand", notype_2, su_8_64;
1600     Vand, [], All (3, Qreg), "vandQ", notype_2, su_8_64;
1601
1602     (* Or.  *)
1603     Vorr, [], All (3, Dreg), "vorr", notype_2, su_8_64;
1604     Vorr, [], All (3, Qreg), "vorrQ", notype_2, su_8_64;
1605
1606     (* Eor.  *)
1607     Veor, [], All (3, Dreg), "veor", notype_2, su_8_64;
1608     Veor, [], All (3, Qreg), "veorQ", notype_2, su_8_64;
1609
1610     (* Bic (And-not).  *)
1611     Vbic, [], All (3, Dreg), "vbic", notype_2, su_8_64;
1612     Vbic, [], All (3, Qreg), "vbicQ", notype_2, su_8_64;
1613
1614     (* Or-not.  *)
1615     Vorn, [], All (3, Dreg), "vorn", notype_2, su_8_64;
1616     Vorn, [], All (3, Qreg), "vornQ", notype_2, su_8_64;
1617   ]
1618
1619 let reinterp =
1620   let elems = P8 :: P16 :: F32 :: su_8_64 in
1621   List.fold_right
1622     (fun convto acc ->
1623       let types = List.fold_right
1624         (fun convfrom acc ->
1625           if convfrom <> convto then
1626             Cast (convto, convfrom) :: acc
1627           else
1628             acc)
1629         elems
1630         []
1631       in
1632         let dconv = Vreinterp, [No_op], Use_operands [| Dreg; Dreg |],
1633                       "vreinterpret", conv_1, types
1634         and qconv = Vreinterp, [No_op], Use_operands [| Qreg; Qreg |],
1635                       "vreinterpretQ", conv_1, types in
1636         dconv :: qconv :: acc)
1637     elems
1638     []
1639
1640 (* Output routines.  *)
1641
1642 let rec string_of_elt = function
1643     S8 -> "s8" | S16 -> "s16" | S32 -> "s32" | S64 -> "s64"
1644   | U8 -> "u8" | U16 -> "u16" | U32 -> "u32" | U64 -> "u64"
1645   | I8 -> "i8" | I16 -> "i16" | I32 -> "i32" | I64 -> "i64"
1646   | B8 -> "8" | B16 -> "16" | B32 -> "32" | B64 -> "64"
1647   | F32 -> "f32" | P8 -> "p8" | P16 -> "p16"
1648   | Conv (a, b) | Cast (a, b) -> string_of_elt a ^ "_" ^ string_of_elt b
1649   | NoElts -> failwith "No elts"
1650
1651 let string_of_elt_dots elt =
1652   match elt with
1653     Conv (a, b) | Cast (a, b) -> string_of_elt a ^ "." ^ string_of_elt b
1654   | _ -> string_of_elt elt
1655
1656 let string_of_vectype vt =
1657   let rec name affix = function
1658     T_int8x8 -> affix "int8x8"
1659   | T_int8x16 -> affix "int8x16"
1660   | T_int16x4 -> affix "int16x4"
1661   | T_int16x8 -> affix "int16x8"
1662   | T_int32x2 -> affix "int32x2"
1663   | T_int32x4 -> affix "int32x4"
1664   | T_int64x1 -> affix "int64x1"
1665   | T_int64x2 -> affix "int64x2"
1666   | T_uint8x8 -> affix "uint8x8"
1667   | T_uint8x16 -> affix "uint8x16"
1668   | T_uint16x4 -> affix "uint16x4"
1669   | T_uint16x8 -> affix "uint16x8"
1670   | T_uint32x2 -> affix "uint32x2"
1671   | T_uint32x4 -> affix "uint32x4"
1672   | T_uint64x1 -> affix "uint64x1"
1673   | T_uint64x2 -> affix "uint64x2"
1674   | T_float32x2 -> affix "float32x2"
1675   | T_float32x4 -> affix "float32x4"
1676   | T_poly8x8 -> affix "poly8x8"
1677   | T_poly8x16 -> affix "poly8x16"
1678   | T_poly16x4 -> affix "poly16x4"
1679   | T_poly16x8 -> affix "poly16x8"
1680   | T_int8 -> affix "int8"
1681   | T_int16 -> affix "int16"
1682   | T_int32 -> affix "int32"
1683   | T_int64 -> affix "int64"
1684   | T_uint8 -> affix "uint8"
1685   | T_uint16 -> affix "uint16"
1686   | T_uint32 -> affix "uint32"
1687   | T_uint64 -> affix "uint64"
1688   | T_poly8 -> affix "poly8"
1689   | T_poly16 -> affix "poly16"
1690   | T_float32 -> affix "float32"
1691   | T_immediate _ -> "const int"
1692   | T_void -> "void"
1693   | T_intQI -> "__builtin_neon_qi"
1694   | T_intHI -> "__builtin_neon_hi"
1695   | T_intSI -> "__builtin_neon_si"
1696   | T_intDI -> "__builtin_neon_di"
1697   | T_arrayof (num, base) ->
1698       let basename = name (fun x -> x) base in
1699       affix (Printf.sprintf "%sx%d" basename num)
1700   | T_ptrto x ->
1701       let basename = name affix x in
1702       Printf.sprintf "%s *" basename
1703   | T_const x ->
1704       let basename = name affix x in
1705       Printf.sprintf "const %s" basename
1706   in
1707     name (fun x -> x ^ "_t") vt
1708
1709 let string_of_inttype = function
1710     B_TImode -> "__builtin_neon_ti"
1711   | B_EImode -> "__builtin_neon_ei"
1712   | B_OImode -> "__builtin_neon_oi"
1713   | B_CImode -> "__builtin_neon_ci"
1714   | B_XImode -> "__builtin_neon_xi"
1715
1716 let string_of_mode = function
1717     V8QI -> "v8qi" | V4HI  -> "v4hi"  | V2SI -> "v2si" | V2SF -> "v2sf"
1718   | DI   -> "di"   | V16QI -> "v16qi" | V8HI -> "v8hi" | V4SI -> "v4si"
1719   | V4SF -> "v4sf" | V2DI  -> "v2di"  | QI -> "qi" | HI -> "hi" | SI -> "si"
1720   | SF -> "sf"
1721
1722 (* Use uppercase chars for letters which form part of the intrinsic name, but
1723    should be omitted from the builtin name (the info is passed in an extra
1724    argument, instead).  *)
1725 let intrinsic_name name = String.lowercase name
1726
1727 (* Allow the name of the builtin to be overridden by things (e.g. Flipped)
1728    found in the features list.  *)
1729 let builtin_name features name =
1730   let name = List.fold_right
1731                (fun el name ->
1732                  match el with
1733                    Flipped x | Builtin_name x -> x
1734                  | _ -> name)
1735                features name in
1736   let islower x = let str = String.make 1 x in (String.lowercase str) = str
1737   and buf = Buffer.create (String.length name) in
1738   String.iter (fun c -> if islower c then Buffer.add_char buf c) name;
1739   Buffer.contents buf
1740
1741 (* Transform an arity into a list of strings.  *)
1742 let strings_of_arity a =
1743   match a with
1744   | Arity0 vt -> [string_of_vectype vt]
1745   | Arity1 (vt1, vt2) -> [string_of_vectype vt1; string_of_vectype vt2]
1746   | Arity2 (vt1, vt2, vt3) -> [string_of_vectype vt1;
1747                                string_of_vectype vt2;
1748                                string_of_vectype vt3]
1749   | Arity3 (vt1, vt2, vt3, vt4) -> [string_of_vectype vt1;
1750                                     string_of_vectype vt2;
1751                                     string_of_vectype vt3;
1752                                     string_of_vectype vt4]
1753   | Arity4 (vt1, vt2, vt3, vt4, vt5) -> [string_of_vectype vt1;
1754                                          string_of_vectype vt2;
1755                                          string_of_vectype vt3;
1756                                          string_of_vectype vt4;
1757                                          string_of_vectype vt5]
1758
1759 (* Suffixes on the end of builtin names that are to be stripped in order
1760    to obtain the name used as an instruction.  They are only stripped if
1761    preceded immediately by an underscore.  *)
1762 let suffixes_to_strip = [ "n"; "lane"; "dup" ]
1763
1764 (* Get the possible names of an instruction corresponding to a "name" from the
1765    ops table.  This is done by getting the equivalent builtin name and
1766    stripping any suffixes from the list at the top of this file, unless
1767    the features list presents with an Instruction_name entry, in which
1768    case that is used; or unless the features list presents with a Flipped
1769    entry, in which case that is used.  If both such entries are present,
1770    the first in the list will be chosen.  *)
1771 let get_insn_names features name =
1772   let names = try
1773   begin
1774     match List.find (fun feature -> match feature with
1775                                       Instruction_name _ -> true
1776                                     | Flipped _ -> true
1777                                     | _ -> false) features
1778     with
1779       Instruction_name names -> names
1780     | Flipped name -> [name]
1781     | _ -> assert false
1782   end
1783   with Not_found -> [builtin_name features name]
1784   in
1785   begin
1786     List.map (fun name' ->
1787       try
1788         let underscore = String.rindex name' '_' in
1789         let our_suffix = String.sub name' (underscore + 1)
1790                                     ((String.length name') - underscore - 1)
1791         in
1792           let rec strip remaining_suffixes =
1793             match remaining_suffixes with
1794               [] -> name'
1795             | s::ss when our_suffix = s -> String.sub name' 0 underscore
1796             | _::ss -> strip ss
1797           in
1798             strip suffixes_to_strip
1799       with (Not_found | Invalid_argument _) -> name') names
1800   end
1801
1802 (* Apply a function to each element of a list and then comma-separate
1803    the resulting strings.  *)
1804 let rec commas f elts acc =
1805   match elts with
1806     [] -> acc
1807   | [elt] -> acc ^ (f elt)
1808   | elt::elts ->
1809     commas f elts (acc ^ (f elt) ^ ", ")
1810
1811 (* Given a list of features and the shape specified in the "ops" table, apply
1812    a function to each possible shape that the instruction may have.
1813    By default, this is the "shape" entry in "ops".  If the features list
1814    contains a Disassembles_as entry, the shapes contained in that entry are
1815    mapped to corresponding outputs and returned in a list.  If there is more
1816    than one Disassembles_as entry, only the first is used.  *)
1817 let analyze_all_shapes features shape f =
1818   try
1819     match List.find (fun feature ->
1820                        match feature with Disassembles_as _ -> true
1821                                         | _ -> false)
1822                     features with
1823       Disassembles_as shapes -> List.map f shapes
1824     | _ -> assert false
1825   with Not_found -> [f shape]
1826