1 /* Common hooks for AArch64.
2 Copyright (C) 2012-2017 Free Software Foundation, Inc.
3 Contributed by ARM Ltd.
5 This file is part of GCC.
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.
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.
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/>. */
22 #define INCLUDE_STRING
24 #include "coretypes.h"
28 #include "common/common-target.h"
29 #include "common/common-target-def.h"
32 #include "diagnostic.h"
34 #ifdef TARGET_BIG_ENDIAN_DEFAULT
35 #undef TARGET_DEFAULT_TARGET_FLAGS
36 #define TARGET_DEFAULT_TARGET_FLAGS (MASK_BIG_END)
39 #undef TARGET_HANDLE_OPTION
40 #define TARGET_HANDLE_OPTION aarch64_handle_option
42 #undef TARGET_OPTION_OPTIMIZATION_TABLE
43 #define TARGET_OPTION_OPTIMIZATION_TABLE aarch_option_optimization_table
45 /* Set default optimization options. */
46 static const struct default_options aarch_option_optimization_table
[] =
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 }
57 /* Implement TARGET_HANDLE_OPTION.
58 This function handles the target specific options for CPU/target selection.
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. */
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
)
71 size_t code
= decoded
->opt_index
;
72 const char *arg
= decoded
->arg
;
73 int val
= decoded
->value
;
78 opts
->x_aarch64_arch_string
= arg
;
82 opts
->x_aarch64_cpu_string
= arg
;
86 opts
->x_aarch64_tune_string
= arg
;
89 case OPT_mgeneral_regs_only
:
90 opts
->x_target_flags
|= MASK_GENERAL_REGS_ONLY
;
93 case OPT_mfix_cortex_a53_835769
:
94 opts
->x_aarch64_fix_a53_err835769
= val
;
97 case OPT_mstrict_align
:
98 opts
->x_target_flags
|= MASK_STRICT_ALIGN
;
101 case OPT_momit_leaf_frame_pointer
:
102 opts
->x_flag_omit_leaf_frame_pointer
= val
;
110 struct gcc_targetm_common targetm_common
= TARGETM_COMMON_INITIALIZER
;
112 /* An ISA extension in the co-processor and main instruction set space. */
113 struct aarch64_option_extension
115 const char *const name
;
116 const unsigned long flag_canonical
;
117 const unsigned long flags_on
;
118 const unsigned long flags_off
;
121 /* ISA extensions in AArch64. */
122 static const struct aarch64_option_extension all_extensions
[] =
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"
130 struct processor_name_to_arch
132 const std::string processor_name
;
133 const enum aarch64_arch arch
;
134 const unsigned long flags
;
137 struct arch_to_arch_name
139 const enum aarch64_arch arch
;
140 const std::string arch_name
;
141 const unsigned long flags
;
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
[] =
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}
155 /* Map architecture revisions to their string representation. */
156 static const struct arch_to_arch_name all_architectures
[] =
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}
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. */
168 enum aarch64_parse_opt_result
169 aarch64_parse_extension (const char *str
, unsigned long *isa_flags
)
171 /* The extension string is parsed left to right. */
172 const struct aarch64_option_extension
*opt
= NULL
;
174 /* Flag to say whether we are adding or removing an extension. */
177 while (str
!= NULL
&& *str
!= 0)
183 ext
= strchr (str
, '+');
190 if (len
>= 2 && strncmp (str
, "no", 2) == 0)
200 return AARCH64_PARSE_MISSING_ARG
;
203 /* Scan over the extensions table trying to find an exact match. */
204 for (opt
= all_extensions
; opt
->name
!= NULL
; opt
++)
206 if (strlen (opt
->name
) == len
&& strncmp (opt
->name
, str
, len
) == 0)
208 /* Add or remove the extension. */
210 *isa_flags
|= (opt
->flags_on
| opt
->flag_canonical
);
212 *isa_flags
&= ~(opt
->flags_off
| opt
->flag_canonical
);
217 if (opt
->name
== NULL
)
219 /* Extension not found in list. */
220 return AARCH64_PARSE_INVALID_FEATURE
;
226 return AARCH64_PARSE_OK
;
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. */
236 aarch64_get_extension_string_for_isa_flags (unsigned long isa_flags
,
237 unsigned long default_arch_flags
)
239 const struct aarch64_option_extension
*opt
= NULL
;
240 std::string outstr
= "";
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
))
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
))
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. */
271 aarch64_rewrite_selected_cpu (const char *name
)
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 ('+');
278 /* Strip and save the extension string. */
279 if (extension_pos
!= std::string::npos
)
281 processor
= original_string
.substr (0, extension_pos
);
282 extension_str
= original_string
.substr (extension_pos
,
288 processor
= original_string
;
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
;
296 if (p_to_a
->processor_name
== processor
)
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
;
305 if (a_to_an
->arch
== p_to_a
->arch
)
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
);
315 unsigned long extensions
= p_to_a
->flags
;
316 aarch64_parse_extension (extension_str
.c_str (), &extensions
);
318 std::string outstr
= a_to_an
->arch_name
319 + aarch64_get_extension_string_for_isa_flags (extensions
,
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 ());
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. */
336 aarch64_rewrite_mcpu (int argc
, const char **argv
)
339 return aarch64_rewrite_selected_cpu (argv
[argc
- 1]);
342 #undef AARCH64_CPU_NAME_LENGTH