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