111
|
1 /* Common hooks for AArch64.
|
131
|
2 Copyright (C) 2012-2018 Free Software Foundation, Inc.
|
111
|
3 Contributed by ARM Ltd.
|
|
4
|
|
5 This file is part of GCC.
|
|
6
|
|
7 GCC is free software; you can redistribute it and/or modify it
|
|
8 under the terms of the GNU General Public License as published
|
|
9 by the Free Software Foundation; either version 3, or (at your
|
|
10 option) any later version.
|
|
11
|
|
12 GCC is distributed in the hope that it will be useful, but WITHOUT
|
|
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
15 License for more details.
|
|
16
|
|
17 You should have received a copy of the GNU General Public License
|
|
18 along with GCC; see the file COPYING3. If not see
|
|
19 <http://www.gnu.org/licenses/>. */
|
|
20
|
|
21 #include "config.h"
|
|
22 #define INCLUDE_STRING
|
|
23 #include "system.h"
|
|
24 #include "coretypes.h"
|
|
25 #include "tm.h"
|
|
26 #include "memmodel.h"
|
|
27 #include "tm_p.h"
|
|
28 #include "common/common-target.h"
|
|
29 #include "common/common-target-def.h"
|
|
30 #include "opts.h"
|
|
31 #include "flags.h"
|
|
32 #include "diagnostic.h"
|
131
|
33 #include "params.h"
|
111
|
34
|
|
35 #ifdef TARGET_BIG_ENDIAN_DEFAULT
|
|
36 #undef TARGET_DEFAULT_TARGET_FLAGS
|
|
37 #define TARGET_DEFAULT_TARGET_FLAGS (MASK_BIG_END)
|
|
38 #endif
|
|
39
|
|
40 #undef TARGET_HANDLE_OPTION
|
|
41 #define TARGET_HANDLE_OPTION aarch64_handle_option
|
|
42
|
|
43 #undef TARGET_OPTION_OPTIMIZATION_TABLE
|
|
44 #define TARGET_OPTION_OPTIMIZATION_TABLE aarch_option_optimization_table
|
131
|
45 #undef TARGET_OPTION_DEFAULT_PARAMS
|
|
46 #define TARGET_OPTION_DEFAULT_PARAMS aarch64_option_default_params
|
|
47 #undef TARGET_OPTION_VALIDATE_PARAM
|
|
48 #define TARGET_OPTION_VALIDATE_PARAM aarch64_option_validate_param
|
111
|
49
|
|
50 /* Set default optimization options. */
|
|
51 static const struct default_options aarch_option_optimization_table[] =
|
|
52 {
|
|
53 /* Enable section anchors by default at -O1 or higher. */
|
|
54 { OPT_LEVELS_1_PLUS, OPT_fsection_anchors, NULL, 1 },
|
131
|
55 /* Disable fomit-frame-pointer by default. */
|
|
56 { OPT_LEVELS_ALL, OPT_fomit_frame_pointer, NULL, 0 },
|
111
|
57 /* Enable -fsched-pressure by default when optimizing. */
|
|
58 { OPT_LEVELS_1_PLUS, OPT_fsched_pressure, NULL, 1 },
|
|
59 /* Enable redundant extension instructions removal at -O2 and higher. */
|
|
60 { OPT_LEVELS_2_PLUS, OPT_free, NULL, 1 },
|
131
|
61 #if (TARGET_DEFAULT_ASYNC_UNWIND_TABLES == 1)
|
|
62 { OPT_LEVELS_ALL, OPT_fasynchronous_unwind_tables, NULL, 1 },
|
|
63 { OPT_LEVELS_ALL, OPT_funwind_tables, NULL, 1},
|
|
64 #endif
|
111
|
65 { OPT_LEVELS_NONE, 0, NULL, 0 }
|
|
66 };
|
|
67
|
131
|
68 /* Implement target validation TARGET_OPTION_DEFAULT_PARAM. */
|
|
69
|
|
70 static bool
|
|
71 aarch64_option_validate_param (const int value, const int param)
|
|
72 {
|
|
73 /* Check that both parameters are the same. */
|
|
74 if (param == (int) PARAM_STACK_CLASH_PROTECTION_GUARD_SIZE)
|
|
75 {
|
|
76 if (value != 12 && value != 16)
|
|
77 {
|
|
78 error ("only values 12 (4 KB) and 16 (64 KB) are supported for guard "
|
|
79 "size. Given value %d (%llu KB) is out of range",
|
|
80 value, (1ULL << value) / 1024ULL);
|
|
81 return false;
|
|
82 }
|
|
83 }
|
|
84
|
|
85 return true;
|
|
86 }
|
|
87
|
|
88 /* Implement TARGET_OPTION_DEFAULT_PARAMS. */
|
|
89
|
|
90 static void
|
|
91 aarch64_option_default_params (void)
|
|
92 {
|
|
93 /* We assume the guard page is 64k. */
|
|
94 int index = (int) PARAM_STACK_CLASH_PROTECTION_GUARD_SIZE;
|
|
95 set_default_param_value (PARAM_STACK_CLASH_PROTECTION_GUARD_SIZE,
|
|
96 DEFAULT_STK_CLASH_GUARD_SIZE == 0
|
|
97 ? 16 : DEFAULT_STK_CLASH_GUARD_SIZE);
|
|
98
|
|
99 int guard_size
|
|
100 = default_param_value (PARAM_STACK_CLASH_PROTECTION_GUARD_SIZE);
|
|
101
|
|
102 /* Set the interval parameter to be the same as the guard size. This way the
|
|
103 mid-end code does the right thing for us. */
|
|
104 set_default_param_value (PARAM_STACK_CLASH_PROTECTION_PROBE_INTERVAL,
|
|
105 guard_size);
|
|
106
|
|
107 /* Validate the options. */
|
|
108 aarch64_option_validate_param (guard_size, index);
|
|
109 }
|
|
110
|
111
|
111 /* Implement TARGET_HANDLE_OPTION.
|
|
112 This function handles the target specific options for CPU/target selection.
|
|
113
|
|
114 -mcpu=CPU is shorthand for -march=ARCH_FOR_CPU, -mtune=CPU.
|
|
115 If either of -march or -mtune is given, they override their
|
|
116 respective component of -mcpu. This logic is implemented
|
|
117 in config/aarch64/aarch64.c:aarch64_override_options. */
|
|
118
|
|
119 bool
|
|
120 aarch64_handle_option (struct gcc_options *opts,
|
|
121 struct gcc_options *opts_set ATTRIBUTE_UNUSED,
|
|
122 const struct cl_decoded_option *decoded,
|
|
123 location_t loc ATTRIBUTE_UNUSED)
|
|
124 {
|
|
125 size_t code = decoded->opt_index;
|
|
126 const char *arg = decoded->arg;
|
|
127 int val = decoded->value;
|
|
128
|
|
129 switch (code)
|
|
130 {
|
|
131 case OPT_march_:
|
|
132 opts->x_aarch64_arch_string = arg;
|
|
133 return true;
|
|
134
|
|
135 case OPT_mcpu_:
|
|
136 opts->x_aarch64_cpu_string = arg;
|
|
137 return true;
|
|
138
|
|
139 case OPT_mtune_:
|
|
140 opts->x_aarch64_tune_string = arg;
|
|
141 return true;
|
|
142
|
|
143 case OPT_mgeneral_regs_only:
|
|
144 opts->x_target_flags |= MASK_GENERAL_REGS_ONLY;
|
|
145 return true;
|
|
146
|
|
147 case OPT_mfix_cortex_a53_835769:
|
|
148 opts->x_aarch64_fix_a53_err835769 = val;
|
|
149 return true;
|
|
150
|
|
151 case OPT_mstrict_align:
|
131
|
152 if (val)
|
|
153 opts->x_target_flags |= MASK_STRICT_ALIGN;
|
|
154 else
|
|
155 opts->x_target_flags &= ~MASK_STRICT_ALIGN;
|
111
|
156 return true;
|
|
157
|
|
158 case OPT_momit_leaf_frame_pointer:
|
|
159 opts->x_flag_omit_leaf_frame_pointer = val;
|
|
160 return true;
|
|
161
|
|
162 default:
|
|
163 return true;
|
|
164 }
|
|
165 }
|
|
166
|
|
167 struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
|
|
168
|
|
169 /* An ISA extension in the co-processor and main instruction set space. */
|
|
170 struct aarch64_option_extension
|
|
171 {
|
|
172 const char *const name;
|
|
173 const unsigned long flag_canonical;
|
|
174 const unsigned long flags_on;
|
|
175 const unsigned long flags_off;
|
|
176 };
|
|
177
|
|
178 /* ISA extensions in AArch64. */
|
|
179 static const struct aarch64_option_extension all_extensions[] =
|
|
180 {
|
|
181 #define AARCH64_OPT_EXTENSION(NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, Z) \
|
|
182 {NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF},
|
|
183 #include "config/aarch64/aarch64-option-extensions.def"
|
|
184 {NULL, 0, 0, 0}
|
|
185 };
|
|
186
|
|
187 struct processor_name_to_arch
|
|
188 {
|
|
189 const std::string processor_name;
|
|
190 const enum aarch64_arch arch;
|
|
191 const unsigned long flags;
|
|
192 };
|
|
193
|
|
194 struct arch_to_arch_name
|
|
195 {
|
|
196 const enum aarch64_arch arch;
|
|
197 const std::string arch_name;
|
|
198 const unsigned long flags;
|
|
199 };
|
|
200
|
|
201 /* Map processor names to the architecture revision they implement and
|
|
202 the default set of architectural feature flags they support. */
|
|
203 static const struct processor_name_to_arch all_cores[] =
|
|
204 {
|
|
205 #define AARCH64_CORE(NAME, X, IDENT, ARCH_IDENT, FLAGS, COSTS, IMP, PART, VARIANT) \
|
|
206 {NAME, AARCH64_ARCH_##ARCH_IDENT, FLAGS},
|
|
207 #include "config/aarch64/aarch64-cores.def"
|
|
208 {"generic", AARCH64_ARCH_8A, AARCH64_FL_FOR_ARCH8},
|
|
209 {"", aarch64_no_arch, 0}
|
|
210 };
|
|
211
|
|
212 /* Map architecture revisions to their string representation. */
|
|
213 static const struct arch_to_arch_name all_architectures[] =
|
|
214 {
|
|
215 #define AARCH64_ARCH(NAME, CORE, ARCH_IDENT, ARCH, FLAGS) \
|
|
216 {AARCH64_ARCH_##ARCH_IDENT, NAME, FLAGS},
|
|
217 #include "config/aarch64/aarch64-arches.def"
|
|
218 {aarch64_no_arch, "", 0}
|
|
219 };
|
|
220
|
|
221 /* Parse the architecture extension string STR and update ISA_FLAGS
|
|
222 with the architecture features turned on or off. Return a
|
|
223 aarch64_parse_opt_result describing the result. */
|
|
224
|
|
225 enum aarch64_parse_opt_result
|
|
226 aarch64_parse_extension (const char *str, unsigned long *isa_flags)
|
|
227 {
|
|
228 /* The extension string is parsed left to right. */
|
|
229 const struct aarch64_option_extension *opt = NULL;
|
|
230
|
|
231 /* Flag to say whether we are adding or removing an extension. */
|
|
232 int adding_ext = -1;
|
|
233
|
|
234 while (str != NULL && *str != 0)
|
|
235 {
|
|
236 const char *ext;
|
|
237 size_t len;
|
|
238
|
|
239 str++;
|
|
240 ext = strchr (str, '+');
|
|
241
|
|
242 if (ext != NULL)
|
|
243 len = ext - str;
|
|
244 else
|
|
245 len = strlen (str);
|
|
246
|
|
247 if (len >= 2 && strncmp (str, "no", 2) == 0)
|
|
248 {
|
|
249 adding_ext = 0;
|
|
250 len -= 2;
|
|
251 str += 2;
|
|
252 }
|
|
253 else if (len > 0)
|
|
254 adding_ext = 1;
|
|
255
|
|
256 if (len == 0)
|
|
257 return AARCH64_PARSE_MISSING_ARG;
|
|
258
|
|
259
|
|
260 /* Scan over the extensions table trying to find an exact match. */
|
|
261 for (opt = all_extensions; opt->name != NULL; opt++)
|
|
262 {
|
|
263 if (strlen (opt->name) == len && strncmp (opt->name, str, len) == 0)
|
|
264 {
|
|
265 /* Add or remove the extension. */
|
|
266 if (adding_ext)
|
|
267 *isa_flags |= (opt->flags_on | opt->flag_canonical);
|
|
268 else
|
|
269 *isa_flags &= ~(opt->flags_off | opt->flag_canonical);
|
|
270 break;
|
|
271 }
|
|
272 }
|
|
273
|
|
274 if (opt->name == NULL)
|
|
275 {
|
|
276 /* Extension not found in list. */
|
|
277 return AARCH64_PARSE_INVALID_FEATURE;
|
|
278 }
|
|
279
|
|
280 str = ext;
|
|
281 };
|
|
282
|
|
283 return AARCH64_PARSE_OK;
|
|
284 }
|
|
285
|
|
286 /* Return a string representation of ISA_FLAGS. DEFAULT_ARCH_FLAGS
|
|
287 gives the default set of flags which are implied by whatever -march
|
|
288 we'd put out. Our job is to figure out the minimal set of "+" and
|
|
289 "+no" feature flags to put out, and to put them out grouped such
|
|
290 that all the "+" flags come before the "+no" flags. */
|
|
291
|
|
292 std::string
|
|
293 aarch64_get_extension_string_for_isa_flags (unsigned long isa_flags,
|
|
294 unsigned long default_arch_flags)
|
|
295 {
|
|
296 const struct aarch64_option_extension *opt = NULL;
|
|
297 std::string outstr = "";
|
|
298
|
|
299 /* Pass one: Find all the things we need to turn on. As a special case,
|
|
300 we always want to put out +crc if it is enabled. */
|
|
301 for (opt = all_extensions; opt->name != NULL; opt++)
|
|
302 if ((isa_flags & opt->flag_canonical
|
|
303 && !(default_arch_flags & opt->flag_canonical))
|
|
304 || (default_arch_flags & opt->flag_canonical
|
|
305 && opt->flag_canonical == AARCH64_ISA_CRC))
|
|
306 {
|
|
307 outstr += "+";
|
|
308 outstr += opt->name;
|
|
309 }
|
|
310
|
|
311 /* Pass two: Find all the things we need to turn off. */
|
|
312 for (opt = all_extensions; opt->name != NULL; opt++)
|
|
313 if ((~isa_flags) & opt->flag_canonical
|
|
314 && !((~default_arch_flags) & opt->flag_canonical))
|
|
315 {
|
|
316 outstr += "+no";
|
|
317 outstr += opt->name;
|
|
318 }
|
|
319
|
|
320 return outstr;
|
|
321 }
|
|
322
|
|
323 /* Attempt to rewrite NAME, which has been passed on the command line
|
|
324 as a -mcpu option to an equivalent -march value. If we can do so,
|
|
325 return the new string, otherwise return an error. */
|
|
326
|
|
327 const char *
|
|
328 aarch64_rewrite_selected_cpu (const char *name)
|
|
329 {
|
|
330 std::string original_string (name);
|
|
331 std::string extension_str;
|
|
332 std::string processor;
|
|
333 size_t extension_pos = original_string.find_first_of ('+');
|
|
334
|
|
335 /* Strip and save the extension string. */
|
|
336 if (extension_pos != std::string::npos)
|
|
337 {
|
|
338 processor = original_string.substr (0, extension_pos);
|
|
339 extension_str = original_string.substr (extension_pos,
|
|
340 std::string::npos);
|
|
341 }
|
|
342 else
|
|
343 {
|
|
344 /* No extensions. */
|
|
345 processor = original_string;
|
|
346 }
|
|
347
|
|
348 const struct processor_name_to_arch* p_to_a;
|
|
349 for (p_to_a = all_cores;
|
|
350 p_to_a->arch != aarch64_no_arch;
|
|
351 p_to_a++)
|
|
352 {
|
|
353 if (p_to_a->processor_name == processor)
|
|
354 break;
|
|
355 }
|
|
356
|
|
357 const struct arch_to_arch_name* a_to_an;
|
|
358 for (a_to_an = all_architectures;
|
|
359 a_to_an->arch != aarch64_no_arch;
|
|
360 a_to_an++)
|
|
361 {
|
|
362 if (a_to_an->arch == p_to_a->arch)
|
|
363 break;
|
|
364 }
|
|
365
|
|
366 /* We couldn't find that proceesor name, or the processor name we
|
|
367 found does not map to an architecture we understand. */
|
|
368 if (p_to_a->arch == aarch64_no_arch
|
|
369 || a_to_an->arch == aarch64_no_arch)
|
|
370 fatal_error (input_location, "unknown value %qs for -mcpu", name);
|
|
371
|
|
372 unsigned long extensions = p_to_a->flags;
|
|
373 aarch64_parse_extension (extension_str.c_str (), &extensions);
|
|
374
|
|
375 std::string outstr = a_to_an->arch_name
|
|
376 + aarch64_get_extension_string_for_isa_flags (extensions,
|
|
377 a_to_an->flags);
|
|
378
|
|
379 /* We are going to memory leak here, nobody elsewhere
|
|
380 in the callchain is going to clean up after us. The alternative is
|
|
381 to allocate a static buffer, and assert that it is big enough for our
|
|
382 modified string, which seems much worse! */
|
|
383 return xstrdup (outstr.c_str ());
|
|
384 }
|
|
385
|
|
386 /* Called by the driver to rewrite a name passed to the -mcpu
|
|
387 argument in preparation to be passed to the assembler. The
|
|
388 names passed from the commend line will be in ARGV, we want
|
|
389 to use the right-most argument, which should be in
|
|
390 ARGV[ARGC - 1]. ARGC should always be greater than 0. */
|
|
391
|
|
392 const char *
|
|
393 aarch64_rewrite_mcpu (int argc, const char **argv)
|
|
394 {
|
|
395 gcc_assert (argc);
|
|
396 return aarch64_rewrite_selected_cpu (argv[argc - 1]);
|
|
397 }
|
|
398
|
|
399 #undef AARCH64_CPU_NAME_LENGTH
|
|
400
|