]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/common/config/aarch64/aarch64-common.c
Update copyright years.
[thirdparty/gcc.git] / gcc / common / config / aarch64 / aarch64-common.c
1 /* Common hooks for AArch64.
2 Copyright (C) 2012-2018 Free Software Foundation, Inc.
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"
33
34 #ifdef TARGET_BIG_ENDIAN_DEFAULT
35 #undef TARGET_DEFAULT_TARGET_FLAGS
36 #define TARGET_DEFAULT_TARGET_FLAGS (MASK_BIG_END)
37 #endif
38
39 #undef TARGET_HANDLE_OPTION
40 #define TARGET_HANDLE_OPTION aarch64_handle_option
41
42 #undef TARGET_OPTION_OPTIMIZATION_TABLE
43 #define TARGET_OPTION_OPTIMIZATION_TABLE aarch_option_optimization_table
44
45 /* Set default optimization options. */
46 static const struct default_options aarch_option_optimization_table[] =
47 {
48 /* Enable section anchors by default at -O1 or higher. */
49 { OPT_LEVELS_1_PLUS, OPT_fsection_anchors, NULL, 1 },
50 /* Enable -fsched-pressure by default when optimizing. */
51 { OPT_LEVELS_1_PLUS, OPT_fsched_pressure, NULL, 1 },
52 /* Enable redundant extension instructions removal at -O2 and higher. */
53 { OPT_LEVELS_2_PLUS, OPT_free, NULL, 1 },
54 { OPT_LEVELS_NONE, 0, NULL, 0 }
55 };
56
57 /* Implement TARGET_HANDLE_OPTION.
58 This function handles the target specific options for CPU/target selection.
59
60 -mcpu=CPU is shorthand for -march=ARCH_FOR_CPU, -mtune=CPU.
61 If either of -march or -mtune is given, they override their
62 respective component of -mcpu. This logic is implemented
63 in config/aarch64/aarch64.c:aarch64_override_options. */
64
65 bool
66 aarch64_handle_option (struct gcc_options *opts,
67 struct gcc_options *opts_set ATTRIBUTE_UNUSED,
68 const struct cl_decoded_option *decoded,
69 location_t loc ATTRIBUTE_UNUSED)
70 {
71 size_t code = decoded->opt_index;
72 const char *arg = decoded->arg;
73 int val = decoded->value;
74
75 switch (code)
76 {
77 case OPT_march_:
78 opts->x_aarch64_arch_string = arg;
79 return true;
80
81 case OPT_mcpu_:
82 opts->x_aarch64_cpu_string = arg;
83 return true;
84
85 case OPT_mtune_:
86 opts->x_aarch64_tune_string = arg;
87 return true;
88
89 case OPT_mgeneral_regs_only:
90 opts->x_target_flags |= MASK_GENERAL_REGS_ONLY;
91 return true;
92
93 case OPT_mfix_cortex_a53_835769:
94 opts->x_aarch64_fix_a53_err835769 = val;
95 return true;
96
97 case OPT_mstrict_align:
98 opts->x_target_flags |= MASK_STRICT_ALIGN;
99 return true;
100
101 case OPT_momit_leaf_frame_pointer:
102 opts->x_flag_omit_leaf_frame_pointer = val;
103 return true;
104
105 default:
106 return true;
107 }
108 }
109
110 struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
111
112 /* An ISA extension in the co-processor and main instruction set space. */
113 struct aarch64_option_extension
114 {
115 const char *const name;
116 const unsigned long flag_canonical;
117 const unsigned long flags_on;
118 const unsigned long flags_off;
119 };
120
121 /* ISA extensions in AArch64. */
122 static const struct aarch64_option_extension all_extensions[] =
123 {
124 #define AARCH64_OPT_EXTENSION(NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, Z) \
125 {NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF},
126 #include "config/aarch64/aarch64-option-extensions.def"
127 {NULL, 0, 0, 0}
128 };
129
130 struct processor_name_to_arch
131 {
132 const std::string processor_name;
133 const enum aarch64_arch arch;
134 const unsigned long flags;
135 };
136
137 struct arch_to_arch_name
138 {
139 const enum aarch64_arch arch;
140 const std::string arch_name;
141 const unsigned long flags;
142 };
143
144 /* Map processor names to the architecture revision they implement and
145 the default set of architectural feature flags they support. */
146 static const struct processor_name_to_arch all_cores[] =
147 {
148 #define AARCH64_CORE(NAME, X, IDENT, ARCH_IDENT, FLAGS, COSTS, IMP, PART, VARIANT) \
149 {NAME, AARCH64_ARCH_##ARCH_IDENT, FLAGS},
150 #include "config/aarch64/aarch64-cores.def"
151 {"generic", AARCH64_ARCH_8A, AARCH64_FL_FOR_ARCH8},
152 {"", aarch64_no_arch, 0}
153 };
154
155 /* Map architecture revisions to their string representation. */
156 static const struct arch_to_arch_name all_architectures[] =
157 {
158 #define AARCH64_ARCH(NAME, CORE, ARCH_IDENT, ARCH, FLAGS) \
159 {AARCH64_ARCH_##ARCH_IDENT, NAME, FLAGS},
160 #include "config/aarch64/aarch64-arches.def"
161 {aarch64_no_arch, "", 0}
162 };
163
164 /* Parse the architecture extension string STR and update ISA_FLAGS
165 with the architecture features turned on or off. Return a
166 aarch64_parse_opt_result describing the result. */
167
168 enum aarch64_parse_opt_result
169 aarch64_parse_extension (const char *str, unsigned long *isa_flags)
170 {
171 /* The extension string is parsed left to right. */
172 const struct aarch64_option_extension *opt = NULL;
173
174 /* Flag to say whether we are adding or removing an extension. */
175 int adding_ext = -1;
176
177 while (str != NULL && *str != 0)
178 {
179 const char *ext;
180 size_t len;
181
182 str++;
183 ext = strchr (str, '+');
184
185 if (ext != NULL)
186 len = ext - str;
187 else
188 len = strlen (str);
189
190 if (len >= 2 && strncmp (str, "no", 2) == 0)
191 {
192 adding_ext = 0;
193 len -= 2;
194 str += 2;
195 }
196 else if (len > 0)
197 adding_ext = 1;
198
199 if (len == 0)
200 return AARCH64_PARSE_MISSING_ARG;
201
202
203 /* Scan over the extensions table trying to find an exact match. */
204 for (opt = all_extensions; opt->name != NULL; opt++)
205 {
206 if (strlen (opt->name) == len && strncmp (opt->name, str, len) == 0)
207 {
208 /* Add or remove the extension. */
209 if (adding_ext)
210 *isa_flags |= (opt->flags_on | opt->flag_canonical);
211 else
212 *isa_flags &= ~(opt->flags_off | opt->flag_canonical);
213 break;
214 }
215 }
216
217 if (opt->name == NULL)
218 {
219 /* Extension not found in list. */
220 return AARCH64_PARSE_INVALID_FEATURE;
221 }
222
223 str = ext;
224 };
225
226 return AARCH64_PARSE_OK;
227 }
228
229 /* Return a string representation of ISA_FLAGS. DEFAULT_ARCH_FLAGS
230 gives the default set of flags which are implied by whatever -march
231 we'd put out. Our job is to figure out the minimal set of "+" and
232 "+no" feature flags to put out, and to put them out grouped such
233 that all the "+" flags come before the "+no" flags. */
234
235 std::string
236 aarch64_get_extension_string_for_isa_flags (unsigned long isa_flags,
237 unsigned long default_arch_flags)
238 {
239 const struct aarch64_option_extension *opt = NULL;
240 std::string outstr = "";
241
242 /* Pass one: Find all the things we need to turn on. As a special case,
243 we always want to put out +crc if it is enabled. */
244 for (opt = all_extensions; opt->name != NULL; opt++)
245 if ((isa_flags & opt->flag_canonical
246 && !(default_arch_flags & opt->flag_canonical))
247 || (default_arch_flags & opt->flag_canonical
248 && opt->flag_canonical == AARCH64_ISA_CRC))
249 {
250 outstr += "+";
251 outstr += opt->name;
252 }
253
254 /* Pass two: Find all the things we need to turn off. */
255 for (opt = all_extensions; opt->name != NULL; opt++)
256 if ((~isa_flags) & opt->flag_canonical
257 && !((~default_arch_flags) & opt->flag_canonical))
258 {
259 outstr += "+no";
260 outstr += opt->name;
261 }
262
263 return outstr;
264 }
265
266 /* Attempt to rewrite NAME, which has been passed on the command line
267 as a -mcpu option to an equivalent -march value. If we can do so,
268 return the new string, otherwise return an error. */
269
270 const char *
271 aarch64_rewrite_selected_cpu (const char *name)
272 {
273 std::string original_string (name);
274 std::string extension_str;
275 std::string processor;
276 size_t extension_pos = original_string.find_first_of ('+');
277
278 /* Strip and save the extension string. */
279 if (extension_pos != std::string::npos)
280 {
281 processor = original_string.substr (0, extension_pos);
282 extension_str = original_string.substr (extension_pos,
283 std::string::npos);
284 }
285 else
286 {
287 /* No extensions. */
288 processor = original_string;
289 }
290
291 const struct processor_name_to_arch* p_to_a;
292 for (p_to_a = all_cores;
293 p_to_a->arch != aarch64_no_arch;
294 p_to_a++)
295 {
296 if (p_to_a->processor_name == processor)
297 break;
298 }
299
300 const struct arch_to_arch_name* a_to_an;
301 for (a_to_an = all_architectures;
302 a_to_an->arch != aarch64_no_arch;
303 a_to_an++)
304 {
305 if (a_to_an->arch == p_to_a->arch)
306 break;
307 }
308
309 /* We couldn't find that proceesor name, or the processor name we
310 found does not map to an architecture we understand. */
311 if (p_to_a->arch == aarch64_no_arch
312 || a_to_an->arch == aarch64_no_arch)
313 fatal_error (input_location, "unknown value %qs for -mcpu", name);
314
315 unsigned long extensions = p_to_a->flags;
316 aarch64_parse_extension (extension_str.c_str (), &extensions);
317
318 std::string outstr = a_to_an->arch_name
319 + aarch64_get_extension_string_for_isa_flags (extensions,
320 a_to_an->flags);
321
322 /* We are going to memory leak here, nobody elsewhere
323 in the callchain is going to clean up after us. The alternative is
324 to allocate a static buffer, and assert that it is big enough for our
325 modified string, which seems much worse! */
326 return xstrdup (outstr.c_str ());
327 }
328
329 /* Called by the driver to rewrite a name passed to the -mcpu
330 argument in preparation to be passed to the assembler. The
331 names passed from the commend line will be in ARGV, we want
332 to use the right-most argument, which should be in
333 ARGV[ARGC - 1]. ARGC should always be greater than 0. */
334
335 const char *
336 aarch64_rewrite_mcpu (int argc, const char **argv)
337 {
338 gcc_assert (argc);
339 return aarch64_rewrite_selected_cpu (argv[argc - 1]);
340 }
341
342 #undef AARCH64_CPU_NAME_LENGTH
343