1/* Description of builtins used by the ARM backend.
2   Copyright (C) 2014-2022 Free Software Foundation, Inc.
3
4   This file is part of GCC.
5
6   GCC is free software; you can redistribute it and/or modify it
7   under the terms of the GNU General Public License as published
8   by the Free Software Foundation; either version 3, or (at your
9   option) any later version.
10
11   GCC is distributed in the hope that it will be useful, but WITHOUT
12   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
14   License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with GCC; see the file COPYING3.  If not see
18   <http://www.gnu.org/licenses/>.  */
19
20#define IN_TARGET_CODE 1
21
22#include "config.h"
23#include "system.h"
24#include "coretypes.h"
25#include "target.h"
26#include "function.h"
27#include "rtl.h"
28#include "tree.h"
29#include "gimple-expr.h"
30#include "memmodel.h"
31#include "tm_p.h"
32#include "profile-count.h"
33#include "optabs.h"
34#include "emit-rtl.h"
35#include "recog.h"
36#include "diagnostic-core.h"
37#include "fold-const.h"
38#include "stor-layout.h"
39#include "explow.h"
40#include "expr.h"
41#include "langhooks.h"
42#include "case-cfn-macros.h"
43#include "sbitmap.h"
44#include "stringpool.h"
45#include "arm-builtins.h"
46#include "stringpool.h"
47#include "attribs.h"
48
49#define SIMD_MAX_BUILTIN_ARGS 7
50
51/*  The qualifier_internal allows generation of a unary builtin from
52    a pattern with a third pseudo-operand such as a match_scratch.
53    T (T).  */
54static enum arm_type_qualifiers
55arm_unop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
56  = { qualifier_none, qualifier_none, qualifier_internal };
57#define UNOP_QUALIFIERS (arm_unop_qualifiers)
58
59/* unsigned T (unsigned T).  */
60static enum arm_type_qualifiers
61arm_bswap_qualifiers[SIMD_MAX_BUILTIN_ARGS]
62  = { qualifier_unsigned, qualifier_unsigned };
63#define BSWAP_QUALIFIERS (arm_bswap_qualifiers)
64
65/* T (T, T [maybe_immediate]).  */
66static enum arm_type_qualifiers
67arm_binop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
68  = { qualifier_none, qualifier_none, qualifier_maybe_immediate };
69#define BINOP_QUALIFIERS (arm_binop_qualifiers)
70
71/* T (T, T, T).  */
72static enum arm_type_qualifiers
73arm_ternop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
74  = { qualifier_none, qualifier_none, qualifier_none, qualifier_none };
75#define TERNOP_QUALIFIERS (arm_ternop_qualifiers)
76
77/* unsigned T (unsigned T, unsigned T, unsigned T).  */
78static enum arm_type_qualifiers
79arm_unsigned_uternop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
80  = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned,
81      qualifier_unsigned };
82#define UTERNOP_QUALIFIERS (arm_unsigned_uternop_qualifiers)
83
84/* T (T, unsigned T, T).  */
85static enum arm_type_qualifiers
86arm_usternop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
87  = { qualifier_none, qualifier_none, qualifier_unsigned,
88      qualifier_none };
89#define USTERNOP_QUALIFIERS (arm_usternop_qualifiers)
90
91/* T (T, immediate).  */
92static enum arm_type_qualifiers
93arm_binop_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
94  = { qualifier_none, qualifier_none, qualifier_immediate };
95#define BINOP_IMM_QUALIFIERS (arm_binop_imm_qualifiers)
96
97/* T (T, unsigned immediate).  */
98static enum arm_type_qualifiers
99arm_sat_binop_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
100  = { qualifier_unsigned, qualifier_none, qualifier_unsigned_immediate };
101#define SAT_BINOP_UNSIGNED_IMM_QUALIFIERS \
102  (arm_sat_binop_imm_qualifiers)
103
104/* unsigned T (T, unsigned immediate).  */
105static enum arm_type_qualifiers
106arm_unsigned_sat_binop_unsigned_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
107  = { qualifier_unsigned, qualifier_none, qualifier_unsigned_immediate };
108#define UNSIGNED_SAT_BINOP_UNSIGNED_IMM_QUALIFIERS \
109  (arm_unsigned_sat_binop_unsigned_imm_qualifiers)
110
111/* T (T, lane index).  */
112static enum arm_type_qualifiers
113arm_getlane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
114  = { qualifier_none, qualifier_none, qualifier_lane_index };
115#define GETLANE_QUALIFIERS (arm_getlane_qualifiers)
116
117/* T (T, T, T, immediate).  */
118static enum arm_type_qualifiers
119arm_mac_n_qualifiers[SIMD_MAX_BUILTIN_ARGS]
120  = { qualifier_none, qualifier_none, qualifier_none,
121      qualifier_none, qualifier_immediate };
122#define MAC_N_QUALIFIERS (arm_mac_n_qualifiers)
123
124/* T (T, T, T, lane index).  */
125static enum arm_type_qualifiers
126arm_mac_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
127  = { qualifier_none, qualifier_none, qualifier_none,
128      qualifier_none, qualifier_lane_index };
129#define MAC_LANE_QUALIFIERS (arm_mac_lane_qualifiers)
130
131/* T (T, T, T, lane pair index).  */
132static enum arm_type_qualifiers
133arm_mac_lane_pair_qualifiers[SIMD_MAX_BUILTIN_ARGS]
134  = { qualifier_none, qualifier_none, qualifier_none,
135      qualifier_none, qualifier_lane_pair_index };
136#define MAC_LANE_PAIR_QUALIFIERS (arm_mac_lane_pair_qualifiers)
137
138/* unsigned T (unsigned T, unsigned T, unsigend T, lane index).  */
139static enum arm_type_qualifiers
140arm_umac_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
141  = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned,
142      qualifier_unsigned, qualifier_lane_index };
143#define UMAC_LANE_QUALIFIERS (arm_umac_lane_qualifiers)
144
145/* T (T, unsigned T, T, lane index).  */
146static enum arm_type_qualifiers
147arm_usmac_lane_quadtup_qualifiers[SIMD_MAX_BUILTIN_ARGS]
148  = { qualifier_none, qualifier_none, qualifier_unsigned,
149      qualifier_none, qualifier_lane_quadtup_index };
150#define USMAC_LANE_QUADTUP_QUALIFIERS (arm_usmac_lane_quadtup_qualifiers)
151
152/* T (T, T, unsigend T, lane index).  */
153static enum arm_type_qualifiers
154arm_sumac_lane_quadtup_qualifiers[SIMD_MAX_BUILTIN_ARGS]
155  = { qualifier_none, qualifier_none, qualifier_none,
156      qualifier_unsigned, qualifier_lane_quadtup_index };
157#define SUMAC_LANE_QUADTUP_QUALIFIERS (arm_sumac_lane_quadtup_qualifiers)
158
159/* T (T, T, immediate).  */
160static enum arm_type_qualifiers
161arm_ternop_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
162  = { qualifier_none, qualifier_none, qualifier_none, qualifier_immediate };
163#define TERNOP_IMM_QUALIFIERS (arm_ternop_imm_qualifiers)
164
165/* T (T, T, lane index).  */
166static enum arm_type_qualifiers
167arm_setlane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
168  = { qualifier_none, qualifier_none, qualifier_none, qualifier_lane_index };
169#define SETLANE_QUALIFIERS (arm_setlane_qualifiers)
170
171/* T (T, T).  */
172static enum arm_type_qualifiers
173arm_combine_qualifiers[SIMD_MAX_BUILTIN_ARGS]
174  = { qualifier_none, qualifier_none, qualifier_none };
175#define COMBINE_QUALIFIERS (arm_combine_qualifiers)
176
177/* T ([T element type] *).  */
178static enum arm_type_qualifiers
179arm_load1_qualifiers[SIMD_MAX_BUILTIN_ARGS]
180  = { qualifier_none, qualifier_const_pointer_map_mode };
181#define LOAD1_QUALIFIERS (arm_load1_qualifiers)
182
183/* T ([T element type] *, T, immediate).  */
184static enum arm_type_qualifiers
185arm_load1_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
186  = { qualifier_none, qualifier_const_pointer_map_mode,
187      qualifier_none, qualifier_struct_load_store_lane_index };
188#define LOAD1LANE_QUALIFIERS (arm_load1_lane_qualifiers)
189
190/* unsigned T (unsigned T, unsigned T, unsigned T).  */
191static enum arm_type_qualifiers
192arm_unsigned_binop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
193  = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned,
194      qualifier_unsigned };
195#define UBINOP_QUALIFIERS (arm_unsigned_binop_qualifiers)
196
197/* void (unsigned immediate, unsigned immediate, unsigned immediate,
198	 unsigned immediate, unsigned immediate, unsigned immediate).  */
199static enum arm_type_qualifiers
200arm_cdp_qualifiers[SIMD_MAX_BUILTIN_ARGS]
201  = { qualifier_void, qualifier_unsigned_immediate,
202      qualifier_unsigned_immediate,
203      qualifier_unsigned_immediate,
204      qualifier_unsigned_immediate,
205      qualifier_unsigned_immediate,
206      qualifier_unsigned_immediate };
207#define CDP_QUALIFIERS \
208  (arm_cdp_qualifiers)
209
210/* void (unsigned immediate, unsigned immediate,  const void *).  */
211static enum arm_type_qualifiers
212arm_ldc_qualifiers[SIMD_MAX_BUILTIN_ARGS]
213  = { qualifier_void, qualifier_unsigned_immediate,
214      qualifier_unsigned_immediate, qualifier_const_void_pointer };
215#define LDC_QUALIFIERS \
216  (arm_ldc_qualifiers)
217
218/* void (unsigned immediate, unsigned immediate,  void *).  */
219static enum arm_type_qualifiers
220arm_stc_qualifiers[SIMD_MAX_BUILTIN_ARGS]
221  = { qualifier_void, qualifier_unsigned_immediate,
222      qualifier_unsigned_immediate, qualifier_void_pointer };
223#define STC_QUALIFIERS \
224  (arm_stc_qualifiers)
225
226/* void (unsigned immediate, unsigned immediate,  T, unsigned immediate,
227	 unsigned immediate, unsigned immediate).  */
228static enum arm_type_qualifiers
229arm_mcr_qualifiers[SIMD_MAX_BUILTIN_ARGS]
230  = { qualifier_void, qualifier_unsigned_immediate,
231      qualifier_unsigned_immediate, qualifier_none,
232      qualifier_unsigned_immediate, qualifier_unsigned_immediate,
233      qualifier_unsigned_immediate };
234#define MCR_QUALIFIERS \
235  (arm_mcr_qualifiers)
236
237/* T (unsigned immediate, unsigned immediate, unsigned immediate,
238      unsigned immediate, unsigned immediate).  */
239static enum arm_type_qualifiers
240arm_mrc_qualifiers[SIMD_MAX_BUILTIN_ARGS]
241  = { qualifier_none, qualifier_unsigned_immediate,
242      qualifier_unsigned_immediate, qualifier_unsigned_immediate,
243      qualifier_unsigned_immediate, qualifier_unsigned_immediate };
244#define MRC_QUALIFIERS \
245  (arm_mrc_qualifiers)
246
247/* void (unsigned immediate, unsigned immediate,  T, unsigned immediate).  */
248static enum arm_type_qualifiers
249arm_mcrr_qualifiers[SIMD_MAX_BUILTIN_ARGS]
250  = { qualifier_void, qualifier_unsigned_immediate,
251      qualifier_unsigned_immediate, qualifier_none,
252      qualifier_unsigned_immediate };
253#define MCRR_QUALIFIERS \
254  (arm_mcrr_qualifiers)
255
256/* T (unsigned immediate, unsigned immediate, unsigned immediate).  */
257static enum arm_type_qualifiers
258arm_mrrc_qualifiers[SIMD_MAX_BUILTIN_ARGS]
259  = { qualifier_none, qualifier_unsigned_immediate,
260      qualifier_unsigned_immediate, qualifier_unsigned_immediate };
261#define MRRC_QUALIFIERS \
262  (arm_mrrc_qualifiers)
263
264/* T (immediate, unsigned immediate).  */
265static enum arm_type_qualifiers
266arm_cx_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
267  = { qualifier_none, qualifier_immediate, qualifier_unsigned_immediate };
268#define CX_IMM_QUALIFIERS (arm_cx_imm_qualifiers)
269
270/* T (immediate, T, unsigned immediate).  */
271static enum arm_type_qualifiers
272arm_cx_unary_qualifiers[SIMD_MAX_BUILTIN_ARGS]
273  = { qualifier_none, qualifier_immediate, qualifier_none,
274      qualifier_unsigned_immediate };
275#define CX_UNARY_QUALIFIERS (arm_cx_unary_qualifiers)
276
277/* T (immediate, T, T, unsigned immediate).  */
278static enum arm_type_qualifiers
279arm_cx_binary_qualifiers[SIMD_MAX_BUILTIN_ARGS]
280  = { qualifier_none, qualifier_immediate,
281      qualifier_none, qualifier_none,
282      qualifier_unsigned_immediate };
283#define CX_BINARY_QUALIFIERS (arm_cx_binary_qualifiers)
284
285/* T (immediate, T, T, T, unsigned immediate).  */
286static enum arm_type_qualifiers
287arm_cx_ternary_qualifiers[SIMD_MAX_BUILTIN_ARGS]
288  = { qualifier_none, qualifier_immediate,
289      qualifier_none, qualifier_none, qualifier_none,
290      qualifier_unsigned_immediate };
291#define CX_TERNARY_QUALIFIERS (arm_cx_ternary_qualifiers)
292
293/* T (immediate, T, unsigned immediate).  */
294static enum arm_type_qualifiers
295arm_cx_unary_unone_qualifiers[SIMD_MAX_BUILTIN_ARGS]
296  = { qualifier_none, qualifier_immediate, qualifier_none,
297      qualifier_unsigned_immediate,
298      qualifier_predicate };
299#define CX_UNARY_UNONE_QUALIFIERS (arm_cx_unary_unone_qualifiers)
300
301/* T (immediate, T, T, unsigned immediate).  */
302static enum arm_type_qualifiers
303arm_cx_binary_unone_qualifiers[SIMD_MAX_BUILTIN_ARGS]
304  = { qualifier_none, qualifier_immediate,
305      qualifier_none, qualifier_none,
306      qualifier_unsigned_immediate,
307      qualifier_predicate };
308#define CX_BINARY_UNONE_QUALIFIERS (arm_cx_binary_unone_qualifiers)
309
310/* T (immediate, T, T, T, unsigned immediate).  */
311static enum arm_type_qualifiers
312arm_cx_ternary_unone_qualifiers[SIMD_MAX_BUILTIN_ARGS]
313  = { qualifier_none, qualifier_immediate,
314      qualifier_none, qualifier_none, qualifier_none,
315      qualifier_unsigned_immediate,
316      qualifier_predicate };
317#define CX_TERNARY_UNONE_QUALIFIERS (arm_cx_ternary_unone_qualifiers)
318
319/* The first argument (return type) of a store should be void type,
320   which we represent with qualifier_void.  Their first operand will be
321   a DImode pointer to the location to store to, so we must use
322   qualifier_map_mode | qualifier_pointer to build a pointer to the
323   element type of the vector.
324
325   void ([T element type] *, T).  */
326static enum arm_type_qualifiers
327arm_store1_qualifiers[SIMD_MAX_BUILTIN_ARGS]
328  = { qualifier_void, qualifier_pointer_map_mode, qualifier_none };
329#define STORE1_QUALIFIERS (arm_store1_qualifiers)
330
331/* Qualifiers for MVE builtins.  */
332
333static enum arm_type_qualifiers
334arm_unop_none_none_qualifiers[SIMD_MAX_BUILTIN_ARGS]
335  = { qualifier_none, qualifier_none };
336#define UNOP_NONE_NONE_QUALIFIERS \
337  (arm_unop_none_none_qualifiers)
338
339static enum arm_type_qualifiers
340arm_unop_none_snone_qualifiers[SIMD_MAX_BUILTIN_ARGS]
341  = { qualifier_none, qualifier_none };
342#define UNOP_NONE_SNONE_QUALIFIERS \
343  (arm_unop_none_snone_qualifiers)
344
345static enum arm_type_qualifiers
346arm_unop_none_unone_qualifiers[SIMD_MAX_BUILTIN_ARGS]
347  = { qualifier_none, qualifier_unsigned };
348#define UNOP_NONE_UNONE_QUALIFIERS \
349  (arm_unop_none_unone_qualifiers)
350
351static enum arm_type_qualifiers
352arm_unop_snone_snone_qualifiers[SIMD_MAX_BUILTIN_ARGS]
353  = { qualifier_none, qualifier_none };
354#define UNOP_SNONE_SNONE_QUALIFIERS \
355  (arm_unop_snone_snone_qualifiers)
356
357static enum arm_type_qualifiers
358arm_unop_snone_none_qualifiers[SIMD_MAX_BUILTIN_ARGS]
359  = { qualifier_none, qualifier_none };
360#define UNOP_SNONE_NONE_QUALIFIERS \
361  (arm_unop_snone_none_qualifiers)
362
363static enum arm_type_qualifiers
364arm_unop_snone_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
365  = { qualifier_none, qualifier_immediate };
366#define UNOP_SNONE_IMM_QUALIFIERS \
367  (arm_unop_snone_imm_qualifiers)
368
369static enum arm_type_qualifiers
370arm_unop_unone_none_qualifiers[SIMD_MAX_BUILTIN_ARGS]
371  = { qualifier_unsigned, qualifier_none };
372#define UNOP_UNONE_NONE_QUALIFIERS \
373  (arm_unop_unone_none_qualifiers)
374
375static enum arm_type_qualifiers
376arm_unop_unone_unone_qualifiers[SIMD_MAX_BUILTIN_ARGS]
377  = { qualifier_unsigned, qualifier_unsigned };
378#define UNOP_UNONE_UNONE_QUALIFIERS \
379  (arm_unop_unone_unone_qualifiers)
380
381static enum arm_type_qualifiers
382arm_unop_unone_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
383  = { qualifier_unsigned, qualifier_immediate };
384#define UNOP_UNONE_IMM_QUALIFIERS \
385  (arm_unop_unone_imm_qualifiers)
386
387static enum arm_type_qualifiers
388arm_binop_none_none_none_qualifiers[SIMD_MAX_BUILTIN_ARGS]
389  = { qualifier_none, qualifier_none, qualifier_none };
390#define BINOP_NONE_NONE_NONE_QUALIFIERS \
391  (arm_binop_none_none_none_qualifiers)
392
393static enum arm_type_qualifiers
394arm_binop_none_none_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
395  = { qualifier_none, qualifier_none, qualifier_immediate };
396#define BINOP_NONE_NONE_IMM_QUALIFIERS \
397  (arm_binop_none_none_imm_qualifiers)
398
399static enum arm_type_qualifiers
400arm_binop_none_unone_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
401  = { qualifier_none, qualifier_unsigned, qualifier_immediate };
402#define BINOP_NONE_UNONE_IMM_QUALIFIERS \
403  (arm_binop_none_unone_imm_qualifiers)
404
405static enum arm_type_qualifiers
406arm_binop_none_unone_unone_qualifiers[SIMD_MAX_BUILTIN_ARGS]
407  = { qualifier_none, qualifier_unsigned, qualifier_unsigned };
408#define BINOP_NONE_UNONE_UNONE_QUALIFIERS \
409  (arm_binop_none_unone_unone_qualifiers)
410
411static enum arm_type_qualifiers
412arm_binop_unone_unone_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
413  = { qualifier_unsigned, qualifier_unsigned, qualifier_immediate };
414#define BINOP_UNONE_UNONE_IMM_QUALIFIERS \
415  (arm_binop_unone_unone_imm_qualifiers)
416
417static enum arm_type_qualifiers
418arm_binop_unone_unone_unone_qualifiers[SIMD_MAX_BUILTIN_ARGS]
419  = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned };
420#define BINOP_UNONE_UNONE_UNONE_QUALIFIERS \
421  (arm_binop_unone_unone_unone_qualifiers)
422
423static enum arm_type_qualifiers
424arm_binop_pred_unone_unone_qualifiers[SIMD_MAX_BUILTIN_ARGS]
425  = { qualifier_predicate, qualifier_unsigned, qualifier_unsigned };
426#define BINOP_PRED_UNONE_UNONE_QUALIFIERS \
427  (arm_binop_pred_unone_unone_qualifiers)
428
429static enum arm_type_qualifiers
430arm_binop_unone_none_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
431  = { qualifier_unsigned, qualifier_none, qualifier_immediate };
432#define BINOP_UNONE_NONE_IMM_QUALIFIERS \
433  (arm_binop_unone_none_imm_qualifiers)
434
435static enum arm_type_qualifiers
436arm_binop_pred_none_none_qualifiers[SIMD_MAX_BUILTIN_ARGS]
437  = { qualifier_predicate, qualifier_none, qualifier_none };
438#define BINOP_PRED_NONE_NONE_QUALIFIERS \
439  (arm_binop_pred_none_none_qualifiers)
440
441static enum arm_type_qualifiers
442arm_binop_unone_unone_none_qualifiers[SIMD_MAX_BUILTIN_ARGS]
443  = { qualifier_unsigned, qualifier_unsigned, qualifier_none };
444#define BINOP_UNONE_UNONE_NONE_QUALIFIERS \
445  (arm_binop_unone_unone_none_qualifiers)
446
447static enum arm_type_qualifiers
448arm_ternop_unone_unone_unone_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
449  = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned,
450    qualifier_immediate };
451#define TERNOP_UNONE_UNONE_UNONE_IMM_QUALIFIERS \
452  (arm_ternop_unone_unone_unone_imm_qualifiers)
453
454static enum arm_type_qualifiers
455arm_ternop_unone_unone_none_none_qualifiers[SIMD_MAX_BUILTIN_ARGS]
456  = { qualifier_unsigned, qualifier_unsigned, qualifier_none, qualifier_none };
457#define TERNOP_UNONE_UNONE_NONE_NONE_QUALIFIERS \
458  (arm_ternop_unone_unone_none_none_qualifiers)
459
460static enum arm_type_qualifiers
461arm_ternop_unone_none_unone_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
462  = { qualifier_unsigned, qualifier_none, qualifier_unsigned,
463      qualifier_immediate };
464#define TERNOP_UNONE_NONE_UNONE_IMM_QUALIFIERS \
465  (arm_ternop_unone_none_unone_imm_qualifiers)
466
467static enum arm_type_qualifiers
468arm_ternop_none_none_unone_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
469  = { qualifier_none, qualifier_none, qualifier_unsigned, qualifier_immediate };
470#define TERNOP_NONE_NONE_UNONE_IMM_QUALIFIERS \
471  (arm_ternop_none_none_unone_imm_qualifiers)
472
473static enum arm_type_qualifiers
474arm_ternop_unone_unone_none_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
475  = { qualifier_unsigned, qualifier_unsigned, qualifier_none,
476    qualifier_immediate };
477#define TERNOP_UNONE_UNONE_NONE_IMM_QUALIFIERS \
478  (arm_ternop_unone_unone_none_imm_qualifiers)
479
480static enum arm_type_qualifiers
481arm_ternop_unone_unone_none_pred_qualifiers[SIMD_MAX_BUILTIN_ARGS]
482  = { qualifier_unsigned, qualifier_unsigned, qualifier_none,
483      qualifier_predicate };
484#define TERNOP_UNONE_UNONE_NONE_PRED_QUALIFIERS \
485  (arm_ternop_unone_unone_none_pred_qualifiers)
486
487static enum arm_type_qualifiers
488arm_ternop_unone_unone_imm_pred_qualifiers[SIMD_MAX_BUILTIN_ARGS]
489  = { qualifier_unsigned, qualifier_unsigned, qualifier_immediate,
490    qualifier_predicate };
491#define TERNOP_UNONE_UNONE_IMM_PRED_QUALIFIERS \
492  (arm_ternop_unone_unone_imm_pred_qualifiers)
493
494static enum arm_type_qualifiers
495arm_ternop_pred_none_none_pred_qualifiers[SIMD_MAX_BUILTIN_ARGS]
496  = { qualifier_predicate, qualifier_none, qualifier_none, qualifier_predicate };
497#define TERNOP_PRED_NONE_NONE_PRED_QUALIFIERS \
498  (arm_ternop_pred_none_none_pred_qualifiers)
499
500static enum arm_type_qualifiers
501arm_ternop_none_none_none_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
502  = { qualifier_none, qualifier_none, qualifier_none, qualifier_immediate };
503#define TERNOP_NONE_NONE_NONE_IMM_QUALIFIERS \
504  (arm_ternop_none_none_none_imm_qualifiers)
505
506static enum arm_type_qualifiers
507arm_ternop_none_none_none_pred_qualifiers[SIMD_MAX_BUILTIN_ARGS]
508  = { qualifier_none, qualifier_none, qualifier_none, qualifier_predicate };
509#define TERNOP_NONE_NONE_NONE_PRED_QUALIFIERS \
510  (arm_ternop_none_none_none_pred_qualifiers)
511
512static enum arm_type_qualifiers
513arm_ternop_none_none_imm_pred_qualifiers[SIMD_MAX_BUILTIN_ARGS]
514  = { qualifier_none, qualifier_none, qualifier_immediate, qualifier_predicate };
515#define TERNOP_NONE_NONE_IMM_PRED_QUALIFIERS \
516  (arm_ternop_none_none_imm_pred_qualifiers)
517
518static enum arm_type_qualifiers
519arm_ternop_none_none_unone_pred_qualifiers[SIMD_MAX_BUILTIN_ARGS]
520  = { qualifier_none, qualifier_none, qualifier_unsigned, qualifier_predicate };
521#define TERNOP_NONE_NONE_UNONE_PRED_QUALIFIERS \
522  (arm_ternop_none_none_unone_pred_qualifiers)
523
524static enum arm_type_qualifiers
525arm_ternop_unone_unone_unone_unone_qualifiers[SIMD_MAX_BUILTIN_ARGS]
526  = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned,
527    qualifier_unsigned };
528#define TERNOP_UNONE_UNONE_UNONE_UNONE_QUALIFIERS \
529  (arm_ternop_unone_unone_unone_unone_qualifiers)
530
531static enum arm_type_qualifiers
532arm_ternop_unone_unone_unone_pred_qualifiers[SIMD_MAX_BUILTIN_ARGS]
533  = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned,
534    qualifier_predicate };
535#define TERNOP_UNONE_UNONE_UNONE_PRED_QUALIFIERS \
536  (arm_ternop_unone_unone_unone_pred_qualifiers)
537
538static enum arm_type_qualifiers
539arm_ternop_pred_unone_unone_pred_qualifiers[SIMD_MAX_BUILTIN_ARGS]
540  = { qualifier_predicate, qualifier_unsigned, qualifier_unsigned,
541    qualifier_predicate };
542#define TERNOP_PRED_UNONE_UNONE_PRED_QUALIFIERS \
543  (arm_ternop_pred_unone_unone_pred_qualifiers)
544
545static enum arm_type_qualifiers
546arm_ternop_none_none_none_none_qualifiers[SIMD_MAX_BUILTIN_ARGS]
547  = { qualifier_none, qualifier_none, qualifier_none, qualifier_none };
548#define TERNOP_NONE_NONE_NONE_NONE_QUALIFIERS \
549  (arm_ternop_none_none_none_none_qualifiers)
550
551static enum arm_type_qualifiers
552arm_quadop_unone_unone_none_none_pred_qualifiers[SIMD_MAX_BUILTIN_ARGS]
553  = { qualifier_unsigned, qualifier_unsigned, qualifier_none, qualifier_none,
554    qualifier_predicate };
555#define QUADOP_UNONE_UNONE_NONE_NONE_PRED_QUALIFIERS \
556  (arm_quadop_unone_unone_none_none_pred_qualifiers)
557
558static enum arm_type_qualifiers
559arm_quadop_none_none_none_none_pred_qualifiers[SIMD_MAX_BUILTIN_ARGS]
560  = { qualifier_none, qualifier_none, qualifier_none, qualifier_none,
561    qualifier_predicate };
562#define QUADOP_NONE_NONE_NONE_NONE_PRED_QUALIFIERS \
563  (arm_quadop_none_none_none_none_pred_qualifiers)
564
565static enum arm_type_qualifiers
566arm_quadop_none_none_none_imm_pred_qualifiers[SIMD_MAX_BUILTIN_ARGS]
567  = { qualifier_none, qualifier_none, qualifier_none, qualifier_immediate,
568    qualifier_predicate };
569#define QUADOP_NONE_NONE_NONE_IMM_PRED_QUALIFIERS \
570  (arm_quadop_none_none_none_imm_pred_qualifiers)
571
572static enum arm_type_qualifiers
573arm_quadop_unone_unone_unone_unone_pred_qualifiers[SIMD_MAX_BUILTIN_ARGS]
574  = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned,
575    qualifier_unsigned, qualifier_predicate };
576#define QUADOP_UNONE_UNONE_UNONE_UNONE_PRED_QUALIFIERS \
577  (arm_quadop_unone_unone_unone_unone_pred_qualifiers)
578
579static enum arm_type_qualifiers
580arm_quadop_unone_unone_none_imm_pred_qualifiers[SIMD_MAX_BUILTIN_ARGS]
581  = { qualifier_unsigned, qualifier_unsigned, qualifier_none,
582    qualifier_immediate, qualifier_predicate };
583#define QUADOP_UNONE_UNONE_NONE_IMM_PRED_QUALIFIERS \
584  (arm_quadop_unone_unone_none_imm_pred_qualifiers)
585
586static enum arm_type_qualifiers
587arm_quadop_none_none_unone_imm_pred_qualifiers[SIMD_MAX_BUILTIN_ARGS]
588  = { qualifier_none, qualifier_none, qualifier_unsigned, qualifier_immediate,
589    qualifier_predicate };
590#define QUADOP_NONE_NONE_UNONE_IMM_PRED_QUALIFIERS \
591  (arm_quadop_none_none_unone_imm_pred_qualifiers)
592
593static enum arm_type_qualifiers
594arm_quadop_unone_unone_unone_imm_pred_qualifiers[SIMD_MAX_BUILTIN_ARGS]
595  = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned,
596    qualifier_immediate, qualifier_predicate };
597#define QUADOP_UNONE_UNONE_UNONE_IMM_PRED_QUALIFIERS \
598  (arm_quadop_unone_unone_unone_imm_pred_qualifiers)
599
600static enum arm_type_qualifiers
601arm_quadop_unone_unone_unone_none_pred_qualifiers[SIMD_MAX_BUILTIN_ARGS]
602  = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned,
603    qualifier_none, qualifier_predicate };
604#define QUADOP_UNONE_UNONE_UNONE_NONE_PRED_QUALIFIERS \
605  (arm_quadop_unone_unone_unone_none_pred_qualifiers)
606
607static enum arm_type_qualifiers
608arm_strs_qualifiers[SIMD_MAX_BUILTIN_ARGS]
609  = { qualifier_void, qualifier_pointer, qualifier_none };
610#define STRS_QUALIFIERS (arm_strs_qualifiers)
611
612static enum arm_type_qualifiers
613arm_stru_qualifiers[SIMD_MAX_BUILTIN_ARGS]
614  = { qualifier_void, qualifier_pointer, qualifier_unsigned };
615#define STRU_QUALIFIERS (arm_stru_qualifiers)
616
617static enum arm_type_qualifiers
618arm_strss_qualifiers[SIMD_MAX_BUILTIN_ARGS]
619  = { qualifier_void, qualifier_pointer, qualifier_unsigned,
620      qualifier_none};
621#define STRSS_QUALIFIERS (arm_strss_qualifiers)
622
623static enum arm_type_qualifiers
624arm_strsu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
625  = { qualifier_void, qualifier_pointer, qualifier_unsigned,
626      qualifier_unsigned};
627#define STRSU_QUALIFIERS (arm_strsu_qualifiers)
628
629static enum arm_type_qualifiers
630arm_strsbs_qualifiers[SIMD_MAX_BUILTIN_ARGS]
631  = { qualifier_void, qualifier_unsigned, qualifier_immediate, qualifier_none};
632#define STRSBS_QUALIFIERS (arm_strsbs_qualifiers)
633
634static enum arm_type_qualifiers
635arm_strsbu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
636  = { qualifier_void, qualifier_unsigned, qualifier_immediate,
637      qualifier_unsigned};
638#define STRSBU_QUALIFIERS (arm_strsbu_qualifiers)
639
640static enum arm_type_qualifiers
641arm_strs_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
642  = { qualifier_void, qualifier_pointer, qualifier_none, qualifier_predicate};
643#define STRS_P_QUALIFIERS (arm_strs_p_qualifiers)
644
645static enum arm_type_qualifiers
646arm_stru_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
647  = { qualifier_void, qualifier_pointer, qualifier_unsigned,
648      qualifier_predicate};
649#define STRU_P_QUALIFIERS (arm_stru_p_qualifiers)
650
651static enum arm_type_qualifiers
652arm_strsu_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
653  = { qualifier_void, qualifier_pointer, qualifier_unsigned,
654      qualifier_unsigned, qualifier_predicate};
655#define STRSU_P_QUALIFIERS (arm_strsu_p_qualifiers)
656
657static enum arm_type_qualifiers
658arm_strss_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
659  = { qualifier_void, qualifier_pointer, qualifier_unsigned,
660      qualifier_none, qualifier_predicate};
661#define STRSS_P_QUALIFIERS (arm_strss_p_qualifiers)
662
663static enum arm_type_qualifiers
664arm_strsbs_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
665  = { qualifier_void, qualifier_unsigned, qualifier_immediate,
666      qualifier_none, qualifier_predicate};
667#define STRSBS_P_QUALIFIERS (arm_strsbs_p_qualifiers)
668
669static enum arm_type_qualifiers
670arm_strsbu_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
671  = { qualifier_void, qualifier_unsigned, qualifier_immediate,
672      qualifier_unsigned, qualifier_predicate};
673#define STRSBU_P_QUALIFIERS (arm_strsbu_p_qualifiers)
674
675static enum arm_type_qualifiers
676arm_ldrgu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
677  = { qualifier_unsigned, qualifier_pointer, qualifier_unsigned};
678#define LDRGU_QUALIFIERS (arm_ldrgu_qualifiers)
679
680static enum arm_type_qualifiers
681arm_ldrgs_qualifiers[SIMD_MAX_BUILTIN_ARGS]
682  = { qualifier_none, qualifier_pointer, qualifier_unsigned};
683#define LDRGS_QUALIFIERS (arm_ldrgs_qualifiers)
684
685static enum arm_type_qualifiers
686arm_ldrs_qualifiers[SIMD_MAX_BUILTIN_ARGS]
687  = { qualifier_none, qualifier_pointer};
688#define LDRS_QUALIFIERS (arm_ldrs_qualifiers)
689
690static enum arm_type_qualifiers
691arm_ldru_qualifiers[SIMD_MAX_BUILTIN_ARGS]
692  = { qualifier_unsigned, qualifier_pointer};
693#define LDRU_QUALIFIERS (arm_ldru_qualifiers)
694
695static enum arm_type_qualifiers
696arm_ldrgbs_qualifiers[SIMD_MAX_BUILTIN_ARGS]
697  = { qualifier_none, qualifier_unsigned, qualifier_immediate};
698#define LDRGBS_QUALIFIERS (arm_ldrgbs_qualifiers)
699
700static enum arm_type_qualifiers
701arm_ldrgbu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
702  = { qualifier_unsigned, qualifier_unsigned, qualifier_immediate};
703#define LDRGBU_QUALIFIERS (arm_ldrgbu_qualifiers)
704
705static enum arm_type_qualifiers
706arm_ldrgbs_z_qualifiers[SIMD_MAX_BUILTIN_ARGS]
707  = { qualifier_none, qualifier_unsigned, qualifier_immediate,
708      qualifier_predicate};
709#define LDRGBS_Z_QUALIFIERS (arm_ldrgbs_z_qualifiers)
710
711static enum arm_type_qualifiers
712arm_ldrgbu_z_qualifiers[SIMD_MAX_BUILTIN_ARGS]
713  = { qualifier_unsigned, qualifier_unsigned, qualifier_immediate,
714      qualifier_predicate};
715#define LDRGBU_Z_QUALIFIERS (arm_ldrgbu_z_qualifiers)
716
717static enum arm_type_qualifiers
718arm_ldrgs_z_qualifiers[SIMD_MAX_BUILTIN_ARGS]
719  = { qualifier_none, qualifier_pointer, qualifier_unsigned,
720      qualifier_predicate};
721#define LDRGS_Z_QUALIFIERS (arm_ldrgs_z_qualifiers)
722
723static enum arm_type_qualifiers
724arm_ldrgu_z_qualifiers[SIMD_MAX_BUILTIN_ARGS]
725  = { qualifier_unsigned, qualifier_pointer, qualifier_unsigned,
726      qualifier_predicate};
727#define LDRGU_Z_QUALIFIERS (arm_ldrgu_z_qualifiers)
728
729static enum arm_type_qualifiers
730arm_ldrs_z_qualifiers[SIMD_MAX_BUILTIN_ARGS]
731  = { qualifier_none, qualifier_pointer, qualifier_predicate};
732#define LDRS_Z_QUALIFIERS (arm_ldrs_z_qualifiers)
733
734static enum arm_type_qualifiers
735arm_ldru_z_qualifiers[SIMD_MAX_BUILTIN_ARGS]
736  = { qualifier_unsigned, qualifier_pointer, qualifier_predicate};
737#define LDRU_Z_QUALIFIERS (arm_ldru_z_qualifiers)
738
739static enum arm_type_qualifiers
740arm_quinop_unone_unone_unone_unone_imm_pred_qualifiers[SIMD_MAX_BUILTIN_ARGS]
741  = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned,
742      qualifier_unsigned, qualifier_immediate, qualifier_predicate };
743#define QUINOP_UNONE_UNONE_UNONE_UNONE_IMM_PRED_QUALIFIERS \
744  (arm_quinop_unone_unone_unone_unone_imm_pred_qualifiers)
745
746static enum arm_type_qualifiers
747arm_ldrgbwbxu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
748  = { qualifier_unsigned, qualifier_unsigned, qualifier_immediate};
749#define LDRGBWBXU_QUALIFIERS (arm_ldrgbwbxu_qualifiers)
750
751static enum arm_type_qualifiers
752arm_ldrgbwbxu_z_qualifiers[SIMD_MAX_BUILTIN_ARGS]
753  = { qualifier_unsigned, qualifier_unsigned, qualifier_immediate,
754      qualifier_predicate};
755#define LDRGBWBXU_Z_QUALIFIERS (arm_ldrgbwbxu_z_qualifiers)
756
757static enum arm_type_qualifiers
758arm_ldrgbwbs_qualifiers[SIMD_MAX_BUILTIN_ARGS]
759  = { qualifier_none, qualifier_unsigned, qualifier_immediate};
760#define LDRGBWBS_QUALIFIERS (arm_ldrgbwbs_qualifiers)
761
762static enum arm_type_qualifiers
763arm_ldrgbwbu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
764  = { qualifier_unsigned, qualifier_unsigned, qualifier_immediate};
765#define LDRGBWBU_QUALIFIERS (arm_ldrgbwbu_qualifiers)
766
767static enum arm_type_qualifiers
768arm_ldrgbwbs_z_qualifiers[SIMD_MAX_BUILTIN_ARGS]
769  = { qualifier_none, qualifier_unsigned, qualifier_immediate,
770      qualifier_predicate};
771#define LDRGBWBS_Z_QUALIFIERS (arm_ldrgbwbs_z_qualifiers)
772
773static enum arm_type_qualifiers
774arm_ldrgbwbu_z_qualifiers[SIMD_MAX_BUILTIN_ARGS]
775  = { qualifier_unsigned, qualifier_unsigned, qualifier_immediate,
776      qualifier_predicate};
777#define LDRGBWBU_Z_QUALIFIERS (arm_ldrgbwbu_z_qualifiers)
778
779static enum arm_type_qualifiers
780arm_strsbwbs_qualifiers[SIMD_MAX_BUILTIN_ARGS]
781  = { qualifier_unsigned, qualifier_unsigned, qualifier_const, qualifier_none};
782#define STRSBWBS_QUALIFIERS (arm_strsbwbs_qualifiers)
783
784static enum arm_type_qualifiers
785arm_strsbwbu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
786  = { qualifier_unsigned, qualifier_unsigned, qualifier_const, qualifier_unsigned};
787#define STRSBWBU_QUALIFIERS (arm_strsbwbu_qualifiers)
788
789static enum arm_type_qualifiers
790arm_strsbwbs_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
791  = { qualifier_unsigned, qualifier_unsigned, qualifier_const,
792      qualifier_none, qualifier_predicate};
793#define STRSBWBS_P_QUALIFIERS (arm_strsbwbs_p_qualifiers)
794
795static enum arm_type_qualifiers
796arm_strsbwbu_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
797  = { qualifier_unsigned, qualifier_unsigned, qualifier_const,
798      qualifier_unsigned, qualifier_predicate};
799#define STRSBWBU_P_QUALIFIERS (arm_strsbwbu_p_qualifiers)
800
801static enum arm_type_qualifiers
802arm_lsll_qualifiers[SIMD_MAX_BUILTIN_ARGS]
803  = { qualifier_unsigned, qualifier_unsigned, qualifier_none};
804#define LSLL_QUALIFIERS (arm_lsll_qualifiers)
805
806static enum arm_type_qualifiers
807arm_uqshl_qualifiers[SIMD_MAX_BUILTIN_ARGS]
808  = { qualifier_unsigned, qualifier_unsigned, qualifier_const};
809#define UQSHL_QUALIFIERS (arm_uqshl_qualifiers)
810
811static enum arm_type_qualifiers
812arm_asrl_qualifiers[SIMD_MAX_BUILTIN_ARGS]
813  = { qualifier_none, qualifier_none, qualifier_none};
814#define ASRL_QUALIFIERS (arm_asrl_qualifiers)
815
816static enum arm_type_qualifiers
817arm_sqshl_qualifiers[SIMD_MAX_BUILTIN_ARGS]
818  = { qualifier_unsigned, qualifier_unsigned, qualifier_const};
819#define SQSHL_QUALIFIERS (arm_sqshl_qualifiers)
820
821static enum arm_type_qualifiers
822arm_binop_none_none_pred_qualifiers[SIMD_MAX_BUILTIN_ARGS]
823  = { qualifier_none, qualifier_none, qualifier_predicate };
824#define BINOP_NONE_NONE_PRED_QUALIFIERS \
825  (arm_binop_none_none_pred_qualifiers)
826
827static enum arm_type_qualifiers
828arm_binop_unone_unone_pred_qualifiers[SIMD_MAX_BUILTIN_ARGS]
829  = { qualifier_unsigned, qualifier_unsigned, qualifier_predicate };
830#define BINOP_UNONE_UNONE_PRED_QUALIFIERS \
831  (arm_binop_unone_unone_pred_qualifiers)
832
833/* End of Qualifier for MVE builtins.  */
834
835   /* void ([T element type] *, T, immediate).  */
836static enum arm_type_qualifiers
837arm_storestruct_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
838  = { qualifier_void, qualifier_pointer_map_mode,
839      qualifier_none, qualifier_struct_load_store_lane_index };
840#define STORE1LANE_QUALIFIERS (arm_storestruct_lane_qualifiers)
841
842   /* int (void).  */
843static enum arm_type_qualifiers
844arm_sat_occurred_qualifiers[SIMD_MAX_BUILTIN_ARGS]
845  = { qualifier_none, qualifier_void };
846#define SAT_OCCURRED_QUALIFIERS (arm_sat_occurred_qualifiers)
847
848   /* void (int).  */
849static enum arm_type_qualifiers
850arm_set_sat_qualifiers[SIMD_MAX_BUILTIN_ARGS]
851  = { qualifier_void, qualifier_none };
852#define SET_SAT_QUALIFIERS (arm_set_sat_qualifiers)
853
854#define v8qi_UP  E_V8QImode
855#define v4hi_UP  E_V4HImode
856#define v4hf_UP  E_V4HFmode
857#define v4bf_UP  E_V4BFmode
858#define v2si_UP  E_V2SImode
859#define v2sf_UP  E_V2SFmode
860#define v2bf_UP  E_V2BFmode
861#define di_UP    E_DImode
862#define v16qi_UP E_V16QImode
863#define v8hi_UP  E_V8HImode
864#define v8hf_UP  E_V8HFmode
865#define v8bf_UP  E_V8BFmode
866#define v4si_UP  E_V4SImode
867#define v4sf_UP  E_V4SFmode
868#define v2di_UP  E_V2DImode
869#define ti_UP	 E_TImode
870#define ei_UP	 E_EImode
871#define oi_UP	 E_OImode
872#define hf_UP	 E_HFmode
873#define bf_UP    E_BFmode
874#define si_UP	 E_SImode
875#define hi_UP    E_HImode
876#define void_UP	 E_VOIDmode
877#define sf_UP	 E_SFmode
878#define UP(X) X##_UP
879
880typedef struct {
881  const char *name;
882  machine_mode mode;
883  const enum insn_code code;
884  unsigned int fcode;
885  enum arm_type_qualifiers *qualifiers;
886} arm_builtin_datum;
887
888#define CF(N,X) CODE_FOR_neon_##N##X
889
890#define VAR1(T, N, A) \
891  {#N #A, UP (A), CF (N, A), 0, T##_QUALIFIERS},
892#define VAR2(T, N, A, B) \
893  VAR1 (T, N, A) \
894  VAR1 (T, N, B)
895#define VAR3(T, N, A, B, C) \
896  VAR2 (T, N, A, B) \
897  VAR1 (T, N, C)
898#define VAR4(T, N, A, B, C, D) \
899  VAR3 (T, N, A, B, C) \
900  VAR1 (T, N, D)
901#define VAR5(T, N, A, B, C, D, E) \
902  VAR4 (T, N, A, B, C, D) \
903  VAR1 (T, N, E)
904#define VAR6(T, N, A, B, C, D, E, F) \
905  VAR5 (T, N, A, B, C, D, E) \
906  VAR1 (T, N, F)
907#define VAR7(T, N, A, B, C, D, E, F, G) \
908  VAR6 (T, N, A, B, C, D, E, F) \
909  VAR1 (T, N, G)
910#define VAR8(T, N, A, B, C, D, E, F, G, H) \
911  VAR7 (T, N, A, B, C, D, E, F, G) \
912  VAR1 (T, N, H)
913#define VAR9(T, N, A, B, C, D, E, F, G, H, I) \
914  VAR8 (T, N, A, B, C, D, E, F, G, H) \
915  VAR1 (T, N, I)
916#define VAR10(T, N, A, B, C, D, E, F, G, H, I, J) \
917  VAR9 (T, N, A, B, C, D, E, F, G, H, I) \
918  VAR1 (T, N, J)
919#define VAR11(T, N, A, B, C, D, E, F, G, H, I, J, K) \
920  VAR10 (T, N, A, B, C, D, E, F, G, H, I, J) \
921  VAR1 (T, N, K)
922#define VAR12(T, N, A, B, C, D, E, F, G, H, I, J, K, L) \
923  VAR11 (T, N, A, B, C, D, E, F, G, H, I, J, K) \
924  VAR1 (T, N, L)
925#define VAR13(T, N, A, B, C, D, E, F, G, H, I, J, K, L, M) \
926  VAR12 (T, N, A, B, C, D, E, F, G, H, I, J, K, L) \
927  VAR1 (T, N, M)
928#define VAR14(T, N, A, B, C, D, E, F, G, H, I, J, K, L, M, O) \
929  VAR13 (T, N, A, B, C, D, E, F, G, H, I, J, K, L, M) \
930  VAR1 (T, N, O)
931
932/* The builtin data can be found in arm_neon_builtins.def, arm_vfp_builtins.def
933   and arm_acle_builtins.def.  The entries in arm_neon_builtins.def require
934   TARGET_NEON to be true.  The feature tests are checked when the builtins are
935   expanded.
936
937   The mode entries in the following table correspond to the "key" type of the
938   instruction variant, i.e. equivalent to that which would be specified after
939   the assembler mnemonic for neon instructions, which usually refers to the
940   last vector operand.  The modes listed per instruction should be the same as
941   those defined for that instruction's pattern, for instance in neon.md.  */
942
943static arm_builtin_datum vfp_builtin_data[] =
944{
945#include "arm_vfp_builtins.def"
946};
947
948static arm_builtin_datum neon_builtin_data[] =
949{
950#include "arm_neon_builtins.def"
951};
952
953#undef CF
954#define CF(N,X) CODE_FOR_mve_##N##X
955static arm_builtin_datum mve_builtin_data[] =
956{
957#include "arm_mve_builtins.def"
958};
959
960#undef CF
961#undef VAR1
962#define VAR1(T, N, A) \
963  {#N, UP (A), CODE_FOR_arm_##N, 0, T##_QUALIFIERS},
964
965static arm_builtin_datum acle_builtin_data[] =
966{
967#include "arm_acle_builtins.def"
968};
969
970#undef VAR1
971/* IMM_MAX sets the maximum valid value of the CDE immediate operand.
972   ECF_FLAG sets the flag used for set_call_expr_flags.  */
973#define VAR1(T, N, A, IMM_MAX, ECF_FLAG) \
974  {{#N #A, UP (A), CODE_FOR_arm_##N##A, 0, T##_QUALIFIERS}, IMM_MAX, ECF_FLAG},
975
976typedef struct {
977  arm_builtin_datum base;
978  unsigned int imm_max;
979  int ecf_flag;
980} arm_builtin_cde_datum;
981
982static arm_builtin_cde_datum cde_builtin_data[] =
983{
984#include "arm_cde_builtins.def"
985};
986
987#undef VAR1
988#define VAR1(T, N, X) \
989  ARM_BUILTIN_NEON_##N##X,
990
991enum arm_builtins
992{
993  ARM_BUILTIN_GETWCGR0,
994  ARM_BUILTIN_GETWCGR1,
995  ARM_BUILTIN_GETWCGR2,
996  ARM_BUILTIN_GETWCGR3,
997
998  ARM_BUILTIN_SETWCGR0,
999  ARM_BUILTIN_SETWCGR1,
1000  ARM_BUILTIN_SETWCGR2,
1001  ARM_BUILTIN_SETWCGR3,
1002
1003  ARM_BUILTIN_WZERO,
1004
1005  ARM_BUILTIN_WAVG2BR,
1006  ARM_BUILTIN_WAVG2HR,
1007  ARM_BUILTIN_WAVG2B,
1008  ARM_BUILTIN_WAVG2H,
1009
1010  ARM_BUILTIN_WACCB,
1011  ARM_BUILTIN_WACCH,
1012  ARM_BUILTIN_WACCW,
1013
1014  ARM_BUILTIN_WMACS,
1015  ARM_BUILTIN_WMACSZ,
1016  ARM_BUILTIN_WMACU,
1017  ARM_BUILTIN_WMACUZ,
1018
1019  ARM_BUILTIN_WSADB,
1020  ARM_BUILTIN_WSADBZ,
1021  ARM_BUILTIN_WSADH,
1022  ARM_BUILTIN_WSADHZ,
1023
1024  ARM_BUILTIN_WALIGNI,
1025  ARM_BUILTIN_WALIGNR0,
1026  ARM_BUILTIN_WALIGNR1,
1027  ARM_BUILTIN_WALIGNR2,
1028  ARM_BUILTIN_WALIGNR3,
1029
1030  ARM_BUILTIN_TMIA,
1031  ARM_BUILTIN_TMIAPH,
1032  ARM_BUILTIN_TMIABB,
1033  ARM_BUILTIN_TMIABT,
1034  ARM_BUILTIN_TMIATB,
1035  ARM_BUILTIN_TMIATT,
1036
1037  ARM_BUILTIN_TMOVMSKB,
1038  ARM_BUILTIN_TMOVMSKH,
1039  ARM_BUILTIN_TMOVMSKW,
1040
1041  ARM_BUILTIN_TBCSTB,
1042  ARM_BUILTIN_TBCSTH,
1043  ARM_BUILTIN_TBCSTW,
1044
1045  ARM_BUILTIN_WMADDS,
1046  ARM_BUILTIN_WMADDU,
1047
1048  ARM_BUILTIN_WPACKHSS,
1049  ARM_BUILTIN_WPACKWSS,
1050  ARM_BUILTIN_WPACKDSS,
1051  ARM_BUILTIN_WPACKHUS,
1052  ARM_BUILTIN_WPACKWUS,
1053  ARM_BUILTIN_WPACKDUS,
1054
1055  ARM_BUILTIN_WADDB,
1056  ARM_BUILTIN_WADDH,
1057  ARM_BUILTIN_WADDW,
1058  ARM_BUILTIN_WADDSSB,
1059  ARM_BUILTIN_WADDSSH,
1060  ARM_BUILTIN_WADDSSW,
1061  ARM_BUILTIN_WADDUSB,
1062  ARM_BUILTIN_WADDUSH,
1063  ARM_BUILTIN_WADDUSW,
1064  ARM_BUILTIN_WSUBB,
1065  ARM_BUILTIN_WSUBH,
1066  ARM_BUILTIN_WSUBW,
1067  ARM_BUILTIN_WSUBSSB,
1068  ARM_BUILTIN_WSUBSSH,
1069  ARM_BUILTIN_WSUBSSW,
1070  ARM_BUILTIN_WSUBUSB,
1071  ARM_BUILTIN_WSUBUSH,
1072  ARM_BUILTIN_WSUBUSW,
1073
1074  ARM_BUILTIN_WAND,
1075  ARM_BUILTIN_WANDN,
1076  ARM_BUILTIN_WOR,
1077  ARM_BUILTIN_WXOR,
1078
1079  ARM_BUILTIN_WCMPEQB,
1080  ARM_BUILTIN_WCMPEQH,
1081  ARM_BUILTIN_WCMPEQW,
1082  ARM_BUILTIN_WCMPGTUB,
1083  ARM_BUILTIN_WCMPGTUH,
1084  ARM_BUILTIN_WCMPGTUW,
1085  ARM_BUILTIN_WCMPGTSB,
1086  ARM_BUILTIN_WCMPGTSH,
1087  ARM_BUILTIN_WCMPGTSW,
1088
1089  ARM_BUILTIN_TEXTRMSB,
1090  ARM_BUILTIN_TEXTRMSH,
1091  ARM_BUILTIN_TEXTRMSW,
1092  ARM_BUILTIN_TEXTRMUB,
1093  ARM_BUILTIN_TEXTRMUH,
1094  ARM_BUILTIN_TEXTRMUW,
1095  ARM_BUILTIN_TINSRB,
1096  ARM_BUILTIN_TINSRH,
1097  ARM_BUILTIN_TINSRW,
1098
1099  ARM_BUILTIN_WMAXSW,
1100  ARM_BUILTIN_WMAXSH,
1101  ARM_BUILTIN_WMAXSB,
1102  ARM_BUILTIN_WMAXUW,
1103  ARM_BUILTIN_WMAXUH,
1104  ARM_BUILTIN_WMAXUB,
1105  ARM_BUILTIN_WMINSW,
1106  ARM_BUILTIN_WMINSH,
1107  ARM_BUILTIN_WMINSB,
1108  ARM_BUILTIN_WMINUW,
1109  ARM_BUILTIN_WMINUH,
1110  ARM_BUILTIN_WMINUB,
1111
1112  ARM_BUILTIN_WMULUM,
1113  ARM_BUILTIN_WMULSM,
1114  ARM_BUILTIN_WMULUL,
1115
1116  ARM_BUILTIN_PSADBH,
1117  ARM_BUILTIN_WSHUFH,
1118
1119  ARM_BUILTIN_WSLLH,
1120  ARM_BUILTIN_WSLLW,
1121  ARM_BUILTIN_WSLLD,
1122  ARM_BUILTIN_WSRAH,
1123  ARM_BUILTIN_WSRAW,
1124  ARM_BUILTIN_WSRAD,
1125  ARM_BUILTIN_WSRLH,
1126  ARM_BUILTIN_WSRLW,
1127  ARM_BUILTIN_WSRLD,
1128  ARM_BUILTIN_WRORH,
1129  ARM_BUILTIN_WRORW,
1130  ARM_BUILTIN_WRORD,
1131  ARM_BUILTIN_WSLLHI,
1132  ARM_BUILTIN_WSLLWI,
1133  ARM_BUILTIN_WSLLDI,
1134  ARM_BUILTIN_WSRAHI,
1135  ARM_BUILTIN_WSRAWI,
1136  ARM_BUILTIN_WSRADI,
1137  ARM_BUILTIN_WSRLHI,
1138  ARM_BUILTIN_WSRLWI,
1139  ARM_BUILTIN_WSRLDI,
1140  ARM_BUILTIN_WRORHI,
1141  ARM_BUILTIN_WRORWI,
1142  ARM_BUILTIN_WRORDI,
1143
1144  ARM_BUILTIN_WUNPCKIHB,
1145  ARM_BUILTIN_WUNPCKIHH,
1146  ARM_BUILTIN_WUNPCKIHW,
1147  ARM_BUILTIN_WUNPCKILB,
1148  ARM_BUILTIN_WUNPCKILH,
1149  ARM_BUILTIN_WUNPCKILW,
1150
1151  ARM_BUILTIN_WUNPCKEHSB,
1152  ARM_BUILTIN_WUNPCKEHSH,
1153  ARM_BUILTIN_WUNPCKEHSW,
1154  ARM_BUILTIN_WUNPCKEHUB,
1155  ARM_BUILTIN_WUNPCKEHUH,
1156  ARM_BUILTIN_WUNPCKEHUW,
1157  ARM_BUILTIN_WUNPCKELSB,
1158  ARM_BUILTIN_WUNPCKELSH,
1159  ARM_BUILTIN_WUNPCKELSW,
1160  ARM_BUILTIN_WUNPCKELUB,
1161  ARM_BUILTIN_WUNPCKELUH,
1162  ARM_BUILTIN_WUNPCKELUW,
1163
1164  ARM_BUILTIN_WABSB,
1165  ARM_BUILTIN_WABSH,
1166  ARM_BUILTIN_WABSW,
1167
1168  ARM_BUILTIN_WADDSUBHX,
1169  ARM_BUILTIN_WSUBADDHX,
1170
1171  ARM_BUILTIN_WABSDIFFB,
1172  ARM_BUILTIN_WABSDIFFH,
1173  ARM_BUILTIN_WABSDIFFW,
1174
1175  ARM_BUILTIN_WADDCH,
1176  ARM_BUILTIN_WADDCW,
1177
1178  ARM_BUILTIN_WAVG4,
1179  ARM_BUILTIN_WAVG4R,
1180
1181  ARM_BUILTIN_WMADDSX,
1182  ARM_BUILTIN_WMADDUX,
1183
1184  ARM_BUILTIN_WMADDSN,
1185  ARM_BUILTIN_WMADDUN,
1186
1187  ARM_BUILTIN_WMULWSM,
1188  ARM_BUILTIN_WMULWUM,
1189
1190  ARM_BUILTIN_WMULWSMR,
1191  ARM_BUILTIN_WMULWUMR,
1192
1193  ARM_BUILTIN_WMULWL,
1194
1195  ARM_BUILTIN_WMULSMR,
1196  ARM_BUILTIN_WMULUMR,
1197
1198  ARM_BUILTIN_WQMULM,
1199  ARM_BUILTIN_WQMULMR,
1200
1201  ARM_BUILTIN_WQMULWM,
1202  ARM_BUILTIN_WQMULWMR,
1203
1204  ARM_BUILTIN_WADDBHUSM,
1205  ARM_BUILTIN_WADDBHUSL,
1206
1207  ARM_BUILTIN_WQMIABB,
1208  ARM_BUILTIN_WQMIABT,
1209  ARM_BUILTIN_WQMIATB,
1210  ARM_BUILTIN_WQMIATT,
1211
1212  ARM_BUILTIN_WQMIABBN,
1213  ARM_BUILTIN_WQMIABTN,
1214  ARM_BUILTIN_WQMIATBN,
1215  ARM_BUILTIN_WQMIATTN,
1216
1217  ARM_BUILTIN_WMIABB,
1218  ARM_BUILTIN_WMIABT,
1219  ARM_BUILTIN_WMIATB,
1220  ARM_BUILTIN_WMIATT,
1221
1222  ARM_BUILTIN_WMIABBN,
1223  ARM_BUILTIN_WMIABTN,
1224  ARM_BUILTIN_WMIATBN,
1225  ARM_BUILTIN_WMIATTN,
1226
1227  ARM_BUILTIN_WMIAWBB,
1228  ARM_BUILTIN_WMIAWBT,
1229  ARM_BUILTIN_WMIAWTB,
1230  ARM_BUILTIN_WMIAWTT,
1231
1232  ARM_BUILTIN_WMIAWBBN,
1233  ARM_BUILTIN_WMIAWBTN,
1234  ARM_BUILTIN_WMIAWTBN,
1235  ARM_BUILTIN_WMIAWTTN,
1236
1237  ARM_BUILTIN_WMERGE,
1238
1239  ARM_BUILTIN_GET_FPSCR,
1240  ARM_BUILTIN_SET_FPSCR,
1241  ARM_BUILTIN_GET_FPSCR_NZCVQC,
1242  ARM_BUILTIN_SET_FPSCR_NZCVQC,
1243
1244  ARM_BUILTIN_CMSE_NONSECURE_CALLER,
1245  ARM_BUILTIN_SIMD_LANE_CHECK,
1246
1247#undef CRYPTO1
1248#undef CRYPTO2
1249#undef CRYPTO3
1250
1251#define CRYPTO1(L, U, M1, M2) \
1252  ARM_BUILTIN_CRYPTO_##U,
1253#define CRYPTO2(L, U, M1, M2, M3) \
1254  ARM_BUILTIN_CRYPTO_##U,
1255#define CRYPTO3(L, U, M1, M2, M3, M4) \
1256  ARM_BUILTIN_CRYPTO_##U,
1257
1258  ARM_BUILTIN_CRYPTO_BASE,
1259
1260#include "crypto.def"
1261
1262#undef CRYPTO1
1263#undef CRYPTO2
1264#undef CRYPTO3
1265
1266  ARM_BUILTIN_VFP_BASE,
1267
1268#include "arm_vfp_builtins.def"
1269
1270  ARM_BUILTIN_NEON_BASE,
1271
1272#include "arm_neon_builtins.def"
1273
1274#undef VAR1
1275#define VAR1(T, N, X) \
1276  ARM_BUILTIN_##N,
1277
1278  ARM_BUILTIN_ACLE_BASE,
1279  ARM_BUILTIN_SAT_IMM_CHECK = ARM_BUILTIN_ACLE_BASE,
1280
1281#include "arm_acle_builtins.def"
1282
1283#undef VAR1
1284#define VAR1(T, N, X, ... ) \
1285  ARM_BUILTIN_##N##X,
1286
1287  ARM_BUILTIN_CDE_BASE,
1288
1289#include "arm_cde_builtins.def"
1290
1291  ARM_BUILTIN_MVE_BASE,
1292
1293#undef VAR1
1294#define VAR1(T, N, X) \
1295  ARM_BUILTIN_MVE_##N##X,
1296#include "arm_mve_builtins.def"
1297
1298  ARM_BUILTIN_MAX
1299};
1300
1301#define ARM_BUILTIN_VFP_PATTERN_START \
1302  (ARM_BUILTIN_VFP_BASE + 1)
1303
1304#define ARM_BUILTIN_NEON_PATTERN_START \
1305  (ARM_BUILTIN_NEON_BASE + 1)
1306
1307#define ARM_BUILTIN_MVE_PATTERN_START \
1308  (ARM_BUILTIN_MVE_BASE + 1)
1309
1310#define ARM_BUILTIN_ACLE_PATTERN_START \
1311  (ARM_BUILTIN_ACLE_BASE + 1)
1312
1313#define ARM_BUILTIN_CDE_PATTERN_START \
1314  (ARM_BUILTIN_CDE_BASE + 1)
1315
1316#define ARM_BUILTIN_CDE_PATTERN_END \
1317  (ARM_BUILTIN_CDE_BASE + ARRAY_SIZE (cde_builtin_data))
1318
1319#undef CF
1320#undef VAR1
1321#undef VAR2
1322#undef VAR3
1323#undef VAR4
1324#undef VAR5
1325#undef VAR6
1326#undef VAR7
1327#undef VAR8
1328#undef VAR9
1329#undef VAR10
1330
1331static GTY(()) tree arm_builtin_decls[ARM_BUILTIN_MAX];
1332
1333#define NUM_DREG_TYPES 5
1334#define NUM_QREG_TYPES 6
1335
1336/* Internal scalar builtin types.  These types are used to support
1337   neon intrinsic builtins.  They are _not_ user-visible types.  Therefore
1338   the mangling for these types are implementation defined.  */
1339const char *arm_scalar_builtin_types[] = {
1340  "__builtin_neon_qi",
1341  "__builtin_neon_hi",
1342  "__builtin_neon_si",
1343  "__builtin_neon_sf",
1344  "__builtin_neon_di",
1345  "__builtin_neon_df",
1346  "__builtin_neon_ti",
1347  "__builtin_neon_uqi",
1348  "__builtin_neon_uhi",
1349  "__builtin_neon_usi",
1350  "__builtin_neon_udi",
1351  "__builtin_neon_ei",
1352  "__builtin_neon_oi",
1353  "__builtin_neon_ci",
1354  "__builtin_neon_xi",
1355  "__builtin_neon_bf",
1356  NULL
1357};
1358
1359#define ENTRY(E, M, Q, S, T, G)		\
1360  {E,					\
1361   "__simd" #S "_" #T "_t",		\
1362   #G "__simd" #S "_" #T "_t",		\
1363   NULL_TREE, NULL_TREE, M##mode, qualifier_##Q},
1364struct arm_simd_type_info arm_simd_types [] = {
1365#include "arm-simd-builtin-types.def"
1366};
1367#undef ENTRY
1368
1369/* The user-visible __fp16 type.  */
1370tree arm_fp16_type_node = NULL_TREE;
1371
1372/* Back-end node type for brain float (bfloat) types.  */
1373tree arm_bf16_type_node = NULL_TREE;
1374tree arm_bf16_ptr_type_node = NULL_TREE;
1375
1376static tree arm_simd_intOI_type_node = NULL_TREE;
1377static tree arm_simd_intEI_type_node = NULL_TREE;
1378static tree arm_simd_intCI_type_node = NULL_TREE;
1379static tree arm_simd_intXI_type_node = NULL_TREE;
1380static tree arm_simd_polyQI_type_node = NULL_TREE;
1381static tree arm_simd_polyHI_type_node = NULL_TREE;
1382static tree arm_simd_polyDI_type_node = NULL_TREE;
1383static tree arm_simd_polyTI_type_node = NULL_TREE;
1384
1385static const char *
1386arm_mangle_builtin_scalar_type (const_tree type)
1387{
1388  int i = 0;
1389
1390  while (arm_scalar_builtin_types[i] != NULL)
1391    {
1392      const char *name = arm_scalar_builtin_types[i];
1393
1394      if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
1395	  && DECL_NAME (TYPE_NAME (type))
1396	  && !strcmp (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))), name))
1397	return arm_scalar_builtin_types[i];
1398      i++;
1399    }
1400  return NULL;
1401}
1402
1403static const char *
1404arm_mangle_builtin_vector_type (const_tree type)
1405{
1406  tree attrs = TYPE_ATTRIBUTES (type);
1407  if (tree attr = lookup_attribute ("Advanced SIMD type", attrs))
1408    {
1409      tree mangled_name = TREE_VALUE (TREE_VALUE (attr));
1410      return IDENTIFIER_POINTER (mangled_name);
1411    }
1412
1413  return NULL;
1414}
1415
1416const char *
1417arm_mangle_builtin_type (const_tree type)
1418{
1419  const char *mangle;
1420  /* Walk through all the Arm builtins types tables to filter out the
1421     incoming type.  */
1422  if ((mangle = arm_mangle_builtin_vector_type (type))
1423      || (mangle = arm_mangle_builtin_scalar_type (type)))
1424    return mangle;
1425
1426  return NULL;
1427}
1428
1429static tree
1430arm_simd_builtin_std_type (machine_mode mode,
1431			   enum arm_type_qualifiers q)
1432{
1433#define QUAL_TYPE(M)  \
1434  ((q == qualifier_none) ? int##M##_type_node : unsigned_int##M##_type_node);
1435  switch (mode)
1436    {
1437    case E_QImode:
1438      return QUAL_TYPE (QI);
1439    case E_HImode:
1440      return QUAL_TYPE (HI);
1441    case E_SImode:
1442      return QUAL_TYPE (SI);
1443    case E_DImode:
1444      return QUAL_TYPE (DI);
1445    case E_TImode:
1446      return QUAL_TYPE (TI);
1447    case E_OImode:
1448      return arm_simd_intOI_type_node;
1449    case E_EImode:
1450      return arm_simd_intEI_type_node;
1451    case E_CImode:
1452      return arm_simd_intCI_type_node;
1453    case E_XImode:
1454      return arm_simd_intXI_type_node;
1455    case E_HFmode:
1456      return arm_fp16_type_node;
1457    case E_SFmode:
1458      return float_type_node;
1459    case E_DFmode:
1460      return double_type_node;
1461    case E_BFmode:
1462      return arm_bf16_type_node;
1463    default:
1464      gcc_unreachable ();
1465    }
1466#undef QUAL_TYPE
1467}
1468
1469static tree
1470arm_lookup_simd_builtin_type (machine_mode mode,
1471			      enum arm_type_qualifiers q)
1472{
1473  int i;
1474  int nelts = sizeof (arm_simd_types) / sizeof (arm_simd_types[0]);
1475
1476  /* Non-poly scalar modes map to standard types not in the table.  */
1477  if (q != qualifier_poly && !VECTOR_MODE_P (mode))
1478    return arm_simd_builtin_std_type (mode, q);
1479
1480  for (i = 0; i < nelts; i++)
1481    if (arm_simd_types[i].mode == mode
1482	&& arm_simd_types[i].q == q)
1483      return arm_simd_types[i].itype;
1484
1485  /* Note that we won't have caught the underlying type for poly64x2_t
1486     in the above table.  This gets default mangling.  */
1487
1488  return NULL_TREE;
1489}
1490
1491static tree
1492arm_simd_builtin_type (machine_mode mode, bool unsigned_p, bool poly_p)
1493{
1494  if (poly_p)
1495    return arm_lookup_simd_builtin_type (mode, qualifier_poly);
1496  else if (unsigned_p)
1497    return arm_lookup_simd_builtin_type (mode, qualifier_unsigned);
1498  else
1499    return arm_lookup_simd_builtin_type (mode, qualifier_none);
1500}
1501
1502static void
1503arm_init_simd_builtin_types (void)
1504{
1505  int i;
1506  int nelts = sizeof (arm_simd_types) / sizeof (arm_simd_types[0]);
1507  tree tdecl;
1508
1509  /* Poly types are a world of their own.  In order to maintain legacy
1510     ABI, they get initialized using the old interface, and don't get
1511     an entry in our mangling table, consequently, they get default
1512     mangling.  As a further gotcha, poly8_t and poly16_t are signed
1513     types, poly64_t and poly128_t are unsigned types.  */
1514  if (!TARGET_HAVE_MVE)
1515    {
1516      arm_simd_polyQI_type_node
1517	= build_distinct_type_copy (intQI_type_node);
1518      (*lang_hooks.types.register_builtin_type) (arm_simd_polyQI_type_node,
1519						 "__builtin_neon_poly8");
1520      arm_simd_polyHI_type_node
1521	= build_distinct_type_copy (intHI_type_node);
1522      (*lang_hooks.types.register_builtin_type) (arm_simd_polyHI_type_node,
1523						 "__builtin_neon_poly16");
1524      arm_simd_polyDI_type_node
1525	= build_distinct_type_copy (unsigned_intDI_type_node);
1526      (*lang_hooks.types.register_builtin_type) (arm_simd_polyDI_type_node,
1527						 "__builtin_neon_poly64");
1528      arm_simd_polyTI_type_node
1529	= build_distinct_type_copy (unsigned_intTI_type_node);
1530      (*lang_hooks.types.register_builtin_type) (arm_simd_polyTI_type_node,
1531						 "__builtin_neon_poly128");
1532      /* Init poly vector element types with scalar poly types.  */
1533      arm_simd_types[Poly8x8_t].eltype = arm_simd_polyQI_type_node;
1534      arm_simd_types[Poly8x16_t].eltype = arm_simd_polyQI_type_node;
1535      arm_simd_types[Poly16x4_t].eltype = arm_simd_polyHI_type_node;
1536      arm_simd_types[Poly16x8_t].eltype = arm_simd_polyHI_type_node;
1537      /* Note: poly64x2_t is defined in arm_neon.h, to ensure it gets default
1538	 mangling.  */
1539
1540      /* Prevent front-ends from transforming poly vectors into string
1541	 literals.  */
1542      TYPE_STRING_FLAG (arm_simd_polyQI_type_node) = false;
1543      TYPE_STRING_FLAG (arm_simd_polyHI_type_node) = false;
1544    }
1545  /* Init all the element types built by the front-end.  */
1546  arm_simd_types[Int8x8_t].eltype = intQI_type_node;
1547  arm_simd_types[Int8x16_t].eltype = intQI_type_node;
1548  arm_simd_types[Int16x4_t].eltype = intHI_type_node;
1549  arm_simd_types[Int16x8_t].eltype = intHI_type_node;
1550  arm_simd_types[Int32x2_t].eltype = intSI_type_node;
1551  arm_simd_types[Int32x4_t].eltype = intSI_type_node;
1552  arm_simd_types[Int64x2_t].eltype = intDI_type_node;
1553  arm_simd_types[Uint8x8_t].eltype = unsigned_intQI_type_node;
1554  arm_simd_types[Uint8x16_t].eltype = unsigned_intQI_type_node;
1555  arm_simd_types[Uint16x4_t].eltype = unsigned_intHI_type_node;
1556  arm_simd_types[Uint16x8_t].eltype = unsigned_intHI_type_node;
1557  arm_simd_types[Uint32x2_t].eltype = unsigned_intSI_type_node;
1558  arm_simd_types[Uint32x4_t].eltype = unsigned_intSI_type_node;
1559  arm_simd_types[Uint64x2_t].eltype = unsigned_intDI_type_node;
1560
1561  /* Note: poly64x2_t is defined in arm_neon.h, to ensure it gets default
1562     mangling.  */
1563
1564  /* Continue with standard types.  */
1565  /* The __builtin_simd{64,128}_float16 types are kept private unless
1566     we have a scalar __fp16 type.  */
1567  arm_simd_types[Float16x4_t].eltype = arm_fp16_type_node;
1568  arm_simd_types[Float16x8_t].eltype = arm_fp16_type_node;
1569  arm_simd_types[Float32x2_t].eltype = float_type_node;
1570  arm_simd_types[Float32x4_t].eltype = float_type_node;
1571
1572  /* Init Bfloat vector types with underlying __bf16 scalar type.  */
1573  arm_simd_types[Bfloat16x2_t].eltype = arm_bf16_type_node;
1574  arm_simd_types[Bfloat16x4_t].eltype = arm_bf16_type_node;
1575  arm_simd_types[Bfloat16x8_t].eltype = arm_bf16_type_node;
1576
1577  for (i = 0; i < nelts; i++)
1578    {
1579      tree eltype = arm_simd_types[i].eltype;
1580      machine_mode mode = arm_simd_types[i].mode;
1581
1582      if (eltype == NULL
1583	  /* VECTOR_BOOL is not supported unless MVE is activated,
1584	     this would make build_truth_vector_type_for_mode
1585	     crash.  */
1586	  && ((GET_MODE_CLASS (mode) != MODE_VECTOR_BOOL)
1587	      || !TARGET_HAVE_MVE))
1588	continue;
1589      if (arm_simd_types[i].itype == NULL)
1590	{
1591	  tree type;
1592	  if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL)
1593	    {
1594	      /* Handle MVE predicates: they are internally stored as
1595		 16 bits, but are used as vectors of 1, 2 or 4-bit
1596		 elements.  */
1597	      type = build_truth_vector_type_for_mode (GET_MODE_NUNITS (mode),
1598						       mode);
1599	      eltype = TREE_TYPE (type);
1600	    }
1601	  else
1602	    type = build_vector_type (eltype, GET_MODE_NUNITS (mode));
1603
1604	  type = build_distinct_type_copy (type);
1605	  SET_TYPE_STRUCTURAL_EQUALITY (type);
1606
1607	  tree mangled_name = get_identifier (arm_simd_types[i].mangle);
1608	  tree value = tree_cons (NULL_TREE, mangled_name, NULL_TREE);
1609	  TYPE_ATTRIBUTES (type)
1610	    = tree_cons (get_identifier ("Advanced SIMD type"), value,
1611			 TYPE_ATTRIBUTES (type));
1612	  arm_simd_types[i].itype = type;
1613	}
1614
1615      tdecl = add_builtin_type (arm_simd_types[i].name,
1616				arm_simd_types[i].itype);
1617      TYPE_NAME (arm_simd_types[i].itype) = tdecl;
1618      SET_TYPE_STRUCTURAL_EQUALITY (arm_simd_types[i].itype);
1619    }
1620
1621#define AARCH_BUILD_SIGNED_TYPE(mode)  \
1622  make_signed_type (GET_MODE_PRECISION (mode));
1623  arm_simd_intOI_type_node = AARCH_BUILD_SIGNED_TYPE (OImode);
1624  arm_simd_intEI_type_node = AARCH_BUILD_SIGNED_TYPE (EImode);
1625  arm_simd_intCI_type_node = AARCH_BUILD_SIGNED_TYPE (CImode);
1626  arm_simd_intXI_type_node = AARCH_BUILD_SIGNED_TYPE (XImode);
1627#undef AARCH_BUILD_SIGNED_TYPE
1628
1629  tdecl = add_builtin_type
1630	    ("__builtin_neon_ei" , arm_simd_intEI_type_node);
1631  TYPE_NAME (arm_simd_intEI_type_node) = tdecl;
1632  tdecl = add_builtin_type
1633	    ("__builtin_neon_oi" , arm_simd_intOI_type_node);
1634  TYPE_NAME (arm_simd_intOI_type_node) = tdecl;
1635  tdecl = add_builtin_type
1636	    ("__builtin_neon_ci" , arm_simd_intCI_type_node);
1637  TYPE_NAME (arm_simd_intCI_type_node) = tdecl;
1638  tdecl = add_builtin_type
1639	    ("__builtin_neon_xi" , arm_simd_intXI_type_node);
1640  TYPE_NAME (arm_simd_intXI_type_node) = tdecl;
1641}
1642
1643static void
1644arm_init_simd_builtin_scalar_types (void)
1645{
1646  /* Define typedefs for all the standard scalar types.  */
1647  (*lang_hooks.types.register_builtin_type) (intQI_type_node,
1648					     "__builtin_neon_qi");
1649  (*lang_hooks.types.register_builtin_type) (intHI_type_node,
1650					     "__builtin_neon_hi");
1651  (*lang_hooks.types.register_builtin_type) (intSI_type_node,
1652					     "__builtin_neon_si");
1653  (*lang_hooks.types.register_builtin_type) (float_type_node,
1654					     "__builtin_neon_sf");
1655  (*lang_hooks.types.register_builtin_type) (intDI_type_node,
1656					     "__builtin_neon_di");
1657  (*lang_hooks.types.register_builtin_type) (double_type_node,
1658					     "__builtin_neon_df");
1659  (*lang_hooks.types.register_builtin_type) (intTI_type_node,
1660					     "__builtin_neon_ti");
1661  (*lang_hooks.types.register_builtin_type) (arm_bf16_type_node,
1662                                             "__builtin_neon_bf");
1663  /* Unsigned integer types for various mode sizes.  */
1664  (*lang_hooks.types.register_builtin_type) (unsigned_intQI_type_node,
1665					     "__builtin_neon_uqi");
1666  (*lang_hooks.types.register_builtin_type) (unsigned_intHI_type_node,
1667					     "__builtin_neon_uhi");
1668  (*lang_hooks.types.register_builtin_type) (unsigned_intSI_type_node,
1669					     "__builtin_neon_usi");
1670  (*lang_hooks.types.register_builtin_type) (unsigned_intDI_type_node,
1671					     "__builtin_neon_udi");
1672  (*lang_hooks.types.register_builtin_type) (unsigned_intTI_type_node,
1673					     "__builtin_neon_uti");
1674}
1675
1676/* Set up a builtin.  It will use information stored in the argument struct D to
1677   derive the builtin's type signature and name.  It will append the name in D
1678   to the PREFIX passed and use these to create a builtin declaration that is
1679   then stored in 'arm_builtin_decls' under index FCODE.  This FCODE is also
1680   written back to D for future use.  */
1681
1682static void
1683arm_init_builtin (unsigned int fcode, arm_builtin_datum *d,
1684		  const char * prefix)
1685{
1686  bool print_type_signature_p = false;
1687  char type_signature[SIMD_MAX_BUILTIN_ARGS] = { 0 };
1688  char namebuf[60];
1689  tree ftype = NULL;
1690  tree fndecl = NULL;
1691
1692  d->fcode = fcode;
1693
1694  /* We must track two variables here.  op_num is
1695     the operand number as in the RTL pattern.  This is
1696     required to access the mode (e.g. V4SF mode) of the
1697     argument, from which the base type can be derived.
1698     arg_num is an index in to the qualifiers data, which
1699     gives qualifiers to the type (e.g. const unsigned).
1700     The reason these two variables may differ by one is the
1701     void return type.  While all return types take the 0th entry
1702     in the qualifiers array, there is no operand for them in the
1703     RTL pattern.  */
1704  int op_num = insn_data[d->code].n_operands - 1;
1705  int arg_num = d->qualifiers[0] & qualifier_void
1706    ? op_num + 1
1707    : op_num;
1708  tree return_type = void_type_node, args = void_list_node;
1709  tree eltype;
1710
1711  /* Build a function type directly from the insn_data for this
1712     builtin.  The build_function_type () function takes care of
1713     removing duplicates for us.  */
1714  for (; op_num >= 0; arg_num--, op_num--)
1715    {
1716      machine_mode op_mode = insn_data[d->code].operand[op_num].mode;
1717      enum arm_type_qualifiers qualifiers = d->qualifiers[arg_num];
1718
1719      if (qualifiers & qualifier_unsigned)
1720	{
1721	  type_signature[arg_num] = 'u';
1722	  print_type_signature_p = true;
1723	}
1724      else if (qualifiers & qualifier_poly)
1725	{
1726	  type_signature[arg_num] = 'p';
1727	  print_type_signature_p = true;
1728	}
1729      else
1730	type_signature[arg_num] = 's';
1731
1732      /* Skip an internal operand for vget_{low, high}.  */
1733      if (qualifiers & qualifier_internal)
1734	continue;
1735
1736      /* Some builtins have different user-facing types
1737	 for certain arguments, encoded in d->mode.  */
1738      if (qualifiers & qualifier_map_mode)
1739	op_mode = d->mode;
1740
1741      /* MVE Predicates use HImode as mandated by the ABI: pred16_t is
1742	 unsigned short.  */
1743      if (qualifiers & qualifier_predicate)
1744	op_mode = HImode;
1745
1746      /* For pointers, we want a pointer to the basic type
1747	 of the vector.  */
1748      if (qualifiers & qualifier_pointer && VECTOR_MODE_P (op_mode))
1749	op_mode = GET_MODE_INNER (op_mode);
1750
1751      /* For void pointers we already have nodes constructed by the midend.  */
1752      if (qualifiers & qualifier_void_pointer)
1753	eltype = qualifiers & qualifier_const
1754		 ? const_ptr_type_node : ptr_type_node;
1755      else
1756	{
1757	  eltype
1758	    = arm_simd_builtin_type (op_mode,
1759				     (qualifiers & qualifier_unsigned) != 0,
1760				     (qualifiers & qualifier_poly) != 0);
1761	  gcc_assert (eltype != NULL);
1762
1763	  /* Add qualifiers.  */
1764	  if (qualifiers & qualifier_const)
1765	    eltype = build_qualified_type (eltype, TYPE_QUAL_CONST);
1766
1767	  if (qualifiers & qualifier_pointer)
1768	    eltype = build_pointer_type (eltype);
1769	}
1770      /* If we have reached arg_num == 0, we are at a non-void
1771	 return type.  Otherwise, we are still processing
1772	 arguments.  */
1773      if (arg_num == 0)
1774	return_type = eltype;
1775      else
1776	args = tree_cons (NULL_TREE, eltype, args);
1777    }
1778
1779  ftype = build_function_type (return_type, args);
1780
1781  gcc_assert (ftype != NULL);
1782
1783  if (print_type_signature_p
1784      && IN_RANGE (fcode, ARM_BUILTIN_VFP_BASE, ARM_BUILTIN_ACLE_BASE - 1))
1785    snprintf (namebuf, sizeof (namebuf), "%s_%s_%s",
1786	      prefix, d->name, type_signature);
1787  else
1788    snprintf (namebuf, sizeof (namebuf), "%s_%s",
1789	      prefix, d->name);
1790
1791  fndecl = add_builtin_function (namebuf, ftype, fcode, BUILT_IN_MD,
1792				 NULL, NULL_TREE);
1793  arm_builtin_decls[fcode] = fndecl;
1794}
1795
1796/* Initialize the backend REAL_TYPE type supporting bfloat types.  */
1797static void
1798arm_init_bf16_types (void)
1799{
1800  arm_bf16_type_node = make_node (REAL_TYPE);
1801  TYPE_PRECISION (arm_bf16_type_node) = 16;
1802  SET_TYPE_MODE (arm_bf16_type_node, BFmode);
1803  layout_type (arm_bf16_type_node);
1804
1805  lang_hooks.types.register_builtin_type (arm_bf16_type_node, "__bf16");
1806  arm_bf16_ptr_type_node = build_pointer_type (arm_bf16_type_node);
1807}
1808
1809/* Set up ACLE builtins, even builtins for instructions that are not
1810   in the current target ISA to allow the user to compile particular modules
1811   with different target specific options that differ from the command line
1812   options.  Such builtins will be rejected in arm_expand_builtin.  */
1813
1814static void
1815arm_init_acle_builtins (void)
1816{
1817  unsigned int i, fcode = ARM_BUILTIN_ACLE_PATTERN_START;
1818
1819  tree sat_check_fpr = build_function_type_list (void_type_node,
1820						 intSI_type_node,
1821						 intSI_type_node,
1822						 intSI_type_node,
1823						 NULL);
1824  arm_builtin_decls[ARM_BUILTIN_SAT_IMM_CHECK]
1825    = add_builtin_function ("__builtin_sat_imm_check", sat_check_fpr,
1826			    ARM_BUILTIN_SAT_IMM_CHECK, BUILT_IN_MD,
1827			    NULL, NULL_TREE);
1828
1829  for (i = 0; i < ARRAY_SIZE (acle_builtin_data); i++, fcode++)
1830    {
1831      arm_builtin_datum *d = &acle_builtin_data[i];
1832      arm_init_builtin (fcode, d, "__builtin_arm");
1833    }
1834}
1835
1836static void
1837arm_init_cde_builtins (void)
1838{
1839  unsigned int i, fcode = ARM_BUILTIN_CDE_PATTERN_START;
1840  for (i = 0; i < ARRAY_SIZE (cde_builtin_data); i++, fcode++)
1841    {
1842      /* Only define CDE floating point builtins if the target has floating
1843	 point registers.  NOTE: without HARD_FLOAT we don't have MVE, so we
1844	 can break out of this loop directly here.  */
1845      if (!TARGET_MAYBE_HARD_FLOAT && fcode >= ARM_BUILTIN_vcx1si)
1846	break;
1847      /* Only define CDE/MVE builtins if MVE is available.  */
1848      if (!TARGET_HAVE_MVE && fcode >= ARM_BUILTIN_vcx1qv16qi)
1849	break;
1850      arm_builtin_cde_datum *cde = &cde_builtin_data[i];
1851      arm_builtin_datum *d = &cde->base;
1852      arm_init_builtin (fcode, d, "__builtin_arm");
1853      set_call_expr_flags (arm_builtin_decls[fcode], cde->ecf_flag);
1854    }
1855}
1856
1857/* Set up all the MVE builtins mentioned in arm_mve_builtins.def file.  */
1858static void
1859arm_init_mve_builtins (void)
1860{
1861  volatile unsigned int i, fcode = ARM_BUILTIN_MVE_PATTERN_START;
1862
1863  arm_init_simd_builtin_scalar_types ();
1864  arm_init_simd_builtin_types ();
1865
1866  /* Add support for __builtin_{get,set}_fpscr_nzcvqc, used by MVE intrinsics
1867     that read and/or write the carry bit.  */
1868  tree get_fpscr_nzcvqc = build_function_type_list (intSI_type_node,
1869						    NULL);
1870  tree set_fpscr_nzcvqc = build_function_type_list (void_type_node,
1871						    intSI_type_node,
1872						    NULL);
1873  arm_builtin_decls[ARM_BUILTIN_GET_FPSCR_NZCVQC]
1874    = add_builtin_function ("__builtin_arm_get_fpscr_nzcvqc", get_fpscr_nzcvqc,
1875			    ARM_BUILTIN_GET_FPSCR_NZCVQC, BUILT_IN_MD, NULL,
1876			    NULL_TREE);
1877  arm_builtin_decls[ARM_BUILTIN_SET_FPSCR_NZCVQC]
1878    = add_builtin_function ("__builtin_arm_set_fpscr_nzcvqc", set_fpscr_nzcvqc,
1879			    ARM_BUILTIN_SET_FPSCR_NZCVQC, BUILT_IN_MD, NULL,
1880			    NULL_TREE);
1881
1882  for (i = 0; i < ARRAY_SIZE (mve_builtin_data); i++, fcode++)
1883    {
1884      arm_builtin_datum *d = &mve_builtin_data[i];
1885      arm_init_builtin (fcode, d, "__builtin_mve");
1886    }
1887}
1888
1889/* Set up all the NEON builtins, even builtins for instructions that are not
1890   in the current target ISA to allow the user to compile particular modules
1891   with different target specific options that differ from the command line
1892   options. Such builtins will be rejected in arm_expand_builtin.  */
1893
1894static void
1895arm_init_neon_builtins (void)
1896{
1897  unsigned int i, fcode = ARM_BUILTIN_NEON_PATTERN_START;
1898
1899  arm_init_simd_builtin_types ();
1900
1901  /* Strong-typing hasn't been implemented for all AdvSIMD builtin intrinsics.
1902     Therefore we need to preserve the old __builtin scalar types.  It can be
1903     removed once all the intrinsics become strongly typed using the qualifier
1904     system.  */
1905  arm_init_simd_builtin_scalar_types ();
1906
1907  for (i = 0; i < ARRAY_SIZE (neon_builtin_data); i++, fcode++)
1908    {
1909      arm_builtin_datum *d = &neon_builtin_data[i];
1910      arm_init_builtin (fcode, d, "__builtin_neon");
1911    }
1912}
1913
1914/* Set up all the scalar floating point builtins.  */
1915
1916static void
1917arm_init_vfp_builtins (void)
1918{
1919  unsigned int i, fcode = ARM_BUILTIN_VFP_PATTERN_START;
1920
1921  for (i = 0; i < ARRAY_SIZE (vfp_builtin_data); i++, fcode++)
1922    {
1923      arm_builtin_datum *d = &vfp_builtin_data[i];
1924      arm_init_builtin (fcode, d, "__builtin_neon");
1925    }
1926}
1927
1928static void
1929arm_init_crypto_builtins (void)
1930{
1931  tree V16UQI_type_node
1932    = arm_simd_builtin_type (V16QImode, true, false);
1933
1934  tree V4USI_type_node
1935    = arm_simd_builtin_type (V4SImode, true, false);
1936
1937  tree v16uqi_ftype_v16uqi
1938    = build_function_type_list (V16UQI_type_node, V16UQI_type_node,
1939				NULL_TREE);
1940
1941  tree v16uqi_ftype_v16uqi_v16uqi
1942	= build_function_type_list (V16UQI_type_node, V16UQI_type_node,
1943				    V16UQI_type_node, NULL_TREE);
1944
1945  tree v4usi_ftype_v4usi
1946    = build_function_type_list (V4USI_type_node, V4USI_type_node,
1947				NULL_TREE);
1948
1949  tree v4usi_ftype_v4usi_v4usi
1950    = build_function_type_list (V4USI_type_node, V4USI_type_node,
1951				V4USI_type_node, NULL_TREE);
1952
1953  tree v4usi_ftype_v4usi_v4usi_v4usi
1954    = build_function_type_list (V4USI_type_node, V4USI_type_node,
1955				V4USI_type_node, V4USI_type_node,
1956				NULL_TREE);
1957
1958  tree uti_ftype_udi_udi
1959    = build_function_type_list (unsigned_intTI_type_node,
1960				unsigned_intDI_type_node,
1961				unsigned_intDI_type_node,
1962				NULL_TREE);
1963
1964  #undef CRYPTO1
1965  #undef CRYPTO2
1966  #undef CRYPTO3
1967  #undef C
1968  #undef N
1969  #undef CF
1970  #undef FT1
1971  #undef FT2
1972  #undef FT3
1973
1974  #define C(U) \
1975    ARM_BUILTIN_CRYPTO_##U
1976  #define N(L) \
1977    "__builtin_arm_crypto_"#L
1978  #define FT1(R, A) \
1979    R##_ftype_##A
1980  #define FT2(R, A1, A2) \
1981    R##_ftype_##A1##_##A2
1982  #define FT3(R, A1, A2, A3) \
1983    R##_ftype_##A1##_##A2##_##A3
1984  #define CRYPTO1(L, U, R, A) \
1985    arm_builtin_decls[C (U)] \
1986      = add_builtin_function (N (L), FT1 (R, A), \
1987		  C (U), BUILT_IN_MD, NULL, NULL_TREE);
1988  #define CRYPTO2(L, U, R, A1, A2)  \
1989    arm_builtin_decls[C (U)]	\
1990      = add_builtin_function (N (L), FT2 (R, A1, A2), \
1991		  C (U), BUILT_IN_MD, NULL, NULL_TREE);
1992
1993  #define CRYPTO3(L, U, R, A1, A2, A3) \
1994    arm_builtin_decls[C (U)]	   \
1995      = add_builtin_function (N (L), FT3 (R, A1, A2, A3), \
1996				  C (U), BUILT_IN_MD, NULL, NULL_TREE);
1997  #include "crypto.def"
1998
1999  #undef CRYPTO1
2000  #undef CRYPTO2
2001  #undef CRYPTO3
2002  #undef C
2003  #undef N
2004  #undef FT1
2005  #undef FT2
2006  #undef FT3
2007}
2008
2009#undef NUM_DREG_TYPES
2010#undef NUM_QREG_TYPES
2011
2012#define def_mbuiltin(FLAG, NAME, TYPE, CODE)				\
2013  do									\
2014    {									\
2015      if (FLAG == isa_nobit						\
2016	  || bitmap_bit_p (arm_active_target.isa, FLAG))		\
2017	{								\
2018	  tree bdecl;							\
2019	  bdecl = add_builtin_function ((NAME), (TYPE), (CODE),		\
2020					BUILT_IN_MD, NULL, NULL_TREE);	\
2021	  arm_builtin_decls[CODE] = bdecl;				\
2022	}								\
2023    }									\
2024  while (0)
2025
2026struct builtin_description
2027{
2028  const enum isa_feature   feature;
2029  const enum insn_code     icode;
2030  const char * const       name;
2031  const enum arm_builtins  code;
2032  const enum rtx_code      comparison;
2033  const unsigned int       flag;
2034};
2035
2036static const struct builtin_description bdesc_2arg[] =
2037{
2038#define IWMMXT_BUILTIN(code, string, builtin) \
2039  { isa_bit_iwmmxt, CODE_FOR_##code, \
2040    "__builtin_arm_" string,			     \
2041    ARM_BUILTIN_##builtin, UNKNOWN, 0 },
2042
2043#define IWMMXT2_BUILTIN(code, string, builtin) \
2044  { isa_bit_iwmmxt2, CODE_FOR_##code, \
2045    "__builtin_arm_" string,			      \
2046    ARM_BUILTIN_##builtin, UNKNOWN, 0 },
2047
2048  IWMMXT_BUILTIN (addv8qi3, "waddb", WADDB)
2049  IWMMXT_BUILTIN (addv4hi3, "waddh", WADDH)
2050  IWMMXT_BUILTIN (addv2si3, "waddw", WADDW)
2051  IWMMXT_BUILTIN (subv8qi3, "wsubb", WSUBB)
2052  IWMMXT_BUILTIN (subv4hi3, "wsubh", WSUBH)
2053  IWMMXT_BUILTIN (subv2si3, "wsubw", WSUBW)
2054  IWMMXT_BUILTIN (ssaddv8qi3, "waddbss", WADDSSB)
2055  IWMMXT_BUILTIN (ssaddv4hi3, "waddhss", WADDSSH)
2056  IWMMXT_BUILTIN (ssaddv2si3, "waddwss", WADDSSW)
2057  IWMMXT_BUILTIN (sssubv8qi3, "wsubbss", WSUBSSB)
2058  IWMMXT_BUILTIN (sssubv4hi3, "wsubhss", WSUBSSH)
2059  IWMMXT_BUILTIN (sssubv2si3, "wsubwss", WSUBSSW)
2060  IWMMXT_BUILTIN (usaddv8qi3, "waddbus", WADDUSB)
2061  IWMMXT_BUILTIN (usaddv4hi3, "waddhus", WADDUSH)
2062  IWMMXT_BUILTIN (usaddv2si3, "waddwus", WADDUSW)
2063  IWMMXT_BUILTIN (ussubv8qi3, "wsubbus", WSUBUSB)
2064  IWMMXT_BUILTIN (ussubv4hi3, "wsubhus", WSUBUSH)
2065  IWMMXT_BUILTIN (ussubv2si3, "wsubwus", WSUBUSW)
2066  IWMMXT_BUILTIN (mulv4hi3, "wmulul", WMULUL)
2067  IWMMXT_BUILTIN (smulv4hi3_highpart, "wmulsm", WMULSM)
2068  IWMMXT_BUILTIN (umulv4hi3_highpart, "wmulum", WMULUM)
2069  IWMMXT_BUILTIN (eqv8qi3, "wcmpeqb", WCMPEQB)
2070  IWMMXT_BUILTIN (eqv4hi3, "wcmpeqh", WCMPEQH)
2071  IWMMXT_BUILTIN (eqv2si3, "wcmpeqw", WCMPEQW)
2072  IWMMXT_BUILTIN (gtuv8qi3, "wcmpgtub", WCMPGTUB)
2073  IWMMXT_BUILTIN (gtuv4hi3, "wcmpgtuh", WCMPGTUH)
2074  IWMMXT_BUILTIN (gtuv2si3, "wcmpgtuw", WCMPGTUW)
2075  IWMMXT_BUILTIN (gtv8qi3, "wcmpgtsb", WCMPGTSB)
2076  IWMMXT_BUILTIN (gtv4hi3, "wcmpgtsh", WCMPGTSH)
2077  IWMMXT_BUILTIN (gtv2si3, "wcmpgtsw", WCMPGTSW)
2078  IWMMXT_BUILTIN (umaxv8qi3, "wmaxub", WMAXUB)
2079  IWMMXT_BUILTIN (smaxv8qi3, "wmaxsb", WMAXSB)
2080  IWMMXT_BUILTIN (umaxv4hi3, "wmaxuh", WMAXUH)
2081  IWMMXT_BUILTIN (smaxv4hi3, "wmaxsh", WMAXSH)
2082  IWMMXT_BUILTIN (umaxv2si3, "wmaxuw", WMAXUW)
2083  IWMMXT_BUILTIN (smaxv2si3, "wmaxsw", WMAXSW)
2084  IWMMXT_BUILTIN (uminv8qi3, "wminub", WMINUB)
2085  IWMMXT_BUILTIN (sminv8qi3, "wminsb", WMINSB)
2086  IWMMXT_BUILTIN (uminv4hi3, "wminuh", WMINUH)
2087  IWMMXT_BUILTIN (sminv4hi3, "wminsh", WMINSH)
2088  IWMMXT_BUILTIN (uminv2si3, "wminuw", WMINUW)
2089  IWMMXT_BUILTIN (sminv2si3, "wminsw", WMINSW)
2090  IWMMXT_BUILTIN (iwmmxt_anddi3, "wand", WAND)
2091  IWMMXT_BUILTIN (iwmmxt_nanddi3, "wandn", WANDN)
2092  IWMMXT_BUILTIN (iwmmxt_iordi3, "wor", WOR)
2093  IWMMXT_BUILTIN (iwmmxt_xordi3, "wxor", WXOR)
2094  IWMMXT_BUILTIN (iwmmxt_uavgv8qi3, "wavg2b", WAVG2B)
2095  IWMMXT_BUILTIN (iwmmxt_uavgv4hi3, "wavg2h", WAVG2H)
2096  IWMMXT_BUILTIN (iwmmxt_uavgrndv8qi3, "wavg2br", WAVG2BR)
2097  IWMMXT_BUILTIN (iwmmxt_uavgrndv4hi3, "wavg2hr", WAVG2HR)
2098  IWMMXT_BUILTIN (iwmmxt_wunpckilb, "wunpckilb", WUNPCKILB)
2099  IWMMXT_BUILTIN (iwmmxt_wunpckilh, "wunpckilh", WUNPCKILH)
2100  IWMMXT_BUILTIN (iwmmxt_wunpckilw, "wunpckilw", WUNPCKILW)
2101  IWMMXT_BUILTIN (iwmmxt_wunpckihb, "wunpckihb", WUNPCKIHB)
2102  IWMMXT_BUILTIN (iwmmxt_wunpckihh, "wunpckihh", WUNPCKIHH)
2103  IWMMXT_BUILTIN (iwmmxt_wunpckihw, "wunpckihw", WUNPCKIHW)
2104  IWMMXT2_BUILTIN (iwmmxt_waddsubhx, "waddsubhx", WADDSUBHX)
2105  IWMMXT2_BUILTIN (iwmmxt_wsubaddhx, "wsubaddhx", WSUBADDHX)
2106  IWMMXT2_BUILTIN (iwmmxt_wabsdiffb, "wabsdiffb", WABSDIFFB)
2107  IWMMXT2_BUILTIN (iwmmxt_wabsdiffh, "wabsdiffh", WABSDIFFH)
2108  IWMMXT2_BUILTIN (iwmmxt_wabsdiffw, "wabsdiffw", WABSDIFFW)
2109  IWMMXT2_BUILTIN (iwmmxt_avg4, "wavg4", WAVG4)
2110  IWMMXT2_BUILTIN (iwmmxt_avg4r, "wavg4r", WAVG4R)
2111  IWMMXT2_BUILTIN (iwmmxt_wmulwsm, "wmulwsm", WMULWSM)
2112  IWMMXT2_BUILTIN (iwmmxt_wmulwum, "wmulwum", WMULWUM)
2113  IWMMXT2_BUILTIN (iwmmxt_wmulwsmr, "wmulwsmr", WMULWSMR)
2114  IWMMXT2_BUILTIN (iwmmxt_wmulwumr, "wmulwumr", WMULWUMR)
2115  IWMMXT2_BUILTIN (iwmmxt_wmulwl, "wmulwl", WMULWL)
2116  IWMMXT2_BUILTIN (iwmmxt_wmulsmr, "wmulsmr", WMULSMR)
2117  IWMMXT2_BUILTIN (iwmmxt_wmulumr, "wmulumr", WMULUMR)
2118  IWMMXT2_BUILTIN (iwmmxt_wqmulm, "wqmulm", WQMULM)
2119  IWMMXT2_BUILTIN (iwmmxt_wqmulmr, "wqmulmr", WQMULMR)
2120  IWMMXT2_BUILTIN (iwmmxt_wqmulwm, "wqmulwm", WQMULWM)
2121  IWMMXT2_BUILTIN (iwmmxt_wqmulwmr, "wqmulwmr", WQMULWMR)
2122  IWMMXT_BUILTIN (iwmmxt_walignr0, "walignr0", WALIGNR0)
2123  IWMMXT_BUILTIN (iwmmxt_walignr1, "walignr1", WALIGNR1)
2124  IWMMXT_BUILTIN (iwmmxt_walignr2, "walignr2", WALIGNR2)
2125  IWMMXT_BUILTIN (iwmmxt_walignr3, "walignr3", WALIGNR3)
2126
2127#define IWMMXT_BUILTIN2(code, builtin) \
2128  { isa_bit_iwmmxt, CODE_FOR_##code, NULL, \
2129    ARM_BUILTIN_##builtin, UNKNOWN, 0 },
2130
2131#define IWMMXT2_BUILTIN2(code, builtin) \
2132  { isa_bit_iwmmxt2, CODE_FOR_##code, NULL, \
2133    ARM_BUILTIN_##builtin, UNKNOWN, 0 },
2134
2135  IWMMXT2_BUILTIN2 (iwmmxt_waddbhusm, WADDBHUSM)
2136  IWMMXT2_BUILTIN2 (iwmmxt_waddbhusl, WADDBHUSL)
2137  IWMMXT_BUILTIN2 (iwmmxt_wpackhss, WPACKHSS)
2138  IWMMXT_BUILTIN2 (iwmmxt_wpackwss, WPACKWSS)
2139  IWMMXT_BUILTIN2 (iwmmxt_wpackdss, WPACKDSS)
2140  IWMMXT_BUILTIN2 (iwmmxt_wpackhus, WPACKHUS)
2141  IWMMXT_BUILTIN2 (iwmmxt_wpackwus, WPACKWUS)
2142  IWMMXT_BUILTIN2 (iwmmxt_wpackdus, WPACKDUS)
2143  IWMMXT_BUILTIN2 (iwmmxt_wmacuz, WMACUZ)
2144  IWMMXT_BUILTIN2 (iwmmxt_wmacsz, WMACSZ)
2145
2146
2147#define FP_BUILTIN(L, U) \
2148  {isa_nobit, CODE_FOR_##L, "__builtin_arm_"#L, ARM_BUILTIN_##U, \
2149   UNKNOWN, 0},
2150
2151  FP_BUILTIN (get_fpscr, GET_FPSCR)
2152  FP_BUILTIN (set_fpscr, SET_FPSCR)
2153#undef FP_BUILTIN
2154
2155#define CRYPTO_BUILTIN(L, U)					   \
2156  {isa_nobit, CODE_FOR_crypto_##L,	"__builtin_arm_crypto_"#L, \
2157   ARM_BUILTIN_CRYPTO_##U, UNKNOWN, 0},
2158#undef CRYPTO1
2159#undef CRYPTO2
2160#undef CRYPTO3
2161#define CRYPTO2(L, U, R, A1, A2) CRYPTO_BUILTIN (L, U)
2162#define CRYPTO1(L, U, R, A)
2163#define CRYPTO3(L, U, R, A1, A2, A3)
2164#include "crypto.def"
2165#undef CRYPTO1
2166#undef CRYPTO2
2167#undef CRYPTO3
2168
2169};
2170
2171static const struct builtin_description bdesc_1arg[] =
2172{
2173  IWMMXT_BUILTIN (iwmmxt_tmovmskb, "tmovmskb", TMOVMSKB)
2174  IWMMXT_BUILTIN (iwmmxt_tmovmskh, "tmovmskh", TMOVMSKH)
2175  IWMMXT_BUILTIN (iwmmxt_tmovmskw, "tmovmskw", TMOVMSKW)
2176  IWMMXT_BUILTIN (iwmmxt_waccb, "waccb", WACCB)
2177  IWMMXT_BUILTIN (iwmmxt_wacch, "wacch", WACCH)
2178  IWMMXT_BUILTIN (iwmmxt_waccw, "waccw", WACCW)
2179  IWMMXT_BUILTIN (iwmmxt_wunpckehub, "wunpckehub", WUNPCKEHUB)
2180  IWMMXT_BUILTIN (iwmmxt_wunpckehuh, "wunpckehuh", WUNPCKEHUH)
2181  IWMMXT_BUILTIN (iwmmxt_wunpckehuw, "wunpckehuw", WUNPCKEHUW)
2182  IWMMXT_BUILTIN (iwmmxt_wunpckehsb, "wunpckehsb", WUNPCKEHSB)
2183  IWMMXT_BUILTIN (iwmmxt_wunpckehsh, "wunpckehsh", WUNPCKEHSH)
2184  IWMMXT_BUILTIN (iwmmxt_wunpckehsw, "wunpckehsw", WUNPCKEHSW)
2185  IWMMXT_BUILTIN (iwmmxt_wunpckelub, "wunpckelub", WUNPCKELUB)
2186  IWMMXT_BUILTIN (iwmmxt_wunpckeluh, "wunpckeluh", WUNPCKELUH)
2187  IWMMXT_BUILTIN (iwmmxt_wunpckeluw, "wunpckeluw", WUNPCKELUW)
2188  IWMMXT_BUILTIN (iwmmxt_wunpckelsb, "wunpckelsb", WUNPCKELSB)
2189  IWMMXT_BUILTIN (iwmmxt_wunpckelsh, "wunpckelsh", WUNPCKELSH)
2190  IWMMXT_BUILTIN (iwmmxt_wunpckelsw, "wunpckelsw", WUNPCKELSW)
2191  IWMMXT2_BUILTIN (iwmmxt_wabsv8qi3, "wabsb", WABSB)
2192  IWMMXT2_BUILTIN (iwmmxt_wabsv4hi3, "wabsh", WABSH)
2193  IWMMXT2_BUILTIN (iwmmxt_wabsv2si3, "wabsw", WABSW)
2194  IWMMXT_BUILTIN (tbcstv8qi, "tbcstb", TBCSTB)
2195  IWMMXT_BUILTIN (tbcstv4hi, "tbcsth", TBCSTH)
2196  IWMMXT_BUILTIN (tbcstv2si, "tbcstw", TBCSTW)
2197
2198#define CRYPTO1(L, U, R, A) CRYPTO_BUILTIN (L, U)
2199#define CRYPTO2(L, U, R, A1, A2)
2200#define CRYPTO3(L, U, R, A1, A2, A3)
2201#include "crypto.def"
2202#undef CRYPTO1
2203#undef CRYPTO2
2204#undef CRYPTO3
2205};
2206
2207static const struct builtin_description bdesc_3arg[] =
2208{
2209#define CRYPTO3(L, U, R, A1, A2, A3) CRYPTO_BUILTIN (L, U)
2210#define CRYPTO1(L, U, R, A)
2211#define CRYPTO2(L, U, R, A1, A2)
2212#include "crypto.def"
2213#undef CRYPTO1
2214#undef CRYPTO2
2215#undef CRYPTO3
2216 };
2217#undef CRYPTO_BUILTIN
2218
2219/* Set up all the iWMMXt builtins.  This is not called if
2220   TARGET_IWMMXT is zero.  */
2221
2222static void
2223arm_init_iwmmxt_builtins (void)
2224{
2225  const struct builtin_description * d;
2226  size_t i;
2227
2228  tree V2SI_type_node = build_vector_type_for_mode (intSI_type_node, V2SImode);
2229  tree V4HI_type_node = build_vector_type_for_mode (intHI_type_node, V4HImode);
2230  tree V8QI_type_node = build_vector_type_for_mode (intQI_type_node, V8QImode);
2231
2232  tree v8qi_ftype_v8qi_v8qi_int
2233    = build_function_type_list (V8QI_type_node,
2234				V8QI_type_node, V8QI_type_node,
2235				integer_type_node, NULL_TREE);
2236  tree v4hi_ftype_v4hi_int
2237    = build_function_type_list (V4HI_type_node,
2238				V4HI_type_node, integer_type_node, NULL_TREE);
2239  tree v2si_ftype_v2si_int
2240    = build_function_type_list (V2SI_type_node,
2241				V2SI_type_node, integer_type_node, NULL_TREE);
2242  tree v2si_ftype_di_di
2243    = build_function_type_list (V2SI_type_node,
2244				long_long_integer_type_node,
2245				long_long_integer_type_node,
2246				NULL_TREE);
2247  tree di_ftype_di_int
2248    = build_function_type_list (long_long_integer_type_node,
2249				long_long_integer_type_node,
2250				integer_type_node, NULL_TREE);
2251  tree di_ftype_di_int_int
2252    = build_function_type_list (long_long_integer_type_node,
2253				long_long_integer_type_node,
2254				integer_type_node,
2255				integer_type_node, NULL_TREE);
2256  tree int_ftype_v8qi
2257    = build_function_type_list (integer_type_node,
2258				V8QI_type_node, NULL_TREE);
2259  tree int_ftype_v4hi
2260    = build_function_type_list (integer_type_node,
2261				V4HI_type_node, NULL_TREE);
2262  tree int_ftype_v2si
2263    = build_function_type_list (integer_type_node,
2264				V2SI_type_node, NULL_TREE);
2265  tree int_ftype_v8qi_int
2266    = build_function_type_list (integer_type_node,
2267				V8QI_type_node, integer_type_node, NULL_TREE);
2268  tree int_ftype_v4hi_int
2269    = build_function_type_list (integer_type_node,
2270				V4HI_type_node, integer_type_node, NULL_TREE);
2271  tree int_ftype_v2si_int
2272    = build_function_type_list (integer_type_node,
2273				V2SI_type_node, integer_type_node, NULL_TREE);
2274  tree v8qi_ftype_v8qi_int_int
2275    = build_function_type_list (V8QI_type_node,
2276				V8QI_type_node, integer_type_node,
2277				integer_type_node, NULL_TREE);
2278  tree v4hi_ftype_v4hi_int_int
2279    = build_function_type_list (V4HI_type_node,
2280				V4HI_type_node, integer_type_node,
2281				integer_type_node, NULL_TREE);
2282  tree v2si_ftype_v2si_int_int
2283    = build_function_type_list (V2SI_type_node,
2284				V2SI_type_node, integer_type_node,
2285				integer_type_node, NULL_TREE);
2286  /* Miscellaneous.  */
2287  tree v8qi_ftype_v4hi_v4hi
2288    = build_function_type_list (V8QI_type_node,
2289				V4HI_type_node, V4HI_type_node, NULL_TREE);
2290  tree v4hi_ftype_v2si_v2si
2291    = build_function_type_list (V4HI_type_node,
2292				V2SI_type_node, V2SI_type_node, NULL_TREE);
2293  tree v8qi_ftype_v4hi_v8qi
2294    = build_function_type_list (V8QI_type_node,
2295	                        V4HI_type_node, V8QI_type_node, NULL_TREE);
2296  tree v2si_ftype_v4hi_v4hi
2297    = build_function_type_list (V2SI_type_node,
2298				V4HI_type_node, V4HI_type_node, NULL_TREE);
2299  tree v2si_ftype_v8qi_v8qi
2300    = build_function_type_list (V2SI_type_node,
2301				V8QI_type_node, V8QI_type_node, NULL_TREE);
2302  tree v4hi_ftype_v4hi_di
2303    = build_function_type_list (V4HI_type_node,
2304				V4HI_type_node, long_long_integer_type_node,
2305				NULL_TREE);
2306  tree v2si_ftype_v2si_di
2307    = build_function_type_list (V2SI_type_node,
2308				V2SI_type_node, long_long_integer_type_node,
2309				NULL_TREE);
2310  tree di_ftype_void
2311    = build_function_type_list (long_long_unsigned_type_node, NULL_TREE);
2312  tree int_ftype_void
2313    = build_function_type_list (integer_type_node, NULL_TREE);
2314  tree di_ftype_v8qi
2315    = build_function_type_list (long_long_integer_type_node,
2316				V8QI_type_node, NULL_TREE);
2317  tree di_ftype_v4hi
2318    = build_function_type_list (long_long_integer_type_node,
2319				V4HI_type_node, NULL_TREE);
2320  tree di_ftype_v2si
2321    = build_function_type_list (long_long_integer_type_node,
2322				V2SI_type_node, NULL_TREE);
2323  tree v2si_ftype_v4hi
2324    = build_function_type_list (V2SI_type_node,
2325				V4HI_type_node, NULL_TREE);
2326  tree v4hi_ftype_v8qi
2327    = build_function_type_list (V4HI_type_node,
2328				V8QI_type_node, NULL_TREE);
2329  tree v8qi_ftype_v8qi
2330    = build_function_type_list (V8QI_type_node,
2331	                        V8QI_type_node, NULL_TREE);
2332  tree v4hi_ftype_v4hi
2333    = build_function_type_list (V4HI_type_node,
2334	                        V4HI_type_node, NULL_TREE);
2335  tree v2si_ftype_v2si
2336    = build_function_type_list (V2SI_type_node,
2337	                        V2SI_type_node, NULL_TREE);
2338
2339  tree di_ftype_di_v4hi_v4hi
2340    = build_function_type_list (long_long_unsigned_type_node,
2341				long_long_unsigned_type_node,
2342				V4HI_type_node, V4HI_type_node,
2343				NULL_TREE);
2344
2345  tree di_ftype_v4hi_v4hi
2346    = build_function_type_list (long_long_unsigned_type_node,
2347				V4HI_type_node,V4HI_type_node,
2348				NULL_TREE);
2349
2350  tree v2si_ftype_v2si_v4hi_v4hi
2351    = build_function_type_list (V2SI_type_node,
2352                                V2SI_type_node, V4HI_type_node,
2353                                V4HI_type_node, NULL_TREE);
2354
2355  tree v2si_ftype_v2si_v8qi_v8qi
2356    = build_function_type_list (V2SI_type_node,
2357                                V2SI_type_node, V8QI_type_node,
2358                                V8QI_type_node, NULL_TREE);
2359
2360  tree di_ftype_di_v2si_v2si
2361     = build_function_type_list (long_long_unsigned_type_node,
2362                                 long_long_unsigned_type_node,
2363                                 V2SI_type_node, V2SI_type_node,
2364                                 NULL_TREE);
2365
2366   tree di_ftype_di_di_int
2367     = build_function_type_list (long_long_unsigned_type_node,
2368                                 long_long_unsigned_type_node,
2369                                 long_long_unsigned_type_node,
2370                                 integer_type_node, NULL_TREE);
2371
2372   tree void_ftype_int
2373     = build_function_type_list (void_type_node,
2374                                 integer_type_node, NULL_TREE);
2375
2376   tree v8qi_ftype_char
2377     = build_function_type_list (V8QI_type_node,
2378                                 signed_char_type_node, NULL_TREE);
2379
2380   tree v4hi_ftype_short
2381     = build_function_type_list (V4HI_type_node,
2382                                 short_integer_type_node, NULL_TREE);
2383
2384   tree v2si_ftype_int
2385     = build_function_type_list (V2SI_type_node,
2386                                 integer_type_node, NULL_TREE);
2387
2388  /* Normal vector binops.  */
2389  tree v8qi_ftype_v8qi_v8qi
2390    = build_function_type_list (V8QI_type_node,
2391				V8QI_type_node, V8QI_type_node, NULL_TREE);
2392  tree v4hi_ftype_v4hi_v4hi
2393    = build_function_type_list (V4HI_type_node,
2394				V4HI_type_node,V4HI_type_node, NULL_TREE);
2395  tree v2si_ftype_v2si_v2si
2396    = build_function_type_list (V2SI_type_node,
2397				V2SI_type_node, V2SI_type_node, NULL_TREE);
2398  tree di_ftype_di_di
2399    = build_function_type_list (long_long_unsigned_type_node,
2400				long_long_unsigned_type_node,
2401				long_long_unsigned_type_node,
2402				NULL_TREE);
2403
2404  /* Add all builtins that are more or less simple operations on two
2405     operands.  */
2406  for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
2407    {
2408      /* Use one of the operands; the target can have a different mode for
2409	 mask-generating compares.  */
2410      machine_mode mode;
2411      tree type;
2412
2413      if (d->name == 0
2414	  || !(d->feature == isa_bit_iwmmxt
2415	       || d->feature == isa_bit_iwmmxt2))
2416	continue;
2417
2418      mode = insn_data[d->icode].operand[1].mode;
2419
2420      switch (mode)
2421	{
2422	case E_V8QImode:
2423	  type = v8qi_ftype_v8qi_v8qi;
2424	  break;
2425	case E_V4HImode:
2426	  type = v4hi_ftype_v4hi_v4hi;
2427	  break;
2428	case E_V2SImode:
2429	  type = v2si_ftype_v2si_v2si;
2430	  break;
2431	case E_DImode:
2432	  type = di_ftype_di_di;
2433	  break;
2434
2435	default:
2436	  gcc_unreachable ();
2437	}
2438
2439      def_mbuiltin (d->feature, d->name, type, d->code);
2440    }
2441
2442  /* Add the remaining MMX insns with somewhat more complicated types.  */
2443#define iwmmx_mbuiltin(NAME, TYPE, CODE)			\
2444  def_mbuiltin (isa_bit_iwmmxt, "__builtin_arm_" NAME, \
2445		(TYPE), ARM_BUILTIN_ ## CODE)
2446
2447#define iwmmx2_mbuiltin(NAME, TYPE, CODE)                      \
2448  def_mbuiltin (isa_bit_iwmmxt2, "__builtin_arm_" NAME, \
2449		(TYPE),	ARM_BUILTIN_ ## CODE)
2450
2451  iwmmx_mbuiltin ("wzero", di_ftype_void, WZERO);
2452  iwmmx_mbuiltin ("setwcgr0", void_ftype_int, SETWCGR0);
2453  iwmmx_mbuiltin ("setwcgr1", void_ftype_int, SETWCGR1);
2454  iwmmx_mbuiltin ("setwcgr2", void_ftype_int, SETWCGR2);
2455  iwmmx_mbuiltin ("setwcgr3", void_ftype_int, SETWCGR3);
2456  iwmmx_mbuiltin ("getwcgr0", int_ftype_void, GETWCGR0);
2457  iwmmx_mbuiltin ("getwcgr1", int_ftype_void, GETWCGR1);
2458  iwmmx_mbuiltin ("getwcgr2", int_ftype_void, GETWCGR2);
2459  iwmmx_mbuiltin ("getwcgr3", int_ftype_void, GETWCGR3);
2460
2461  iwmmx_mbuiltin ("wsllh", v4hi_ftype_v4hi_di, WSLLH);
2462  iwmmx_mbuiltin ("wsllw", v2si_ftype_v2si_di, WSLLW);
2463  iwmmx_mbuiltin ("wslld", di_ftype_di_di, WSLLD);
2464  iwmmx_mbuiltin ("wsllhi", v4hi_ftype_v4hi_int, WSLLHI);
2465  iwmmx_mbuiltin ("wsllwi", v2si_ftype_v2si_int, WSLLWI);
2466  iwmmx_mbuiltin ("wslldi", di_ftype_di_int, WSLLDI);
2467
2468  iwmmx_mbuiltin ("wsrlh", v4hi_ftype_v4hi_di, WSRLH);
2469  iwmmx_mbuiltin ("wsrlw", v2si_ftype_v2si_di, WSRLW);
2470  iwmmx_mbuiltin ("wsrld", di_ftype_di_di, WSRLD);
2471  iwmmx_mbuiltin ("wsrlhi", v4hi_ftype_v4hi_int, WSRLHI);
2472  iwmmx_mbuiltin ("wsrlwi", v2si_ftype_v2si_int, WSRLWI);
2473  iwmmx_mbuiltin ("wsrldi", di_ftype_di_int, WSRLDI);
2474
2475  iwmmx_mbuiltin ("wsrah", v4hi_ftype_v4hi_di, WSRAH);
2476  iwmmx_mbuiltin ("wsraw", v2si_ftype_v2si_di, WSRAW);
2477  iwmmx_mbuiltin ("wsrad", di_ftype_di_di, WSRAD);
2478  iwmmx_mbuiltin ("wsrahi", v4hi_ftype_v4hi_int, WSRAHI);
2479  iwmmx_mbuiltin ("wsrawi", v2si_ftype_v2si_int, WSRAWI);
2480  iwmmx_mbuiltin ("wsradi", di_ftype_di_int, WSRADI);
2481
2482  iwmmx_mbuiltin ("wrorh", v4hi_ftype_v4hi_di, WRORH);
2483  iwmmx_mbuiltin ("wrorw", v2si_ftype_v2si_di, WRORW);
2484  iwmmx_mbuiltin ("wrord", di_ftype_di_di, WRORD);
2485  iwmmx_mbuiltin ("wrorhi", v4hi_ftype_v4hi_int, WRORHI);
2486  iwmmx_mbuiltin ("wrorwi", v2si_ftype_v2si_int, WRORWI);
2487  iwmmx_mbuiltin ("wrordi", di_ftype_di_int, WRORDI);
2488
2489  iwmmx_mbuiltin ("wshufh", v4hi_ftype_v4hi_int, WSHUFH);
2490
2491  iwmmx_mbuiltin ("wsadb", v2si_ftype_v2si_v8qi_v8qi, WSADB);
2492  iwmmx_mbuiltin ("wsadh", v2si_ftype_v2si_v4hi_v4hi, WSADH);
2493  iwmmx_mbuiltin ("wmadds", v2si_ftype_v4hi_v4hi, WMADDS);
2494  iwmmx2_mbuiltin ("wmaddsx", v2si_ftype_v4hi_v4hi, WMADDSX);
2495  iwmmx2_mbuiltin ("wmaddsn", v2si_ftype_v4hi_v4hi, WMADDSN);
2496  iwmmx_mbuiltin ("wmaddu", v2si_ftype_v4hi_v4hi, WMADDU);
2497  iwmmx2_mbuiltin ("wmaddux", v2si_ftype_v4hi_v4hi, WMADDUX);
2498  iwmmx2_mbuiltin ("wmaddun", v2si_ftype_v4hi_v4hi, WMADDUN);
2499  iwmmx_mbuiltin ("wsadbz", v2si_ftype_v8qi_v8qi, WSADBZ);
2500  iwmmx_mbuiltin ("wsadhz", v2si_ftype_v4hi_v4hi, WSADHZ);
2501
2502  iwmmx_mbuiltin ("textrmsb", int_ftype_v8qi_int, TEXTRMSB);
2503  iwmmx_mbuiltin ("textrmsh", int_ftype_v4hi_int, TEXTRMSH);
2504  iwmmx_mbuiltin ("textrmsw", int_ftype_v2si_int, TEXTRMSW);
2505  iwmmx_mbuiltin ("textrmub", int_ftype_v8qi_int, TEXTRMUB);
2506  iwmmx_mbuiltin ("textrmuh", int_ftype_v4hi_int, TEXTRMUH);
2507  iwmmx_mbuiltin ("textrmuw", int_ftype_v2si_int, TEXTRMUW);
2508  iwmmx_mbuiltin ("tinsrb", v8qi_ftype_v8qi_int_int, TINSRB);
2509  iwmmx_mbuiltin ("tinsrh", v4hi_ftype_v4hi_int_int, TINSRH);
2510  iwmmx_mbuiltin ("tinsrw", v2si_ftype_v2si_int_int, TINSRW);
2511
2512  iwmmx_mbuiltin ("waccb", di_ftype_v8qi, WACCB);
2513  iwmmx_mbuiltin ("wacch", di_ftype_v4hi, WACCH);
2514  iwmmx_mbuiltin ("waccw", di_ftype_v2si, WACCW);
2515
2516  iwmmx_mbuiltin ("tmovmskb", int_ftype_v8qi, TMOVMSKB);
2517  iwmmx_mbuiltin ("tmovmskh", int_ftype_v4hi, TMOVMSKH);
2518  iwmmx_mbuiltin ("tmovmskw", int_ftype_v2si, TMOVMSKW);
2519
2520  iwmmx2_mbuiltin ("waddbhusm", v8qi_ftype_v4hi_v8qi, WADDBHUSM);
2521  iwmmx2_mbuiltin ("waddbhusl", v8qi_ftype_v4hi_v8qi, WADDBHUSL);
2522
2523  iwmmx_mbuiltin ("wpackhss", v8qi_ftype_v4hi_v4hi, WPACKHSS);
2524  iwmmx_mbuiltin ("wpackhus", v8qi_ftype_v4hi_v4hi, WPACKHUS);
2525  iwmmx_mbuiltin ("wpackwus", v4hi_ftype_v2si_v2si, WPACKWUS);
2526  iwmmx_mbuiltin ("wpackwss", v4hi_ftype_v2si_v2si, WPACKWSS);
2527  iwmmx_mbuiltin ("wpackdus", v2si_ftype_di_di, WPACKDUS);
2528  iwmmx_mbuiltin ("wpackdss", v2si_ftype_di_di, WPACKDSS);
2529
2530  iwmmx_mbuiltin ("wunpckehub", v4hi_ftype_v8qi, WUNPCKEHUB);
2531  iwmmx_mbuiltin ("wunpckehuh", v2si_ftype_v4hi, WUNPCKEHUH);
2532  iwmmx_mbuiltin ("wunpckehuw", di_ftype_v2si, WUNPCKEHUW);
2533  iwmmx_mbuiltin ("wunpckehsb", v4hi_ftype_v8qi, WUNPCKEHSB);
2534  iwmmx_mbuiltin ("wunpckehsh", v2si_ftype_v4hi, WUNPCKEHSH);
2535  iwmmx_mbuiltin ("wunpckehsw", di_ftype_v2si, WUNPCKEHSW);
2536  iwmmx_mbuiltin ("wunpckelub", v4hi_ftype_v8qi, WUNPCKELUB);
2537  iwmmx_mbuiltin ("wunpckeluh", v2si_ftype_v4hi, WUNPCKELUH);
2538  iwmmx_mbuiltin ("wunpckeluw", di_ftype_v2si, WUNPCKELUW);
2539  iwmmx_mbuiltin ("wunpckelsb", v4hi_ftype_v8qi, WUNPCKELSB);
2540  iwmmx_mbuiltin ("wunpckelsh", v2si_ftype_v4hi, WUNPCKELSH);
2541  iwmmx_mbuiltin ("wunpckelsw", di_ftype_v2si, WUNPCKELSW);
2542
2543  iwmmx_mbuiltin ("wmacs", di_ftype_di_v4hi_v4hi, WMACS);
2544  iwmmx_mbuiltin ("wmacsz", di_ftype_v4hi_v4hi, WMACSZ);
2545  iwmmx_mbuiltin ("wmacu", di_ftype_di_v4hi_v4hi, WMACU);
2546  iwmmx_mbuiltin ("wmacuz", di_ftype_v4hi_v4hi, WMACUZ);
2547
2548  iwmmx_mbuiltin ("walign", v8qi_ftype_v8qi_v8qi_int, WALIGNI);
2549  iwmmx_mbuiltin ("tmia", di_ftype_di_int_int, TMIA);
2550  iwmmx_mbuiltin ("tmiaph", di_ftype_di_int_int, TMIAPH);
2551  iwmmx_mbuiltin ("tmiabb", di_ftype_di_int_int, TMIABB);
2552  iwmmx_mbuiltin ("tmiabt", di_ftype_di_int_int, TMIABT);
2553  iwmmx_mbuiltin ("tmiatb", di_ftype_di_int_int, TMIATB);
2554  iwmmx_mbuiltin ("tmiatt", di_ftype_di_int_int, TMIATT);
2555
2556  iwmmx2_mbuiltin ("wabsb", v8qi_ftype_v8qi, WABSB);
2557  iwmmx2_mbuiltin ("wabsh", v4hi_ftype_v4hi, WABSH);
2558  iwmmx2_mbuiltin ("wabsw", v2si_ftype_v2si, WABSW);
2559
2560  iwmmx2_mbuiltin ("wqmiabb", v2si_ftype_v2si_v4hi_v4hi, WQMIABB);
2561  iwmmx2_mbuiltin ("wqmiabt", v2si_ftype_v2si_v4hi_v4hi, WQMIABT);
2562  iwmmx2_mbuiltin ("wqmiatb", v2si_ftype_v2si_v4hi_v4hi, WQMIATB);
2563  iwmmx2_mbuiltin ("wqmiatt", v2si_ftype_v2si_v4hi_v4hi, WQMIATT);
2564
2565  iwmmx2_mbuiltin ("wqmiabbn", v2si_ftype_v2si_v4hi_v4hi, WQMIABBN);
2566  iwmmx2_mbuiltin ("wqmiabtn", v2si_ftype_v2si_v4hi_v4hi, WQMIABTN);
2567  iwmmx2_mbuiltin ("wqmiatbn", v2si_ftype_v2si_v4hi_v4hi, WQMIATBN);
2568  iwmmx2_mbuiltin ("wqmiattn", v2si_ftype_v2si_v4hi_v4hi, WQMIATTN);
2569
2570  iwmmx2_mbuiltin ("wmiabb", di_ftype_di_v4hi_v4hi, WMIABB);
2571  iwmmx2_mbuiltin ("wmiabt", di_ftype_di_v4hi_v4hi, WMIABT);
2572  iwmmx2_mbuiltin ("wmiatb", di_ftype_di_v4hi_v4hi, WMIATB);
2573  iwmmx2_mbuiltin ("wmiatt", di_ftype_di_v4hi_v4hi, WMIATT);
2574
2575  iwmmx2_mbuiltin ("wmiabbn", di_ftype_di_v4hi_v4hi, WMIABBN);
2576  iwmmx2_mbuiltin ("wmiabtn", di_ftype_di_v4hi_v4hi, WMIABTN);
2577  iwmmx2_mbuiltin ("wmiatbn", di_ftype_di_v4hi_v4hi, WMIATBN);
2578  iwmmx2_mbuiltin ("wmiattn", di_ftype_di_v4hi_v4hi, WMIATTN);
2579
2580  iwmmx2_mbuiltin ("wmiawbb", di_ftype_di_v2si_v2si, WMIAWBB);
2581  iwmmx2_mbuiltin ("wmiawbt", di_ftype_di_v2si_v2si, WMIAWBT);
2582  iwmmx2_mbuiltin ("wmiawtb", di_ftype_di_v2si_v2si, WMIAWTB);
2583  iwmmx2_mbuiltin ("wmiawtt", di_ftype_di_v2si_v2si, WMIAWTT);
2584
2585  iwmmx2_mbuiltin ("wmiawbbn", di_ftype_di_v2si_v2si, WMIAWBBN);
2586  iwmmx2_mbuiltin ("wmiawbtn", di_ftype_di_v2si_v2si, WMIAWBTN);
2587  iwmmx2_mbuiltin ("wmiawtbn", di_ftype_di_v2si_v2si, WMIAWTBN);
2588  iwmmx2_mbuiltin ("wmiawttn", di_ftype_di_v2si_v2si, WMIAWTTN);
2589
2590  iwmmx2_mbuiltin ("wmerge", di_ftype_di_di_int, WMERGE);
2591
2592  iwmmx_mbuiltin ("tbcstb", v8qi_ftype_char, TBCSTB);
2593  iwmmx_mbuiltin ("tbcsth", v4hi_ftype_short, TBCSTH);
2594  iwmmx_mbuiltin ("tbcstw", v2si_ftype_int, TBCSTW);
2595
2596#undef iwmmx_mbuiltin
2597#undef iwmmx2_mbuiltin
2598}
2599
2600static void
2601arm_init_fp16_builtins (void)
2602{
2603  arm_fp16_type_node = make_node (REAL_TYPE);
2604  TYPE_PRECISION (arm_fp16_type_node) = GET_MODE_PRECISION (HFmode);
2605  layout_type (arm_fp16_type_node);
2606  if (arm_fp16_format)
2607    (*lang_hooks.types.register_builtin_type) (arm_fp16_type_node,
2608					       "__fp16");
2609}
2610
2611void
2612arm_init_builtins (void)
2613{
2614  if (TARGET_REALLY_IWMMXT)
2615    arm_init_iwmmxt_builtins ();
2616
2617  /* This creates the arm_simd_floatHF_type_node so must come before
2618     arm_init_neon_builtins which uses it.  */
2619  arm_init_fp16_builtins ();
2620
2621  arm_init_bf16_types ();
2622
2623  if (TARGET_MAYBE_HARD_FLOAT)
2624    {
2625      tree lane_check_fpr = build_function_type_list (void_type_node,
2626						      intSI_type_node,
2627						      intSI_type_node,
2628						      NULL);
2629      arm_builtin_decls[ARM_BUILTIN_SIMD_LANE_CHECK]
2630      = add_builtin_function ("__builtin_arm_lane_check", lane_check_fpr,
2631			      ARM_BUILTIN_SIMD_LANE_CHECK, BUILT_IN_MD,
2632			      NULL, NULL_TREE);
2633      if (TARGET_HAVE_MVE)
2634	arm_init_mve_builtins ();
2635      else
2636	arm_init_neon_builtins ();
2637      arm_init_vfp_builtins ();
2638      arm_init_crypto_builtins ();
2639    }
2640
2641  if (TARGET_CDE)
2642    arm_init_cde_builtins ();
2643
2644  arm_init_acle_builtins ();
2645
2646  if (TARGET_MAYBE_HARD_FLOAT)
2647    {
2648      tree ftype_set_fpscr
2649	= build_function_type_list (void_type_node, unsigned_type_node, NULL);
2650      tree ftype_get_fpscr
2651	= build_function_type_list (unsigned_type_node, NULL);
2652
2653      arm_builtin_decls[ARM_BUILTIN_GET_FPSCR]
2654	= add_builtin_function ("__builtin_arm_get_fpscr", ftype_get_fpscr,
2655				ARM_BUILTIN_GET_FPSCR, BUILT_IN_MD, NULL, NULL_TREE);
2656      arm_builtin_decls[ARM_BUILTIN_SET_FPSCR]
2657	= add_builtin_function ("__builtin_arm_set_fpscr", ftype_set_fpscr,
2658				ARM_BUILTIN_SET_FPSCR, BUILT_IN_MD, NULL, NULL_TREE);
2659    }
2660
2661  if (use_cmse)
2662    {
2663      tree ftype_cmse_nonsecure_caller
2664	= build_function_type_list (unsigned_type_node, NULL);
2665      arm_builtin_decls[ARM_BUILTIN_CMSE_NONSECURE_CALLER]
2666	= add_builtin_function ("__builtin_arm_cmse_nonsecure_caller",
2667				ftype_cmse_nonsecure_caller,
2668				ARM_BUILTIN_CMSE_NONSECURE_CALLER, BUILT_IN_MD,
2669				NULL, NULL_TREE);
2670    }
2671}
2672
2673/* Return the ARM builtin for CODE.  */
2674
2675tree
2676arm_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
2677{
2678  if (code >= ARM_BUILTIN_MAX)
2679    return error_mark_node;
2680
2681  return arm_builtin_decls[code];
2682}
2683
2684/* Errors in the source file can cause expand_expr to return const0_rtx
2685   where we expect a vector.  To avoid crashing, use one of the vector
2686   clear instructions.  */
2687
2688static rtx
2689safe_vector_operand (rtx x, machine_mode mode)
2690{
2691  if (x != const0_rtx)
2692    return x;
2693  x = gen_reg_rtx (mode);
2694
2695  emit_insn (gen_iwmmxt_clrdi (mode == DImode ? x
2696			       : gen_rtx_SUBREG (DImode, x, 0)));
2697  return x;
2698}
2699
2700/* Function to expand ternary builtins.  */
2701static rtx
2702arm_expand_ternop_builtin (enum insn_code icode,
2703                           tree exp, rtx target)
2704{
2705  rtx pat;
2706  tree arg0 = CALL_EXPR_ARG (exp, 0);
2707  tree arg1 = CALL_EXPR_ARG (exp, 1);
2708  tree arg2 = CALL_EXPR_ARG (exp, 2);
2709
2710  rtx op0 = expand_normal (arg0);
2711  rtx op1 = expand_normal (arg1);
2712  rtx op2 = expand_normal (arg2);
2713
2714  machine_mode tmode = insn_data[icode].operand[0].mode;
2715  machine_mode mode0 = insn_data[icode].operand[1].mode;
2716  machine_mode mode1 = insn_data[icode].operand[2].mode;
2717  machine_mode mode2 = insn_data[icode].operand[3].mode;
2718
2719  if (VECTOR_MODE_P (mode0))
2720    op0 = safe_vector_operand (op0, mode0);
2721  if (VECTOR_MODE_P (mode1))
2722    op1 = safe_vector_operand (op1, mode1);
2723  if (VECTOR_MODE_P (mode2))
2724    op2 = safe_vector_operand (op2, mode2);
2725
2726  if (! target
2727      || GET_MODE (target) != tmode
2728      || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
2729    target = gen_reg_rtx (tmode);
2730
2731  gcc_assert ((GET_MODE (op0) == mode0 || GET_MODE (op0) == VOIDmode)
2732	      && (GET_MODE (op1) == mode1 || GET_MODE (op1) == VOIDmode)
2733	      && (GET_MODE (op2) == mode2 || GET_MODE (op2) == VOIDmode));
2734
2735  if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
2736    op0 = copy_to_mode_reg (mode0, op0);
2737  if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
2738    op1 = copy_to_mode_reg (mode1, op1);
2739  if (! (*insn_data[icode].operand[3].predicate) (op2, mode2))
2740    op2 = copy_to_mode_reg (mode2, op2);
2741
2742  pat = GEN_FCN (icode) (target, op0, op1, op2);
2743  if (! pat)
2744    return 0;
2745  emit_insn (pat);
2746  return target;
2747}
2748
2749/* Subroutine of arm_expand_builtin to take care of binop insns.  */
2750
2751static rtx
2752arm_expand_binop_builtin (enum insn_code icode,
2753			  tree exp, rtx target)
2754{
2755  rtx pat;
2756  tree arg0 = CALL_EXPR_ARG (exp, 0);
2757  tree arg1 = CALL_EXPR_ARG (exp, 1);
2758  rtx op0 = expand_normal (arg0);
2759  rtx op1 = expand_normal (arg1);
2760  machine_mode tmode = insn_data[icode].operand[0].mode;
2761  machine_mode mode0 = insn_data[icode].operand[1].mode;
2762  machine_mode mode1 = insn_data[icode].operand[2].mode;
2763
2764  if (VECTOR_MODE_P (mode0))
2765    op0 = safe_vector_operand (op0, mode0);
2766  if (VECTOR_MODE_P (mode1))
2767    op1 = safe_vector_operand (op1, mode1);
2768
2769  if (! target
2770      || GET_MODE (target) != tmode
2771      || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
2772    target = gen_reg_rtx (tmode);
2773
2774  gcc_assert ((GET_MODE (op0) == mode0 || GET_MODE (op0) == VOIDmode)
2775	      && (GET_MODE (op1) == mode1 || GET_MODE (op1) == VOIDmode));
2776
2777  if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
2778    op0 = copy_to_mode_reg (mode0, op0);
2779  if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
2780    op1 = copy_to_mode_reg (mode1, op1);
2781
2782  pat = GEN_FCN (icode) (target, op0, op1);
2783  if (! pat)
2784    return 0;
2785  emit_insn (pat);
2786  return target;
2787}
2788
2789/* Subroutine of arm_expand_builtin to take care of unop insns.  */
2790
2791static rtx
2792arm_expand_unop_builtin (enum insn_code icode,
2793			 tree exp, rtx target, int do_load)
2794{
2795  rtx pat;
2796  tree arg0 = CALL_EXPR_ARG (exp, 0);
2797  rtx op0 = expand_normal (arg0);
2798  machine_mode tmode = insn_data[icode].operand[0].mode;
2799  machine_mode mode0 = insn_data[icode].operand[1].mode;
2800
2801  if (! target
2802      || GET_MODE (target) != tmode
2803      || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
2804    target = gen_reg_rtx (tmode);
2805  if (do_load)
2806    op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
2807  else
2808    {
2809      if (VECTOR_MODE_P (mode0))
2810	op0 = safe_vector_operand (op0, mode0);
2811
2812      if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
2813	op0 = copy_to_mode_reg (mode0, op0);
2814    }
2815
2816  pat = GEN_FCN (icode) (target, op0);
2817
2818  if (! pat)
2819    return 0;
2820  emit_insn (pat);
2821  return target;
2822}
2823
2824typedef enum {
2825  ARG_BUILTIN_COPY_TO_REG,
2826  ARG_BUILTIN_CONSTANT,
2827  ARG_BUILTIN_LANE_INDEX,
2828  ARG_BUILTIN_STRUCT_LOAD_STORE_LANE_INDEX,
2829  ARG_BUILTIN_LANE_PAIR_INDEX,
2830  ARG_BUILTIN_LANE_QUADTUP_INDEX,
2831  ARG_BUILTIN_NEON_MEMORY,
2832  ARG_BUILTIN_MEMORY,
2833  ARG_BUILTIN_STOP
2834} builtin_arg;
2835
2836
2837/* EXP is a pointer argument to a Neon load or store intrinsic.  Derive
2838   and return an expression for the accessed memory.
2839
2840   The intrinsic function operates on a block of registers that has
2841   mode REG_MODE.  This block contains vectors of type TYPE_MODE.  The
2842   function references the memory at EXP of type TYPE and in mode
2843   MEM_MODE; this mode may be BLKmode if no more suitable mode is
2844   available.  */
2845
2846static tree
2847neon_dereference_pointer (tree exp, tree type, machine_mode mem_mode,
2848			  machine_mode reg_mode,
2849			  machine_mode vector_mode)
2850{
2851  HOST_WIDE_INT reg_size, vector_size, nvectors, nelems;
2852  tree elem_type, upper_bound, array_type;
2853
2854  /* Work out the size of the register block in bytes.  */
2855  reg_size = GET_MODE_SIZE (reg_mode);
2856
2857  /* Work out the size of each vector in bytes.  */
2858  vector_size = GET_MODE_SIZE (vector_mode);
2859
2860  /* Work out how many vectors there are.  */
2861  gcc_assert (reg_size % vector_size == 0);
2862  nvectors = reg_size / vector_size;
2863
2864  /* Work out the type of each element.  */
2865  gcc_assert (POINTER_TYPE_P (type));
2866  elem_type = TREE_TYPE (type);
2867
2868  /* Work out how many elements are being loaded or stored.
2869     MEM_MODE == REG_MODE implies a one-to-one mapping between register
2870     and memory elements; anything else implies a lane load or store.  */
2871  if (mem_mode == reg_mode)
2872    nelems = vector_size * nvectors / int_size_in_bytes (elem_type);
2873  else
2874    nelems = nvectors;
2875
2876  /* Create a type that describes the full access.  */
2877  upper_bound = build_int_cst (size_type_node, nelems - 1);
2878  array_type = build_array_type (elem_type, build_index_type (upper_bound));
2879
2880  /* Dereference EXP using that type.  */
2881  return fold_build2 (MEM_REF, array_type, exp,
2882		      build_int_cst (build_pointer_type (array_type), 0));
2883}
2884
2885/* EXP is a pointer argument to a vector scatter store intrinsics.
2886
2887   Consider the following example:
2888	VSTRW<v>.<dt> Qd, [Qm{, #+/-<imm>}]!
2889   When <Qm> used as the base register for the target address,
2890   this function is used to derive and return an expression for the
2891   accessed memory.
2892
2893   The intrinsic function operates on a block of registers that has mode
2894   REG_MODE.  This block contains vectors of type TYPE_MODE.  The function
2895   references the memory at EXP of type TYPE and in mode MEM_MODE.  This
2896   mode may be BLKmode if no more suitable mode is available.  */
2897
2898static tree
2899mve_dereference_pointer (tree exp, tree type, machine_mode reg_mode,
2900			 machine_mode vector_mode)
2901{
2902  HOST_WIDE_INT reg_size, vector_size, nelems;
2903  tree elem_type, upper_bound, array_type;
2904
2905  /* Work out the size of each vector in bytes.  */
2906  vector_size = GET_MODE_SIZE (vector_mode);
2907
2908  /* Work out the size of the register block in bytes.  */
2909  reg_size = GET_MODE_SIZE (reg_mode);
2910
2911  /* Work out the type of each element.  */
2912  gcc_assert (POINTER_TYPE_P (type));
2913  elem_type = TREE_TYPE (type);
2914
2915  nelems = reg_size / vector_size;
2916
2917  /* Create a type that describes the full access.  */
2918  upper_bound = build_int_cst (size_type_node, nelems - 1);
2919  array_type = build_array_type (elem_type, build_index_type (upper_bound));
2920
2921  /* Dereference EXP using that type.  */
2922  return fold_build2 (MEM_REF, array_type, exp,
2923		      build_int_cst (build_pointer_type (array_type), 0));
2924}
2925
2926/* Expand a builtin.  */
2927static rtx
2928arm_expand_builtin_args (rtx target, machine_mode map_mode, int fcode,
2929		      int icode, int have_retval, tree exp,
2930		      builtin_arg *args)
2931{
2932  rtx pat;
2933  tree arg[SIMD_MAX_BUILTIN_ARGS];
2934  rtx op[SIMD_MAX_BUILTIN_ARGS];
2935  machine_mode tmode = insn_data[icode].operand[0].mode;
2936  machine_mode mode[SIMD_MAX_BUILTIN_ARGS];
2937  tree formals;
2938  int argc = 0;
2939  rtx_insn * insn;
2940
2941  if (have_retval
2942      && (!target
2943	  || GET_MODE (target) != tmode
2944	  || !(*insn_data[icode].operand[0].predicate) (target, tmode)))
2945    target = gen_reg_rtx (tmode);
2946
2947  formals = TYPE_ARG_TYPES (TREE_TYPE (arm_builtin_decls[fcode]));
2948
2949  for (;;)
2950    {
2951      builtin_arg thisarg = args[argc];
2952
2953      if (thisarg == ARG_BUILTIN_STOP)
2954	break;
2955      else
2956	{
2957	  int opno = argc + have_retval;
2958	  arg[argc] = CALL_EXPR_ARG (exp, argc);
2959	  mode[argc] = insn_data[icode].operand[opno].mode;
2960	  if (thisarg == ARG_BUILTIN_NEON_MEMORY)
2961            {
2962              machine_mode other_mode
2963		= insn_data[icode].operand[1 - opno].mode;
2964	      if (TARGET_HAVE_MVE && mode[argc] != other_mode)
2965		{
2966		  arg[argc] = mve_dereference_pointer (arg[argc],
2967						    TREE_VALUE (formals),
2968						    other_mode, map_mode);
2969		}
2970	      else
2971		arg[argc] = neon_dereference_pointer (arg[argc],
2972						      TREE_VALUE (formals),
2973						      mode[argc], other_mode,
2974						      map_mode);
2975            }
2976
2977	  /* Use EXPAND_MEMORY for ARG_BUILTIN_MEMORY and
2978	     ARG_BUILTIN_NEON_MEMORY to ensure a MEM_P be returned.  */
2979	  op[argc] = expand_expr (arg[argc], NULL_RTX, VOIDmode,
2980				  ((thisarg == ARG_BUILTIN_MEMORY
2981				    || thisarg == ARG_BUILTIN_NEON_MEMORY)
2982				   ? EXPAND_MEMORY : EXPAND_NORMAL));
2983
2984	  switch (thisarg)
2985	    {
2986	    case ARG_BUILTIN_MEMORY:
2987	    case ARG_BUILTIN_COPY_TO_REG:
2988	      if (POINTER_TYPE_P (TREE_TYPE (arg[argc])))
2989		op[argc] = convert_memory_address (Pmode, op[argc]);
2990
2991	      /* MVE uses mve_pred16_t (aka HImode) for vectors of
2992		 predicates.  */
2993	      if (GET_MODE_CLASS (mode[argc]) == MODE_VECTOR_BOOL)
2994		op[argc] = gen_lowpart (mode[argc], op[argc]);
2995
2996	      /*gcc_assert (GET_MODE (op[argc]) == mode[argc]); */
2997	      if (!(*insn_data[icode].operand[opno].predicate)
2998		  (op[argc], mode[argc]))
2999		op[argc] = copy_to_mode_reg (mode[argc], op[argc]);
3000	      break;
3001
3002	    case ARG_BUILTIN_STRUCT_LOAD_STORE_LANE_INDEX:
3003	      gcc_assert (argc > 1);
3004	      if (CONST_INT_P (op[argc]))
3005		{
3006		  neon_lane_bounds (op[argc], 0,
3007				    GET_MODE_NUNITS (map_mode), exp);
3008		  /* Keep to GCC-vector-extension lane indices in the RTL.  */
3009		  op[argc] =
3010		    GEN_INT (NEON_ENDIAN_LANE_N (map_mode, INTVAL (op[argc])));
3011		}
3012	      goto constant_arg;
3013
3014	    case ARG_BUILTIN_LANE_INDEX:
3015	      /* Previous argument must be a vector, which this indexes.  */
3016	      gcc_assert (argc > 0);
3017	      if (CONST_INT_P (op[argc]))
3018		{
3019		  machine_mode vmode = mode[argc - 1];
3020		  neon_lane_bounds (op[argc], 0, GET_MODE_NUNITS (vmode), exp);
3021		}
3022	      /* If the lane index isn't a constant then error out.  */
3023	      goto constant_arg;
3024
3025	    case ARG_BUILTIN_LANE_PAIR_INDEX:
3026	      /* Previous argument must be a vector, which this indexes. The
3027		 indexing will always select i and i+1 out of the vector, which
3028		 puts a limit on i.  */
3029	      gcc_assert (argc > 0);
3030	      if (CONST_INT_P (op[argc]))
3031		{
3032		  machine_mode vmode = mode[argc - 1];
3033		  neon_lane_bounds (op[argc], 0,
3034				    GET_MODE_NUNITS (vmode) / 2, exp);
3035		}
3036	      /* If the lane index isn't a constant then error out.  */
3037	      goto constant_arg;
3038
3039	    case ARG_BUILTIN_LANE_QUADTUP_INDEX:
3040	      /* Previous argument must be a vector, which this indexes.  */
3041	      gcc_assert (argc > 0);
3042	      if (CONST_INT_P (op[argc]))
3043		{
3044		  machine_mode vmode = mode[argc - 1];
3045		  neon_lane_bounds (op[argc], 0,
3046				    GET_MODE_NUNITS (vmode) / 4, exp);
3047		}
3048	      /* If the lane index isn't a constant then error out.  */
3049	      goto constant_arg;
3050
3051	    case ARG_BUILTIN_CONSTANT:
3052constant_arg:
3053	      if (!(*insn_data[icode].operand[opno].predicate)
3054		  (op[argc], mode[argc]))
3055		{
3056		  if (IN_RANGE (fcode, ARM_BUILTIN_CDE_PATTERN_START,
3057				ARM_BUILTIN_CDE_PATTERN_END))
3058		    {
3059		      if (argc == 0)
3060			{
3061			  unsigned int cp_bit = (CONST_INT_P (op[argc])
3062						 ? UINTVAL (op[argc]) : -1);
3063			  if (IN_RANGE (cp_bit, 0, ARM_CDE_CONST_COPROC))
3064			    error_at (EXPR_LOCATION (exp),
3065				      "coprocessor %d is not enabled "
3066				      "with +cdecp%d", cp_bit, cp_bit);
3067			  else
3068			    error_at (EXPR_LOCATION (exp),
3069				      "coproc must be a constant immediate in "
3070				      "range [0-%d] enabled with %<+cdecp<N>%>",
3071				      ARM_CDE_CONST_COPROC);
3072			}
3073		      else
3074			/* Here we mention the builtin name to follow the same
3075			   format that the C/C++ frontends use for referencing
3076			   a given argument index.  */
3077			error_at (EXPR_LOCATION (exp),
3078				  "argument %d to %qE must be a constant "
3079				  "immediate in range [0-%d]", argc + 1,
3080			       arm_builtin_decls[fcode],
3081			       cde_builtin_data[fcode -
3082			       ARM_BUILTIN_CDE_PATTERN_START].imm_max);
3083		    }
3084		  else
3085		    error_at (EXPR_LOCATION (exp),
3086			      "argument %d must be a constant immediate",
3087			      argc + 1);
3088		  /* We have failed to expand the pattern, and are safely
3089		     in to invalid code.  But the mid-end will still try to
3090		     build an assignment for this node while it expands,
3091		     before stopping for the error, just pass it back
3092		     TARGET to ensure a valid assignment.  */
3093		  return target;
3094		}
3095	      break;
3096
3097	      case ARG_BUILTIN_NEON_MEMORY:
3098	      /* Check if expand failed.  */
3099	      if (op[argc] == const0_rtx)
3100		return 0;
3101	      gcc_assert (MEM_P (op[argc]));
3102	      PUT_MODE (op[argc], mode[argc]);
3103	      /* ??? arm_neon.h uses the same built-in functions for signed
3104		 and unsigned accesses, casting where necessary.  This isn't
3105		 alias safe.  */
3106	      set_mem_alias_set (op[argc], 0);
3107	      if (!(*insn_data[icode].operand[opno].predicate)
3108                   (op[argc], mode[argc]))
3109		op[argc] = (replace_equiv_address
3110			    (op[argc],
3111			     copy_to_mode_reg (Pmode, XEXP (op[argc], 0))));
3112              break;
3113
3114	    case ARG_BUILTIN_STOP:
3115	      gcc_unreachable ();
3116	    }
3117
3118	  argc++;
3119	}
3120    }
3121
3122  if (have_retval)
3123    switch (argc)
3124      {
3125      case 0:
3126	pat = GEN_FCN (icode) (target);
3127	break;
3128      case 1:
3129	pat = GEN_FCN (icode) (target, op[0]);
3130	break;
3131
3132      case 2:
3133	pat = GEN_FCN (icode) (target, op[0], op[1]);
3134	break;
3135
3136      case 3:
3137	pat = GEN_FCN (icode) (target, op[0], op[1], op[2]);
3138	break;
3139
3140      case 4:
3141	pat = GEN_FCN (icode) (target, op[0], op[1], op[2], op[3]);
3142	break;
3143
3144      case 5:
3145	pat = GEN_FCN (icode) (target, op[0], op[1], op[2], op[3], op[4]);
3146	break;
3147
3148      case 6:
3149	pat = GEN_FCN (icode) (target, op[0], op[1], op[2], op[3], op[4], op[5]);
3150	break;
3151
3152      default:
3153	gcc_unreachable ();
3154      }
3155  else
3156    switch (argc)
3157      {
3158      case 1:
3159	pat = GEN_FCN (icode) (op[0]);
3160	break;
3161
3162      case 2:
3163	pat = GEN_FCN (icode) (op[0], op[1]);
3164	break;
3165
3166      case 3:
3167	pat = GEN_FCN (icode) (op[0], op[1], op[2]);
3168	break;
3169
3170      case 4:
3171	pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
3172	break;
3173
3174      case 5:
3175	pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4]);
3176	break;
3177
3178      case 6:
3179	pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4], op[5]);
3180	break;
3181
3182      default:
3183	gcc_unreachable ();
3184      }
3185
3186  if (!pat)
3187    return 0;
3188
3189  /* Check whether our current target implements the pattern chosen for this
3190     builtin and error out if not.  */
3191  start_sequence ();
3192  emit_insn (pat);
3193  insn = get_insns ();
3194  end_sequence ();
3195
3196  if (recog_memoized (insn) < 0)
3197    error ("this builtin is not supported for this target");
3198  else
3199    emit_insn (insn);
3200
3201  if (GET_MODE_CLASS (tmode) == MODE_VECTOR_BOOL)
3202    {
3203      rtx HItarget = gen_reg_rtx (HImode);
3204      emit_move_insn (HItarget, gen_lowpart (HImode, target));
3205      return HItarget;
3206    }
3207
3208  return target;
3209}
3210
3211/* Expand a builtin.  These builtins are "special" because they don't have
3212   symbolic constants defined per-instruction or per instruction-variant.
3213   Instead, the required info is looked up in the ARM_BUILTIN_DATA record that
3214   is passed into the function.  */
3215
3216static rtx
3217arm_expand_builtin_1 (int fcode, tree exp, rtx target,
3218			   arm_builtin_datum *d)
3219{
3220  enum insn_code icode = d->code;
3221  builtin_arg args[SIMD_MAX_BUILTIN_ARGS + 1];
3222  int num_args = insn_data[d->code].n_operands;
3223  int is_void = 0;
3224  int k;
3225  bool neon = false;
3226  bool mve = false;
3227
3228  if (IN_RANGE (fcode, ARM_BUILTIN_VFP_BASE, ARM_BUILTIN_ACLE_BASE - 1))
3229    neon = true;
3230
3231  if (IN_RANGE (fcode, ARM_BUILTIN_MVE_BASE, ARM_BUILTIN_MAX - 1))
3232    mve = true;
3233
3234  is_void = !!(d->qualifiers[0] & qualifier_void);
3235
3236  num_args += is_void;
3237
3238  for (k = 1; k < num_args; k++)
3239    {
3240      /* We have four arrays of data, each indexed in a different fashion.
3241	 qualifiers - element 0 always describes the function return type.
3242	 operands - element 0 is either the operand for return value (if
3243	 the function has a non-void return type) or the operand for the
3244	 first argument.
3245	 expr_args - element 0 always holds the first argument.
3246	 args - element 0 is always used for the return type.  */
3247      int qualifiers_k = k;
3248      int operands_k = k - is_void;
3249      int expr_args_k = k - 1;
3250
3251      if (d->qualifiers[qualifiers_k] & qualifier_lane_index)
3252	args[k] = ARG_BUILTIN_LANE_INDEX;
3253      else if (d->qualifiers[qualifiers_k] & qualifier_lane_pair_index)
3254	args[k] = ARG_BUILTIN_LANE_PAIR_INDEX;
3255      else if (d->qualifiers[qualifiers_k] & qualifier_lane_quadtup_index)
3256	args[k] = ARG_BUILTIN_LANE_QUADTUP_INDEX;
3257      else if (d->qualifiers[qualifiers_k] & qualifier_struct_load_store_lane_index)
3258	args[k] = ARG_BUILTIN_STRUCT_LOAD_STORE_LANE_INDEX;
3259      else if (d->qualifiers[qualifiers_k] & qualifier_immediate)
3260	args[k] = ARG_BUILTIN_CONSTANT;
3261      else if (d->qualifiers[qualifiers_k] & qualifier_maybe_immediate)
3262	{
3263	  rtx arg
3264	    = expand_normal (CALL_EXPR_ARG (exp,
3265					    (expr_args_k)));
3266	  /* Handle constants only if the predicate allows it.  */
3267	  bool op_const_int_p =
3268	    (CONST_INT_P (arg)
3269	     && (*insn_data[icode].operand[operands_k].predicate)
3270	     (arg, insn_data[icode].operand[operands_k].mode));
3271	  args[k] = op_const_int_p ? ARG_BUILTIN_CONSTANT : ARG_BUILTIN_COPY_TO_REG;
3272	}
3273      else if (d->qualifiers[qualifiers_k] & qualifier_pointer)
3274	{
3275	  if (neon || mve)
3276	    args[k] = ARG_BUILTIN_NEON_MEMORY;
3277	  else
3278	    args[k] = ARG_BUILTIN_MEMORY;
3279	}
3280      else
3281	args[k] = ARG_BUILTIN_COPY_TO_REG;
3282    }
3283  args[k] = ARG_BUILTIN_STOP;
3284
3285  /* The interface to arm_expand_builtin_args expects a 0 if
3286     the function is void, and a 1 if it is not.  */
3287  return arm_expand_builtin_args
3288    (target, d->mode, fcode, icode, !is_void, exp,
3289     &args[1]);
3290}
3291
3292/* Expand an ACLE builtin, i.e. those registered only if their respective
3293   target constraints are met.  This check happens within
3294   arm_expand_builtin_args.  */
3295
3296static rtx
3297arm_expand_acle_builtin (int fcode, tree exp, rtx target)
3298{
3299  if (fcode == ARM_BUILTIN_SAT_IMM_CHECK)
3300    {
3301      /* Check the saturation immediate bounds.  */
3302
3303      rtx min_sat = expand_normal (CALL_EXPR_ARG (exp, 1));
3304      rtx max_sat = expand_normal (CALL_EXPR_ARG (exp, 2));
3305      gcc_assert (CONST_INT_P (min_sat));
3306      gcc_assert (CONST_INT_P (max_sat));
3307      rtx sat_imm = expand_normal (CALL_EXPR_ARG (exp, 0));
3308      if (CONST_INT_P (sat_imm))
3309	{
3310	  if (!IN_RANGE (sat_imm, min_sat, max_sat))
3311	    error_at (EXPR_LOCATION (exp),
3312		      "saturation bit range must be in the range [%wd, %wd]",
3313		      UINTVAL (min_sat), UINTVAL (max_sat));
3314	}
3315      else
3316	error_at (EXPR_LOCATION (exp),
3317		  "saturation bit range must be a constant immediate");
3318      /* Don't generate any RTL.  */
3319      return const0_rtx;
3320    }
3321
3322  gcc_assert (fcode != ARM_BUILTIN_CDE_BASE);
3323  arm_builtin_datum *d
3324    = (fcode < ARM_BUILTIN_CDE_BASE)
3325      ? &acle_builtin_data[fcode - ARM_BUILTIN_ACLE_PATTERN_START]
3326      : &cde_builtin_data[fcode - ARM_BUILTIN_CDE_PATTERN_START].base;
3327
3328  return arm_expand_builtin_1 (fcode, exp, target, d);
3329}
3330
3331/* Expand an MVE builtin, i.e. those registered only if their respective target
3332   constraints are met.  This check happens within arm_expand_builtin.  */
3333
3334static rtx
3335arm_expand_mve_builtin (int fcode, tree exp, rtx target)
3336{
3337  if (fcode >= ARM_BUILTIN_MVE_BASE && !TARGET_HAVE_MVE)
3338  {
3339    fatal_error (input_location,
3340		"You must enable MVE instructions"
3341		" to use these intrinsics");
3342    return const0_rtx;
3343  }
3344
3345  arm_builtin_datum *d
3346    = &mve_builtin_data[fcode - ARM_BUILTIN_MVE_PATTERN_START];
3347
3348  return arm_expand_builtin_1 (fcode, exp, target, d);
3349}
3350
3351/* Expand a Neon builtin, i.e. those registered only if TARGET_NEON holds.
3352   Most of these are "special" because they don't have symbolic
3353   constants defined per-instruction or per instruction-variant.  Instead, the
3354   required info is looked up in the table neon_builtin_data.  */
3355
3356static rtx
3357arm_expand_neon_builtin (int fcode, tree exp, rtx target)
3358{
3359  if (fcode >= ARM_BUILTIN_NEON_BASE && ! TARGET_NEON)
3360    {
3361      fatal_error (input_location,
3362		   "You must enable NEON instructions"
3363		   " (e.g. %<-mfloat-abi=softfp%> %<-mfpu=neon%>)"
3364		   " to use these intrinsics.");
3365      return const0_rtx;
3366    }
3367
3368  arm_builtin_datum *d
3369    = &neon_builtin_data[fcode - ARM_BUILTIN_NEON_PATTERN_START];
3370
3371  return arm_expand_builtin_1 (fcode, exp, target, d);
3372}
3373
3374/* Expand a VFP builtin.  These builtins are treated like
3375   neon builtins except that the data is looked up in table
3376   VFP_BUILTIN_DATA.  */
3377
3378static rtx
3379arm_expand_vfp_builtin (int fcode, tree exp, rtx target)
3380{
3381  if (fcode >= ARM_BUILTIN_VFP_BASE && ! TARGET_HARD_FLOAT)
3382    {
3383      fatal_error (input_location,
3384		   "You must enable VFP instructions"
3385		   " to use these intrinsics.");
3386      return const0_rtx;
3387    }
3388
3389  arm_builtin_datum *d
3390    = &vfp_builtin_data[fcode - ARM_BUILTIN_VFP_PATTERN_START];
3391
3392  return arm_expand_builtin_1 (fcode, exp, target, d);
3393}
3394
3395/* Expand an expression EXP that calls a built-in function,
3396   with result going to TARGET if that's convenient
3397   (and in mode MODE if that's convenient).
3398   SUBTARGET may be used as the target for computing one of EXP's operands.
3399   IGNORE is nonzero if the value is to be ignored.  */
3400
3401rtx
3402arm_expand_builtin (tree exp,
3403		    rtx target,
3404		    rtx subtarget ATTRIBUTE_UNUSED,
3405		    machine_mode mode ATTRIBUTE_UNUSED,
3406		    int ignore ATTRIBUTE_UNUSED)
3407{
3408  const struct builtin_description * d;
3409  enum insn_code    icode;
3410  tree              fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
3411  tree              arg0;
3412  tree              arg1;
3413  tree              arg2;
3414  rtx               op0;
3415  rtx               op1;
3416  rtx               op2;
3417  rtx               pat;
3418  unsigned int      fcode = DECL_MD_FUNCTION_CODE (fndecl);
3419  size_t            i;
3420  machine_mode tmode;
3421  machine_mode mode0;
3422  machine_mode mode1;
3423  machine_mode mode2;
3424  int opint;
3425  int selector;
3426  int mask;
3427  int imm;
3428
3429  if (fcode == ARM_BUILTIN_SIMD_LANE_CHECK)
3430    {
3431      /* Builtin is only to check bounds of the lane passed to some intrinsics
3432	 that are implemented with gcc vector extensions in arm_neon.h.  */
3433
3434      tree nlanes = CALL_EXPR_ARG (exp, 0);
3435      gcc_assert (TREE_CODE (nlanes) == INTEGER_CST);
3436      rtx lane_idx = expand_normal (CALL_EXPR_ARG (exp, 1));
3437      if (CONST_INT_P (lane_idx))
3438	neon_lane_bounds (lane_idx, 0, TREE_INT_CST_LOW (nlanes), exp);
3439      else
3440	error_at (EXPR_LOCATION (exp),
3441		  "lane index must be a constant immediate");
3442      /* Don't generate any RTL.  */
3443      return const0_rtx;
3444    }
3445  if (fcode >= ARM_BUILTIN_MVE_BASE)
3446    return arm_expand_mve_builtin (fcode, exp, target);
3447
3448  if (fcode >= ARM_BUILTIN_ACLE_BASE)
3449    return arm_expand_acle_builtin (fcode, exp, target);
3450
3451  if (fcode >= ARM_BUILTIN_NEON_BASE)
3452    return arm_expand_neon_builtin (fcode, exp, target);
3453
3454  if (fcode >= ARM_BUILTIN_VFP_BASE)
3455    return arm_expand_vfp_builtin (fcode, exp, target);
3456
3457  /* Check in the context of the function making the call whether the
3458     builtin is supported.  */
3459  if (fcode >= ARM_BUILTIN_CRYPTO_BASE
3460      && (!TARGET_CRYPTO || !TARGET_HARD_FLOAT))
3461    {
3462      fatal_error (input_location,
3463		   "You must enable crypto instructions"
3464		   " (e.g. include %<-mfloat-abi=softfp%> "
3465		   "%<-mfpu=crypto-neon%>)"
3466		   " to use these intrinsics.");
3467      return const0_rtx;
3468    }
3469
3470  switch (fcode)
3471    {
3472    case ARM_BUILTIN_GET_FPSCR_NZCVQC:
3473    case ARM_BUILTIN_SET_FPSCR_NZCVQC:
3474      if (fcode == ARM_BUILTIN_GET_FPSCR_NZCVQC)
3475	{
3476	  icode = CODE_FOR_get_fpscr_nzcvqc;
3477	  target = gen_reg_rtx (SImode);
3478	  emit_insn (GEN_FCN (icode) (target));
3479	  return target;
3480	}
3481      else
3482	{
3483	  icode = CODE_FOR_set_fpscr_nzcvqc;
3484	  op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
3485	  emit_insn (GEN_FCN (icode) (force_reg (SImode, op0)));
3486	  return NULL_RTX;
3487	}
3488
3489    case ARM_BUILTIN_GET_FPSCR:
3490    case ARM_BUILTIN_SET_FPSCR:
3491      if (fcode == ARM_BUILTIN_GET_FPSCR)
3492	{
3493	  icode = CODE_FOR_get_fpscr;
3494	  target = gen_reg_rtx (SImode);
3495	  pat = GEN_FCN (icode) (target);
3496	}
3497      else
3498	{
3499	  target = NULL_RTX;
3500	  icode = CODE_FOR_set_fpscr;
3501	  arg0 = CALL_EXPR_ARG (exp, 0);
3502	  op0 = expand_normal (arg0);
3503	  pat = GEN_FCN (icode) (force_reg (SImode, op0));
3504	}
3505      emit_insn (pat);
3506      return target;
3507
3508    case ARM_BUILTIN_CMSE_NONSECURE_CALLER:
3509      target = gen_reg_rtx (SImode);
3510      op0 = arm_return_addr (0, NULL_RTX);
3511      emit_insn (gen_andsi3 (target, op0, const1_rtx));
3512      op1 = gen_rtx_EQ (SImode, target, const0_rtx);
3513      emit_insn (gen_cstoresi4 (target, op1, target, const0_rtx));
3514      return target;
3515
3516    case ARM_BUILTIN_TEXTRMSB:
3517    case ARM_BUILTIN_TEXTRMUB:
3518    case ARM_BUILTIN_TEXTRMSH:
3519    case ARM_BUILTIN_TEXTRMUH:
3520    case ARM_BUILTIN_TEXTRMSW:
3521    case ARM_BUILTIN_TEXTRMUW:
3522      icode = (fcode == ARM_BUILTIN_TEXTRMSB ? CODE_FOR_iwmmxt_textrmsb
3523	       : fcode == ARM_BUILTIN_TEXTRMUB ? CODE_FOR_iwmmxt_textrmub
3524	       : fcode == ARM_BUILTIN_TEXTRMSH ? CODE_FOR_iwmmxt_textrmsh
3525	       : fcode == ARM_BUILTIN_TEXTRMUH ? CODE_FOR_iwmmxt_textrmuh
3526	       : CODE_FOR_iwmmxt_textrmw);
3527
3528      arg0 = CALL_EXPR_ARG (exp, 0);
3529      arg1 = CALL_EXPR_ARG (exp, 1);
3530      op0 = expand_normal (arg0);
3531      op1 = expand_normal (arg1);
3532      tmode = insn_data[icode].operand[0].mode;
3533      mode0 = insn_data[icode].operand[1].mode;
3534      mode1 = insn_data[icode].operand[2].mode;
3535
3536      if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
3537	op0 = copy_to_mode_reg (mode0, op0);
3538      if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
3539	{
3540	  /* @@@ better error message */
3541	  error ("selector must be an immediate");
3542	  return gen_reg_rtx (tmode);
3543	}
3544
3545      opint = INTVAL (op1);
3546      if (fcode == ARM_BUILTIN_TEXTRMSB || fcode == ARM_BUILTIN_TEXTRMUB)
3547	{
3548	  if (opint > 7 || opint < 0)
3549	    error ("the range of selector should be in 0 to 7");
3550	}
3551      else if (fcode == ARM_BUILTIN_TEXTRMSH || fcode == ARM_BUILTIN_TEXTRMUH)
3552	{
3553	  if (opint > 3 || opint < 0)
3554	    error ("the range of selector should be in 0 to 3");
3555	}
3556      else /* ARM_BUILTIN_TEXTRMSW || ARM_BUILTIN_TEXTRMUW.  */
3557	{
3558	  if (opint > 1 || opint < 0)
3559	    error ("the range of selector should be in 0 to 1");
3560	}
3561
3562      if (target == 0
3563	  || GET_MODE (target) != tmode
3564	  || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
3565	target = gen_reg_rtx (tmode);
3566      pat = GEN_FCN (icode) (target, op0, op1);
3567      if (! pat)
3568	return 0;
3569      emit_insn (pat);
3570      return target;
3571
3572    case ARM_BUILTIN_WALIGNI:
3573      /* If op2 is immediate, call walighi, else call walighr.  */
3574      arg0 = CALL_EXPR_ARG (exp, 0);
3575      arg1 = CALL_EXPR_ARG (exp, 1);
3576      arg2 = CALL_EXPR_ARG (exp, 2);
3577      op0 = expand_normal (arg0);
3578      op1 = expand_normal (arg1);
3579      op2 = expand_normal (arg2);
3580      if (CONST_INT_P (op2))
3581        {
3582	  icode = CODE_FOR_iwmmxt_waligni;
3583          tmode = insn_data[icode].operand[0].mode;
3584	  mode0 = insn_data[icode].operand[1].mode;
3585	  mode1 = insn_data[icode].operand[2].mode;
3586	  mode2 = insn_data[icode].operand[3].mode;
3587          if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
3588	    op0 = copy_to_mode_reg (mode0, op0);
3589          if (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
3590	    op1 = copy_to_mode_reg (mode1, op1);
3591          gcc_assert ((*insn_data[icode].operand[3].predicate) (op2, mode2));
3592	  selector = INTVAL (op2);
3593	  if (selector > 7 || selector < 0)
3594	    error ("the range of selector should be in 0 to 7");
3595	}
3596      else
3597        {
3598	  icode = CODE_FOR_iwmmxt_walignr;
3599          tmode = insn_data[icode].operand[0].mode;
3600	  mode0 = insn_data[icode].operand[1].mode;
3601	  mode1 = insn_data[icode].operand[2].mode;
3602	  mode2 = insn_data[icode].operand[3].mode;
3603          if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
3604	    op0 = copy_to_mode_reg (mode0, op0);
3605          if (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
3606	    op1 = copy_to_mode_reg (mode1, op1);
3607          if (!(*insn_data[icode].operand[3].predicate) (op2, mode2))
3608	    op2 = copy_to_mode_reg (mode2, op2);
3609	}
3610      if (target == 0
3611	  || GET_MODE (target) != tmode
3612	  || !(*insn_data[icode].operand[0].predicate) (target, tmode))
3613	target = gen_reg_rtx (tmode);
3614      pat = GEN_FCN (icode) (target, op0, op1, op2);
3615      if (!pat)
3616	return 0;
3617      emit_insn (pat);
3618      return target;
3619
3620    case ARM_BUILTIN_TINSRB:
3621    case ARM_BUILTIN_TINSRH:
3622    case ARM_BUILTIN_TINSRW:
3623    case ARM_BUILTIN_WMERGE:
3624      icode = (fcode == ARM_BUILTIN_TINSRB ? CODE_FOR_iwmmxt_tinsrb
3625	       : fcode == ARM_BUILTIN_TINSRH ? CODE_FOR_iwmmxt_tinsrh
3626	       : fcode == ARM_BUILTIN_WMERGE ? CODE_FOR_iwmmxt_wmerge
3627	       : CODE_FOR_iwmmxt_tinsrw);
3628      arg0 = CALL_EXPR_ARG (exp, 0);
3629      arg1 = CALL_EXPR_ARG (exp, 1);
3630      arg2 = CALL_EXPR_ARG (exp, 2);
3631      op0 = expand_normal (arg0);
3632      op1 = expand_normal (arg1);
3633      op2 = expand_normal (arg2);
3634      tmode = insn_data[icode].operand[0].mode;
3635      mode0 = insn_data[icode].operand[1].mode;
3636      mode1 = insn_data[icode].operand[2].mode;
3637      mode2 = insn_data[icode].operand[3].mode;
3638
3639      if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
3640	op0 = copy_to_mode_reg (mode0, op0);
3641      if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
3642	op1 = copy_to_mode_reg (mode1, op1);
3643      if (! (*insn_data[icode].operand[3].predicate) (op2, mode2))
3644	{
3645	  error ("selector must be an immediate");
3646	  return const0_rtx;
3647	}
3648      if (icode == CODE_FOR_iwmmxt_wmerge)
3649	{
3650	  selector = INTVAL (op2);
3651	  if (selector > 7 || selector < 0)
3652	    error ("the range of selector should be in 0 to 7");
3653	}
3654      if ((icode == CODE_FOR_iwmmxt_tinsrb)
3655	  || (icode == CODE_FOR_iwmmxt_tinsrh)
3656	  || (icode == CODE_FOR_iwmmxt_tinsrw))
3657        {
3658	  mask = 0x01;
3659	  selector= INTVAL (op2);
3660	  if (icode == CODE_FOR_iwmmxt_tinsrb && (selector < 0 || selector > 7))
3661	    error ("the range of selector should be in 0 to 7");
3662	  else if (icode == CODE_FOR_iwmmxt_tinsrh && (selector < 0 ||selector > 3))
3663	    error ("the range of selector should be in 0 to 3");
3664	  else if (icode == CODE_FOR_iwmmxt_tinsrw && (selector < 0 ||selector > 1))
3665	    error ("the range of selector should be in 0 to 1");
3666	  mask <<= selector;
3667	  op2 = GEN_INT (mask);
3668	}
3669      if (target == 0
3670	  || GET_MODE (target) != tmode
3671	  || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
3672	target = gen_reg_rtx (tmode);
3673      pat = GEN_FCN (icode) (target, op0, op1, op2);
3674      if (! pat)
3675	return 0;
3676      emit_insn (pat);
3677      return target;
3678
3679    case ARM_BUILTIN_SETWCGR0:
3680    case ARM_BUILTIN_SETWCGR1:
3681    case ARM_BUILTIN_SETWCGR2:
3682    case ARM_BUILTIN_SETWCGR3:
3683      icode = (fcode == ARM_BUILTIN_SETWCGR0 ? CODE_FOR_iwmmxt_setwcgr0
3684	       : fcode == ARM_BUILTIN_SETWCGR1 ? CODE_FOR_iwmmxt_setwcgr1
3685	       : fcode == ARM_BUILTIN_SETWCGR2 ? CODE_FOR_iwmmxt_setwcgr2
3686	       : CODE_FOR_iwmmxt_setwcgr3);
3687      arg0 = CALL_EXPR_ARG (exp, 0);
3688      op0 = expand_normal (arg0);
3689      mode0 = insn_data[icode].operand[0].mode;
3690      if (!(*insn_data[icode].operand[0].predicate) (op0, mode0))
3691        op0 = copy_to_mode_reg (mode0, op0);
3692      pat = GEN_FCN (icode) (op0);
3693      if (!pat)
3694	return 0;
3695      emit_insn (pat);
3696      return 0;
3697
3698    case ARM_BUILTIN_GETWCGR0:
3699    case ARM_BUILTIN_GETWCGR1:
3700    case ARM_BUILTIN_GETWCGR2:
3701    case ARM_BUILTIN_GETWCGR3:
3702      icode = (fcode == ARM_BUILTIN_GETWCGR0 ? CODE_FOR_iwmmxt_getwcgr0
3703	       : fcode == ARM_BUILTIN_GETWCGR1 ? CODE_FOR_iwmmxt_getwcgr1
3704	       : fcode == ARM_BUILTIN_GETWCGR2 ? CODE_FOR_iwmmxt_getwcgr2
3705	       : CODE_FOR_iwmmxt_getwcgr3);
3706      tmode = insn_data[icode].operand[0].mode;
3707      if (target == 0
3708	  || GET_MODE (target) != tmode
3709	  || !(*insn_data[icode].operand[0].predicate) (target, tmode))
3710        target = gen_reg_rtx (tmode);
3711      pat = GEN_FCN (icode) (target);
3712      if (!pat)
3713        return 0;
3714      emit_insn (pat);
3715      return target;
3716
3717    case ARM_BUILTIN_WSHUFH:
3718      icode = CODE_FOR_iwmmxt_wshufh;
3719      arg0 = CALL_EXPR_ARG (exp, 0);
3720      arg1 = CALL_EXPR_ARG (exp, 1);
3721      op0 = expand_normal (arg0);
3722      op1 = expand_normal (arg1);
3723      tmode = insn_data[icode].operand[0].mode;
3724      mode1 = insn_data[icode].operand[1].mode;
3725      mode2 = insn_data[icode].operand[2].mode;
3726
3727      if (! (*insn_data[icode].operand[1].predicate) (op0, mode1))
3728	op0 = copy_to_mode_reg (mode1, op0);
3729      if (! (*insn_data[icode].operand[2].predicate) (op1, mode2))
3730	{
3731	  error ("mask must be an immediate");
3732	  return const0_rtx;
3733	}
3734      selector = INTVAL (op1);
3735      if (selector < 0 || selector > 255)
3736	error ("the range of mask should be in 0 to 255");
3737      if (target == 0
3738	  || GET_MODE (target) != tmode
3739	  || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
3740	target = gen_reg_rtx (tmode);
3741      pat = GEN_FCN (icode) (target, op0, op1);
3742      if (! pat)
3743	return 0;
3744      emit_insn (pat);
3745      return target;
3746
3747    case ARM_BUILTIN_WMADDS:
3748      return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wmadds, exp, target);
3749    case ARM_BUILTIN_WMADDSX:
3750      return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wmaddsx, exp, target);
3751    case ARM_BUILTIN_WMADDSN:
3752      return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wmaddsn, exp, target);
3753    case ARM_BUILTIN_WMADDU:
3754      return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wmaddu, exp, target);
3755    case ARM_BUILTIN_WMADDUX:
3756      return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wmaddux, exp, target);
3757    case ARM_BUILTIN_WMADDUN:
3758      return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wmaddun, exp, target);
3759    case ARM_BUILTIN_WSADBZ:
3760      return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wsadbz, exp, target);
3761    case ARM_BUILTIN_WSADHZ:
3762      return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wsadhz, exp, target);
3763
3764      /* Several three-argument builtins.  */
3765    case ARM_BUILTIN_WMACS:
3766    case ARM_BUILTIN_WMACU:
3767    case ARM_BUILTIN_TMIA:
3768    case ARM_BUILTIN_TMIAPH:
3769    case ARM_BUILTIN_TMIATT:
3770    case ARM_BUILTIN_TMIATB:
3771    case ARM_BUILTIN_TMIABT:
3772    case ARM_BUILTIN_TMIABB:
3773    case ARM_BUILTIN_WQMIABB:
3774    case ARM_BUILTIN_WQMIABT:
3775    case ARM_BUILTIN_WQMIATB:
3776    case ARM_BUILTIN_WQMIATT:
3777    case ARM_BUILTIN_WQMIABBN:
3778    case ARM_BUILTIN_WQMIABTN:
3779    case ARM_BUILTIN_WQMIATBN:
3780    case ARM_BUILTIN_WQMIATTN:
3781    case ARM_BUILTIN_WMIABB:
3782    case ARM_BUILTIN_WMIABT:
3783    case ARM_BUILTIN_WMIATB:
3784    case ARM_BUILTIN_WMIATT:
3785    case ARM_BUILTIN_WMIABBN:
3786    case ARM_BUILTIN_WMIABTN:
3787    case ARM_BUILTIN_WMIATBN:
3788    case ARM_BUILTIN_WMIATTN:
3789    case ARM_BUILTIN_WMIAWBB:
3790    case ARM_BUILTIN_WMIAWBT:
3791    case ARM_BUILTIN_WMIAWTB:
3792    case ARM_BUILTIN_WMIAWTT:
3793    case ARM_BUILTIN_WMIAWBBN:
3794    case ARM_BUILTIN_WMIAWBTN:
3795    case ARM_BUILTIN_WMIAWTBN:
3796    case ARM_BUILTIN_WMIAWTTN:
3797    case ARM_BUILTIN_WSADB:
3798    case ARM_BUILTIN_WSADH:
3799      icode = (fcode == ARM_BUILTIN_WMACS ? CODE_FOR_iwmmxt_wmacs
3800	       : fcode == ARM_BUILTIN_WMACU ? CODE_FOR_iwmmxt_wmacu
3801	       : fcode == ARM_BUILTIN_TMIA ? CODE_FOR_iwmmxt_tmia
3802	       : fcode == ARM_BUILTIN_TMIAPH ? CODE_FOR_iwmmxt_tmiaph
3803	       : fcode == ARM_BUILTIN_TMIABB ? CODE_FOR_iwmmxt_tmiabb
3804	       : fcode == ARM_BUILTIN_TMIABT ? CODE_FOR_iwmmxt_tmiabt
3805	       : fcode == ARM_BUILTIN_TMIATB ? CODE_FOR_iwmmxt_tmiatb
3806	       : fcode == ARM_BUILTIN_TMIATT ? CODE_FOR_iwmmxt_tmiatt
3807	       : fcode == ARM_BUILTIN_WQMIABB ? CODE_FOR_iwmmxt_wqmiabb
3808	       : fcode == ARM_BUILTIN_WQMIABT ? CODE_FOR_iwmmxt_wqmiabt
3809	       : fcode == ARM_BUILTIN_WQMIATB ? CODE_FOR_iwmmxt_wqmiatb
3810	       : fcode == ARM_BUILTIN_WQMIATT ? CODE_FOR_iwmmxt_wqmiatt
3811	       : fcode == ARM_BUILTIN_WQMIABBN ? CODE_FOR_iwmmxt_wqmiabbn
3812	       : fcode == ARM_BUILTIN_WQMIABTN ? CODE_FOR_iwmmxt_wqmiabtn
3813	       : fcode == ARM_BUILTIN_WQMIATBN ? CODE_FOR_iwmmxt_wqmiatbn
3814	       : fcode == ARM_BUILTIN_WQMIATTN ? CODE_FOR_iwmmxt_wqmiattn
3815	       : fcode == ARM_BUILTIN_WMIABB ? CODE_FOR_iwmmxt_wmiabb
3816	       : fcode == ARM_BUILTIN_WMIABT ? CODE_FOR_iwmmxt_wmiabt
3817	       : fcode == ARM_BUILTIN_WMIATB ? CODE_FOR_iwmmxt_wmiatb
3818	       : fcode == ARM_BUILTIN_WMIATT ? CODE_FOR_iwmmxt_wmiatt
3819	       : fcode == ARM_BUILTIN_WMIABBN ? CODE_FOR_iwmmxt_wmiabbn
3820	       : fcode == ARM_BUILTIN_WMIABTN ? CODE_FOR_iwmmxt_wmiabtn
3821	       : fcode == ARM_BUILTIN_WMIATBN ? CODE_FOR_iwmmxt_wmiatbn
3822	       : fcode == ARM_BUILTIN_WMIATTN ? CODE_FOR_iwmmxt_wmiattn
3823	       : fcode == ARM_BUILTIN_WMIAWBB ? CODE_FOR_iwmmxt_wmiawbb
3824	       : fcode == ARM_BUILTIN_WMIAWBT ? CODE_FOR_iwmmxt_wmiawbt
3825	       : fcode == ARM_BUILTIN_WMIAWTB ? CODE_FOR_iwmmxt_wmiawtb
3826	       : fcode == ARM_BUILTIN_WMIAWTT ? CODE_FOR_iwmmxt_wmiawtt
3827	       : fcode == ARM_BUILTIN_WMIAWBBN ? CODE_FOR_iwmmxt_wmiawbbn
3828	       : fcode == ARM_BUILTIN_WMIAWBTN ? CODE_FOR_iwmmxt_wmiawbtn
3829	       : fcode == ARM_BUILTIN_WMIAWTBN ? CODE_FOR_iwmmxt_wmiawtbn
3830	       : fcode == ARM_BUILTIN_WMIAWTTN ? CODE_FOR_iwmmxt_wmiawttn
3831	       : fcode == ARM_BUILTIN_WSADB ? CODE_FOR_iwmmxt_wsadb
3832	       : CODE_FOR_iwmmxt_wsadh);
3833      arg0 = CALL_EXPR_ARG (exp, 0);
3834      arg1 = CALL_EXPR_ARG (exp, 1);
3835      arg2 = CALL_EXPR_ARG (exp, 2);
3836      op0 = expand_normal (arg0);
3837      op1 = expand_normal (arg1);
3838      op2 = expand_normal (arg2);
3839      tmode = insn_data[icode].operand[0].mode;
3840      mode0 = insn_data[icode].operand[1].mode;
3841      mode1 = insn_data[icode].operand[2].mode;
3842      mode2 = insn_data[icode].operand[3].mode;
3843
3844      if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
3845	op0 = copy_to_mode_reg (mode0, op0);
3846      if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
3847	op1 = copy_to_mode_reg (mode1, op1);
3848      if (! (*insn_data[icode].operand[3].predicate) (op2, mode2))
3849	op2 = copy_to_mode_reg (mode2, op2);
3850      if (target == 0
3851	  || GET_MODE (target) != tmode
3852	  || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
3853	target = gen_reg_rtx (tmode);
3854      pat = GEN_FCN (icode) (target, op0, op1, op2);
3855      if (! pat)
3856	return 0;
3857      emit_insn (pat);
3858      return target;
3859
3860    case ARM_BUILTIN_WZERO:
3861      target = gen_reg_rtx (DImode);
3862      emit_insn (gen_iwmmxt_clrdi (target));
3863      return target;
3864
3865    case ARM_BUILTIN_WSRLHI:
3866    case ARM_BUILTIN_WSRLWI:
3867    case ARM_BUILTIN_WSRLDI:
3868    case ARM_BUILTIN_WSLLHI:
3869    case ARM_BUILTIN_WSLLWI:
3870    case ARM_BUILTIN_WSLLDI:
3871    case ARM_BUILTIN_WSRAHI:
3872    case ARM_BUILTIN_WSRAWI:
3873    case ARM_BUILTIN_WSRADI:
3874    case ARM_BUILTIN_WRORHI:
3875    case ARM_BUILTIN_WRORWI:
3876    case ARM_BUILTIN_WRORDI:
3877    case ARM_BUILTIN_WSRLH:
3878    case ARM_BUILTIN_WSRLW:
3879    case ARM_BUILTIN_WSRLD:
3880    case ARM_BUILTIN_WSLLH:
3881    case ARM_BUILTIN_WSLLW:
3882    case ARM_BUILTIN_WSLLD:
3883    case ARM_BUILTIN_WSRAH:
3884    case ARM_BUILTIN_WSRAW:
3885    case ARM_BUILTIN_WSRAD:
3886    case ARM_BUILTIN_WRORH:
3887    case ARM_BUILTIN_WRORW:
3888    case ARM_BUILTIN_WRORD:
3889      icode = (fcode == ARM_BUILTIN_WSRLHI ? CODE_FOR_lshrv4hi3_iwmmxt
3890	       : fcode == ARM_BUILTIN_WSRLWI ? CODE_FOR_lshrv2si3_iwmmxt
3891	       : fcode == ARM_BUILTIN_WSRLDI ? CODE_FOR_lshrdi3_iwmmxt
3892	       : fcode == ARM_BUILTIN_WSLLHI ? CODE_FOR_ashlv4hi3_iwmmxt
3893	       : fcode == ARM_BUILTIN_WSLLWI ? CODE_FOR_ashlv2si3_iwmmxt
3894	       : fcode == ARM_BUILTIN_WSLLDI ? CODE_FOR_ashldi3_iwmmxt
3895	       : fcode == ARM_BUILTIN_WSRAHI ? CODE_FOR_ashrv4hi3_iwmmxt
3896	       : fcode == ARM_BUILTIN_WSRAWI ? CODE_FOR_ashrv2si3_iwmmxt
3897	       : fcode == ARM_BUILTIN_WSRADI ? CODE_FOR_ashrdi3_iwmmxt
3898	       : fcode == ARM_BUILTIN_WRORHI ? CODE_FOR_rorv4hi3
3899	       : fcode == ARM_BUILTIN_WRORWI ? CODE_FOR_rorv2si3
3900	       : fcode == ARM_BUILTIN_WRORDI ? CODE_FOR_rordi3
3901	       : fcode == ARM_BUILTIN_WSRLH  ? CODE_FOR_lshrv4hi3_di
3902	       : fcode == ARM_BUILTIN_WSRLW  ? CODE_FOR_lshrv2si3_di
3903	       : fcode == ARM_BUILTIN_WSRLD  ? CODE_FOR_lshrdi3_di
3904	       : fcode == ARM_BUILTIN_WSLLH  ? CODE_FOR_ashlv4hi3_di
3905	       : fcode == ARM_BUILTIN_WSLLW  ? CODE_FOR_ashlv2si3_di
3906	       : fcode == ARM_BUILTIN_WSLLD  ? CODE_FOR_ashldi3_di
3907	       : fcode == ARM_BUILTIN_WSRAH  ? CODE_FOR_ashrv4hi3_di
3908	       : fcode == ARM_BUILTIN_WSRAW  ? CODE_FOR_ashrv2si3_di
3909	       : fcode == ARM_BUILTIN_WSRAD  ? CODE_FOR_ashrdi3_di
3910	       : fcode == ARM_BUILTIN_WRORH  ? CODE_FOR_rorv4hi3_di
3911	       : fcode == ARM_BUILTIN_WRORW  ? CODE_FOR_rorv2si3_di
3912	       : fcode == ARM_BUILTIN_WRORD  ? CODE_FOR_rordi3_di
3913	       : CODE_FOR_nothing);
3914      arg1 = CALL_EXPR_ARG (exp, 1);
3915      op1 = expand_normal (arg1);
3916      if (GET_MODE (op1) == VOIDmode)
3917	{
3918	  imm = INTVAL (op1);
3919	  if ((fcode == ARM_BUILTIN_WRORWI || fcode == ARM_BUILTIN_WRORW)
3920	      && (imm < 0 || imm > 32))
3921	    {
3922	      const char *builtin = (fcode == ARM_BUILTIN_WRORWI
3923				     ? "_mm_rori_pi32" : "_mm_ror_pi32");
3924	      error ("the range of count should be in 0 to 32; "
3925		     "please check the intrinsic %qs in code", builtin);
3926	    }
3927	  else if ((fcode == ARM_BUILTIN_WRORHI || fcode == ARM_BUILTIN_WRORH)
3928		   && (imm < 0 || imm > 16))
3929	    {
3930	      const char *builtin = (fcode == ARM_BUILTIN_WRORHI
3931				     ? "_mm_rori_pi16" : "_mm_ror_pi16");
3932	      error ("the range of count should be in 0 to 16; "
3933		     "please check the intrinsic %qs in code", builtin);
3934	    }
3935	  else if ((fcode == ARM_BUILTIN_WRORDI || fcode == ARM_BUILTIN_WRORD)
3936		   && (imm < 0 || imm > 64))
3937	    {
3938	      const char *builtin = (fcode == ARM_BUILTIN_WRORDI
3939				     ? "_mm_rori_si64" : "_mm_ror_si64");
3940	      error ("the range of count should be in 0 to 64; "
3941		     "please check the intrinsic %qs in code", builtin);
3942	    }
3943	  else if (imm < 0)
3944	    {
3945	      const char *builtin;
3946	      switch (fcode)
3947		{
3948		  case ARM_BUILTIN_WSRLHI:
3949		    builtin = "_mm_srli_pi16";
3950		    break;
3951		  case ARM_BUILTIN_WSRLWI:
3952		    builtin = "_mm_srli_pi32";
3953		    break;
3954		  case ARM_BUILTIN_WSRLDI:
3955		    builtin = "_mm_srli_si64";
3956		    break;
3957		  case ARM_BUILTIN_WSLLHI:
3958		    builtin = "_mm_slli_pi16";
3959		    break;
3960		  case ARM_BUILTIN_WSLLWI:
3961		    builtin = "_mm_slli_pi32";
3962		    break;
3963		  case ARM_BUILTIN_WSLLDI:
3964		    builtin = "_mm_slli_si64";
3965		    break;
3966		  case ARM_BUILTIN_WSRAHI:
3967		    builtin = "_mm_srai_pi16";
3968		    break;
3969		  case ARM_BUILTIN_WSRAWI:
3970		    builtin = "_mm_srai_pi32";
3971		    break;
3972		  case ARM_BUILTIN_WSRADI:
3973		    builtin = "_mm_srai_si64";
3974		    break;
3975		  case ARM_BUILTIN_WSRLH:
3976		    builtin = "_mm_srl_pi16";
3977		    break;
3978		  case ARM_BUILTIN_WSRLW:
3979		    builtin = "_mm_srl_pi32";
3980		    break;
3981		  case ARM_BUILTIN_WSRLD:
3982		    builtin = "_mm_srl_si64";
3983		    break;
3984		  case ARM_BUILTIN_WSLLH:
3985		    builtin = "_mm_sll_pi16";
3986		    break;
3987		  case ARM_BUILTIN_WSLLW:
3988		    builtin = "_mm_sll_pi32";
3989		    break;
3990		  case ARM_BUILTIN_WSLLD:
3991		    builtin = "_mm_sll_si64";
3992		    break;
3993		  case ARM_BUILTIN_WSRAH:
3994		    builtin = "_mm_sra_pi16";
3995		    break;
3996		  case ARM_BUILTIN_WSRAW:
3997		    builtin = "_mm_sra_si64";
3998		    break;
3999		  default:
4000		    builtin = "_mm_sra_si64";
4001		    break;
4002		}
4003	      error ("the count should be no less than 0; "
4004		     "please check the intrinsic %qs in code", builtin);
4005	    }
4006	}
4007      return arm_expand_binop_builtin (icode, exp, target);
4008
4009    default:
4010      break;
4011    }
4012
4013  for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
4014    if (d->code == (enum arm_builtins) fcode)
4015      return arm_expand_binop_builtin (d->icode, exp, target);
4016
4017  for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
4018    if (d->code == (enum arm_builtins) fcode)
4019      return arm_expand_unop_builtin (d->icode, exp, target, 0);
4020
4021  for (i = 0, d = bdesc_3arg; i < ARRAY_SIZE (bdesc_3arg); i++, d++)
4022    if (d->code == (enum arm_builtins) fcode)
4023      return arm_expand_ternop_builtin (d->icode, exp, target);
4024
4025  /* @@@ Should really do something sensible here.  */
4026  return NULL_RTX;
4027}
4028
4029tree
4030arm_builtin_vectorized_function (unsigned int fn, tree type_out, tree type_in)
4031{
4032  machine_mode in_mode, out_mode;
4033  int in_n, out_n;
4034  bool out_unsigned_p = TYPE_UNSIGNED (type_out);
4035
4036  /* Can't provide any vectorized builtins when we can't use NEON.  */
4037  if (!TARGET_NEON)
4038    return NULL_TREE;
4039
4040  if (TREE_CODE (type_out) != VECTOR_TYPE
4041      || TREE_CODE (type_in) != VECTOR_TYPE)
4042    return NULL_TREE;
4043
4044  out_mode = TYPE_MODE (TREE_TYPE (type_out));
4045  out_n = TYPE_VECTOR_SUBPARTS (type_out);
4046  in_mode = TYPE_MODE (TREE_TYPE (type_in));
4047  in_n = TYPE_VECTOR_SUBPARTS (type_in);
4048
4049/* ARM_CHECK_BUILTIN_MODE and ARM_FIND_VRINT_VARIANT are used to find the
4050   decl of the vectorized builtin for the appropriate vector mode.
4051   NULL_TREE is returned if no such builtin is available.  */
4052#undef ARM_CHECK_BUILTIN_MODE
4053#define ARM_CHECK_BUILTIN_MODE(C)    \
4054  (TARGET_VFP5   \
4055   && flag_unsafe_math_optimizations \
4056   && ARM_CHECK_BUILTIN_MODE_1 (C))
4057
4058#undef ARM_CHECK_BUILTIN_MODE_1
4059#define ARM_CHECK_BUILTIN_MODE_1(C) \
4060  (out_mode == SFmode && out_n == C \
4061   && in_mode == SFmode && in_n == C)
4062
4063#undef ARM_FIND_VRINT_VARIANT
4064#define ARM_FIND_VRINT_VARIANT(N) \
4065  (ARM_CHECK_BUILTIN_MODE (2) \
4066    ? arm_builtin_decl(ARM_BUILTIN_NEON_##N##v2sf, false) \
4067    : (ARM_CHECK_BUILTIN_MODE (4) \
4068      ? arm_builtin_decl(ARM_BUILTIN_NEON_##N##v4sf, false) \
4069      : NULL_TREE))
4070
4071  switch (fn)
4072    {
4073    CASE_CFN_FLOOR:
4074      return ARM_FIND_VRINT_VARIANT (vrintm);
4075    CASE_CFN_CEIL:
4076      return ARM_FIND_VRINT_VARIANT (vrintp);
4077    CASE_CFN_TRUNC:
4078      return ARM_FIND_VRINT_VARIANT (vrintz);
4079    CASE_CFN_ROUND:
4080      return ARM_FIND_VRINT_VARIANT (vrinta);
4081#undef ARM_CHECK_BUILTIN_MODE_1
4082#define ARM_CHECK_BUILTIN_MODE_1(C) \
4083  (out_mode == SImode && out_n == C \
4084   && in_mode == SFmode && in_n == C)
4085
4086#define ARM_FIND_VCVT_VARIANT(N) \
4087  (ARM_CHECK_BUILTIN_MODE (2) \
4088   ? arm_builtin_decl(ARM_BUILTIN_NEON_##N##v2sfv2si, false) \
4089   : (ARM_CHECK_BUILTIN_MODE (4) \
4090     ? arm_builtin_decl(ARM_BUILTIN_NEON_##N##v4sfv4si, false) \
4091     : NULL_TREE))
4092
4093#define ARM_FIND_VCVTU_VARIANT(N) \
4094  (ARM_CHECK_BUILTIN_MODE (2) \
4095   ? arm_builtin_decl(ARM_BUILTIN_NEON_##N##uv2sfv2si, false) \
4096   : (ARM_CHECK_BUILTIN_MODE (4) \
4097     ? arm_builtin_decl(ARM_BUILTIN_NEON_##N##uv4sfv4si, false) \
4098     : NULL_TREE))
4099    CASE_CFN_LROUND:
4100      return (out_unsigned_p
4101	      ? ARM_FIND_VCVTU_VARIANT (vcvta)
4102	      : ARM_FIND_VCVT_VARIANT (vcvta));
4103    CASE_CFN_LCEIL:
4104      return (out_unsigned_p
4105	      ? ARM_FIND_VCVTU_VARIANT (vcvtp)
4106	      : ARM_FIND_VCVT_VARIANT (vcvtp));
4107    CASE_CFN_LFLOOR:
4108      return (out_unsigned_p
4109	      ? ARM_FIND_VCVTU_VARIANT (vcvtm)
4110	      : ARM_FIND_VCVT_VARIANT (vcvtm));
4111#undef ARM_CHECK_BUILTIN_MODE
4112#define ARM_CHECK_BUILTIN_MODE(C, N) \
4113  (out_mode == N##mode && out_n == C \
4114   && in_mode == N##mode && in_n == C)
4115    case CFN_BUILT_IN_BSWAP16:
4116      if (ARM_CHECK_BUILTIN_MODE (4, HI))
4117	return arm_builtin_decl (ARM_BUILTIN_NEON_bswapv4hi, false);
4118      else if (ARM_CHECK_BUILTIN_MODE (8, HI))
4119	return arm_builtin_decl (ARM_BUILTIN_NEON_bswapv8hi, false);
4120      else
4121	return NULL_TREE;
4122    case CFN_BUILT_IN_BSWAP32:
4123      if (ARM_CHECK_BUILTIN_MODE (2, SI))
4124	return arm_builtin_decl (ARM_BUILTIN_NEON_bswapv2si, false);
4125      else if (ARM_CHECK_BUILTIN_MODE (4, SI))
4126	return arm_builtin_decl (ARM_BUILTIN_NEON_bswapv4si, false);
4127      else
4128	return NULL_TREE;
4129    case CFN_BUILT_IN_BSWAP64:
4130      if (ARM_CHECK_BUILTIN_MODE (2, DI))
4131	return arm_builtin_decl (ARM_BUILTIN_NEON_bswapv2di, false);
4132      else
4133	return NULL_TREE;
4134    CASE_CFN_COPYSIGN:
4135      if (ARM_CHECK_BUILTIN_MODE (2, SF))
4136	return arm_builtin_decl (ARM_BUILTIN_NEON_copysignfv2sf, false);
4137      else if (ARM_CHECK_BUILTIN_MODE (4, SF))
4138	return arm_builtin_decl (ARM_BUILTIN_NEON_copysignfv4sf, false);
4139      else
4140	return NULL_TREE;
4141
4142    default:
4143      return NULL_TREE;
4144    }
4145  return NULL_TREE;
4146}
4147#undef ARM_FIND_VCVT_VARIANT
4148#undef ARM_FIND_VCVTU_VARIANT
4149#undef ARM_CHECK_BUILTIN_MODE
4150#undef ARM_FIND_VRINT_VARIANT
4151
4152void
4153arm_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
4154{
4155  const unsigned ARM_FE_INVALID = 1;
4156  const unsigned ARM_FE_DIVBYZERO = 2;
4157  const unsigned ARM_FE_OVERFLOW = 4;
4158  const unsigned ARM_FE_UNDERFLOW = 8;
4159  const unsigned ARM_FE_INEXACT = 16;
4160  const unsigned HOST_WIDE_INT ARM_FE_ALL_EXCEPT = (ARM_FE_INVALID
4161						    | ARM_FE_DIVBYZERO
4162						    | ARM_FE_OVERFLOW
4163						    | ARM_FE_UNDERFLOW
4164						    | ARM_FE_INEXACT);
4165  const unsigned HOST_WIDE_INT ARM_FE_EXCEPT_SHIFT = 8;
4166  tree fenv_var, get_fpscr, set_fpscr, mask, ld_fenv, masked_fenv;
4167  tree new_fenv_var, reload_fenv, restore_fnenv;
4168  tree update_call, atomic_feraiseexcept, hold_fnclex;
4169
4170  if (!TARGET_HARD_FLOAT)
4171    return;
4172
4173  /* Generate the equivalent of :
4174       unsigned int fenv_var;
4175       fenv_var = __builtin_arm_get_fpscr ();
4176
4177       unsigned int masked_fenv;
4178       masked_fenv = fenv_var & mask;
4179
4180       __builtin_arm_set_fpscr (masked_fenv);  */
4181
4182  fenv_var = create_tmp_var_raw (unsigned_type_node);
4183  get_fpscr = arm_builtin_decls[ARM_BUILTIN_GET_FPSCR];
4184  set_fpscr = arm_builtin_decls[ARM_BUILTIN_SET_FPSCR];
4185  mask = build_int_cst (unsigned_type_node,
4186			~((ARM_FE_ALL_EXCEPT << ARM_FE_EXCEPT_SHIFT)
4187			  | ARM_FE_ALL_EXCEPT));
4188  ld_fenv = build4 (TARGET_EXPR, unsigned_type_node,
4189		    fenv_var, build_call_expr (get_fpscr, 0),
4190		    NULL_TREE, NULL_TREE);
4191  masked_fenv = build2 (BIT_AND_EXPR, unsigned_type_node, fenv_var, mask);
4192  hold_fnclex = build_call_expr (set_fpscr, 1, masked_fenv);
4193  *hold = build2 (COMPOUND_EXPR, void_type_node,
4194		  build2 (COMPOUND_EXPR, void_type_node, masked_fenv, ld_fenv),
4195		  hold_fnclex);
4196
4197  /* Store the value of masked_fenv to clear the exceptions:
4198     __builtin_arm_set_fpscr (masked_fenv);  */
4199
4200  *clear = build_call_expr (set_fpscr, 1, masked_fenv);
4201
4202  /* Generate the equivalent of :
4203       unsigned int new_fenv_var;
4204       new_fenv_var = __builtin_arm_get_fpscr ();
4205
4206       __builtin_arm_set_fpscr (fenv_var);
4207
4208       __atomic_feraiseexcept (new_fenv_var);  */
4209
4210  new_fenv_var = create_tmp_var_raw (unsigned_type_node);
4211  reload_fenv = build4 (TARGET_EXPR, unsigned_type_node, new_fenv_var,
4212			build_call_expr (get_fpscr, 0), NULL_TREE, NULL_TREE);
4213  restore_fnenv = build_call_expr (set_fpscr, 1, fenv_var);
4214  atomic_feraiseexcept = builtin_decl_implicit (BUILT_IN_ATOMIC_FERAISEEXCEPT);
4215  update_call = build_call_expr (atomic_feraiseexcept, 1,
4216				 fold_convert (integer_type_node, new_fenv_var));
4217  *update = build2 (COMPOUND_EXPR, void_type_node,
4218		    build2 (COMPOUND_EXPR, void_type_node,
4219			    reload_fenv, restore_fnenv), update_call);
4220}
4221
4222/* Implement TARGET_CHECK_BUILTIN_CALL.  Record a read of the Q bit through
4223   intrinsics in the machine function.  */
4224bool
4225arm_check_builtin_call (location_t , vec<location_t> , tree fndecl,
4226			tree, unsigned int, tree *)
4227{
4228  int fcode = DECL_MD_FUNCTION_CODE (fndecl);
4229  if (fcode == ARM_BUILTIN_saturation_occurred
4230      || fcode == ARM_BUILTIN_set_saturation)
4231    {
4232      if (cfun && cfun->decl)
4233	DECL_ATTRIBUTES (cfun->decl)
4234	  = tree_cons (get_identifier ("acle qbit"), NULL_TREE,
4235		       DECL_ATTRIBUTES (cfun->decl));
4236    }
4237  if (fcode == ARM_BUILTIN_sel)
4238    {
4239      if (cfun && cfun->decl)
4240	DECL_ATTRIBUTES (cfun->decl)
4241	  = tree_cons (get_identifier ("acle gebits"), NULL_TREE,
4242		       DECL_ATTRIBUTES (cfun->decl));
4243    }
4244  return true;
4245}
4246
4247enum resolver_ident
4248arm_describe_resolver (tree fndecl)
4249{
4250  if (DECL_MD_FUNCTION_CODE (fndecl) >= ARM_BUILTIN_vcx1qv16qi
4251    && DECL_MD_FUNCTION_CODE (fndecl) < ARM_BUILTIN_MVE_BASE)
4252    return arm_cde_resolver;
4253  return arm_no_resolver;
4254}
4255
4256unsigned
4257arm_cde_end_args (tree fndecl)
4258{
4259  return DECL_MD_FUNCTION_CODE (fndecl) >= ARM_BUILTIN_vcx1q_p_v16qi ? 2 : 1;
4260}
4261
4262#include "gt-arm-builtins.h"
4263