1/* Description of builtins used by the ARM backend.
2   Copyright (C) 2014-2015 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#include "config.h"
21#include "system.h"
22#include "coretypes.h"
23#include "tm.h"
24#include "rtl.h"
25#include "hash-set.h"
26#include "machmode.h"
27#include "vec.h"
28#include "double-int.h"
29#include "input.h"
30#include "alias.h"
31#include "symtab.h"
32#include "wide-int.h"
33#include "inchash.h"
34#include "tree.h"
35#include "fold-const.h"
36#include "stor-layout.h"
37#include "hashtab.h"
38#include "hard-reg-set.h"
39#include "function.h"
40#include "flags.h"
41#include "statistics.h"
42#include "real.h"
43#include "fixed-value.h"
44#include "insn-config.h"
45#include "expmed.h"
46#include "dojump.h"
47#include "explow.h"
48#include "calls.h"
49#include "emit-rtl.h"
50#include "varasm.h"
51#include "stmt.h"
52#include "expr.h"
53#include "tm_p.h"
54#include "recog.h"
55#include "langhooks.h"
56#include "diagnostic-core.h"
57#include "optabs.h"
58#include "gimple-expr.h"
59#include "target.h"
60#include "ggc.h"
61#include "arm-protos.h"
62
63#define SIMD_MAX_BUILTIN_ARGS 5
64
65enum arm_type_qualifiers
66{
67  /* T foo.  */
68  qualifier_none = 0x0,
69  /* unsigned T foo.  */
70  qualifier_unsigned = 0x1, /* 1 << 0  */
71  /* const T foo.  */
72  qualifier_const = 0x2, /* 1 << 1  */
73  /* T *foo.  */
74  qualifier_pointer = 0x4, /* 1 << 2  */
75  /* Used when expanding arguments if an operand could
76     be an immediate.  */
77  qualifier_immediate = 0x8, /* 1 << 3  */
78  qualifier_maybe_immediate = 0x10, /* 1 << 4  */
79  /* void foo (...).  */
80  qualifier_void = 0x20, /* 1 << 5  */
81  /* Some patterns may have internal operands, this qualifier is an
82     instruction to the initialisation code to skip this operand.  */
83  qualifier_internal = 0x40, /* 1 << 6  */
84  /* Some builtins should use the T_*mode* encoded in a simd_builtin_datum
85     rather than using the type of the operand.  */
86  qualifier_map_mode = 0x80, /* 1 << 7  */
87  /* qualifier_pointer | qualifier_map_mode  */
88  qualifier_pointer_map_mode = 0x84,
89  /* qualifier_const_pointer | qualifier_map_mode  */
90  qualifier_const_pointer_map_mode = 0x86,
91  /* Polynomial types.  */
92  qualifier_poly = 0x100
93};
94
95/*  The qualifier_internal allows generation of a unary builtin from
96    a pattern with a third pseudo-operand such as a match_scratch.
97    T (T).  */
98static enum arm_type_qualifiers
99arm_unop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
100  = { qualifier_none, qualifier_none, qualifier_internal };
101#define UNOP_QUALIFIERS (arm_unop_qualifiers)
102
103/* unsigned T (unsigned T).  */
104static enum arm_type_qualifiers
105arm_bswap_qualifiers[SIMD_MAX_BUILTIN_ARGS]
106  = { qualifier_unsigned, qualifier_unsigned };
107#define BSWAP_QUALIFIERS (arm_bswap_qualifiers)
108
109/* T (T, T [maybe_immediate]).  */
110static enum arm_type_qualifiers
111arm_binop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
112  = { qualifier_none, qualifier_none, qualifier_maybe_immediate };
113#define BINOP_QUALIFIERS (arm_binop_qualifiers)
114
115/* T (T, T, T).  */
116static enum arm_type_qualifiers
117arm_ternop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
118  = { qualifier_none, qualifier_none, qualifier_none, qualifier_none };
119#define TERNOP_QUALIFIERS (arm_ternop_qualifiers)
120
121/* T (T, immediate).  */
122static enum arm_type_qualifiers
123arm_getlane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
124  = { qualifier_none, qualifier_none, qualifier_immediate };
125#define GETLANE_QUALIFIERS (arm_getlane_qualifiers)
126
127/* T (T, T, T, immediate).  */
128static enum arm_type_qualifiers
129arm_lanemac_qualifiers[SIMD_MAX_BUILTIN_ARGS]
130  = { qualifier_none, qualifier_none, qualifier_none,
131      qualifier_none, qualifier_immediate };
132#define LANEMAC_QUALIFIERS (arm_lanemac_qualifiers)
133
134/* T (T, T, immediate).  */
135static enum arm_type_qualifiers
136arm_setlane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
137  = { qualifier_none, qualifier_none, qualifier_none, qualifier_immediate };
138#define SETLANE_QUALIFIERS (arm_setlane_qualifiers)
139
140/* T (T, T).  */
141static enum arm_type_qualifiers
142arm_combine_qualifiers[SIMD_MAX_BUILTIN_ARGS]
143  = { qualifier_none, qualifier_none, qualifier_none };
144#define COMBINE_QUALIFIERS (arm_combine_qualifiers)
145
146/* T ([T element type] *).  */
147static enum arm_type_qualifiers
148arm_load1_qualifiers[SIMD_MAX_BUILTIN_ARGS]
149  = { qualifier_none, qualifier_const_pointer_map_mode };
150#define LOAD1_QUALIFIERS (arm_load1_qualifiers)
151
152/* T ([T element type] *, T, immediate).  */
153static enum arm_type_qualifiers
154arm_load1_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
155  = { qualifier_none, qualifier_const_pointer_map_mode,
156      qualifier_none, qualifier_immediate };
157#define LOAD1LANE_QUALIFIERS (arm_load1_lane_qualifiers)
158
159/* The first argument (return type) of a store should be void type,
160   which we represent with qualifier_void.  Their first operand will be
161   a DImode pointer to the location to store to, so we must use
162   qualifier_map_mode | qualifier_pointer to build a pointer to the
163   element type of the vector.
164
165   void ([T element type] *, T).  */
166static enum arm_type_qualifiers
167arm_store1_qualifiers[SIMD_MAX_BUILTIN_ARGS]
168  = { qualifier_void, qualifier_pointer_map_mode, qualifier_none };
169#define STORE1_QUALIFIERS (arm_store1_qualifiers)
170
171   /* void ([T element type] *, T, immediate).  */
172static enum arm_type_qualifiers
173arm_storestruct_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
174  = { qualifier_void, qualifier_pointer_map_mode,
175      qualifier_none, qualifier_immediate };
176#define STORE1LANE_QUALIFIERS (arm_storestruct_lane_qualifiers)
177
178#define v8qi_UP  V8QImode
179#define v4hi_UP  V4HImode
180#define v4hf_UP  V4HFmode
181#define v2si_UP  V2SImode
182#define v2sf_UP  V2SFmode
183#define di_UP    DImode
184#define v16qi_UP V16QImode
185#define v8hi_UP  V8HImode
186#define v4si_UP  V4SImode
187#define v4sf_UP  V4SFmode
188#define v2di_UP  V2DImode
189#define ti_UP	 TImode
190#define ei_UP	 EImode
191#define oi_UP	 OImode
192
193#define UP(X) X##_UP
194
195typedef struct {
196  const char *name;
197  machine_mode mode;
198  const enum insn_code code;
199  unsigned int fcode;
200  enum arm_type_qualifiers *qualifiers;
201} neon_builtin_datum;
202
203#define CF(N,X) CODE_FOR_neon_##N##X
204
205#define VAR1(T, N, A) \
206  {#N #A, UP (A), CF (N, A), 0, T##_QUALIFIERS},
207#define VAR2(T, N, A, B) \
208  VAR1 (T, N, A) \
209  VAR1 (T, N, B)
210#define VAR3(T, N, A, B, C) \
211  VAR2 (T, N, A, B) \
212  VAR1 (T, N, C)
213#define VAR4(T, N, A, B, C, D) \
214  VAR3 (T, N, A, B, C) \
215  VAR1 (T, N, D)
216#define VAR5(T, N, A, B, C, D, E) \
217  VAR4 (T, N, A, B, C, D) \
218  VAR1 (T, N, E)
219#define VAR6(T, N, A, B, C, D, E, F) \
220  VAR5 (T, N, A, B, C, D, E) \
221  VAR1 (T, N, F)
222#define VAR7(T, N, A, B, C, D, E, F, G) \
223  VAR6 (T, N, A, B, C, D, E, F) \
224  VAR1 (T, N, G)
225#define VAR8(T, N, A, B, C, D, E, F, G, H) \
226  VAR7 (T, N, A, B, C, D, E, F, G) \
227  VAR1 (T, N, H)
228#define VAR9(T, N, A, B, C, D, E, F, G, H, I) \
229  VAR8 (T, N, A, B, C, D, E, F, G, H) \
230  VAR1 (T, N, I)
231#define VAR10(T, N, A, B, C, D, E, F, G, H, I, J) \
232  VAR9 (T, N, A, B, C, D, E, F, G, H, I) \
233  VAR1 (T, N, J)
234
235/* The NEON builtin data can be found in arm_neon_builtins.def.
236   The mode entries in the following table correspond to the "key" type of the
237   instruction variant, i.e. equivalent to that which would be specified after
238   the assembler mnemonic, which usually refers to the last vector operand.
239   The modes listed per instruction should be the same as those defined for
240   that instruction's pattern in neon.md.  */
241
242static neon_builtin_datum neon_builtin_data[] =
243{
244#include "arm_neon_builtins.def"
245};
246
247#undef CF
248#undef VAR1
249
250#define VAR1(T, N, X) \
251  ARM_BUILTIN_NEON_##N##X,
252
253enum arm_builtins
254{
255  ARM_BUILTIN_GETWCGR0,
256  ARM_BUILTIN_GETWCGR1,
257  ARM_BUILTIN_GETWCGR2,
258  ARM_BUILTIN_GETWCGR3,
259
260  ARM_BUILTIN_SETWCGR0,
261  ARM_BUILTIN_SETWCGR1,
262  ARM_BUILTIN_SETWCGR2,
263  ARM_BUILTIN_SETWCGR3,
264
265  ARM_BUILTIN_WZERO,
266
267  ARM_BUILTIN_WAVG2BR,
268  ARM_BUILTIN_WAVG2HR,
269  ARM_BUILTIN_WAVG2B,
270  ARM_BUILTIN_WAVG2H,
271
272  ARM_BUILTIN_WACCB,
273  ARM_BUILTIN_WACCH,
274  ARM_BUILTIN_WACCW,
275
276  ARM_BUILTIN_WMACS,
277  ARM_BUILTIN_WMACSZ,
278  ARM_BUILTIN_WMACU,
279  ARM_BUILTIN_WMACUZ,
280
281  ARM_BUILTIN_WSADB,
282  ARM_BUILTIN_WSADBZ,
283  ARM_BUILTIN_WSADH,
284  ARM_BUILTIN_WSADHZ,
285
286  ARM_BUILTIN_WALIGNI,
287  ARM_BUILTIN_WALIGNR0,
288  ARM_BUILTIN_WALIGNR1,
289  ARM_BUILTIN_WALIGNR2,
290  ARM_BUILTIN_WALIGNR3,
291
292  ARM_BUILTIN_TMIA,
293  ARM_BUILTIN_TMIAPH,
294  ARM_BUILTIN_TMIABB,
295  ARM_BUILTIN_TMIABT,
296  ARM_BUILTIN_TMIATB,
297  ARM_BUILTIN_TMIATT,
298
299  ARM_BUILTIN_TMOVMSKB,
300  ARM_BUILTIN_TMOVMSKH,
301  ARM_BUILTIN_TMOVMSKW,
302
303  ARM_BUILTIN_TBCSTB,
304  ARM_BUILTIN_TBCSTH,
305  ARM_BUILTIN_TBCSTW,
306
307  ARM_BUILTIN_WMADDS,
308  ARM_BUILTIN_WMADDU,
309
310  ARM_BUILTIN_WPACKHSS,
311  ARM_BUILTIN_WPACKWSS,
312  ARM_BUILTIN_WPACKDSS,
313  ARM_BUILTIN_WPACKHUS,
314  ARM_BUILTIN_WPACKWUS,
315  ARM_BUILTIN_WPACKDUS,
316
317  ARM_BUILTIN_WADDB,
318  ARM_BUILTIN_WADDH,
319  ARM_BUILTIN_WADDW,
320  ARM_BUILTIN_WADDSSB,
321  ARM_BUILTIN_WADDSSH,
322  ARM_BUILTIN_WADDSSW,
323  ARM_BUILTIN_WADDUSB,
324  ARM_BUILTIN_WADDUSH,
325  ARM_BUILTIN_WADDUSW,
326  ARM_BUILTIN_WSUBB,
327  ARM_BUILTIN_WSUBH,
328  ARM_BUILTIN_WSUBW,
329  ARM_BUILTIN_WSUBSSB,
330  ARM_BUILTIN_WSUBSSH,
331  ARM_BUILTIN_WSUBSSW,
332  ARM_BUILTIN_WSUBUSB,
333  ARM_BUILTIN_WSUBUSH,
334  ARM_BUILTIN_WSUBUSW,
335
336  ARM_BUILTIN_WAND,
337  ARM_BUILTIN_WANDN,
338  ARM_BUILTIN_WOR,
339  ARM_BUILTIN_WXOR,
340
341  ARM_BUILTIN_WCMPEQB,
342  ARM_BUILTIN_WCMPEQH,
343  ARM_BUILTIN_WCMPEQW,
344  ARM_BUILTIN_WCMPGTUB,
345  ARM_BUILTIN_WCMPGTUH,
346  ARM_BUILTIN_WCMPGTUW,
347  ARM_BUILTIN_WCMPGTSB,
348  ARM_BUILTIN_WCMPGTSH,
349  ARM_BUILTIN_WCMPGTSW,
350
351  ARM_BUILTIN_TEXTRMSB,
352  ARM_BUILTIN_TEXTRMSH,
353  ARM_BUILTIN_TEXTRMSW,
354  ARM_BUILTIN_TEXTRMUB,
355  ARM_BUILTIN_TEXTRMUH,
356  ARM_BUILTIN_TEXTRMUW,
357  ARM_BUILTIN_TINSRB,
358  ARM_BUILTIN_TINSRH,
359  ARM_BUILTIN_TINSRW,
360
361  ARM_BUILTIN_WMAXSW,
362  ARM_BUILTIN_WMAXSH,
363  ARM_BUILTIN_WMAXSB,
364  ARM_BUILTIN_WMAXUW,
365  ARM_BUILTIN_WMAXUH,
366  ARM_BUILTIN_WMAXUB,
367  ARM_BUILTIN_WMINSW,
368  ARM_BUILTIN_WMINSH,
369  ARM_BUILTIN_WMINSB,
370  ARM_BUILTIN_WMINUW,
371  ARM_BUILTIN_WMINUH,
372  ARM_BUILTIN_WMINUB,
373
374  ARM_BUILTIN_WMULUM,
375  ARM_BUILTIN_WMULSM,
376  ARM_BUILTIN_WMULUL,
377
378  ARM_BUILTIN_PSADBH,
379  ARM_BUILTIN_WSHUFH,
380
381  ARM_BUILTIN_WSLLH,
382  ARM_BUILTIN_WSLLW,
383  ARM_BUILTIN_WSLLD,
384  ARM_BUILTIN_WSRAH,
385  ARM_BUILTIN_WSRAW,
386  ARM_BUILTIN_WSRAD,
387  ARM_BUILTIN_WSRLH,
388  ARM_BUILTIN_WSRLW,
389  ARM_BUILTIN_WSRLD,
390  ARM_BUILTIN_WRORH,
391  ARM_BUILTIN_WRORW,
392  ARM_BUILTIN_WRORD,
393  ARM_BUILTIN_WSLLHI,
394  ARM_BUILTIN_WSLLWI,
395  ARM_BUILTIN_WSLLDI,
396  ARM_BUILTIN_WSRAHI,
397  ARM_BUILTIN_WSRAWI,
398  ARM_BUILTIN_WSRADI,
399  ARM_BUILTIN_WSRLHI,
400  ARM_BUILTIN_WSRLWI,
401  ARM_BUILTIN_WSRLDI,
402  ARM_BUILTIN_WRORHI,
403  ARM_BUILTIN_WRORWI,
404  ARM_BUILTIN_WRORDI,
405
406  ARM_BUILTIN_WUNPCKIHB,
407  ARM_BUILTIN_WUNPCKIHH,
408  ARM_BUILTIN_WUNPCKIHW,
409  ARM_BUILTIN_WUNPCKILB,
410  ARM_BUILTIN_WUNPCKILH,
411  ARM_BUILTIN_WUNPCKILW,
412
413  ARM_BUILTIN_WUNPCKEHSB,
414  ARM_BUILTIN_WUNPCKEHSH,
415  ARM_BUILTIN_WUNPCKEHSW,
416  ARM_BUILTIN_WUNPCKEHUB,
417  ARM_BUILTIN_WUNPCKEHUH,
418  ARM_BUILTIN_WUNPCKEHUW,
419  ARM_BUILTIN_WUNPCKELSB,
420  ARM_BUILTIN_WUNPCKELSH,
421  ARM_BUILTIN_WUNPCKELSW,
422  ARM_BUILTIN_WUNPCKELUB,
423  ARM_BUILTIN_WUNPCKELUH,
424  ARM_BUILTIN_WUNPCKELUW,
425
426  ARM_BUILTIN_WABSB,
427  ARM_BUILTIN_WABSH,
428  ARM_BUILTIN_WABSW,
429
430  ARM_BUILTIN_WADDSUBHX,
431  ARM_BUILTIN_WSUBADDHX,
432
433  ARM_BUILTIN_WABSDIFFB,
434  ARM_BUILTIN_WABSDIFFH,
435  ARM_BUILTIN_WABSDIFFW,
436
437  ARM_BUILTIN_WADDCH,
438  ARM_BUILTIN_WADDCW,
439
440  ARM_BUILTIN_WAVG4,
441  ARM_BUILTIN_WAVG4R,
442
443  ARM_BUILTIN_WMADDSX,
444  ARM_BUILTIN_WMADDUX,
445
446  ARM_BUILTIN_WMADDSN,
447  ARM_BUILTIN_WMADDUN,
448
449  ARM_BUILTIN_WMULWSM,
450  ARM_BUILTIN_WMULWUM,
451
452  ARM_BUILTIN_WMULWSMR,
453  ARM_BUILTIN_WMULWUMR,
454
455  ARM_BUILTIN_WMULWL,
456
457  ARM_BUILTIN_WMULSMR,
458  ARM_BUILTIN_WMULUMR,
459
460  ARM_BUILTIN_WQMULM,
461  ARM_BUILTIN_WQMULMR,
462
463  ARM_BUILTIN_WQMULWM,
464  ARM_BUILTIN_WQMULWMR,
465
466  ARM_BUILTIN_WADDBHUSM,
467  ARM_BUILTIN_WADDBHUSL,
468
469  ARM_BUILTIN_WQMIABB,
470  ARM_BUILTIN_WQMIABT,
471  ARM_BUILTIN_WQMIATB,
472  ARM_BUILTIN_WQMIATT,
473
474  ARM_BUILTIN_WQMIABBN,
475  ARM_BUILTIN_WQMIABTN,
476  ARM_BUILTIN_WQMIATBN,
477  ARM_BUILTIN_WQMIATTN,
478
479  ARM_BUILTIN_WMIABB,
480  ARM_BUILTIN_WMIABT,
481  ARM_BUILTIN_WMIATB,
482  ARM_BUILTIN_WMIATT,
483
484  ARM_BUILTIN_WMIABBN,
485  ARM_BUILTIN_WMIABTN,
486  ARM_BUILTIN_WMIATBN,
487  ARM_BUILTIN_WMIATTN,
488
489  ARM_BUILTIN_WMIAWBB,
490  ARM_BUILTIN_WMIAWBT,
491  ARM_BUILTIN_WMIAWTB,
492  ARM_BUILTIN_WMIAWTT,
493
494  ARM_BUILTIN_WMIAWBBN,
495  ARM_BUILTIN_WMIAWBTN,
496  ARM_BUILTIN_WMIAWTBN,
497  ARM_BUILTIN_WMIAWTTN,
498
499  ARM_BUILTIN_WMERGE,
500
501  ARM_BUILTIN_CRC32B,
502  ARM_BUILTIN_CRC32H,
503  ARM_BUILTIN_CRC32W,
504  ARM_BUILTIN_CRC32CB,
505  ARM_BUILTIN_CRC32CH,
506  ARM_BUILTIN_CRC32CW,
507
508  ARM_BUILTIN_GET_FPSCR,
509  ARM_BUILTIN_SET_FPSCR,
510
511#undef CRYPTO1
512#undef CRYPTO2
513#undef CRYPTO3
514
515#define CRYPTO1(L, U, M1, M2) \
516  ARM_BUILTIN_CRYPTO_##U,
517#define CRYPTO2(L, U, M1, M2, M3) \
518  ARM_BUILTIN_CRYPTO_##U,
519#define CRYPTO3(L, U, M1, M2, M3, M4) \
520  ARM_BUILTIN_CRYPTO_##U,
521
522#include "crypto.def"
523
524#undef CRYPTO1
525#undef CRYPTO2
526#undef CRYPTO3
527
528#include "arm_neon_builtins.def"
529
530  ARM_BUILTIN_MAX
531};
532
533#define ARM_BUILTIN_NEON_BASE (ARM_BUILTIN_MAX - ARRAY_SIZE (neon_builtin_data))
534
535#undef CF
536#undef VAR1
537#undef VAR2
538#undef VAR3
539#undef VAR4
540#undef VAR5
541#undef VAR6
542#undef VAR7
543#undef VAR8
544#undef VAR9
545#undef VAR10
546
547static GTY(()) tree arm_builtin_decls[ARM_BUILTIN_MAX];
548
549#define NUM_DREG_TYPES 5
550#define NUM_QREG_TYPES 6
551
552/* Internal scalar builtin types.  These types are used to support
553   neon intrinsic builtins.  They are _not_ user-visible types.  Therefore
554   the mangling for these types are implementation defined.  */
555const char *arm_scalar_builtin_types[] = {
556  "__builtin_neon_qi",
557  "__builtin_neon_hi",
558  "__builtin_neon_si",
559  "__builtin_neon_sf",
560  "__builtin_neon_di",
561  "__builtin_neon_df",
562  "__builtin_neon_ti",
563  "__builtin_neon_uqi",
564  "__builtin_neon_uhi",
565  "__builtin_neon_usi",
566  "__builtin_neon_udi",
567  "__builtin_neon_ei",
568  "__builtin_neon_oi",
569  "__builtin_neon_ci",
570  "__builtin_neon_xi",
571  NULL
572};
573
574#define ENTRY(E, M, Q, S, T, G) E,
575enum arm_simd_type
576{
577#include "arm-simd-builtin-types.def"
578  __TYPE_FINAL
579};
580#undef ENTRY
581
582struct arm_simd_type_info
583{
584  enum arm_simd_type type;
585
586  /* Internal type name.  */
587  const char *name;
588
589  /* Internal type name(mangled).  The mangled names conform to the
590     AAPCS (see "Procedure Call Standard for the ARM Architecture",
591     Appendix A).  To qualify for emission with the mangled names defined in
592     that document, a vector type must not only be of the correct mode but also
593     be of the correct internal Neon vector type (e.g. __simd64_int8_t);
594     these types are registered by arm_init_simd_builtin_types ().  In other
595     words, vector types defined in other ways e.g. via vector_size attribute
596     will get default mangled names.  */
597  const char *mangle;
598
599  /* Internal type.  */
600  tree itype;
601
602  /* Element type.  */
603  tree eltype;
604
605  /* Machine mode the internal type maps to.  */
606  machine_mode mode;
607
608  /* Qualifiers.  */
609  enum arm_type_qualifiers q;
610};
611
612#define ENTRY(E, M, Q, S, T, G)		\
613  {E,					\
614   "__simd" #S "_" #T "_t",		\
615   #G "__simd" #S "_" #T "_t",		\
616   NULL_TREE, NULL_TREE, M##mode, qualifier_##Q},
617static struct arm_simd_type_info arm_simd_types [] = {
618#include "arm-simd-builtin-types.def"
619};
620#undef ENTRY
621
622static tree arm_simd_floatHF_type_node = NULL_TREE;
623static tree arm_simd_intOI_type_node = NULL_TREE;
624static tree arm_simd_intEI_type_node = NULL_TREE;
625static tree arm_simd_intCI_type_node = NULL_TREE;
626static tree arm_simd_intXI_type_node = NULL_TREE;
627static tree arm_simd_polyQI_type_node = NULL_TREE;
628static tree arm_simd_polyHI_type_node = NULL_TREE;
629static tree arm_simd_polyDI_type_node = NULL_TREE;
630static tree arm_simd_polyTI_type_node = NULL_TREE;
631
632static const char *
633arm_mangle_builtin_scalar_type (const_tree type)
634{
635  int i = 0;
636
637  while (arm_scalar_builtin_types[i] != NULL)
638    {
639      const char *name = arm_scalar_builtin_types[i];
640
641      if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
642	  && DECL_NAME (TYPE_NAME (type))
643	  && !strcmp (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))), name))
644	return arm_scalar_builtin_types[i];
645      i++;
646    }
647  return NULL;
648}
649
650static const char *
651arm_mangle_builtin_vector_type (const_tree type)
652{
653  int i;
654  int nelts = sizeof (arm_simd_types) / sizeof (arm_simd_types[0]);
655
656  for (i = 0; i < nelts; i++)
657    if (arm_simd_types[i].mode ==  TYPE_MODE (type)
658	&& TYPE_NAME (type)
659	&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
660	&& DECL_NAME (TYPE_NAME (type))
661	&& !strcmp
662	     (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))),
663	      arm_simd_types[i].name))
664      return arm_simd_types[i].mangle;
665
666  return NULL;
667}
668
669const char *
670arm_mangle_builtin_type (const_tree type)
671{
672  const char *mangle;
673  /* Walk through all the AArch64 builtins types tables to filter out the
674     incoming type.  */
675  if ((mangle = arm_mangle_builtin_vector_type (type))
676      || (mangle = arm_mangle_builtin_scalar_type (type)))
677    return mangle;
678
679  return NULL;
680}
681
682static tree
683arm_simd_builtin_std_type (enum machine_mode mode,
684			   enum arm_type_qualifiers q)
685{
686#define QUAL_TYPE(M)  \
687  ((q == qualifier_none) ? int##M##_type_node : unsigned_int##M##_type_node);
688  switch (mode)
689    {
690    case QImode:
691      return QUAL_TYPE (QI);
692    case HImode:
693      return QUAL_TYPE (HI);
694    case SImode:
695      return QUAL_TYPE (SI);
696    case DImode:
697      return QUAL_TYPE (DI);
698    case TImode:
699      return QUAL_TYPE (TI);
700    case OImode:
701      return arm_simd_intOI_type_node;
702    case EImode:
703      return arm_simd_intEI_type_node;
704    case CImode:
705      return arm_simd_intCI_type_node;
706    case XImode:
707      return arm_simd_intXI_type_node;
708    case HFmode:
709      return arm_simd_floatHF_type_node;
710    case SFmode:
711      return float_type_node;
712    case DFmode:
713      return double_type_node;
714    default:
715      gcc_unreachable ();
716    }
717#undef QUAL_TYPE
718}
719
720static tree
721arm_lookup_simd_builtin_type (enum machine_mode mode,
722			      enum arm_type_qualifiers q)
723{
724  int i;
725  int nelts = sizeof (arm_simd_types) / sizeof (arm_simd_types[0]);
726
727  /* Non-poly scalar modes map to standard types not in the table.  */
728  if (q != qualifier_poly && !VECTOR_MODE_P (mode))
729    return arm_simd_builtin_std_type (mode, q);
730
731  for (i = 0; i < nelts; i++)
732    if (arm_simd_types[i].mode == mode
733	&& arm_simd_types[i].q == q)
734      return arm_simd_types[i].itype;
735
736  /* Note that we won't have caught the underlying type for poly64x2_t
737     in the above table.  This gets default mangling.  */
738
739  return NULL_TREE;
740}
741
742static tree
743arm_simd_builtin_type (enum machine_mode mode,
744			   bool unsigned_p, bool poly_p)
745{
746  if (poly_p)
747    return arm_lookup_simd_builtin_type (mode, qualifier_poly);
748  else if (unsigned_p)
749    return arm_lookup_simd_builtin_type (mode, qualifier_unsigned);
750  else
751    return arm_lookup_simd_builtin_type (mode, qualifier_none);
752}
753
754static void
755arm_init_simd_builtin_types (void)
756{
757  int i;
758  int nelts = sizeof (arm_simd_types) / sizeof (arm_simd_types[0]);
759  tree tdecl;
760
761  /* Initialize the HFmode scalar type.  */
762  arm_simd_floatHF_type_node = make_node (REAL_TYPE);
763  TYPE_PRECISION (arm_simd_floatHF_type_node) = GET_MODE_PRECISION (HFmode);
764  layout_type (arm_simd_floatHF_type_node);
765  (*lang_hooks.types.register_builtin_type) (arm_simd_floatHF_type_node,
766					     "__builtin_neon_hf");
767
768  /* Poly types are a world of their own.  In order to maintain legacy
769     ABI, they get initialized using the old interface, and don't get
770     an entry in our mangling table, consequently, they get default
771     mangling.  As a further gotcha, poly8_t and poly16_t are signed
772     types, poly64_t and poly128_t are unsigned types.  */
773  arm_simd_polyQI_type_node
774    = build_distinct_type_copy (intQI_type_node);
775  (*lang_hooks.types.register_builtin_type) (arm_simd_polyQI_type_node,
776					     "__builtin_neon_poly8");
777  arm_simd_polyHI_type_node
778    = build_distinct_type_copy (intHI_type_node);
779  (*lang_hooks.types.register_builtin_type) (arm_simd_polyHI_type_node,
780					     "__builtin_neon_poly16");
781  arm_simd_polyDI_type_node
782    = build_distinct_type_copy (unsigned_intDI_type_node);
783  (*lang_hooks.types.register_builtin_type) (arm_simd_polyDI_type_node,
784					     "__builtin_neon_poly64");
785  arm_simd_polyTI_type_node
786    = build_distinct_type_copy (unsigned_intTI_type_node);
787  (*lang_hooks.types.register_builtin_type) (arm_simd_polyTI_type_node,
788					     "__builtin_neon_poly128");
789
790  /* Init all the element types built by the front-end.  */
791  arm_simd_types[Int8x8_t].eltype = intQI_type_node;
792  arm_simd_types[Int8x16_t].eltype = intQI_type_node;
793  arm_simd_types[Int16x4_t].eltype = intHI_type_node;
794  arm_simd_types[Int16x8_t].eltype = intHI_type_node;
795  arm_simd_types[Int32x2_t].eltype = intSI_type_node;
796  arm_simd_types[Int32x4_t].eltype = intSI_type_node;
797  arm_simd_types[Int64x2_t].eltype = intDI_type_node;
798  arm_simd_types[Uint8x8_t].eltype = unsigned_intQI_type_node;
799  arm_simd_types[Uint8x16_t].eltype = unsigned_intQI_type_node;
800  arm_simd_types[Uint16x4_t].eltype = unsigned_intHI_type_node;
801  arm_simd_types[Uint16x8_t].eltype = unsigned_intHI_type_node;
802  arm_simd_types[Uint32x2_t].eltype = unsigned_intSI_type_node;
803  arm_simd_types[Uint32x4_t].eltype = unsigned_intSI_type_node;
804  arm_simd_types[Uint64x2_t].eltype = unsigned_intDI_type_node;
805
806  /* Init poly vector element types with scalar poly types.  */
807  arm_simd_types[Poly8x8_t].eltype = arm_simd_polyQI_type_node;
808  arm_simd_types[Poly8x16_t].eltype = arm_simd_polyQI_type_node;
809  arm_simd_types[Poly16x4_t].eltype = arm_simd_polyHI_type_node;
810  arm_simd_types[Poly16x8_t].eltype = arm_simd_polyHI_type_node;
811  /* Note: poly64x2_t is defined in arm_neon.h, to ensure it gets default
812     mangling.  */
813
814  /* Continue with standard types.  */
815  arm_simd_types[Float16x4_t].eltype = arm_simd_floatHF_type_node;
816  arm_simd_types[Float32x2_t].eltype = float_type_node;
817  arm_simd_types[Float32x4_t].eltype = float_type_node;
818
819  for (i = 0; i < nelts; i++)
820    {
821      tree eltype = arm_simd_types[i].eltype;
822      enum machine_mode mode = arm_simd_types[i].mode;
823
824      if (arm_simd_types[i].itype == NULL)
825	arm_simd_types[i].itype =
826	  build_distinct_type_copy
827	    (build_vector_type (eltype, GET_MODE_NUNITS (mode)));
828
829      tdecl = add_builtin_type (arm_simd_types[i].name,
830				arm_simd_types[i].itype);
831      TYPE_NAME (arm_simd_types[i].itype) = tdecl;
832      SET_TYPE_STRUCTURAL_EQUALITY (arm_simd_types[i].itype);
833    }
834
835#define AARCH_BUILD_SIGNED_TYPE(mode)  \
836  make_signed_type (GET_MODE_PRECISION (mode));
837  arm_simd_intOI_type_node = AARCH_BUILD_SIGNED_TYPE (OImode);
838  arm_simd_intEI_type_node = AARCH_BUILD_SIGNED_TYPE (EImode);
839  arm_simd_intCI_type_node = AARCH_BUILD_SIGNED_TYPE (CImode);
840  arm_simd_intXI_type_node = AARCH_BUILD_SIGNED_TYPE (XImode);
841#undef AARCH_BUILD_SIGNED_TYPE
842
843  tdecl = add_builtin_type
844	    ("__builtin_neon_ei" , arm_simd_intEI_type_node);
845  TYPE_NAME (arm_simd_intEI_type_node) = tdecl;
846  tdecl = add_builtin_type
847	    ("__builtin_neon_oi" , arm_simd_intOI_type_node);
848  TYPE_NAME (arm_simd_intOI_type_node) = tdecl;
849  tdecl = add_builtin_type
850	    ("__builtin_neon_ci" , arm_simd_intCI_type_node);
851  TYPE_NAME (arm_simd_intCI_type_node) = tdecl;
852  tdecl = add_builtin_type
853	    ("__builtin_neon_xi" , arm_simd_intXI_type_node);
854  TYPE_NAME (arm_simd_intXI_type_node) = tdecl;
855}
856
857static void
858arm_init_simd_builtin_scalar_types (void)
859{
860  /* Define typedefs for all the standard scalar types.  */
861  (*lang_hooks.types.register_builtin_type) (intQI_type_node,
862					     "__builtin_neon_qi");
863  (*lang_hooks.types.register_builtin_type) (intHI_type_node,
864					     "__builtin_neon_hi");
865  (*lang_hooks.types.register_builtin_type) (intSI_type_node,
866					     "__builtin_neon_si");
867  (*lang_hooks.types.register_builtin_type) (float_type_node,
868					     "__builtin_neon_sf");
869  (*lang_hooks.types.register_builtin_type) (intDI_type_node,
870					     "__builtin_neon_di");
871  (*lang_hooks.types.register_builtin_type) (double_type_node,
872					     "__builtin_neon_df");
873  (*lang_hooks.types.register_builtin_type) (intTI_type_node,
874					     "__builtin_neon_ti");
875
876  /* Unsigned integer types for various mode sizes.  */
877  (*lang_hooks.types.register_builtin_type) (unsigned_intQI_type_node,
878					     "__builtin_neon_uqi");
879  (*lang_hooks.types.register_builtin_type) (unsigned_intHI_type_node,
880					     "__builtin_neon_uhi");
881  (*lang_hooks.types.register_builtin_type) (unsigned_intSI_type_node,
882					     "__builtin_neon_usi");
883  (*lang_hooks.types.register_builtin_type) (unsigned_intDI_type_node,
884					     "__builtin_neon_udi");
885  (*lang_hooks.types.register_builtin_type) (unsigned_intTI_type_node,
886					     "__builtin_neon_uti");
887}
888
889static void
890arm_init_neon_builtins (void)
891{
892  unsigned int i, fcode = ARM_BUILTIN_NEON_BASE;
893
894  arm_init_simd_builtin_types ();
895
896  /* Strong-typing hasn't been implemented for all AdvSIMD builtin intrinsics.
897     Therefore we need to preserve the old __builtin scalar types.  It can be
898     removed once all the intrinsics become strongly typed using the qualifier
899     system.  */
900  arm_init_simd_builtin_scalar_types ();
901
902  for (i = 0; i < ARRAY_SIZE (neon_builtin_data); i++, fcode++)
903    {
904      bool print_type_signature_p = false;
905      char type_signature[SIMD_MAX_BUILTIN_ARGS] = { 0 };
906      neon_builtin_datum *d = &neon_builtin_data[i];
907      char namebuf[60];
908      tree ftype = NULL;
909      tree fndecl = NULL;
910
911      d->fcode = fcode;
912
913      /* We must track two variables here.  op_num is
914	 the operand number as in the RTL pattern.  This is
915	 required to access the mode (e.g. V4SF mode) of the
916	 argument, from which the base type can be derived.
917	 arg_num is an index in to the qualifiers data, which
918	 gives qualifiers to the type (e.g. const unsigned).
919	 The reason these two variables may differ by one is the
920	 void return type.  While all return types take the 0th entry
921	 in the qualifiers array, there is no operand for them in the
922	 RTL pattern.  */
923      int op_num = insn_data[d->code].n_operands - 1;
924      int arg_num = d->qualifiers[0] & qualifier_void
925		      ? op_num + 1
926		      : op_num;
927      tree return_type = void_type_node, args = void_list_node;
928      tree eltype;
929
930      /* Build a function type directly from the insn_data for this
931	 builtin.  The build_function_type () function takes care of
932	 removing duplicates for us.  */
933      for (; op_num >= 0; arg_num--, op_num--)
934	{
935	  machine_mode op_mode = insn_data[d->code].operand[op_num].mode;
936	  enum arm_type_qualifiers qualifiers = d->qualifiers[arg_num];
937
938	  if (qualifiers & qualifier_unsigned)
939	    {
940	      type_signature[arg_num] = 'u';
941	      print_type_signature_p = true;
942	    }
943	  else if (qualifiers & qualifier_poly)
944	    {
945	      type_signature[arg_num] = 'p';
946	      print_type_signature_p = true;
947	    }
948	  else
949	    type_signature[arg_num] = 's';
950
951	  /* Skip an internal operand for vget_{low, high}.  */
952	  if (qualifiers & qualifier_internal)
953	    continue;
954
955	  /* Some builtins have different user-facing types
956	     for certain arguments, encoded in d->mode.  */
957	  if (qualifiers & qualifier_map_mode)
958	      op_mode = d->mode;
959
960	  /* For pointers, we want a pointer to the basic type
961	     of the vector.  */
962	  if (qualifiers & qualifier_pointer && VECTOR_MODE_P (op_mode))
963	    op_mode = GET_MODE_INNER (op_mode);
964
965	  eltype = arm_simd_builtin_type
966		     (op_mode,
967		      (qualifiers & qualifier_unsigned) != 0,
968		      (qualifiers & qualifier_poly) != 0);
969	  gcc_assert (eltype != NULL);
970
971	  /* Add qualifiers.  */
972	  if (qualifiers & qualifier_const)
973	    eltype = build_qualified_type (eltype, TYPE_QUAL_CONST);
974
975	  if (qualifiers & qualifier_pointer)
976	      eltype = build_pointer_type (eltype);
977
978	  /* If we have reached arg_num == 0, we are at a non-void
979	     return type.  Otherwise, we are still processing
980	     arguments.  */
981	  if (arg_num == 0)
982	    return_type = eltype;
983	  else
984	    args = tree_cons (NULL_TREE, eltype, args);
985	}
986
987      ftype = build_function_type (return_type, args);
988
989      gcc_assert (ftype != NULL);
990
991      if (print_type_signature_p)
992	snprintf (namebuf, sizeof (namebuf), "__builtin_neon_%s_%s",
993		  d->name, type_signature);
994      else
995	snprintf (namebuf, sizeof (namebuf), "__builtin_neon_%s",
996		  d->name);
997
998      fndecl = add_builtin_function (namebuf, ftype, fcode, BUILT_IN_MD,
999				     NULL, NULL_TREE);
1000      arm_builtin_decls[fcode] = fndecl;
1001    }
1002
1003  if (TARGET_CRYPTO && TARGET_HARD_FLOAT)
1004    {
1005      tree V16UQI_type_node = arm_simd_builtin_type (V16QImode,
1006						       true,
1007						       false);
1008
1009      tree V4USI_type_node = arm_simd_builtin_type (V4SImode,
1010						      true,
1011						      false);
1012
1013      tree v16uqi_ftype_v16uqi
1014	= build_function_type_list (V16UQI_type_node, V16UQI_type_node,
1015				    NULL_TREE);
1016
1017      tree v16uqi_ftype_v16uqi_v16uqi
1018	= build_function_type_list (V16UQI_type_node, V16UQI_type_node,
1019				    V16UQI_type_node, NULL_TREE);
1020
1021      tree v4usi_ftype_v4usi
1022	= build_function_type_list (V4USI_type_node, V4USI_type_node,
1023				    NULL_TREE);
1024
1025      tree v4usi_ftype_v4usi_v4usi
1026	= build_function_type_list (V4USI_type_node, V4USI_type_node,
1027				    V4USI_type_node, NULL_TREE);
1028
1029      tree v4usi_ftype_v4usi_v4usi_v4usi
1030	= build_function_type_list (V4USI_type_node, V4USI_type_node,
1031				    V4USI_type_node, V4USI_type_node,
1032				    NULL_TREE);
1033
1034      tree uti_ftype_udi_udi
1035	= build_function_type_list (unsigned_intTI_type_node,
1036				    unsigned_intDI_type_node,
1037				    unsigned_intDI_type_node,
1038				    NULL_TREE);
1039
1040      #undef CRYPTO1
1041      #undef CRYPTO2
1042      #undef CRYPTO3
1043      #undef C
1044      #undef N
1045      #undef CF
1046      #undef FT1
1047      #undef FT2
1048      #undef FT3
1049
1050      #define C(U) \
1051	ARM_BUILTIN_CRYPTO_##U
1052      #define N(L) \
1053	"__builtin_arm_crypto_"#L
1054      #define FT1(R, A) \
1055	R##_ftype_##A
1056      #define FT2(R, A1, A2) \
1057	R##_ftype_##A1##_##A2
1058      #define FT3(R, A1, A2, A3) \
1059        R##_ftype_##A1##_##A2##_##A3
1060      #define CRYPTO1(L, U, R, A) \
1061	arm_builtin_decls[C (U)] \
1062	  = add_builtin_function (N (L), FT1 (R, A), \
1063				  C (U), BUILT_IN_MD, NULL, NULL_TREE);
1064      #define CRYPTO2(L, U, R, A1, A2)  \
1065	arm_builtin_decls[C (U)]	\
1066	  = add_builtin_function (N (L), FT2 (R, A1, A2), \
1067				  C (U), BUILT_IN_MD, NULL, NULL_TREE);
1068
1069      #define CRYPTO3(L, U, R, A1, A2, A3) \
1070	arm_builtin_decls[C (U)]	   \
1071	  = add_builtin_function (N (L), FT3 (R, A1, A2, A3), \
1072				  C (U), BUILT_IN_MD, NULL, NULL_TREE);
1073      #include "crypto.def"
1074
1075      #undef CRYPTO1
1076      #undef CRYPTO2
1077      #undef CRYPTO3
1078      #undef C
1079      #undef N
1080      #undef FT1
1081      #undef FT2
1082      #undef FT3
1083    }
1084}
1085
1086#undef NUM_DREG_TYPES
1087#undef NUM_QREG_TYPES
1088
1089#define def_mbuiltin(MASK, NAME, TYPE, CODE)				\
1090  do									\
1091    {									\
1092      if ((MASK) & insn_flags)						\
1093	{								\
1094	  tree bdecl;							\
1095	  bdecl = add_builtin_function ((NAME), (TYPE), (CODE),		\
1096					BUILT_IN_MD, NULL, NULL_TREE);	\
1097	  arm_builtin_decls[CODE] = bdecl;				\
1098	}								\
1099    }									\
1100  while (0)
1101
1102struct builtin_description
1103{
1104  const unsigned int       mask;
1105  const enum insn_code     icode;
1106  const char * const       name;
1107  const enum arm_builtins  code;
1108  const enum rtx_code      comparison;
1109  const unsigned int       flag;
1110};
1111
1112static const struct builtin_description bdesc_2arg[] =
1113{
1114#define IWMMXT_BUILTIN(code, string, builtin) \
1115  { FL_IWMMXT, CODE_FOR_##code, "__builtin_arm_" string, \
1116    ARM_BUILTIN_##builtin, UNKNOWN, 0 },
1117
1118#define IWMMXT2_BUILTIN(code, string, builtin) \
1119  { FL_IWMMXT2, CODE_FOR_##code, "__builtin_arm_" string, \
1120    ARM_BUILTIN_##builtin, UNKNOWN, 0 },
1121
1122  IWMMXT_BUILTIN (addv8qi3, "waddb", WADDB)
1123  IWMMXT_BUILTIN (addv4hi3, "waddh", WADDH)
1124  IWMMXT_BUILTIN (addv2si3, "waddw", WADDW)
1125  IWMMXT_BUILTIN (subv8qi3, "wsubb", WSUBB)
1126  IWMMXT_BUILTIN (subv4hi3, "wsubh", WSUBH)
1127  IWMMXT_BUILTIN (subv2si3, "wsubw", WSUBW)
1128  IWMMXT_BUILTIN (ssaddv8qi3, "waddbss", WADDSSB)
1129  IWMMXT_BUILTIN (ssaddv4hi3, "waddhss", WADDSSH)
1130  IWMMXT_BUILTIN (ssaddv2si3, "waddwss", WADDSSW)
1131  IWMMXT_BUILTIN (sssubv8qi3, "wsubbss", WSUBSSB)
1132  IWMMXT_BUILTIN (sssubv4hi3, "wsubhss", WSUBSSH)
1133  IWMMXT_BUILTIN (sssubv2si3, "wsubwss", WSUBSSW)
1134  IWMMXT_BUILTIN (usaddv8qi3, "waddbus", WADDUSB)
1135  IWMMXT_BUILTIN (usaddv4hi3, "waddhus", WADDUSH)
1136  IWMMXT_BUILTIN (usaddv2si3, "waddwus", WADDUSW)
1137  IWMMXT_BUILTIN (ussubv8qi3, "wsubbus", WSUBUSB)
1138  IWMMXT_BUILTIN (ussubv4hi3, "wsubhus", WSUBUSH)
1139  IWMMXT_BUILTIN (ussubv2si3, "wsubwus", WSUBUSW)
1140  IWMMXT_BUILTIN (mulv4hi3, "wmulul", WMULUL)
1141  IWMMXT_BUILTIN (smulv4hi3_highpart, "wmulsm", WMULSM)
1142  IWMMXT_BUILTIN (umulv4hi3_highpart, "wmulum", WMULUM)
1143  IWMMXT_BUILTIN (eqv8qi3, "wcmpeqb", WCMPEQB)
1144  IWMMXT_BUILTIN (eqv4hi3, "wcmpeqh", WCMPEQH)
1145  IWMMXT_BUILTIN (eqv2si3, "wcmpeqw", WCMPEQW)
1146  IWMMXT_BUILTIN (gtuv8qi3, "wcmpgtub", WCMPGTUB)
1147  IWMMXT_BUILTIN (gtuv4hi3, "wcmpgtuh", WCMPGTUH)
1148  IWMMXT_BUILTIN (gtuv2si3, "wcmpgtuw", WCMPGTUW)
1149  IWMMXT_BUILTIN (gtv8qi3, "wcmpgtsb", WCMPGTSB)
1150  IWMMXT_BUILTIN (gtv4hi3, "wcmpgtsh", WCMPGTSH)
1151  IWMMXT_BUILTIN (gtv2si3, "wcmpgtsw", WCMPGTSW)
1152  IWMMXT_BUILTIN (umaxv8qi3, "wmaxub", WMAXUB)
1153  IWMMXT_BUILTIN (smaxv8qi3, "wmaxsb", WMAXSB)
1154  IWMMXT_BUILTIN (umaxv4hi3, "wmaxuh", WMAXUH)
1155  IWMMXT_BUILTIN (smaxv4hi3, "wmaxsh", WMAXSH)
1156  IWMMXT_BUILTIN (umaxv2si3, "wmaxuw", WMAXUW)
1157  IWMMXT_BUILTIN (smaxv2si3, "wmaxsw", WMAXSW)
1158  IWMMXT_BUILTIN (uminv8qi3, "wminub", WMINUB)
1159  IWMMXT_BUILTIN (sminv8qi3, "wminsb", WMINSB)
1160  IWMMXT_BUILTIN (uminv4hi3, "wminuh", WMINUH)
1161  IWMMXT_BUILTIN (sminv4hi3, "wminsh", WMINSH)
1162  IWMMXT_BUILTIN (uminv2si3, "wminuw", WMINUW)
1163  IWMMXT_BUILTIN (sminv2si3, "wminsw", WMINSW)
1164  IWMMXT_BUILTIN (iwmmxt_anddi3, "wand", WAND)
1165  IWMMXT_BUILTIN (iwmmxt_nanddi3, "wandn", WANDN)
1166  IWMMXT_BUILTIN (iwmmxt_iordi3, "wor", WOR)
1167  IWMMXT_BUILTIN (iwmmxt_xordi3, "wxor", WXOR)
1168  IWMMXT_BUILTIN (iwmmxt_uavgv8qi3, "wavg2b", WAVG2B)
1169  IWMMXT_BUILTIN (iwmmxt_uavgv4hi3, "wavg2h", WAVG2H)
1170  IWMMXT_BUILTIN (iwmmxt_uavgrndv8qi3, "wavg2br", WAVG2BR)
1171  IWMMXT_BUILTIN (iwmmxt_uavgrndv4hi3, "wavg2hr", WAVG2HR)
1172  IWMMXT_BUILTIN (iwmmxt_wunpckilb, "wunpckilb", WUNPCKILB)
1173  IWMMXT_BUILTIN (iwmmxt_wunpckilh, "wunpckilh", WUNPCKILH)
1174  IWMMXT_BUILTIN (iwmmxt_wunpckilw, "wunpckilw", WUNPCKILW)
1175  IWMMXT_BUILTIN (iwmmxt_wunpckihb, "wunpckihb", WUNPCKIHB)
1176  IWMMXT_BUILTIN (iwmmxt_wunpckihh, "wunpckihh", WUNPCKIHH)
1177  IWMMXT_BUILTIN (iwmmxt_wunpckihw, "wunpckihw", WUNPCKIHW)
1178  IWMMXT2_BUILTIN (iwmmxt_waddsubhx, "waddsubhx", WADDSUBHX)
1179  IWMMXT2_BUILTIN (iwmmxt_wsubaddhx, "wsubaddhx", WSUBADDHX)
1180  IWMMXT2_BUILTIN (iwmmxt_wabsdiffb, "wabsdiffb", WABSDIFFB)
1181  IWMMXT2_BUILTIN (iwmmxt_wabsdiffh, "wabsdiffh", WABSDIFFH)
1182  IWMMXT2_BUILTIN (iwmmxt_wabsdiffw, "wabsdiffw", WABSDIFFW)
1183  IWMMXT2_BUILTIN (iwmmxt_avg4, "wavg4", WAVG4)
1184  IWMMXT2_BUILTIN (iwmmxt_avg4r, "wavg4r", WAVG4R)
1185  IWMMXT2_BUILTIN (iwmmxt_wmulwsm, "wmulwsm", WMULWSM)
1186  IWMMXT2_BUILTIN (iwmmxt_wmulwum, "wmulwum", WMULWUM)
1187  IWMMXT2_BUILTIN (iwmmxt_wmulwsmr, "wmulwsmr", WMULWSMR)
1188  IWMMXT2_BUILTIN (iwmmxt_wmulwumr, "wmulwumr", WMULWUMR)
1189  IWMMXT2_BUILTIN (iwmmxt_wmulwl, "wmulwl", WMULWL)
1190  IWMMXT2_BUILTIN (iwmmxt_wmulsmr, "wmulsmr", WMULSMR)
1191  IWMMXT2_BUILTIN (iwmmxt_wmulumr, "wmulumr", WMULUMR)
1192  IWMMXT2_BUILTIN (iwmmxt_wqmulm, "wqmulm", WQMULM)
1193  IWMMXT2_BUILTIN (iwmmxt_wqmulmr, "wqmulmr", WQMULMR)
1194  IWMMXT2_BUILTIN (iwmmxt_wqmulwm, "wqmulwm", WQMULWM)
1195  IWMMXT2_BUILTIN (iwmmxt_wqmulwmr, "wqmulwmr", WQMULWMR)
1196  IWMMXT_BUILTIN (iwmmxt_walignr0, "walignr0", WALIGNR0)
1197  IWMMXT_BUILTIN (iwmmxt_walignr1, "walignr1", WALIGNR1)
1198  IWMMXT_BUILTIN (iwmmxt_walignr2, "walignr2", WALIGNR2)
1199  IWMMXT_BUILTIN (iwmmxt_walignr3, "walignr3", WALIGNR3)
1200
1201#define IWMMXT_BUILTIN2(code, builtin) \
1202  { FL_IWMMXT, CODE_FOR_##code, NULL, ARM_BUILTIN_##builtin, UNKNOWN, 0 },
1203
1204#define IWMMXT2_BUILTIN2(code, builtin) \
1205  { FL_IWMMXT2, CODE_FOR_##code, NULL, ARM_BUILTIN_##builtin, UNKNOWN, 0 },
1206
1207  IWMMXT2_BUILTIN2 (iwmmxt_waddbhusm, WADDBHUSM)
1208  IWMMXT2_BUILTIN2 (iwmmxt_waddbhusl, WADDBHUSL)
1209  IWMMXT_BUILTIN2 (iwmmxt_wpackhss, WPACKHSS)
1210  IWMMXT_BUILTIN2 (iwmmxt_wpackwss, WPACKWSS)
1211  IWMMXT_BUILTIN2 (iwmmxt_wpackdss, WPACKDSS)
1212  IWMMXT_BUILTIN2 (iwmmxt_wpackhus, WPACKHUS)
1213  IWMMXT_BUILTIN2 (iwmmxt_wpackwus, WPACKWUS)
1214  IWMMXT_BUILTIN2 (iwmmxt_wpackdus, WPACKDUS)
1215  IWMMXT_BUILTIN2 (iwmmxt_wmacuz, WMACUZ)
1216  IWMMXT_BUILTIN2 (iwmmxt_wmacsz, WMACSZ)
1217
1218
1219#define FP_BUILTIN(L, U) \
1220  {0, CODE_FOR_##L, "__builtin_arm_"#L, ARM_BUILTIN_##U, \
1221   UNKNOWN, 0},
1222
1223  FP_BUILTIN (get_fpscr, GET_FPSCR)
1224  FP_BUILTIN (set_fpscr, SET_FPSCR)
1225#undef FP_BUILTIN
1226
1227#define CRC32_BUILTIN(L, U) \
1228  {0, CODE_FOR_##L, "__builtin_arm_"#L, ARM_BUILTIN_##U, \
1229   UNKNOWN, 0},
1230   CRC32_BUILTIN (crc32b, CRC32B)
1231   CRC32_BUILTIN (crc32h, CRC32H)
1232   CRC32_BUILTIN (crc32w, CRC32W)
1233   CRC32_BUILTIN (crc32cb, CRC32CB)
1234   CRC32_BUILTIN (crc32ch, CRC32CH)
1235   CRC32_BUILTIN (crc32cw, CRC32CW)
1236#undef CRC32_BUILTIN
1237
1238
1239#define CRYPTO_BUILTIN(L, U) \
1240  {0, CODE_FOR_crypto_##L, "__builtin_arm_crypto_"#L, ARM_BUILTIN_CRYPTO_##U, \
1241   UNKNOWN, 0},
1242#undef CRYPTO1
1243#undef CRYPTO2
1244#undef CRYPTO3
1245#define CRYPTO2(L, U, R, A1, A2) CRYPTO_BUILTIN (L, U)
1246#define CRYPTO1(L, U, R, A)
1247#define CRYPTO3(L, U, R, A1, A2, A3)
1248#include "crypto.def"
1249#undef CRYPTO1
1250#undef CRYPTO2
1251#undef CRYPTO3
1252
1253};
1254
1255static const struct builtin_description bdesc_1arg[] =
1256{
1257  IWMMXT_BUILTIN (iwmmxt_tmovmskb, "tmovmskb", TMOVMSKB)
1258  IWMMXT_BUILTIN (iwmmxt_tmovmskh, "tmovmskh", TMOVMSKH)
1259  IWMMXT_BUILTIN (iwmmxt_tmovmskw, "tmovmskw", TMOVMSKW)
1260  IWMMXT_BUILTIN (iwmmxt_waccb, "waccb", WACCB)
1261  IWMMXT_BUILTIN (iwmmxt_wacch, "wacch", WACCH)
1262  IWMMXT_BUILTIN (iwmmxt_waccw, "waccw", WACCW)
1263  IWMMXT_BUILTIN (iwmmxt_wunpckehub, "wunpckehub", WUNPCKEHUB)
1264  IWMMXT_BUILTIN (iwmmxt_wunpckehuh, "wunpckehuh", WUNPCKEHUH)
1265  IWMMXT_BUILTIN (iwmmxt_wunpckehuw, "wunpckehuw", WUNPCKEHUW)
1266  IWMMXT_BUILTIN (iwmmxt_wunpckehsb, "wunpckehsb", WUNPCKEHSB)
1267  IWMMXT_BUILTIN (iwmmxt_wunpckehsh, "wunpckehsh", WUNPCKEHSH)
1268  IWMMXT_BUILTIN (iwmmxt_wunpckehsw, "wunpckehsw", WUNPCKEHSW)
1269  IWMMXT_BUILTIN (iwmmxt_wunpckelub, "wunpckelub", WUNPCKELUB)
1270  IWMMXT_BUILTIN (iwmmxt_wunpckeluh, "wunpckeluh", WUNPCKELUH)
1271  IWMMXT_BUILTIN (iwmmxt_wunpckeluw, "wunpckeluw", WUNPCKELUW)
1272  IWMMXT_BUILTIN (iwmmxt_wunpckelsb, "wunpckelsb", WUNPCKELSB)
1273  IWMMXT_BUILTIN (iwmmxt_wunpckelsh, "wunpckelsh", WUNPCKELSH)
1274  IWMMXT_BUILTIN (iwmmxt_wunpckelsw, "wunpckelsw", WUNPCKELSW)
1275  IWMMXT2_BUILTIN (iwmmxt_wabsv8qi3, "wabsb", WABSB)
1276  IWMMXT2_BUILTIN (iwmmxt_wabsv4hi3, "wabsh", WABSH)
1277  IWMMXT2_BUILTIN (iwmmxt_wabsv2si3, "wabsw", WABSW)
1278  IWMMXT_BUILTIN (tbcstv8qi, "tbcstb", TBCSTB)
1279  IWMMXT_BUILTIN (tbcstv4hi, "tbcsth", TBCSTH)
1280  IWMMXT_BUILTIN (tbcstv2si, "tbcstw", TBCSTW)
1281
1282#define CRYPTO1(L, U, R, A) CRYPTO_BUILTIN (L, U)
1283#define CRYPTO2(L, U, R, A1, A2)
1284#define CRYPTO3(L, U, R, A1, A2, A3)
1285#include "crypto.def"
1286#undef CRYPTO1
1287#undef CRYPTO2
1288#undef CRYPTO3
1289};
1290
1291static const struct builtin_description bdesc_3arg[] =
1292{
1293#define CRYPTO3(L, U, R, A1, A2, A3) CRYPTO_BUILTIN (L, U)
1294#define CRYPTO1(L, U, R, A)
1295#define CRYPTO2(L, U, R, A1, A2)
1296#include "crypto.def"
1297#undef CRYPTO1
1298#undef CRYPTO2
1299#undef CRYPTO3
1300 };
1301#undef CRYPTO_BUILTIN
1302
1303/* Set up all the iWMMXt builtins.  This is not called if
1304   TARGET_IWMMXT is zero.  */
1305
1306static void
1307arm_init_iwmmxt_builtins (void)
1308{
1309  const struct builtin_description * d;
1310  size_t i;
1311
1312  tree V2SI_type_node = build_vector_type_for_mode (intSI_type_node, V2SImode);
1313  tree V4HI_type_node = build_vector_type_for_mode (intHI_type_node, V4HImode);
1314  tree V8QI_type_node = build_vector_type_for_mode (intQI_type_node, V8QImode);
1315
1316  tree v8qi_ftype_v8qi_v8qi_int
1317    = build_function_type_list (V8QI_type_node,
1318				V8QI_type_node, V8QI_type_node,
1319				integer_type_node, NULL_TREE);
1320  tree v4hi_ftype_v4hi_int
1321    = build_function_type_list (V4HI_type_node,
1322				V4HI_type_node, integer_type_node, NULL_TREE);
1323  tree v2si_ftype_v2si_int
1324    = build_function_type_list (V2SI_type_node,
1325				V2SI_type_node, integer_type_node, NULL_TREE);
1326  tree v2si_ftype_di_di
1327    = build_function_type_list (V2SI_type_node,
1328				long_long_integer_type_node,
1329				long_long_integer_type_node,
1330				NULL_TREE);
1331  tree di_ftype_di_int
1332    = build_function_type_list (long_long_integer_type_node,
1333				long_long_integer_type_node,
1334				integer_type_node, NULL_TREE);
1335  tree di_ftype_di_int_int
1336    = build_function_type_list (long_long_integer_type_node,
1337				long_long_integer_type_node,
1338				integer_type_node,
1339				integer_type_node, NULL_TREE);
1340  tree int_ftype_v8qi
1341    = build_function_type_list (integer_type_node,
1342				V8QI_type_node, NULL_TREE);
1343  tree int_ftype_v4hi
1344    = build_function_type_list (integer_type_node,
1345				V4HI_type_node, NULL_TREE);
1346  tree int_ftype_v2si
1347    = build_function_type_list (integer_type_node,
1348				V2SI_type_node, NULL_TREE);
1349  tree int_ftype_v8qi_int
1350    = build_function_type_list (integer_type_node,
1351				V8QI_type_node, integer_type_node, NULL_TREE);
1352  tree int_ftype_v4hi_int
1353    = build_function_type_list (integer_type_node,
1354				V4HI_type_node, integer_type_node, NULL_TREE);
1355  tree int_ftype_v2si_int
1356    = build_function_type_list (integer_type_node,
1357				V2SI_type_node, integer_type_node, NULL_TREE);
1358  tree v8qi_ftype_v8qi_int_int
1359    = build_function_type_list (V8QI_type_node,
1360				V8QI_type_node, integer_type_node,
1361				integer_type_node, NULL_TREE);
1362  tree v4hi_ftype_v4hi_int_int
1363    = build_function_type_list (V4HI_type_node,
1364				V4HI_type_node, integer_type_node,
1365				integer_type_node, NULL_TREE);
1366  tree v2si_ftype_v2si_int_int
1367    = build_function_type_list (V2SI_type_node,
1368				V2SI_type_node, integer_type_node,
1369				integer_type_node, NULL_TREE);
1370  /* Miscellaneous.  */
1371  tree v8qi_ftype_v4hi_v4hi
1372    = build_function_type_list (V8QI_type_node,
1373				V4HI_type_node, V4HI_type_node, NULL_TREE);
1374  tree v4hi_ftype_v2si_v2si
1375    = build_function_type_list (V4HI_type_node,
1376				V2SI_type_node, V2SI_type_node, NULL_TREE);
1377  tree v8qi_ftype_v4hi_v8qi
1378    = build_function_type_list (V8QI_type_node,
1379	                        V4HI_type_node, V8QI_type_node, NULL_TREE);
1380  tree v2si_ftype_v4hi_v4hi
1381    = build_function_type_list (V2SI_type_node,
1382				V4HI_type_node, V4HI_type_node, NULL_TREE);
1383  tree v2si_ftype_v8qi_v8qi
1384    = build_function_type_list (V2SI_type_node,
1385				V8QI_type_node, V8QI_type_node, NULL_TREE);
1386  tree v4hi_ftype_v4hi_di
1387    = build_function_type_list (V4HI_type_node,
1388				V4HI_type_node, long_long_integer_type_node,
1389				NULL_TREE);
1390  tree v2si_ftype_v2si_di
1391    = build_function_type_list (V2SI_type_node,
1392				V2SI_type_node, long_long_integer_type_node,
1393				NULL_TREE);
1394  tree di_ftype_void
1395    = build_function_type_list (long_long_unsigned_type_node, NULL_TREE);
1396  tree int_ftype_void
1397    = build_function_type_list (integer_type_node, NULL_TREE);
1398  tree di_ftype_v8qi
1399    = build_function_type_list (long_long_integer_type_node,
1400				V8QI_type_node, NULL_TREE);
1401  tree di_ftype_v4hi
1402    = build_function_type_list (long_long_integer_type_node,
1403				V4HI_type_node, NULL_TREE);
1404  tree di_ftype_v2si
1405    = build_function_type_list (long_long_integer_type_node,
1406				V2SI_type_node, NULL_TREE);
1407  tree v2si_ftype_v4hi
1408    = build_function_type_list (V2SI_type_node,
1409				V4HI_type_node, NULL_TREE);
1410  tree v4hi_ftype_v8qi
1411    = build_function_type_list (V4HI_type_node,
1412				V8QI_type_node, NULL_TREE);
1413  tree v8qi_ftype_v8qi
1414    = build_function_type_list (V8QI_type_node,
1415	                        V8QI_type_node, NULL_TREE);
1416  tree v4hi_ftype_v4hi
1417    = build_function_type_list (V4HI_type_node,
1418	                        V4HI_type_node, NULL_TREE);
1419  tree v2si_ftype_v2si
1420    = build_function_type_list (V2SI_type_node,
1421	                        V2SI_type_node, NULL_TREE);
1422
1423  tree di_ftype_di_v4hi_v4hi
1424    = build_function_type_list (long_long_unsigned_type_node,
1425				long_long_unsigned_type_node,
1426				V4HI_type_node, V4HI_type_node,
1427				NULL_TREE);
1428
1429  tree di_ftype_v4hi_v4hi
1430    = build_function_type_list (long_long_unsigned_type_node,
1431				V4HI_type_node,V4HI_type_node,
1432				NULL_TREE);
1433
1434  tree v2si_ftype_v2si_v4hi_v4hi
1435    = build_function_type_list (V2SI_type_node,
1436                                V2SI_type_node, V4HI_type_node,
1437                                V4HI_type_node, NULL_TREE);
1438
1439  tree v2si_ftype_v2si_v8qi_v8qi
1440    = build_function_type_list (V2SI_type_node,
1441                                V2SI_type_node, V8QI_type_node,
1442                                V8QI_type_node, NULL_TREE);
1443
1444  tree di_ftype_di_v2si_v2si
1445     = build_function_type_list (long_long_unsigned_type_node,
1446                                 long_long_unsigned_type_node,
1447                                 V2SI_type_node, V2SI_type_node,
1448                                 NULL_TREE);
1449
1450   tree di_ftype_di_di_int
1451     = build_function_type_list (long_long_unsigned_type_node,
1452                                 long_long_unsigned_type_node,
1453                                 long_long_unsigned_type_node,
1454                                 integer_type_node, NULL_TREE);
1455
1456   tree void_ftype_int
1457     = build_function_type_list (void_type_node,
1458                                 integer_type_node, NULL_TREE);
1459
1460   tree v8qi_ftype_char
1461     = build_function_type_list (V8QI_type_node,
1462                                 signed_char_type_node, NULL_TREE);
1463
1464   tree v4hi_ftype_short
1465     = build_function_type_list (V4HI_type_node,
1466                                 short_integer_type_node, NULL_TREE);
1467
1468   tree v2si_ftype_int
1469     = build_function_type_list (V2SI_type_node,
1470                                 integer_type_node, NULL_TREE);
1471
1472  /* Normal vector binops.  */
1473  tree v8qi_ftype_v8qi_v8qi
1474    = build_function_type_list (V8QI_type_node,
1475				V8QI_type_node, V8QI_type_node, NULL_TREE);
1476  tree v4hi_ftype_v4hi_v4hi
1477    = build_function_type_list (V4HI_type_node,
1478				V4HI_type_node,V4HI_type_node, NULL_TREE);
1479  tree v2si_ftype_v2si_v2si
1480    = build_function_type_list (V2SI_type_node,
1481				V2SI_type_node, V2SI_type_node, NULL_TREE);
1482  tree di_ftype_di_di
1483    = build_function_type_list (long_long_unsigned_type_node,
1484				long_long_unsigned_type_node,
1485				long_long_unsigned_type_node,
1486				NULL_TREE);
1487
1488  /* Add all builtins that are more or less simple operations on two
1489     operands.  */
1490  for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
1491    {
1492      /* Use one of the operands; the target can have a different mode for
1493	 mask-generating compares.  */
1494      machine_mode mode;
1495      tree type;
1496
1497      if (d->name == 0 || !(d->mask == FL_IWMMXT || d->mask == FL_IWMMXT2))
1498	continue;
1499
1500      mode = insn_data[d->icode].operand[1].mode;
1501
1502      switch (mode)
1503	{
1504	case V8QImode:
1505	  type = v8qi_ftype_v8qi_v8qi;
1506	  break;
1507	case V4HImode:
1508	  type = v4hi_ftype_v4hi_v4hi;
1509	  break;
1510	case V2SImode:
1511	  type = v2si_ftype_v2si_v2si;
1512	  break;
1513	case DImode:
1514	  type = di_ftype_di_di;
1515	  break;
1516
1517	default:
1518	  gcc_unreachable ();
1519	}
1520
1521      def_mbuiltin (d->mask, d->name, type, d->code);
1522    }
1523
1524  /* Add the remaining MMX insns with somewhat more complicated types.  */
1525#define iwmmx_mbuiltin(NAME, TYPE, CODE)			\
1526  def_mbuiltin (FL_IWMMXT, "__builtin_arm_" NAME, (TYPE),	\
1527		ARM_BUILTIN_ ## CODE)
1528
1529#define iwmmx2_mbuiltin(NAME, TYPE, CODE)                      \
1530  def_mbuiltin (FL_IWMMXT2, "__builtin_arm_" NAME, (TYPE),     \
1531               ARM_BUILTIN_ ## CODE)
1532
1533  iwmmx_mbuiltin ("wzero", di_ftype_void, WZERO);
1534  iwmmx_mbuiltin ("setwcgr0", void_ftype_int, SETWCGR0);
1535  iwmmx_mbuiltin ("setwcgr1", void_ftype_int, SETWCGR1);
1536  iwmmx_mbuiltin ("setwcgr2", void_ftype_int, SETWCGR2);
1537  iwmmx_mbuiltin ("setwcgr3", void_ftype_int, SETWCGR3);
1538  iwmmx_mbuiltin ("getwcgr0", int_ftype_void, GETWCGR0);
1539  iwmmx_mbuiltin ("getwcgr1", int_ftype_void, GETWCGR1);
1540  iwmmx_mbuiltin ("getwcgr2", int_ftype_void, GETWCGR2);
1541  iwmmx_mbuiltin ("getwcgr3", int_ftype_void, GETWCGR3);
1542
1543  iwmmx_mbuiltin ("wsllh", v4hi_ftype_v4hi_di, WSLLH);
1544  iwmmx_mbuiltin ("wsllw", v2si_ftype_v2si_di, WSLLW);
1545  iwmmx_mbuiltin ("wslld", di_ftype_di_di, WSLLD);
1546  iwmmx_mbuiltin ("wsllhi", v4hi_ftype_v4hi_int, WSLLHI);
1547  iwmmx_mbuiltin ("wsllwi", v2si_ftype_v2si_int, WSLLWI);
1548  iwmmx_mbuiltin ("wslldi", di_ftype_di_int, WSLLDI);
1549
1550  iwmmx_mbuiltin ("wsrlh", v4hi_ftype_v4hi_di, WSRLH);
1551  iwmmx_mbuiltin ("wsrlw", v2si_ftype_v2si_di, WSRLW);
1552  iwmmx_mbuiltin ("wsrld", di_ftype_di_di, WSRLD);
1553  iwmmx_mbuiltin ("wsrlhi", v4hi_ftype_v4hi_int, WSRLHI);
1554  iwmmx_mbuiltin ("wsrlwi", v2si_ftype_v2si_int, WSRLWI);
1555  iwmmx_mbuiltin ("wsrldi", di_ftype_di_int, WSRLDI);
1556
1557  iwmmx_mbuiltin ("wsrah", v4hi_ftype_v4hi_di, WSRAH);
1558  iwmmx_mbuiltin ("wsraw", v2si_ftype_v2si_di, WSRAW);
1559  iwmmx_mbuiltin ("wsrad", di_ftype_di_di, WSRAD);
1560  iwmmx_mbuiltin ("wsrahi", v4hi_ftype_v4hi_int, WSRAHI);
1561  iwmmx_mbuiltin ("wsrawi", v2si_ftype_v2si_int, WSRAWI);
1562  iwmmx_mbuiltin ("wsradi", di_ftype_di_int, WSRADI);
1563
1564  iwmmx_mbuiltin ("wrorh", v4hi_ftype_v4hi_di, WRORH);
1565  iwmmx_mbuiltin ("wrorw", v2si_ftype_v2si_di, WRORW);
1566  iwmmx_mbuiltin ("wrord", di_ftype_di_di, WRORD);
1567  iwmmx_mbuiltin ("wrorhi", v4hi_ftype_v4hi_int, WRORHI);
1568  iwmmx_mbuiltin ("wrorwi", v2si_ftype_v2si_int, WRORWI);
1569  iwmmx_mbuiltin ("wrordi", di_ftype_di_int, WRORDI);
1570
1571  iwmmx_mbuiltin ("wshufh", v4hi_ftype_v4hi_int, WSHUFH);
1572
1573  iwmmx_mbuiltin ("wsadb", v2si_ftype_v2si_v8qi_v8qi, WSADB);
1574  iwmmx_mbuiltin ("wsadh", v2si_ftype_v2si_v4hi_v4hi, WSADH);
1575  iwmmx_mbuiltin ("wmadds", v2si_ftype_v4hi_v4hi, WMADDS);
1576  iwmmx2_mbuiltin ("wmaddsx", v2si_ftype_v4hi_v4hi, WMADDSX);
1577  iwmmx2_mbuiltin ("wmaddsn", v2si_ftype_v4hi_v4hi, WMADDSN);
1578  iwmmx_mbuiltin ("wmaddu", v2si_ftype_v4hi_v4hi, WMADDU);
1579  iwmmx2_mbuiltin ("wmaddux", v2si_ftype_v4hi_v4hi, WMADDUX);
1580  iwmmx2_mbuiltin ("wmaddun", v2si_ftype_v4hi_v4hi, WMADDUN);
1581  iwmmx_mbuiltin ("wsadbz", v2si_ftype_v8qi_v8qi, WSADBZ);
1582  iwmmx_mbuiltin ("wsadhz", v2si_ftype_v4hi_v4hi, WSADHZ);
1583
1584  iwmmx_mbuiltin ("textrmsb", int_ftype_v8qi_int, TEXTRMSB);
1585  iwmmx_mbuiltin ("textrmsh", int_ftype_v4hi_int, TEXTRMSH);
1586  iwmmx_mbuiltin ("textrmsw", int_ftype_v2si_int, TEXTRMSW);
1587  iwmmx_mbuiltin ("textrmub", int_ftype_v8qi_int, TEXTRMUB);
1588  iwmmx_mbuiltin ("textrmuh", int_ftype_v4hi_int, TEXTRMUH);
1589  iwmmx_mbuiltin ("textrmuw", int_ftype_v2si_int, TEXTRMUW);
1590  iwmmx_mbuiltin ("tinsrb", v8qi_ftype_v8qi_int_int, TINSRB);
1591  iwmmx_mbuiltin ("tinsrh", v4hi_ftype_v4hi_int_int, TINSRH);
1592  iwmmx_mbuiltin ("tinsrw", v2si_ftype_v2si_int_int, TINSRW);
1593
1594  iwmmx_mbuiltin ("waccb", di_ftype_v8qi, WACCB);
1595  iwmmx_mbuiltin ("wacch", di_ftype_v4hi, WACCH);
1596  iwmmx_mbuiltin ("waccw", di_ftype_v2si, WACCW);
1597
1598  iwmmx_mbuiltin ("tmovmskb", int_ftype_v8qi, TMOVMSKB);
1599  iwmmx_mbuiltin ("tmovmskh", int_ftype_v4hi, TMOVMSKH);
1600  iwmmx_mbuiltin ("tmovmskw", int_ftype_v2si, TMOVMSKW);
1601
1602  iwmmx2_mbuiltin ("waddbhusm", v8qi_ftype_v4hi_v8qi, WADDBHUSM);
1603  iwmmx2_mbuiltin ("waddbhusl", v8qi_ftype_v4hi_v8qi, WADDBHUSL);
1604
1605  iwmmx_mbuiltin ("wpackhss", v8qi_ftype_v4hi_v4hi, WPACKHSS);
1606  iwmmx_mbuiltin ("wpackhus", v8qi_ftype_v4hi_v4hi, WPACKHUS);
1607  iwmmx_mbuiltin ("wpackwus", v4hi_ftype_v2si_v2si, WPACKWUS);
1608  iwmmx_mbuiltin ("wpackwss", v4hi_ftype_v2si_v2si, WPACKWSS);
1609  iwmmx_mbuiltin ("wpackdus", v2si_ftype_di_di, WPACKDUS);
1610  iwmmx_mbuiltin ("wpackdss", v2si_ftype_di_di, WPACKDSS);
1611
1612  iwmmx_mbuiltin ("wunpckehub", v4hi_ftype_v8qi, WUNPCKEHUB);
1613  iwmmx_mbuiltin ("wunpckehuh", v2si_ftype_v4hi, WUNPCKEHUH);
1614  iwmmx_mbuiltin ("wunpckehuw", di_ftype_v2si, WUNPCKEHUW);
1615  iwmmx_mbuiltin ("wunpckehsb", v4hi_ftype_v8qi, WUNPCKEHSB);
1616  iwmmx_mbuiltin ("wunpckehsh", v2si_ftype_v4hi, WUNPCKEHSH);
1617  iwmmx_mbuiltin ("wunpckehsw", di_ftype_v2si, WUNPCKEHSW);
1618  iwmmx_mbuiltin ("wunpckelub", v4hi_ftype_v8qi, WUNPCKELUB);
1619  iwmmx_mbuiltin ("wunpckeluh", v2si_ftype_v4hi, WUNPCKELUH);
1620  iwmmx_mbuiltin ("wunpckeluw", di_ftype_v2si, WUNPCKELUW);
1621  iwmmx_mbuiltin ("wunpckelsb", v4hi_ftype_v8qi, WUNPCKELSB);
1622  iwmmx_mbuiltin ("wunpckelsh", v2si_ftype_v4hi, WUNPCKELSH);
1623  iwmmx_mbuiltin ("wunpckelsw", di_ftype_v2si, WUNPCKELSW);
1624
1625  iwmmx_mbuiltin ("wmacs", di_ftype_di_v4hi_v4hi, WMACS);
1626  iwmmx_mbuiltin ("wmacsz", di_ftype_v4hi_v4hi, WMACSZ);
1627  iwmmx_mbuiltin ("wmacu", di_ftype_di_v4hi_v4hi, WMACU);
1628  iwmmx_mbuiltin ("wmacuz", di_ftype_v4hi_v4hi, WMACUZ);
1629
1630  iwmmx_mbuiltin ("walign", v8qi_ftype_v8qi_v8qi_int, WALIGNI);
1631  iwmmx_mbuiltin ("tmia", di_ftype_di_int_int, TMIA);
1632  iwmmx_mbuiltin ("tmiaph", di_ftype_di_int_int, TMIAPH);
1633  iwmmx_mbuiltin ("tmiabb", di_ftype_di_int_int, TMIABB);
1634  iwmmx_mbuiltin ("tmiabt", di_ftype_di_int_int, TMIABT);
1635  iwmmx_mbuiltin ("tmiatb", di_ftype_di_int_int, TMIATB);
1636  iwmmx_mbuiltin ("tmiatt", di_ftype_di_int_int, TMIATT);
1637
1638  iwmmx2_mbuiltin ("wabsb", v8qi_ftype_v8qi, WABSB);
1639  iwmmx2_mbuiltin ("wabsh", v4hi_ftype_v4hi, WABSH);
1640  iwmmx2_mbuiltin ("wabsw", v2si_ftype_v2si, WABSW);
1641
1642  iwmmx2_mbuiltin ("wqmiabb", v2si_ftype_v2si_v4hi_v4hi, WQMIABB);
1643  iwmmx2_mbuiltin ("wqmiabt", v2si_ftype_v2si_v4hi_v4hi, WQMIABT);
1644  iwmmx2_mbuiltin ("wqmiatb", v2si_ftype_v2si_v4hi_v4hi, WQMIATB);
1645  iwmmx2_mbuiltin ("wqmiatt", v2si_ftype_v2si_v4hi_v4hi, WQMIATT);
1646
1647  iwmmx2_mbuiltin ("wqmiabbn", v2si_ftype_v2si_v4hi_v4hi, WQMIABBN);
1648  iwmmx2_mbuiltin ("wqmiabtn", v2si_ftype_v2si_v4hi_v4hi, WQMIABTN);
1649  iwmmx2_mbuiltin ("wqmiatbn", v2si_ftype_v2si_v4hi_v4hi, WQMIATBN);
1650  iwmmx2_mbuiltin ("wqmiattn", v2si_ftype_v2si_v4hi_v4hi, WQMIATTN);
1651
1652  iwmmx2_mbuiltin ("wmiabb", di_ftype_di_v4hi_v4hi, WMIABB);
1653  iwmmx2_mbuiltin ("wmiabt", di_ftype_di_v4hi_v4hi, WMIABT);
1654  iwmmx2_mbuiltin ("wmiatb", di_ftype_di_v4hi_v4hi, WMIATB);
1655  iwmmx2_mbuiltin ("wmiatt", di_ftype_di_v4hi_v4hi, WMIATT);
1656
1657  iwmmx2_mbuiltin ("wmiabbn", di_ftype_di_v4hi_v4hi, WMIABBN);
1658  iwmmx2_mbuiltin ("wmiabtn", di_ftype_di_v4hi_v4hi, WMIABTN);
1659  iwmmx2_mbuiltin ("wmiatbn", di_ftype_di_v4hi_v4hi, WMIATBN);
1660  iwmmx2_mbuiltin ("wmiattn", di_ftype_di_v4hi_v4hi, WMIATTN);
1661
1662  iwmmx2_mbuiltin ("wmiawbb", di_ftype_di_v2si_v2si, WMIAWBB);
1663  iwmmx2_mbuiltin ("wmiawbt", di_ftype_di_v2si_v2si, WMIAWBT);
1664  iwmmx2_mbuiltin ("wmiawtb", di_ftype_di_v2si_v2si, WMIAWTB);
1665  iwmmx2_mbuiltin ("wmiawtt", di_ftype_di_v2si_v2si, WMIAWTT);
1666
1667  iwmmx2_mbuiltin ("wmiawbbn", di_ftype_di_v2si_v2si, WMIAWBBN);
1668  iwmmx2_mbuiltin ("wmiawbtn", di_ftype_di_v2si_v2si, WMIAWBTN);
1669  iwmmx2_mbuiltin ("wmiawtbn", di_ftype_di_v2si_v2si, WMIAWTBN);
1670  iwmmx2_mbuiltin ("wmiawttn", di_ftype_di_v2si_v2si, WMIAWTTN);
1671
1672  iwmmx2_mbuiltin ("wmerge", di_ftype_di_di_int, WMERGE);
1673
1674  iwmmx_mbuiltin ("tbcstb", v8qi_ftype_char, TBCSTB);
1675  iwmmx_mbuiltin ("tbcsth", v4hi_ftype_short, TBCSTH);
1676  iwmmx_mbuiltin ("tbcstw", v2si_ftype_int, TBCSTW);
1677
1678#undef iwmmx_mbuiltin
1679#undef iwmmx2_mbuiltin
1680}
1681
1682static void
1683arm_init_fp16_builtins (void)
1684{
1685  tree fp16_type = make_node (REAL_TYPE);
1686  TYPE_PRECISION (fp16_type) = 16;
1687  layout_type (fp16_type);
1688  (*lang_hooks.types.register_builtin_type) (fp16_type, "__fp16");
1689}
1690
1691static void
1692arm_init_crc32_builtins ()
1693{
1694  tree si_ftype_si_qi
1695    = build_function_type_list (unsigned_intSI_type_node,
1696                                unsigned_intSI_type_node,
1697                                unsigned_intQI_type_node, NULL_TREE);
1698  tree si_ftype_si_hi
1699    = build_function_type_list (unsigned_intSI_type_node,
1700                                unsigned_intSI_type_node,
1701                                unsigned_intHI_type_node, NULL_TREE);
1702  tree si_ftype_si_si
1703    = build_function_type_list (unsigned_intSI_type_node,
1704                                unsigned_intSI_type_node,
1705                                unsigned_intSI_type_node, NULL_TREE);
1706
1707  arm_builtin_decls[ARM_BUILTIN_CRC32B]
1708    = add_builtin_function ("__builtin_arm_crc32b", si_ftype_si_qi,
1709                            ARM_BUILTIN_CRC32B, BUILT_IN_MD, NULL, NULL_TREE);
1710  arm_builtin_decls[ARM_BUILTIN_CRC32H]
1711    = add_builtin_function ("__builtin_arm_crc32h", si_ftype_si_hi,
1712                            ARM_BUILTIN_CRC32H, BUILT_IN_MD, NULL, NULL_TREE);
1713  arm_builtin_decls[ARM_BUILTIN_CRC32W]
1714    = add_builtin_function ("__builtin_arm_crc32w", si_ftype_si_si,
1715                            ARM_BUILTIN_CRC32W, BUILT_IN_MD, NULL, NULL_TREE);
1716  arm_builtin_decls[ARM_BUILTIN_CRC32CB]
1717    = add_builtin_function ("__builtin_arm_crc32cb", si_ftype_si_qi,
1718                            ARM_BUILTIN_CRC32CB, BUILT_IN_MD, NULL, NULL_TREE);
1719  arm_builtin_decls[ARM_BUILTIN_CRC32CH]
1720    = add_builtin_function ("__builtin_arm_crc32ch", si_ftype_si_hi,
1721                            ARM_BUILTIN_CRC32CH, BUILT_IN_MD, NULL, NULL_TREE);
1722  arm_builtin_decls[ARM_BUILTIN_CRC32CW]
1723    = add_builtin_function ("__builtin_arm_crc32cw", si_ftype_si_si,
1724                            ARM_BUILTIN_CRC32CW, BUILT_IN_MD, NULL, NULL_TREE);
1725}
1726
1727void
1728arm_init_builtins (void)
1729{
1730  if (TARGET_REALLY_IWMMXT)
1731    arm_init_iwmmxt_builtins ();
1732
1733  if (TARGET_NEON)
1734    arm_init_neon_builtins ();
1735
1736  if (arm_fp16_format)
1737    arm_init_fp16_builtins ();
1738
1739  if (TARGET_CRC32)
1740    arm_init_crc32_builtins ();
1741
1742  if (TARGET_VFP && TARGET_HARD_FLOAT)
1743    {
1744      tree ftype_set_fpscr
1745	= build_function_type_list (void_type_node, unsigned_type_node, NULL);
1746      tree ftype_get_fpscr
1747	= build_function_type_list (unsigned_type_node, NULL);
1748
1749      arm_builtin_decls[ARM_BUILTIN_GET_FPSCR]
1750	= add_builtin_function ("__builtin_arm_ldfscr", ftype_get_fpscr,
1751				ARM_BUILTIN_GET_FPSCR, BUILT_IN_MD, NULL, NULL_TREE);
1752      arm_builtin_decls[ARM_BUILTIN_SET_FPSCR]
1753	= add_builtin_function ("__builtin_arm_stfscr", ftype_set_fpscr,
1754				ARM_BUILTIN_SET_FPSCR, BUILT_IN_MD, NULL, NULL_TREE);
1755    }
1756}
1757
1758/* Return the ARM builtin for CODE.  */
1759
1760tree
1761arm_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
1762{
1763  if (code >= ARM_BUILTIN_MAX)
1764    return error_mark_node;
1765
1766  return arm_builtin_decls[code];
1767}
1768
1769/* Errors in the source file can cause expand_expr to return const0_rtx
1770   where we expect a vector.  To avoid crashing, use one of the vector
1771   clear instructions.  */
1772
1773static rtx
1774safe_vector_operand (rtx x, machine_mode mode)
1775{
1776  if (x != const0_rtx)
1777    return x;
1778  x = gen_reg_rtx (mode);
1779
1780  emit_insn (gen_iwmmxt_clrdi (mode == DImode ? x
1781			       : gen_rtx_SUBREG (DImode, x, 0)));
1782  return x;
1783}
1784
1785/* Function to expand ternary builtins.  */
1786static rtx
1787arm_expand_ternop_builtin (enum insn_code icode,
1788                           tree exp, rtx target)
1789{
1790  rtx pat;
1791  tree arg0 = CALL_EXPR_ARG (exp, 0);
1792  tree arg1 = CALL_EXPR_ARG (exp, 1);
1793  tree arg2 = CALL_EXPR_ARG (exp, 2);
1794
1795  rtx op0 = expand_normal (arg0);
1796  rtx op1 = expand_normal (arg1);
1797  rtx op2 = expand_normal (arg2);
1798  rtx op3 = NULL_RTX;
1799
1800  /* The sha1c, sha1p, sha1m crypto builtins require a different vec_select
1801     lane operand depending on endianness.  */
1802  bool builtin_sha1cpm_p = false;
1803
1804  if (insn_data[icode].n_operands == 5)
1805    {
1806      gcc_assert (icode == CODE_FOR_crypto_sha1c
1807                  || icode == CODE_FOR_crypto_sha1p
1808                  || icode == CODE_FOR_crypto_sha1m);
1809      builtin_sha1cpm_p = true;
1810    }
1811  machine_mode tmode = insn_data[icode].operand[0].mode;
1812  machine_mode mode0 = insn_data[icode].operand[1].mode;
1813  machine_mode mode1 = insn_data[icode].operand[2].mode;
1814  machine_mode mode2 = insn_data[icode].operand[3].mode;
1815
1816
1817  if (VECTOR_MODE_P (mode0))
1818    op0 = safe_vector_operand (op0, mode0);
1819  if (VECTOR_MODE_P (mode1))
1820    op1 = safe_vector_operand (op1, mode1);
1821  if (VECTOR_MODE_P (mode2))
1822    op2 = safe_vector_operand (op2, mode2);
1823
1824  if (! target
1825      || GET_MODE (target) != tmode
1826      || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
1827    target = gen_reg_rtx (tmode);
1828
1829  gcc_assert ((GET_MODE (op0) == mode0 || GET_MODE (op0) == VOIDmode)
1830	      && (GET_MODE (op1) == mode1 || GET_MODE (op1) == VOIDmode)
1831	      && (GET_MODE (op2) == mode2 || GET_MODE (op2) == VOIDmode));
1832
1833  if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
1834    op0 = copy_to_mode_reg (mode0, op0);
1835  if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
1836    op1 = copy_to_mode_reg (mode1, op1);
1837  if (! (*insn_data[icode].operand[3].predicate) (op2, mode2))
1838    op2 = copy_to_mode_reg (mode2, op2);
1839  if (builtin_sha1cpm_p)
1840    op3 = GEN_INT (TARGET_BIG_END ? 1 : 0);
1841
1842  if (builtin_sha1cpm_p)
1843    pat = GEN_FCN (icode) (target, op0, op1, op2, op3);
1844  else
1845    pat = GEN_FCN (icode) (target, op0, op1, op2);
1846  if (! pat)
1847    return 0;
1848  emit_insn (pat);
1849  return target;
1850}
1851
1852/* Subroutine of arm_expand_builtin to take care of binop insns.  */
1853
1854static rtx
1855arm_expand_binop_builtin (enum insn_code icode,
1856			  tree exp, rtx target)
1857{
1858  rtx pat;
1859  tree arg0 = CALL_EXPR_ARG (exp, 0);
1860  tree arg1 = CALL_EXPR_ARG (exp, 1);
1861  rtx op0 = expand_normal (arg0);
1862  rtx op1 = expand_normal (arg1);
1863  machine_mode tmode = insn_data[icode].operand[0].mode;
1864  machine_mode mode0 = insn_data[icode].operand[1].mode;
1865  machine_mode mode1 = insn_data[icode].operand[2].mode;
1866
1867  if (VECTOR_MODE_P (mode0))
1868    op0 = safe_vector_operand (op0, mode0);
1869  if (VECTOR_MODE_P (mode1))
1870    op1 = safe_vector_operand (op1, mode1);
1871
1872  if (! target
1873      || GET_MODE (target) != tmode
1874      || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
1875    target = gen_reg_rtx (tmode);
1876
1877  gcc_assert ((GET_MODE (op0) == mode0 || GET_MODE (op0) == VOIDmode)
1878	      && (GET_MODE (op1) == mode1 || GET_MODE (op1) == VOIDmode));
1879
1880  if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
1881    op0 = copy_to_mode_reg (mode0, op0);
1882  if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
1883    op1 = copy_to_mode_reg (mode1, op1);
1884
1885  pat = GEN_FCN (icode) (target, op0, op1);
1886  if (! pat)
1887    return 0;
1888  emit_insn (pat);
1889  return target;
1890}
1891
1892/* Subroutine of arm_expand_builtin to take care of unop insns.  */
1893
1894static rtx
1895arm_expand_unop_builtin (enum insn_code icode,
1896			 tree exp, rtx target, int do_load)
1897{
1898  rtx pat;
1899  tree arg0 = CALL_EXPR_ARG (exp, 0);
1900  rtx op0 = expand_normal (arg0);
1901  rtx op1 = NULL_RTX;
1902  machine_mode tmode = insn_data[icode].operand[0].mode;
1903  machine_mode mode0 = insn_data[icode].operand[1].mode;
1904  bool builtin_sha1h_p = false;
1905
1906  if (insn_data[icode].n_operands == 3)
1907    {
1908      gcc_assert (icode == CODE_FOR_crypto_sha1h);
1909      builtin_sha1h_p = true;
1910    }
1911
1912  if (! target
1913      || GET_MODE (target) != tmode
1914      || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
1915    target = gen_reg_rtx (tmode);
1916  if (do_load)
1917    op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
1918  else
1919    {
1920      if (VECTOR_MODE_P (mode0))
1921	op0 = safe_vector_operand (op0, mode0);
1922
1923      if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
1924	op0 = copy_to_mode_reg (mode0, op0);
1925    }
1926  if (builtin_sha1h_p)
1927    op1 = GEN_INT (TARGET_BIG_END ? 1 : 0);
1928
1929  if (builtin_sha1h_p)
1930    pat = GEN_FCN (icode) (target, op0, op1);
1931  else
1932    pat = GEN_FCN (icode) (target, op0);
1933  if (! pat)
1934    return 0;
1935  emit_insn (pat);
1936  return target;
1937}
1938
1939typedef enum {
1940  NEON_ARG_COPY_TO_REG,
1941  NEON_ARG_CONSTANT,
1942  NEON_ARG_MEMORY,
1943  NEON_ARG_STOP
1944} builtin_arg;
1945
1946#define NEON_MAX_BUILTIN_ARGS 5
1947
1948/* EXP is a pointer argument to a Neon load or store intrinsic.  Derive
1949   and return an expression for the accessed memory.
1950
1951   The intrinsic function operates on a block of registers that has
1952   mode REG_MODE.  This block contains vectors of type TYPE_MODE.  The
1953   function references the memory at EXP of type TYPE and in mode
1954   MEM_MODE; this mode may be BLKmode if no more suitable mode is
1955   available.  */
1956
1957static tree
1958neon_dereference_pointer (tree exp, tree type, machine_mode mem_mode,
1959			  machine_mode reg_mode,
1960			  machine_mode vector_mode)
1961{
1962  HOST_WIDE_INT reg_size, vector_size, nvectors, nelems;
1963  tree elem_type, upper_bound, array_type;
1964
1965  /* Work out the size of the register block in bytes.  */
1966  reg_size = GET_MODE_SIZE (reg_mode);
1967
1968  /* Work out the size of each vector in bytes.  */
1969  vector_size = GET_MODE_SIZE (vector_mode);
1970
1971  /* Work out how many vectors there are.  */
1972  gcc_assert (reg_size % vector_size == 0);
1973  nvectors = reg_size / vector_size;
1974
1975  /* Work out the type of each element.  */
1976  gcc_assert (POINTER_TYPE_P (type));
1977  elem_type = TREE_TYPE (type);
1978
1979  /* Work out how many elements are being loaded or stored.
1980     MEM_MODE == REG_MODE implies a one-to-one mapping between register
1981     and memory elements; anything else implies a lane load or store.  */
1982  if (mem_mode == reg_mode)
1983    nelems = vector_size * nvectors / int_size_in_bytes (elem_type);
1984  else
1985    nelems = nvectors;
1986
1987  /* Create a type that describes the full access.  */
1988  upper_bound = build_int_cst (size_type_node, nelems - 1);
1989  array_type = build_array_type (elem_type, build_index_type (upper_bound));
1990
1991  /* Dereference EXP using that type.  */
1992  return fold_build2 (MEM_REF, array_type, exp,
1993		      build_int_cst (build_pointer_type (array_type), 0));
1994}
1995
1996/* Expand a Neon builtin.  */
1997static rtx
1998arm_expand_neon_args (rtx target, machine_mode map_mode, int fcode,
1999		      int icode, int have_retval, tree exp, ...)
2000{
2001  va_list ap;
2002  rtx pat;
2003  tree arg[SIMD_MAX_BUILTIN_ARGS];
2004  rtx op[SIMD_MAX_BUILTIN_ARGS];
2005  machine_mode tmode = insn_data[icode].operand[0].mode;
2006  machine_mode mode[SIMD_MAX_BUILTIN_ARGS];
2007  tree formals;
2008  int argc = 0;
2009
2010  if (have_retval
2011      && (!target
2012	  || GET_MODE (target) != tmode
2013	  || !(*insn_data[icode].operand[0].predicate) (target, tmode)))
2014    target = gen_reg_rtx (tmode);
2015
2016  va_start (ap, exp);
2017
2018  formals = TYPE_ARG_TYPES (TREE_TYPE (arm_builtin_decls[fcode]));
2019
2020  for (;;)
2021    {
2022      builtin_arg thisarg = (builtin_arg) va_arg (ap, int);
2023
2024      if (thisarg == NEON_ARG_STOP)
2025	break;
2026      else
2027	{
2028	  int opno = argc + have_retval;
2029	  arg[argc] = CALL_EXPR_ARG (exp, argc);
2030	  mode[argc] = insn_data[icode].operand[opno].mode;
2031          if (thisarg == NEON_ARG_MEMORY)
2032            {
2033              machine_mode other_mode
2034		= insn_data[icode].operand[1 - opno].mode;
2035              arg[argc] = neon_dereference_pointer (arg[argc],
2036						    TREE_VALUE (formals),
2037						    mode[argc], other_mode,
2038						    map_mode);
2039            }
2040
2041	  /* Use EXPAND_MEMORY for NEON_ARG_MEMORY to ensure a MEM_P
2042	     be returned.  */
2043	  op[argc] = expand_expr (arg[argc], NULL_RTX, VOIDmode,
2044				  (thisarg == NEON_ARG_MEMORY
2045				   ? EXPAND_MEMORY : EXPAND_NORMAL));
2046
2047	  switch (thisarg)
2048	    {
2049	    case NEON_ARG_COPY_TO_REG:
2050	      if (POINTER_TYPE_P (TREE_TYPE (arg[argc])))
2051		op[argc] = convert_memory_address (Pmode, op[argc]);
2052	      /*gcc_assert (GET_MODE (op[argc]) == mode[argc]); */
2053	      if (!(*insn_data[icode].operand[opno].predicate)
2054		  (op[argc], mode[argc]))
2055		op[argc] = copy_to_mode_reg (mode[argc], op[argc]);
2056	      break;
2057
2058	    case NEON_ARG_CONSTANT:
2059	      if (!(*insn_data[icode].operand[opno].predicate)
2060		  (op[argc], mode[argc]))
2061		error_at (EXPR_LOCATION (exp), "incompatible type for argument %d, "
2062		       "expected %<const int%>", argc + 1);
2063	      break;
2064            case NEON_ARG_MEMORY:
2065	      /* Check if expand failed.  */
2066	      if (op[argc] == const0_rtx)
2067	      {
2068		va_end (ap);
2069		return 0;
2070	      }
2071	      gcc_assert (MEM_P (op[argc]));
2072	      PUT_MODE (op[argc], mode[argc]);
2073	      /* ??? arm_neon.h uses the same built-in functions for signed
2074		 and unsigned accesses, casting where necessary.  This isn't
2075		 alias safe.  */
2076	      set_mem_alias_set (op[argc], 0);
2077	      if (!(*insn_data[icode].operand[opno].predicate)
2078                   (op[argc], mode[argc]))
2079		op[argc] = (replace_equiv_address
2080			    (op[argc],
2081			     copy_to_mode_reg (Pmode, XEXP (op[argc], 0))));
2082              break;
2083
2084	    case NEON_ARG_STOP:
2085	      gcc_unreachable ();
2086	    }
2087
2088	  argc++;
2089	}
2090    }
2091
2092  va_end (ap);
2093
2094  if (have_retval)
2095    switch (argc)
2096      {
2097      case 1:
2098	pat = GEN_FCN (icode) (target, op[0]);
2099	break;
2100
2101      case 2:
2102	pat = GEN_FCN (icode) (target, op[0], op[1]);
2103	break;
2104
2105      case 3:
2106	pat = GEN_FCN (icode) (target, op[0], op[1], op[2]);
2107	break;
2108
2109      case 4:
2110	pat = GEN_FCN (icode) (target, op[0], op[1], op[2], op[3]);
2111	break;
2112
2113      case 5:
2114	pat = GEN_FCN (icode) (target, op[0], op[1], op[2], op[3], op[4]);
2115	break;
2116
2117      default:
2118	gcc_unreachable ();
2119      }
2120  else
2121    switch (argc)
2122      {
2123      case 1:
2124	pat = GEN_FCN (icode) (op[0]);
2125	break;
2126
2127      case 2:
2128	pat = GEN_FCN (icode) (op[0], op[1]);
2129	break;
2130
2131      case 3:
2132	pat = GEN_FCN (icode) (op[0], op[1], op[2]);
2133	break;
2134
2135      case 4:
2136	pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
2137	break;
2138
2139      case 5:
2140	pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4]);
2141	break;
2142
2143      default:
2144	gcc_unreachable ();
2145      }
2146
2147  if (!pat)
2148    return 0;
2149
2150  emit_insn (pat);
2151
2152  return target;
2153}
2154
2155/* Expand a Neon builtin. These are "special" because they don't have symbolic
2156   constants defined per-instruction or per instruction-variant. Instead, the
2157   required info is looked up in the table neon_builtin_data.  */
2158static rtx
2159arm_expand_neon_builtin (int fcode, tree exp, rtx target)
2160{
2161  neon_builtin_datum *d =
2162		&neon_builtin_data[fcode - ARM_BUILTIN_NEON_BASE];
2163  enum insn_code icode = d->code;
2164  builtin_arg args[SIMD_MAX_BUILTIN_ARGS + 1];
2165  int num_args = insn_data[d->code].n_operands;
2166  int is_void = 0;
2167  int k;
2168
2169  is_void = !!(d->qualifiers[0] & qualifier_void);
2170
2171  num_args += is_void;
2172
2173  for (k = 1; k < num_args; k++)
2174    {
2175      /* We have four arrays of data, each indexed in a different fashion.
2176	 qualifiers - element 0 always describes the function return type.
2177	 operands - element 0 is either the operand for return value (if
2178	   the function has a non-void return type) or the operand for the
2179	   first argument.
2180	 expr_args - element 0 always holds the first argument.
2181	 args - element 0 is always used for the return type.  */
2182      int qualifiers_k = k;
2183      int operands_k = k - is_void;
2184      int expr_args_k = k - 1;
2185
2186      if (d->qualifiers[qualifiers_k] & qualifier_immediate)
2187	args[k] = NEON_ARG_CONSTANT;
2188      else if (d->qualifiers[qualifiers_k] & qualifier_maybe_immediate)
2189	{
2190	  rtx arg
2191	    = expand_normal (CALL_EXPR_ARG (exp,
2192					    (expr_args_k)));
2193	  /* Handle constants only if the predicate allows it.  */
2194	  bool op_const_int_p =
2195	    (CONST_INT_P (arg)
2196	     && (*insn_data[icode].operand[operands_k].predicate)
2197		(arg, insn_data[icode].operand[operands_k].mode));
2198	  args[k] = op_const_int_p ? NEON_ARG_CONSTANT : NEON_ARG_COPY_TO_REG;
2199	}
2200      else if (d->qualifiers[qualifiers_k] & qualifier_pointer)
2201	args[k] = NEON_ARG_MEMORY;
2202      else
2203	args[k] = NEON_ARG_COPY_TO_REG;
2204    }
2205  args[k] = NEON_ARG_STOP;
2206
2207  /* The interface to arm_expand_neon_args expects a 0 if
2208     the function is void, and a 1 if it is not.  */
2209  return arm_expand_neon_args
2210	  (target, d->mode, fcode, icode, !is_void, exp,
2211	   args[1],
2212	   args[2],
2213	   args[3],
2214	   args[4],
2215	   NEON_ARG_STOP);
2216}
2217
2218/* Expand an expression EXP that calls a built-in function,
2219   with result going to TARGET if that's convenient
2220   (and in mode MODE if that's convenient).
2221   SUBTARGET may be used as the target for computing one of EXP's operands.
2222   IGNORE is nonzero if the value is to be ignored.  */
2223
2224rtx
2225arm_expand_builtin (tree exp,
2226		    rtx target,
2227		    rtx subtarget ATTRIBUTE_UNUSED,
2228		    machine_mode mode ATTRIBUTE_UNUSED,
2229		    int ignore ATTRIBUTE_UNUSED)
2230{
2231  const struct builtin_description * d;
2232  enum insn_code    icode;
2233  tree              fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
2234  tree              arg0;
2235  tree              arg1;
2236  tree              arg2;
2237  rtx               op0;
2238  rtx               op1;
2239  rtx               op2;
2240  rtx               pat;
2241  unsigned int      fcode = DECL_FUNCTION_CODE (fndecl);
2242  size_t            i;
2243  machine_mode tmode;
2244  machine_mode mode0;
2245  machine_mode mode1;
2246  machine_mode mode2;
2247  int opint;
2248  int selector;
2249  int mask;
2250  int imm;
2251
2252  if (fcode >= ARM_BUILTIN_NEON_BASE)
2253    return arm_expand_neon_builtin (fcode, exp, target);
2254
2255  switch (fcode)
2256    {
2257    case ARM_BUILTIN_GET_FPSCR:
2258    case ARM_BUILTIN_SET_FPSCR:
2259      if (fcode == ARM_BUILTIN_GET_FPSCR)
2260	{
2261	  icode = CODE_FOR_get_fpscr;
2262	  target = gen_reg_rtx (SImode);
2263	  pat = GEN_FCN (icode) (target);
2264	}
2265      else
2266	{
2267	  target = NULL_RTX;
2268	  icode = CODE_FOR_set_fpscr;
2269	  arg0 = CALL_EXPR_ARG (exp, 0);
2270	  op0 = expand_normal (arg0);
2271	  pat = GEN_FCN (icode) (op0);
2272	}
2273      emit_insn (pat);
2274      return target;
2275
2276    case ARM_BUILTIN_TEXTRMSB:
2277    case ARM_BUILTIN_TEXTRMUB:
2278    case ARM_BUILTIN_TEXTRMSH:
2279    case ARM_BUILTIN_TEXTRMUH:
2280    case ARM_BUILTIN_TEXTRMSW:
2281    case ARM_BUILTIN_TEXTRMUW:
2282      icode = (fcode == ARM_BUILTIN_TEXTRMSB ? CODE_FOR_iwmmxt_textrmsb
2283	       : fcode == ARM_BUILTIN_TEXTRMUB ? CODE_FOR_iwmmxt_textrmub
2284	       : fcode == ARM_BUILTIN_TEXTRMSH ? CODE_FOR_iwmmxt_textrmsh
2285	       : fcode == ARM_BUILTIN_TEXTRMUH ? CODE_FOR_iwmmxt_textrmuh
2286	       : CODE_FOR_iwmmxt_textrmw);
2287
2288      arg0 = CALL_EXPR_ARG (exp, 0);
2289      arg1 = CALL_EXPR_ARG (exp, 1);
2290      op0 = expand_normal (arg0);
2291      op1 = expand_normal (arg1);
2292      tmode = insn_data[icode].operand[0].mode;
2293      mode0 = insn_data[icode].operand[1].mode;
2294      mode1 = insn_data[icode].operand[2].mode;
2295
2296      if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
2297	op0 = copy_to_mode_reg (mode0, op0);
2298      if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
2299	{
2300	  /* @@@ better error message */
2301	  error ("selector must be an immediate");
2302	  return gen_reg_rtx (tmode);
2303	}
2304
2305      opint = INTVAL (op1);
2306      if (fcode == ARM_BUILTIN_TEXTRMSB || fcode == ARM_BUILTIN_TEXTRMUB)
2307	{
2308	  if (opint > 7 || opint < 0)
2309	    error ("the range of selector should be in 0 to 7");
2310	}
2311      else if (fcode == ARM_BUILTIN_TEXTRMSH || fcode == ARM_BUILTIN_TEXTRMUH)
2312	{
2313	  if (opint > 3 || opint < 0)
2314	    error ("the range of selector should be in 0 to 3");
2315	}
2316      else /* ARM_BUILTIN_TEXTRMSW || ARM_BUILTIN_TEXTRMUW.  */
2317	{
2318	  if (opint > 1 || opint < 0)
2319	    error ("the range of selector should be in 0 to 1");
2320	}
2321
2322      if (target == 0
2323	  || GET_MODE (target) != tmode
2324	  || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
2325	target = gen_reg_rtx (tmode);
2326      pat = GEN_FCN (icode) (target, op0, op1);
2327      if (! pat)
2328	return 0;
2329      emit_insn (pat);
2330      return target;
2331
2332    case ARM_BUILTIN_WALIGNI:
2333      /* If op2 is immediate, call walighi, else call walighr.  */
2334      arg0 = CALL_EXPR_ARG (exp, 0);
2335      arg1 = CALL_EXPR_ARG (exp, 1);
2336      arg2 = CALL_EXPR_ARG (exp, 2);
2337      op0 = expand_normal (arg0);
2338      op1 = expand_normal (arg1);
2339      op2 = expand_normal (arg2);
2340      if (CONST_INT_P (op2))
2341        {
2342	  icode = CODE_FOR_iwmmxt_waligni;
2343          tmode = insn_data[icode].operand[0].mode;
2344	  mode0 = insn_data[icode].operand[1].mode;
2345	  mode1 = insn_data[icode].operand[2].mode;
2346	  mode2 = insn_data[icode].operand[3].mode;
2347          if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
2348	    op0 = copy_to_mode_reg (mode0, op0);
2349          if (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
2350	    op1 = copy_to_mode_reg (mode1, op1);
2351          gcc_assert ((*insn_data[icode].operand[3].predicate) (op2, mode2));
2352	  selector = INTVAL (op2);
2353	  if (selector > 7 || selector < 0)
2354	    error ("the range of selector should be in 0 to 7");
2355	}
2356      else
2357        {
2358	  icode = CODE_FOR_iwmmxt_walignr;
2359          tmode = insn_data[icode].operand[0].mode;
2360	  mode0 = insn_data[icode].operand[1].mode;
2361	  mode1 = insn_data[icode].operand[2].mode;
2362	  mode2 = insn_data[icode].operand[3].mode;
2363          if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
2364	    op0 = copy_to_mode_reg (mode0, op0);
2365          if (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
2366	    op1 = copy_to_mode_reg (mode1, op1);
2367          if (!(*insn_data[icode].operand[3].predicate) (op2, mode2))
2368	    op2 = copy_to_mode_reg (mode2, op2);
2369	}
2370      if (target == 0
2371	  || GET_MODE (target) != tmode
2372	  || !(*insn_data[icode].operand[0].predicate) (target, tmode))
2373	target = gen_reg_rtx (tmode);
2374      pat = GEN_FCN (icode) (target, op0, op1, op2);
2375      if (!pat)
2376	return 0;
2377      emit_insn (pat);
2378      return target;
2379
2380    case ARM_BUILTIN_TINSRB:
2381    case ARM_BUILTIN_TINSRH:
2382    case ARM_BUILTIN_TINSRW:
2383    case ARM_BUILTIN_WMERGE:
2384      icode = (fcode == ARM_BUILTIN_TINSRB ? CODE_FOR_iwmmxt_tinsrb
2385	       : fcode == ARM_BUILTIN_TINSRH ? CODE_FOR_iwmmxt_tinsrh
2386	       : fcode == ARM_BUILTIN_WMERGE ? CODE_FOR_iwmmxt_wmerge
2387	       : CODE_FOR_iwmmxt_tinsrw);
2388      arg0 = CALL_EXPR_ARG (exp, 0);
2389      arg1 = CALL_EXPR_ARG (exp, 1);
2390      arg2 = CALL_EXPR_ARG (exp, 2);
2391      op0 = expand_normal (arg0);
2392      op1 = expand_normal (arg1);
2393      op2 = expand_normal (arg2);
2394      tmode = insn_data[icode].operand[0].mode;
2395      mode0 = insn_data[icode].operand[1].mode;
2396      mode1 = insn_data[icode].operand[2].mode;
2397      mode2 = insn_data[icode].operand[3].mode;
2398
2399      if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
2400	op0 = copy_to_mode_reg (mode0, op0);
2401      if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
2402	op1 = copy_to_mode_reg (mode1, op1);
2403      if (! (*insn_data[icode].operand[3].predicate) (op2, mode2))
2404	{
2405	  error ("selector must be an immediate");
2406	  return const0_rtx;
2407	}
2408      if (icode == CODE_FOR_iwmmxt_wmerge)
2409	{
2410	  selector = INTVAL (op2);
2411	  if (selector > 7 || selector < 0)
2412	    error ("the range of selector should be in 0 to 7");
2413	}
2414      if ((icode == CODE_FOR_iwmmxt_tinsrb)
2415	  || (icode == CODE_FOR_iwmmxt_tinsrh)
2416	  || (icode == CODE_FOR_iwmmxt_tinsrw))
2417        {
2418	  mask = 0x01;
2419	  selector= INTVAL (op2);
2420	  if (icode == CODE_FOR_iwmmxt_tinsrb && (selector < 0 || selector > 7))
2421	    error ("the range of selector should be in 0 to 7");
2422	  else if (icode == CODE_FOR_iwmmxt_tinsrh && (selector < 0 ||selector > 3))
2423	    error ("the range of selector should be in 0 to 3");
2424	  else if (icode == CODE_FOR_iwmmxt_tinsrw && (selector < 0 ||selector > 1))
2425	    error ("the range of selector should be in 0 to 1");
2426	  mask <<= selector;
2427	  op2 = GEN_INT (mask);
2428	}
2429      if (target == 0
2430	  || GET_MODE (target) != tmode
2431	  || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
2432	target = gen_reg_rtx (tmode);
2433      pat = GEN_FCN (icode) (target, op0, op1, op2);
2434      if (! pat)
2435	return 0;
2436      emit_insn (pat);
2437      return target;
2438
2439    case ARM_BUILTIN_SETWCGR0:
2440    case ARM_BUILTIN_SETWCGR1:
2441    case ARM_BUILTIN_SETWCGR2:
2442    case ARM_BUILTIN_SETWCGR3:
2443      icode = (fcode == ARM_BUILTIN_SETWCGR0 ? CODE_FOR_iwmmxt_setwcgr0
2444	       : fcode == ARM_BUILTIN_SETWCGR1 ? CODE_FOR_iwmmxt_setwcgr1
2445	       : fcode == ARM_BUILTIN_SETWCGR2 ? CODE_FOR_iwmmxt_setwcgr2
2446	       : CODE_FOR_iwmmxt_setwcgr3);
2447      arg0 = CALL_EXPR_ARG (exp, 0);
2448      op0 = expand_normal (arg0);
2449      mode0 = insn_data[icode].operand[0].mode;
2450      if (!(*insn_data[icode].operand[0].predicate) (op0, mode0))
2451        op0 = copy_to_mode_reg (mode0, op0);
2452      pat = GEN_FCN (icode) (op0);
2453      if (!pat)
2454	return 0;
2455      emit_insn (pat);
2456      return 0;
2457
2458    case ARM_BUILTIN_GETWCGR0:
2459    case ARM_BUILTIN_GETWCGR1:
2460    case ARM_BUILTIN_GETWCGR2:
2461    case ARM_BUILTIN_GETWCGR3:
2462      icode = (fcode == ARM_BUILTIN_GETWCGR0 ? CODE_FOR_iwmmxt_getwcgr0
2463	       : fcode == ARM_BUILTIN_GETWCGR1 ? CODE_FOR_iwmmxt_getwcgr1
2464	       : fcode == ARM_BUILTIN_GETWCGR2 ? CODE_FOR_iwmmxt_getwcgr2
2465	       : CODE_FOR_iwmmxt_getwcgr3);
2466      tmode = insn_data[icode].operand[0].mode;
2467      if (target == 0
2468	  || GET_MODE (target) != tmode
2469	  || !(*insn_data[icode].operand[0].predicate) (target, tmode))
2470        target = gen_reg_rtx (tmode);
2471      pat = GEN_FCN (icode) (target);
2472      if (!pat)
2473        return 0;
2474      emit_insn (pat);
2475      return target;
2476
2477    case ARM_BUILTIN_WSHUFH:
2478      icode = CODE_FOR_iwmmxt_wshufh;
2479      arg0 = CALL_EXPR_ARG (exp, 0);
2480      arg1 = CALL_EXPR_ARG (exp, 1);
2481      op0 = expand_normal (arg0);
2482      op1 = expand_normal (arg1);
2483      tmode = insn_data[icode].operand[0].mode;
2484      mode1 = insn_data[icode].operand[1].mode;
2485      mode2 = insn_data[icode].operand[2].mode;
2486
2487      if (! (*insn_data[icode].operand[1].predicate) (op0, mode1))
2488	op0 = copy_to_mode_reg (mode1, op0);
2489      if (! (*insn_data[icode].operand[2].predicate) (op1, mode2))
2490	{
2491	  error ("mask must be an immediate");
2492	  return const0_rtx;
2493	}
2494      selector = INTVAL (op1);
2495      if (selector < 0 || selector > 255)
2496	error ("the range of mask should be in 0 to 255");
2497      if (target == 0
2498	  || GET_MODE (target) != tmode
2499	  || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
2500	target = gen_reg_rtx (tmode);
2501      pat = GEN_FCN (icode) (target, op0, op1);
2502      if (! pat)
2503	return 0;
2504      emit_insn (pat);
2505      return target;
2506
2507    case ARM_BUILTIN_WMADDS:
2508      return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wmadds, exp, target);
2509    case ARM_BUILTIN_WMADDSX:
2510      return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wmaddsx, exp, target);
2511    case ARM_BUILTIN_WMADDSN:
2512      return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wmaddsn, exp, target);
2513    case ARM_BUILTIN_WMADDU:
2514      return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wmaddu, exp, target);
2515    case ARM_BUILTIN_WMADDUX:
2516      return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wmaddux, exp, target);
2517    case ARM_BUILTIN_WMADDUN:
2518      return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wmaddun, exp, target);
2519    case ARM_BUILTIN_WSADBZ:
2520      return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wsadbz, exp, target);
2521    case ARM_BUILTIN_WSADHZ:
2522      return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wsadhz, exp, target);
2523
2524      /* Several three-argument builtins.  */
2525    case ARM_BUILTIN_WMACS:
2526    case ARM_BUILTIN_WMACU:
2527    case ARM_BUILTIN_TMIA:
2528    case ARM_BUILTIN_TMIAPH:
2529    case ARM_BUILTIN_TMIATT:
2530    case ARM_BUILTIN_TMIATB:
2531    case ARM_BUILTIN_TMIABT:
2532    case ARM_BUILTIN_TMIABB:
2533    case ARM_BUILTIN_WQMIABB:
2534    case ARM_BUILTIN_WQMIABT:
2535    case ARM_BUILTIN_WQMIATB:
2536    case ARM_BUILTIN_WQMIATT:
2537    case ARM_BUILTIN_WQMIABBN:
2538    case ARM_BUILTIN_WQMIABTN:
2539    case ARM_BUILTIN_WQMIATBN:
2540    case ARM_BUILTIN_WQMIATTN:
2541    case ARM_BUILTIN_WMIABB:
2542    case ARM_BUILTIN_WMIABT:
2543    case ARM_BUILTIN_WMIATB:
2544    case ARM_BUILTIN_WMIATT:
2545    case ARM_BUILTIN_WMIABBN:
2546    case ARM_BUILTIN_WMIABTN:
2547    case ARM_BUILTIN_WMIATBN:
2548    case ARM_BUILTIN_WMIATTN:
2549    case ARM_BUILTIN_WMIAWBB:
2550    case ARM_BUILTIN_WMIAWBT:
2551    case ARM_BUILTIN_WMIAWTB:
2552    case ARM_BUILTIN_WMIAWTT:
2553    case ARM_BUILTIN_WMIAWBBN:
2554    case ARM_BUILTIN_WMIAWBTN:
2555    case ARM_BUILTIN_WMIAWTBN:
2556    case ARM_BUILTIN_WMIAWTTN:
2557    case ARM_BUILTIN_WSADB:
2558    case ARM_BUILTIN_WSADH:
2559      icode = (fcode == ARM_BUILTIN_WMACS ? CODE_FOR_iwmmxt_wmacs
2560	       : fcode == ARM_BUILTIN_WMACU ? CODE_FOR_iwmmxt_wmacu
2561	       : fcode == ARM_BUILTIN_TMIA ? CODE_FOR_iwmmxt_tmia
2562	       : fcode == ARM_BUILTIN_TMIAPH ? CODE_FOR_iwmmxt_tmiaph
2563	       : fcode == ARM_BUILTIN_TMIABB ? CODE_FOR_iwmmxt_tmiabb
2564	       : fcode == ARM_BUILTIN_TMIABT ? CODE_FOR_iwmmxt_tmiabt
2565	       : fcode == ARM_BUILTIN_TMIATB ? CODE_FOR_iwmmxt_tmiatb
2566	       : fcode == ARM_BUILTIN_TMIATT ? CODE_FOR_iwmmxt_tmiatt
2567	       : fcode == ARM_BUILTIN_WQMIABB ? CODE_FOR_iwmmxt_wqmiabb
2568	       : fcode == ARM_BUILTIN_WQMIABT ? CODE_FOR_iwmmxt_wqmiabt
2569	       : fcode == ARM_BUILTIN_WQMIATB ? CODE_FOR_iwmmxt_wqmiatb
2570	       : fcode == ARM_BUILTIN_WQMIATT ? CODE_FOR_iwmmxt_wqmiatt
2571	       : fcode == ARM_BUILTIN_WQMIABBN ? CODE_FOR_iwmmxt_wqmiabbn
2572	       : fcode == ARM_BUILTIN_WQMIABTN ? CODE_FOR_iwmmxt_wqmiabtn
2573	       : fcode == ARM_BUILTIN_WQMIATBN ? CODE_FOR_iwmmxt_wqmiatbn
2574	       : fcode == ARM_BUILTIN_WQMIATTN ? CODE_FOR_iwmmxt_wqmiattn
2575	       : fcode == ARM_BUILTIN_WMIABB ? CODE_FOR_iwmmxt_wmiabb
2576	       : fcode == ARM_BUILTIN_WMIABT ? CODE_FOR_iwmmxt_wmiabt
2577	       : fcode == ARM_BUILTIN_WMIATB ? CODE_FOR_iwmmxt_wmiatb
2578	       : fcode == ARM_BUILTIN_WMIATT ? CODE_FOR_iwmmxt_wmiatt
2579	       : fcode == ARM_BUILTIN_WMIABBN ? CODE_FOR_iwmmxt_wmiabbn
2580	       : fcode == ARM_BUILTIN_WMIABTN ? CODE_FOR_iwmmxt_wmiabtn
2581	       : fcode == ARM_BUILTIN_WMIATBN ? CODE_FOR_iwmmxt_wmiatbn
2582	       : fcode == ARM_BUILTIN_WMIATTN ? CODE_FOR_iwmmxt_wmiattn
2583	       : fcode == ARM_BUILTIN_WMIAWBB ? CODE_FOR_iwmmxt_wmiawbb
2584	       : fcode == ARM_BUILTIN_WMIAWBT ? CODE_FOR_iwmmxt_wmiawbt
2585	       : fcode == ARM_BUILTIN_WMIAWTB ? CODE_FOR_iwmmxt_wmiawtb
2586	       : fcode == ARM_BUILTIN_WMIAWTT ? CODE_FOR_iwmmxt_wmiawtt
2587	       : fcode == ARM_BUILTIN_WMIAWBBN ? CODE_FOR_iwmmxt_wmiawbbn
2588	       : fcode == ARM_BUILTIN_WMIAWBTN ? CODE_FOR_iwmmxt_wmiawbtn
2589	       : fcode == ARM_BUILTIN_WMIAWTBN ? CODE_FOR_iwmmxt_wmiawtbn
2590	       : fcode == ARM_BUILTIN_WMIAWTTN ? CODE_FOR_iwmmxt_wmiawttn
2591	       : fcode == ARM_BUILTIN_WSADB ? CODE_FOR_iwmmxt_wsadb
2592	       : CODE_FOR_iwmmxt_wsadh);
2593      arg0 = CALL_EXPR_ARG (exp, 0);
2594      arg1 = CALL_EXPR_ARG (exp, 1);
2595      arg2 = CALL_EXPR_ARG (exp, 2);
2596      op0 = expand_normal (arg0);
2597      op1 = expand_normal (arg1);
2598      op2 = expand_normal (arg2);
2599      tmode = insn_data[icode].operand[0].mode;
2600      mode0 = insn_data[icode].operand[1].mode;
2601      mode1 = insn_data[icode].operand[2].mode;
2602      mode2 = insn_data[icode].operand[3].mode;
2603
2604      if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
2605	op0 = copy_to_mode_reg (mode0, op0);
2606      if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
2607	op1 = copy_to_mode_reg (mode1, op1);
2608      if (! (*insn_data[icode].operand[3].predicate) (op2, mode2))
2609	op2 = copy_to_mode_reg (mode2, op2);
2610      if (target == 0
2611	  || GET_MODE (target) != tmode
2612	  || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
2613	target = gen_reg_rtx (tmode);
2614      pat = GEN_FCN (icode) (target, op0, op1, op2);
2615      if (! pat)
2616	return 0;
2617      emit_insn (pat);
2618      return target;
2619
2620    case ARM_BUILTIN_WZERO:
2621      target = gen_reg_rtx (DImode);
2622      emit_insn (gen_iwmmxt_clrdi (target));
2623      return target;
2624
2625    case ARM_BUILTIN_WSRLHI:
2626    case ARM_BUILTIN_WSRLWI:
2627    case ARM_BUILTIN_WSRLDI:
2628    case ARM_BUILTIN_WSLLHI:
2629    case ARM_BUILTIN_WSLLWI:
2630    case ARM_BUILTIN_WSLLDI:
2631    case ARM_BUILTIN_WSRAHI:
2632    case ARM_BUILTIN_WSRAWI:
2633    case ARM_BUILTIN_WSRADI:
2634    case ARM_BUILTIN_WRORHI:
2635    case ARM_BUILTIN_WRORWI:
2636    case ARM_BUILTIN_WRORDI:
2637    case ARM_BUILTIN_WSRLH:
2638    case ARM_BUILTIN_WSRLW:
2639    case ARM_BUILTIN_WSRLD:
2640    case ARM_BUILTIN_WSLLH:
2641    case ARM_BUILTIN_WSLLW:
2642    case ARM_BUILTIN_WSLLD:
2643    case ARM_BUILTIN_WSRAH:
2644    case ARM_BUILTIN_WSRAW:
2645    case ARM_BUILTIN_WSRAD:
2646    case ARM_BUILTIN_WRORH:
2647    case ARM_BUILTIN_WRORW:
2648    case ARM_BUILTIN_WRORD:
2649      icode = (fcode == ARM_BUILTIN_WSRLHI ? CODE_FOR_lshrv4hi3_iwmmxt
2650	       : fcode == ARM_BUILTIN_WSRLWI ? CODE_FOR_lshrv2si3_iwmmxt
2651	       : fcode == ARM_BUILTIN_WSRLDI ? CODE_FOR_lshrdi3_iwmmxt
2652	       : fcode == ARM_BUILTIN_WSLLHI ? CODE_FOR_ashlv4hi3_iwmmxt
2653	       : fcode == ARM_BUILTIN_WSLLWI ? CODE_FOR_ashlv2si3_iwmmxt
2654	       : fcode == ARM_BUILTIN_WSLLDI ? CODE_FOR_ashldi3_iwmmxt
2655	       : fcode == ARM_BUILTIN_WSRAHI ? CODE_FOR_ashrv4hi3_iwmmxt
2656	       : fcode == ARM_BUILTIN_WSRAWI ? CODE_FOR_ashrv2si3_iwmmxt
2657	       : fcode == ARM_BUILTIN_WSRADI ? CODE_FOR_ashrdi3_iwmmxt
2658	       : fcode == ARM_BUILTIN_WRORHI ? CODE_FOR_rorv4hi3
2659	       : fcode == ARM_BUILTIN_WRORWI ? CODE_FOR_rorv2si3
2660	       : fcode == ARM_BUILTIN_WRORDI ? CODE_FOR_rordi3
2661	       : fcode == ARM_BUILTIN_WSRLH  ? CODE_FOR_lshrv4hi3_di
2662	       : fcode == ARM_BUILTIN_WSRLW  ? CODE_FOR_lshrv2si3_di
2663	       : fcode == ARM_BUILTIN_WSRLD  ? CODE_FOR_lshrdi3_di
2664	       : fcode == ARM_BUILTIN_WSLLH  ? CODE_FOR_ashlv4hi3_di
2665	       : fcode == ARM_BUILTIN_WSLLW  ? CODE_FOR_ashlv2si3_di
2666	       : fcode == ARM_BUILTIN_WSLLD  ? CODE_FOR_ashldi3_di
2667	       : fcode == ARM_BUILTIN_WSRAH  ? CODE_FOR_ashrv4hi3_di
2668	       : fcode == ARM_BUILTIN_WSRAW  ? CODE_FOR_ashrv2si3_di
2669	       : fcode == ARM_BUILTIN_WSRAD  ? CODE_FOR_ashrdi3_di
2670	       : fcode == ARM_BUILTIN_WRORH  ? CODE_FOR_rorv4hi3_di
2671	       : fcode == ARM_BUILTIN_WRORW  ? CODE_FOR_rorv2si3_di
2672	       : fcode == ARM_BUILTIN_WRORD  ? CODE_FOR_rordi3_di
2673	       : CODE_FOR_nothing);
2674      arg1 = CALL_EXPR_ARG (exp, 1);
2675      op1 = expand_normal (arg1);
2676      if (GET_MODE (op1) == VOIDmode)
2677	{
2678	  imm = INTVAL (op1);
2679	  if ((fcode == ARM_BUILTIN_WRORHI || fcode == ARM_BUILTIN_WRORWI
2680	       || fcode == ARM_BUILTIN_WRORH || fcode == ARM_BUILTIN_WRORW)
2681	      && (imm < 0 || imm > 32))
2682	    {
2683	      if (fcode == ARM_BUILTIN_WRORHI)
2684		error ("the range of count should be in 0 to 32.  please check the intrinsic _mm_rori_pi16 in code.");
2685	      else if (fcode == ARM_BUILTIN_WRORWI)
2686		error ("the range of count should be in 0 to 32.  please check the intrinsic _mm_rori_pi32 in code.");
2687	      else if (fcode == ARM_BUILTIN_WRORH)
2688		error ("the range of count should be in 0 to 32.  please check the intrinsic _mm_ror_pi16 in code.");
2689	      else
2690		error ("the range of count should be in 0 to 32.  please check the intrinsic _mm_ror_pi32 in code.");
2691	    }
2692	  else if ((fcode == ARM_BUILTIN_WRORDI || fcode == ARM_BUILTIN_WRORD)
2693		   && (imm < 0 || imm > 64))
2694	    {
2695	      if (fcode == ARM_BUILTIN_WRORDI)
2696		error ("the range of count should be in 0 to 64.  please check the intrinsic _mm_rori_si64 in code.");
2697	      else
2698		error ("the range of count should be in 0 to 64.  please check the intrinsic _mm_ror_si64 in code.");
2699	    }
2700	  else if (imm < 0)
2701	    {
2702	      if (fcode == ARM_BUILTIN_WSRLHI)
2703		error ("the count should be no less than 0.  please check the intrinsic _mm_srli_pi16 in code.");
2704	      else if (fcode == ARM_BUILTIN_WSRLWI)
2705		error ("the count should be no less than 0.  please check the intrinsic _mm_srli_pi32 in code.");
2706	      else if (fcode == ARM_BUILTIN_WSRLDI)
2707		error ("the count should be no less than 0.  please check the intrinsic _mm_srli_si64 in code.");
2708	      else if (fcode == ARM_BUILTIN_WSLLHI)
2709		error ("the count should be no less than 0.  please check the intrinsic _mm_slli_pi16 in code.");
2710	      else if (fcode == ARM_BUILTIN_WSLLWI)
2711		error ("the count should be no less than 0.  please check the intrinsic _mm_slli_pi32 in code.");
2712	      else if (fcode == ARM_BUILTIN_WSLLDI)
2713		error ("the count should be no less than 0.  please check the intrinsic _mm_slli_si64 in code.");
2714	      else if (fcode == ARM_BUILTIN_WSRAHI)
2715		error ("the count should be no less than 0.  please check the intrinsic _mm_srai_pi16 in code.");
2716	      else if (fcode == ARM_BUILTIN_WSRAWI)
2717		error ("the count should be no less than 0.  please check the intrinsic _mm_srai_pi32 in code.");
2718	      else if (fcode == ARM_BUILTIN_WSRADI)
2719		error ("the count should be no less than 0.  please check the intrinsic _mm_srai_si64 in code.");
2720	      else if (fcode == ARM_BUILTIN_WSRLH)
2721		error ("the count should be no less than 0.  please check the intrinsic _mm_srl_pi16 in code.");
2722	      else if (fcode == ARM_BUILTIN_WSRLW)
2723		error ("the count should be no less than 0.  please check the intrinsic _mm_srl_pi32 in code.");
2724	      else if (fcode == ARM_BUILTIN_WSRLD)
2725		error ("the count should be no less than 0.  please check the intrinsic _mm_srl_si64 in code.");
2726	      else if (fcode == ARM_BUILTIN_WSLLH)
2727		error ("the count should be no less than 0.  please check the intrinsic _mm_sll_pi16 in code.");
2728	      else if (fcode == ARM_BUILTIN_WSLLW)
2729		error ("the count should be no less than 0.  please check the intrinsic _mm_sll_pi32 in code.");
2730	      else if (fcode == ARM_BUILTIN_WSLLD)
2731		error ("the count should be no less than 0.  please check the intrinsic _mm_sll_si64 in code.");
2732	      else if (fcode == ARM_BUILTIN_WSRAH)
2733		error ("the count should be no less than 0.  please check the intrinsic _mm_sra_pi16 in code.");
2734	      else if (fcode == ARM_BUILTIN_WSRAW)
2735		error ("the count should be no less than 0.  please check the intrinsic _mm_sra_pi32 in code.");
2736	      else
2737		error ("the count should be no less than 0.  please check the intrinsic _mm_sra_si64 in code.");
2738	    }
2739	}
2740      return arm_expand_binop_builtin (icode, exp, target);
2741
2742    default:
2743      break;
2744    }
2745
2746  for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
2747    if (d->code == (const enum arm_builtins) fcode)
2748      return arm_expand_binop_builtin (d->icode, exp, target);
2749
2750  for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
2751    if (d->code == (const enum arm_builtins) fcode)
2752      return arm_expand_unop_builtin (d->icode, exp, target, 0);
2753
2754  for (i = 0, d = bdesc_3arg; i < ARRAY_SIZE (bdesc_3arg); i++, d++)
2755    if (d->code == (const enum arm_builtins) fcode)
2756      return arm_expand_ternop_builtin (d->icode, exp, target);
2757
2758  /* @@@ Should really do something sensible here.  */
2759  return NULL_RTX;
2760}
2761
2762tree
2763arm_builtin_vectorized_function (tree fndecl, tree type_out, tree type_in)
2764{
2765  machine_mode in_mode, out_mode;
2766  int in_n, out_n;
2767  bool out_unsigned_p = TYPE_UNSIGNED (type_out);
2768
2769  if (TREE_CODE (type_out) != VECTOR_TYPE
2770      || TREE_CODE (type_in) != VECTOR_TYPE)
2771    return NULL_TREE;
2772
2773  out_mode = TYPE_MODE (TREE_TYPE (type_out));
2774  out_n = TYPE_VECTOR_SUBPARTS (type_out);
2775  in_mode = TYPE_MODE (TREE_TYPE (type_in));
2776  in_n = TYPE_VECTOR_SUBPARTS (type_in);
2777
2778/* ARM_CHECK_BUILTIN_MODE and ARM_FIND_VRINT_VARIANT are used to find the
2779   decl of the vectorized builtin for the appropriate vector mode.
2780   NULL_TREE is returned if no such builtin is available.  */
2781#undef ARM_CHECK_BUILTIN_MODE
2782#define ARM_CHECK_BUILTIN_MODE(C)    \
2783  (TARGET_NEON && TARGET_FPU_ARMV8   \
2784   && flag_unsafe_math_optimizations \
2785   && ARM_CHECK_BUILTIN_MODE_1 (C))
2786
2787#undef ARM_CHECK_BUILTIN_MODE_1
2788#define ARM_CHECK_BUILTIN_MODE_1(C) \
2789  (out_mode == SFmode && out_n == C \
2790   && in_mode == SFmode && in_n == C)
2791
2792#undef ARM_FIND_VRINT_VARIANT
2793#define ARM_FIND_VRINT_VARIANT(N) \
2794  (ARM_CHECK_BUILTIN_MODE (2) \
2795    ? arm_builtin_decl(ARM_BUILTIN_NEON_##N##v2sf, false) \
2796    : (ARM_CHECK_BUILTIN_MODE (4) \
2797      ? arm_builtin_decl(ARM_BUILTIN_NEON_##N##v4sf, false) \
2798      : NULL_TREE))
2799
2800  if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
2801    {
2802      enum built_in_function fn = DECL_FUNCTION_CODE (fndecl);
2803      switch (fn)
2804        {
2805          case BUILT_IN_FLOORF:
2806            return ARM_FIND_VRINT_VARIANT (vrintm);
2807          case BUILT_IN_CEILF:
2808            return ARM_FIND_VRINT_VARIANT (vrintp);
2809          case BUILT_IN_TRUNCF:
2810            return ARM_FIND_VRINT_VARIANT (vrintz);
2811          case BUILT_IN_ROUNDF:
2812            return ARM_FIND_VRINT_VARIANT (vrinta);
2813#undef ARM_CHECK_BUILTIN_MODE_1
2814#define ARM_CHECK_BUILTIN_MODE_1(C) \
2815  (out_mode == SImode && out_n == C \
2816   && in_mode == SFmode && in_n == C)
2817
2818#define ARM_FIND_VCVT_VARIANT(N) \
2819  (ARM_CHECK_BUILTIN_MODE (2) \
2820   ? arm_builtin_decl(ARM_BUILTIN_NEON_##N##v2sfv2si, false) \
2821   : (ARM_CHECK_BUILTIN_MODE (4) \
2822     ? arm_builtin_decl(ARM_BUILTIN_NEON_##N##v4sfv4si, false) \
2823     : NULL_TREE))
2824
2825#define ARM_FIND_VCVTU_VARIANT(N) \
2826  (ARM_CHECK_BUILTIN_MODE (2) \
2827   ? arm_builtin_decl(ARM_BUILTIN_NEON_##N##uv2sfv2si, false) \
2828   : (ARM_CHECK_BUILTIN_MODE (4) \
2829     ? arm_builtin_decl(ARM_BUILTIN_NEON_##N##uv4sfv4si, false) \
2830     : NULL_TREE))
2831          case BUILT_IN_LROUNDF:
2832            return out_unsigned_p
2833                     ? ARM_FIND_VCVTU_VARIANT (vcvta)
2834                     : ARM_FIND_VCVT_VARIANT (vcvta);
2835          case BUILT_IN_LCEILF:
2836            return out_unsigned_p
2837                     ? ARM_FIND_VCVTU_VARIANT (vcvtp)
2838                     : ARM_FIND_VCVT_VARIANT (vcvtp);
2839          case BUILT_IN_LFLOORF:
2840            return out_unsigned_p
2841                     ? ARM_FIND_VCVTU_VARIANT (vcvtm)
2842                     : ARM_FIND_VCVT_VARIANT (vcvtm);
2843#undef ARM_CHECK_BUILTIN_MODE
2844#define ARM_CHECK_BUILTIN_MODE(C, N) \
2845  (out_mode == N##mode && out_n == C \
2846   && in_mode == N##mode && in_n == C)
2847          case BUILT_IN_BSWAP16:
2848            if (ARM_CHECK_BUILTIN_MODE (4, HI))
2849              return arm_builtin_decl (ARM_BUILTIN_NEON_bswapv4hi, false);
2850            else if (ARM_CHECK_BUILTIN_MODE (8, HI))
2851              return arm_builtin_decl (ARM_BUILTIN_NEON_bswapv8hi, false);
2852            else
2853              return NULL_TREE;
2854          case BUILT_IN_BSWAP32:
2855            if (ARM_CHECK_BUILTIN_MODE (2, SI))
2856              return arm_builtin_decl (ARM_BUILTIN_NEON_bswapv2si, false);
2857            else if (ARM_CHECK_BUILTIN_MODE (4, SI))
2858              return arm_builtin_decl (ARM_BUILTIN_NEON_bswapv4si, false);
2859            else
2860              return NULL_TREE;
2861          case BUILT_IN_BSWAP64:
2862            if (ARM_CHECK_BUILTIN_MODE (2, DI))
2863              return arm_builtin_decl (ARM_BUILTIN_NEON_bswapv2di, false);
2864            else
2865              return NULL_TREE;
2866	  case BUILT_IN_COPYSIGNF:
2867	    if (ARM_CHECK_BUILTIN_MODE (2, SF))
2868              return arm_builtin_decl (ARM_BUILTIN_NEON_copysignfv2sf, false);
2869	    else if (ARM_CHECK_BUILTIN_MODE (4, SF))
2870              return arm_builtin_decl (ARM_BUILTIN_NEON_copysignfv4sf, false);
2871	    else
2872	      return NULL_TREE;
2873
2874          default:
2875            return NULL_TREE;
2876        }
2877    }
2878  return NULL_TREE;
2879}
2880#undef ARM_FIND_VCVT_VARIANT
2881#undef ARM_FIND_VCVTU_VARIANT
2882#undef ARM_CHECK_BUILTIN_MODE
2883#undef ARM_FIND_VRINT_VARIANT
2884
2885void
2886arm_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
2887{
2888  const unsigned ARM_FE_INVALID = 1;
2889  const unsigned ARM_FE_DIVBYZERO = 2;
2890  const unsigned ARM_FE_OVERFLOW = 4;
2891  const unsigned ARM_FE_UNDERFLOW = 8;
2892  const unsigned ARM_FE_INEXACT = 16;
2893  const unsigned HOST_WIDE_INT ARM_FE_ALL_EXCEPT = (ARM_FE_INVALID
2894						    | ARM_FE_DIVBYZERO
2895						    | ARM_FE_OVERFLOW
2896						    | ARM_FE_UNDERFLOW
2897						    | ARM_FE_INEXACT);
2898  const unsigned HOST_WIDE_INT ARM_FE_EXCEPT_SHIFT = 8;
2899  tree fenv_var, get_fpscr, set_fpscr, mask, ld_fenv, masked_fenv;
2900  tree new_fenv_var, reload_fenv, restore_fnenv;
2901  tree update_call, atomic_feraiseexcept, hold_fnclex;
2902
2903  if (!TARGET_VFP || !TARGET_HARD_FLOAT)
2904    return;
2905
2906  /* Generate the equivalent of :
2907       unsigned int fenv_var;
2908       fenv_var = __builtin_arm_get_fpscr ();
2909
2910       unsigned int masked_fenv;
2911       masked_fenv = fenv_var & mask;
2912
2913       __builtin_arm_set_fpscr (masked_fenv);  */
2914
2915  fenv_var = create_tmp_var (unsigned_type_node);
2916  get_fpscr = arm_builtin_decls[ARM_BUILTIN_GET_FPSCR];
2917  set_fpscr = arm_builtin_decls[ARM_BUILTIN_SET_FPSCR];
2918  mask = build_int_cst (unsigned_type_node,
2919			~((ARM_FE_ALL_EXCEPT << ARM_FE_EXCEPT_SHIFT)
2920			  | ARM_FE_ALL_EXCEPT));
2921  ld_fenv = build2 (MODIFY_EXPR, unsigned_type_node,
2922		    fenv_var, build_call_expr (get_fpscr, 0));
2923  masked_fenv = build2 (BIT_AND_EXPR, unsigned_type_node, fenv_var, mask);
2924  hold_fnclex = build_call_expr (set_fpscr, 1, masked_fenv);
2925  *hold = build2 (COMPOUND_EXPR, void_type_node,
2926		  build2 (COMPOUND_EXPR, void_type_node, masked_fenv, ld_fenv),
2927		  hold_fnclex);
2928
2929  /* Store the value of masked_fenv to clear the exceptions:
2930     __builtin_arm_set_fpscr (masked_fenv);  */
2931
2932  *clear = build_call_expr (set_fpscr, 1, masked_fenv);
2933
2934  /* Generate the equivalent of :
2935       unsigned int new_fenv_var;
2936       new_fenv_var = __builtin_arm_get_fpscr ();
2937
2938       __builtin_arm_set_fpscr (fenv_var);
2939
2940       __atomic_feraiseexcept (new_fenv_var);  */
2941
2942  new_fenv_var = create_tmp_var (unsigned_type_node);
2943  reload_fenv = build2 (MODIFY_EXPR, unsigned_type_node, new_fenv_var,
2944			build_call_expr (get_fpscr, 0));
2945  restore_fnenv = build_call_expr (set_fpscr, 1, fenv_var);
2946  atomic_feraiseexcept = builtin_decl_implicit (BUILT_IN_ATOMIC_FERAISEEXCEPT);
2947  update_call = build_call_expr (atomic_feraiseexcept, 1,
2948				 fold_convert (integer_type_node, new_fenv_var));
2949  *update = build2 (COMPOUND_EXPR, void_type_node,
2950		    build2 (COMPOUND_EXPR, void_type_node,
2951			    reload_fenv, restore_fnenv), update_call);
2952}
2953
2954#include "gt-arm-builtins.h"
2955