]>
Commit | Line | Data |
---|---|---|
43e9d192 | 1 | /* Common hooks for AArch64. |
818ab71a | 2 | Copyright (C) 2012-2016 Free Software Foundation, Inc. |
43e9d192 IB |
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 | #include "system.h" | |
23 | #include "coretypes.h" | |
24 | #include "tm.h" | |
25 | #include "tm_p.h" | |
26 | #include "common/common-target.h" | |
27 | #include "common/common-target-def.h" | |
28 | #include "opts.h" | |
29 | #include "flags.h" | |
054b4005 | 30 | #include "diagnostic.h" |
43e9d192 IB |
31 | |
32 | #ifdef TARGET_BIG_ENDIAN_DEFAULT | |
33 | #undef TARGET_DEFAULT_TARGET_FLAGS | |
34 | #define TARGET_DEFAULT_TARGET_FLAGS (MASK_BIG_END) | |
35 | #endif | |
36 | ||
37 | #undef TARGET_HANDLE_OPTION | |
38 | #define TARGET_HANDLE_OPTION aarch64_handle_option | |
39 | ||
40 | #undef TARGET_OPTION_OPTIMIZATION_TABLE | |
41 | #define TARGET_OPTION_OPTIMIZATION_TABLE aarch_option_optimization_table | |
42 | ||
43 | /* Set default optimization options. */ | |
44 | static const struct default_options aarch_option_optimization_table[] = | |
45 | { | |
46 | /* Enable section anchors by default at -O1 or higher. */ | |
47 | { OPT_LEVELS_1_PLUS, OPT_fsection_anchors, NULL, 1 }, | |
de72c50f WD |
48 | /* Enable -fsched-pressure by default when optimizing. */ |
49 | { OPT_LEVELS_1_PLUS, OPT_fsched_pressure, NULL, 1 }, | |
473cec55 IB |
50 | /* Enable redundant extension instructions removal at -O2 and higher. */ |
51 | { OPT_LEVELS_2_PLUS, OPT_free, NULL, 1 }, | |
43e9d192 IB |
52 | { OPT_LEVELS_NONE, 0, NULL, 0 } |
53 | }; | |
54 | ||
55 | /* Implement TARGET_HANDLE_OPTION. | |
56 | This function handles the target specific options for CPU/target selection. | |
57 | ||
ffee7aa9 JG |
58 | -mcpu=CPU is shorthand for -march=ARCH_FOR_CPU, -mtune=CPU. |
59 | If either of -march or -mtune is given, they override their | |
60 | respective component of -mcpu. This logic is implemented | |
61 | in config/aarch64/aarch64.c:aarch64_override_options. */ | |
43e9d192 | 62 | |
5a2c8331 | 63 | bool |
43e9d192 IB |
64 | aarch64_handle_option (struct gcc_options *opts, |
65 | struct gcc_options *opts_set ATTRIBUTE_UNUSED, | |
66 | const struct cl_decoded_option *decoded, | |
67 | location_t loc ATTRIBUTE_UNUSED) | |
68 | { | |
69 | size_t code = decoded->opt_index; | |
70 | const char *arg = decoded->arg; | |
5a2c8331 | 71 | int val = decoded->value; |
43e9d192 IB |
72 | |
73 | switch (code) | |
74 | { | |
75 | case OPT_march_: | |
76 | opts->x_aarch64_arch_string = arg; | |
43e9d192 IB |
77 | return true; |
78 | ||
79 | case OPT_mcpu_: | |
80 | opts->x_aarch64_cpu_string = arg; | |
43e9d192 IB |
81 | return true; |
82 | ||
83 | case OPT_mtune_: | |
84 | opts->x_aarch64_tune_string = arg; | |
85 | return true; | |
86 | ||
5a2c8331 KT |
87 | case OPT_mgeneral_regs_only: |
88 | opts->x_target_flags |= MASK_GENERAL_REGS_ONLY; | |
89 | return true; | |
90 | ||
91 | case OPT_mfix_cortex_a53_835769: | |
92 | opts->x_aarch64_fix_a53_err835769 = val; | |
93 | return true; | |
94 | ||
95 | case OPT_mstrict_align: | |
96 | opts->x_target_flags |= MASK_STRICT_ALIGN; | |
97 | return true; | |
98 | ||
99 | case OPT_momit_leaf_frame_pointer: | |
100 | opts->x_flag_omit_frame_pointer = val; | |
101 | return true; | |
102 | ||
43e9d192 IB |
103 | default: |
104 | return true; | |
105 | } | |
106 | } | |
107 | ||
108 | struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER; | |
682287fb | 109 | |
054b4005 JG |
110 | /* An ISA extension in the co-processor and main instruction set space. */ |
111 | struct aarch64_option_extension | |
112 | { | |
113 | const char *const name; | |
114 | const unsigned long flags_on; | |
115 | const unsigned long flags_off; | |
116 | }; | |
117 | ||
118 | /* ISA extensions in AArch64. */ | |
119 | static const struct aarch64_option_extension all_extensions[] = | |
120 | { | |
121 | #define AARCH64_OPT_EXTENSION(NAME, FLAGS_ON, FLAGS_OFF, FEATURE_STRING) \ | |
122 | {NAME, FLAGS_ON, FLAGS_OFF}, | |
123 | #include "config/aarch64/aarch64-option-extensions.def" | |
124 | #undef AARCH64_OPT_EXTENSION | |
125 | {NULL, 0, 0} | |
126 | }; | |
127 | ||
128 | struct processor_name_to_arch | |
129 | { | |
130 | const std::string processor_name; | |
131 | const enum aarch64_arch arch; | |
132 | const unsigned long flags; | |
133 | }; | |
134 | ||
135 | struct arch_to_arch_name | |
136 | { | |
137 | const enum aarch64_arch arch; | |
138 | const std::string arch_name; | |
139 | }; | |
140 | ||
141 | /* Map processor names to the architecture revision they implement and | |
142 | the default set of architectural feature flags they support. */ | |
143 | static const struct processor_name_to_arch all_cores[] = | |
144 | { | |
145 | #define AARCH64_CORE(NAME, X, IDENT, ARCH_IDENT, FLAGS, COSTS, IMP, PART) \ | |
146 | {NAME, AARCH64_ARCH_##ARCH_IDENT, FLAGS}, | |
147 | #include "config/aarch64/aarch64-cores.def" | |
148 | #undef AARCH64_CORE | |
149 | {"generic", AARCH64_ARCH_8A, AARCH64_FL_FOR_ARCH8}, | |
150 | {"", aarch64_no_arch, 0} | |
151 | }; | |
152 | ||
153 | /* Map architecture revisions to their string representation. */ | |
154 | static const struct arch_to_arch_name all_architectures[] = | |
155 | { | |
156 | #define AARCH64_ARCH(NAME, CORE, ARCH_IDENT, ARCH, FLAGS) \ | |
157 | {AARCH64_ARCH_##ARCH_IDENT, NAME}, | |
158 | #include "config/aarch64/aarch64-arches.def" | |
159 | #undef AARCH64_ARCH | |
160 | {aarch64_no_arch, ""} | |
161 | }; | |
162 | ||
163 | /* Return a string representation of ISA_FLAGS. */ | |
164 | ||
165 | std::string | |
166 | aarch64_get_extension_string_for_isa_flags (unsigned long isa_flags) | |
167 | { | |
168 | const struct aarch64_option_extension *opt = NULL; | |
169 | std::string outstr = ""; | |
170 | ||
171 | for (opt = all_extensions; opt->name != NULL; opt++) | |
172 | if ((isa_flags & opt->flags_on) == opt->flags_on) | |
173 | { | |
174 | outstr += "+"; | |
175 | outstr += opt->name; | |
176 | } | |
177 | return outstr; | |
178 | } | |
682287fb | 179 | |
054b4005 JG |
180 | /* Attempt to rewrite NAME, which has been passed on the command line |
181 | as a -mcpu option to an equivalent -march value. If we can do so, | |
182 | return the new string, otherwise return an error. */ | |
682287fb JG |
183 | |
184 | const char * | |
185 | aarch64_rewrite_selected_cpu (const char *name) | |
186 | { | |
054b4005 JG |
187 | std::string original_string (name); |
188 | std::string extensions; | |
189 | std::string processor; | |
190 | size_t extension_pos = original_string.find_first_of ('+'); | |
682287fb | 191 | |
054b4005 JG |
192 | /* Strip and save the extension string. */ |
193 | if (extension_pos != std::string::npos) | |
194 | { | |
195 | processor = original_string.substr (0, extension_pos); | |
196 | extensions = original_string.substr (extension_pos, | |
197 | std::string::npos); | |
198 | } | |
199 | else | |
200 | { | |
201 | /* No extensions. */ | |
202 | processor = original_string; | |
203 | } | |
efb25f54 | 204 | |
054b4005 JG |
205 | const struct processor_name_to_arch* p_to_a; |
206 | for (p_to_a = all_cores; | |
207 | p_to_a->arch != aarch64_no_arch; | |
208 | p_to_a++) | |
209 | { | |
210 | if (p_to_a->processor_name == processor) | |
211 | break; | |
212 | } | |
efb25f54 | 213 | |
054b4005 JG |
214 | const struct arch_to_arch_name* a_to_an; |
215 | for (a_to_an = all_architectures; | |
216 | a_to_an->arch != aarch64_no_arch; | |
217 | a_to_an++) | |
218 | { | |
219 | if (a_to_an->arch == p_to_a->arch) | |
220 | break; | |
221 | } | |
682287fb | 222 | |
054b4005 JG |
223 | /* We couldn't find that proceesor name, or the processor name we |
224 | found does not map to an architecture we understand. */ | |
225 | if (p_to_a->arch == aarch64_no_arch | |
226 | || a_to_an->arch == aarch64_no_arch) | |
227 | fatal_error (input_location, "unknown value %qs for -mcpu", name); | |
228 | ||
229 | std::string outstr = a_to_an->arch_name | |
230 | + aarch64_get_extension_string_for_isa_flags (p_to_a->flags) | |
231 | + extensions; | |
232 | ||
233 | /* We are going to memory leak here, nobody elsewhere | |
234 | in the callchain is going to clean up after us. The alternative is | |
235 | to allocate a static buffer, and assert that it is big enough for our | |
236 | modified string, which seems much worse! */ | |
237 | return xstrdup (outstr.c_str ()); | |
682287fb JG |
238 | } |
239 | ||
240 | /* Called by the driver to rewrite a name passed to the -mcpu | |
241 | argument in preparation to be passed to the assembler. The | |
1c05df59 JG |
242 | names passed from the commend line will be in ARGV, we want |
243 | to use the right-most argument, which should be in | |
244 | ARGV[ARGC - 1]. ARGC should always be greater than 0. */ | |
682287fb JG |
245 | |
246 | const char * | |
247 | aarch64_rewrite_mcpu (int argc, const char **argv) | |
248 | { | |
1c05df59 JG |
249 | gcc_assert (argc); |
250 | return aarch64_rewrite_selected_cpu (argv[argc - 1]); | |
682287fb JG |
251 | } |
252 | ||
253 | #undef AARCH64_CPU_NAME_LENGTH | |
254 |