cpu-aarch64.c revision 1.9.2.1 1 1.1 christos /* BFD support for AArch64.
2 1.9.2.1 perseant Copyright (C) 2009-2022 Free Software Foundation, Inc.
3 1.1 christos Contributed by ARM Ltd.
4 1.1 christos
5 1.1 christos This file is part of BFD, the Binary File Descriptor library.
6 1.1 christos
7 1.1 christos This program is free software; you can redistribute it and/or modify
8 1.1 christos it under the terms of the GNU General Public License as published by
9 1.1 christos the Free Software Foundation; either version 3 of the License, or
10 1.1 christos (at your option) any later version.
11 1.1 christos
12 1.1 christos This program is distributed in the hope that it will be useful,
13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 christos GNU General Public License for more details.
16 1.1 christos
17 1.1 christos You should have received a copy of the GNU General Public License
18 1.1 christos along with this program; see the file COPYING3. If not,
19 1.1 christos see <http://www.gnu.org/licenses/>. */
20 1.1 christos
21 1.1 christos #include "sysdep.h"
22 1.1 christos #include "bfd.h"
23 1.1 christos #include "libbfd.h"
24 1.1 christos #include "libiberty.h"
25 1.9 christos #include "cpu-aarch64.h"
26 1.1 christos
27 1.1 christos /* This routine is provided two arch_infos and works out which Aarch64
28 1.1 christos machine which would be compatible with both and returns a pointer
29 1.1 christos to its info structure. */
30 1.1 christos
31 1.1 christos static const bfd_arch_info_type *
32 1.1 christos compatible (const bfd_arch_info_type * a, const bfd_arch_info_type * b)
33 1.1 christos {
34 1.1 christos /* If a & b are for different architecture we can do nothing. */
35 1.1 christos if (a->arch != b->arch)
36 1.1 christos return NULL;
37 1.1 christos
38 1.1 christos /* If a & b are for the same machine then all is well. */
39 1.1 christos if (a->mach == b->mach)
40 1.1 christos return a;
41 1.1 christos
42 1.9.2.1 perseant /* Don't allow mixing data models. */
43 1.9.2.1 perseant if ((a->mach ^ b->mach) & (bfd_mach_aarch64_ilp32 | bfd_mach_aarch64_llp64))
44 1.1 christos return NULL;
45 1.1 christos
46 1.1 christos /* Otherwise if either a or b is the 'default' machine
47 1.1 christos then it can be polymorphed into the other. */
48 1.1 christos if (a->the_default)
49 1.1 christos return b;
50 1.1 christos
51 1.1 christos if (b->the_default)
52 1.1 christos return a;
53 1.1 christos
54 1.1 christos /* So far all newer cores are
55 1.1 christos supersets of previous cores. */
56 1.1 christos if (a->mach < b->mach)
57 1.1 christos return b;
58 1.1 christos else if (a->mach > b->mach)
59 1.1 christos return a;
60 1.1 christos
61 1.1 christos /* Never reached! */
62 1.1 christos return NULL;
63 1.1 christos }
64 1.1 christos
65 1.1 christos static struct
66 1.1 christos {
67 1.1 christos unsigned int mach;
68 1.1 christos char *name;
69 1.1 christos }
70 1.1 christos processors[] =
71 1.1 christos {
72 1.9 christos { bfd_mach_aarch64, "cortex-a34" },
73 1.9 christos { bfd_mach_aarch64, "cortex-a65" },
74 1.9 christos { bfd_mach_aarch64, "cortex-a65ae" },
75 1.9 christos { bfd_mach_aarch64, "cortex-a76ae" },
76 1.9 christos { bfd_mach_aarch64, "cortex-a77" }
77 1.1 christos };
78 1.1 christos
79 1.9.2.1 perseant static bool
80 1.1 christos scan (const struct bfd_arch_info *info, const char *string)
81 1.1 christos {
82 1.1 christos int i;
83 1.1 christos
84 1.1 christos /* First test for an exact match. */
85 1.1 christos if (strcasecmp (string, info->printable_name) == 0)
86 1.9.2.1 perseant return true;
87 1.9.2.1 perseant
88 1.9.2.1 perseant /* If there is a prefix of "aarch64:" then skip it. */
89 1.9.2.1 perseant const char * colon;
90 1.9.2.1 perseant if ((colon = strchr (string, ':')) != NULL)
91 1.9.2.1 perseant {
92 1.9.2.1 perseant if (strncasecmp (string, "aarch64", colon - string) != 0)
93 1.9.2.1 perseant return false;
94 1.9.2.1 perseant string = colon + 1;
95 1.9.2.1 perseant }
96 1.1 christos
97 1.1 christos /* Next check for a processor name instead of an Architecture name. */
98 1.1 christos for (i = sizeof (processors) / sizeof (processors[0]); i--;)
99 1.1 christos {
100 1.1 christos if (strcasecmp (string, processors[i].name) == 0)
101 1.1 christos break;
102 1.1 christos }
103 1.1 christos
104 1.1 christos if (i != -1 && info->mach == processors[i].mach)
105 1.9.2.1 perseant return true;
106 1.1 christos
107 1.1 christos /* Finally check for the default architecture. */
108 1.1 christos if (strcasecmp (string, "aarch64") == 0)
109 1.1 christos return info->the_default;
110 1.1 christos
111 1.9.2.1 perseant return false;
112 1.1 christos }
113 1.1 christos
114 1.9.2.1 perseant /* Figure out if llp64 is default */
115 1.9.2.1 perseant #if DEFAULT_VECTOR == aarch64_pe_le_vec
116 1.9.2.1 perseant #define LLP64_DEFAULT true
117 1.9.2.1 perseant #define AARCH64_DEFAULT false
118 1.9.2.1 perseant #else
119 1.9.2.1 perseant #define LLP64_DEFAULT false
120 1.9.2.1 perseant #define AARCH64_DEFAULT true
121 1.9.2.1 perseant #endif
122 1.9.2.1 perseant
123 1.9.2.1 perseant #define N(NUMBER, PRINT, WORDSIZE, ADDRSIZE, DEFAULT, NEXT) \
124 1.9.2.1 perseant { WORDSIZE, ADDRSIZE, 8, bfd_arch_aarch64, NUMBER, \
125 1.9.2.1 perseant "aarch64", PRINT, 4, DEFAULT, compatible, scan, \
126 1.9.2.1 perseant bfd_arch_default_fill, NEXT, 0 }
127 1.9 christos
128 1.9.2.1 perseant static const bfd_arch_info_type bfd_aarch64_arch_v8_r =
129 1.9.2.1 perseant N (bfd_mach_aarch64_8R, "aarch64:armv8-r", 64, 64, false, NULL);
130 1.1 christos
131 1.1 christos static const bfd_arch_info_type bfd_aarch64_arch_ilp32 =
132 1.9.2.1 perseant N (bfd_mach_aarch64_ilp32, "aarch64:ilp32", 32, 32, false,
133 1.9 christos &bfd_aarch64_arch_v8_r);
134 1.1 christos
135 1.9.2.1 perseant static const bfd_arch_info_type bfd_aarch64_arch_llp64 =
136 1.9.2.1 perseant N (bfd_mach_aarch64_llp64, "aarch64:llp64", 32, 64, LLP64_DEFAULT,
137 1.9.2.1 perseant &bfd_aarch64_arch_ilp32);
138 1.9.2.1 perseant
139 1.9.2.1 perseant const bfd_arch_info_type bfd_aarch64_arch =
140 1.9.2.1 perseant N (0, "aarch64", 64, 64, AARCH64_DEFAULT, &bfd_aarch64_arch_llp64);
141 1.1 christos
142 1.9.2.1 perseant bool
143 1.1 christos bfd_is_aarch64_special_symbol_name (const char *name, int type)
144 1.1 christos {
145 1.1 christos if (!name || name[0] != '$')
146 1.9.2.1 perseant return false;
147 1.1 christos if (name[1] == 'x' || name[1] == 'd')
148 1.1 christos type &= BFD_AARCH64_SPECIAL_SYM_TYPE_MAP;
149 1.1 christos else if (name[1] == 'm' || name[1] == 'f' || name[1] == 'p')
150 1.1 christos type &= BFD_AARCH64_SPECIAL_SYM_TYPE_TAG;
151 1.1 christos else
152 1.9.2.1 perseant return false;
153 1.1 christos
154 1.1 christos return (type != 0 && (name[2] == 0 || name[2] == '.'));
155 1.1 christos }
156