1 1.1 christos /* BFD support for AArch64. 2 1.11 christos Copyright (C) 2009-2024 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.10 christos /* Don't allow mixing data models. */ 43 1.10 christos 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.11 christos { bfd_mach_aarch64, "cortex-a77" }, 77 1.11 christos { bfd_mach_aarch64, "cortex-a720" }, 78 1.11 christos { bfd_mach_aarch64, "cortex-x3" }, 79 1.11 christos { bfd_mach_aarch64, "cortex-x4" }, 80 1.1 christos }; 81 1.1 christos 82 1.10 christos static bool 83 1.1 christos scan (const struct bfd_arch_info *info, const char *string) 84 1.1 christos { 85 1.1 christos int i; 86 1.1 christos 87 1.1 christos /* First test for an exact match. */ 88 1.1 christos if (strcasecmp (string, info->printable_name) == 0) 89 1.10 christos return true; 90 1.10 christos 91 1.10 christos /* If there is a prefix of "aarch64:" then skip it. */ 92 1.10 christos const char * colon; 93 1.10 christos if ((colon = strchr (string, ':')) != NULL) 94 1.10 christos { 95 1.10 christos if (strncasecmp (string, "aarch64", colon - string) != 0) 96 1.10 christos return false; 97 1.10 christos string = colon + 1; 98 1.10 christos } 99 1.1 christos 100 1.1 christos /* Next check for a processor name instead of an Architecture name. */ 101 1.1 christos for (i = sizeof (processors) / sizeof (processors[0]); i--;) 102 1.1 christos { 103 1.1 christos if (strcasecmp (string, processors[i].name) == 0) 104 1.1 christos break; 105 1.1 christos } 106 1.1 christos 107 1.1 christos if (i != -1 && info->mach == processors[i].mach) 108 1.10 christos return true; 109 1.1 christos 110 1.1 christos /* Finally check for the default architecture. */ 111 1.1 christos if (strcasecmp (string, "aarch64") == 0) 112 1.1 christos return info->the_default; 113 1.1 christos 114 1.10 christos return false; 115 1.1 christos } 116 1.1 christos 117 1.10 christos /* Figure out if llp64 is default */ 118 1.10 christos #if DEFAULT_VECTOR == aarch64_pe_le_vec 119 1.10 christos #define LLP64_DEFAULT true 120 1.10 christos #define AARCH64_DEFAULT false 121 1.10 christos #else 122 1.10 christos #define LLP64_DEFAULT false 123 1.10 christos #define AARCH64_DEFAULT true 124 1.10 christos #endif 125 1.10 christos 126 1.10 christos #define N(NUMBER, PRINT, WORDSIZE, ADDRSIZE, DEFAULT, NEXT) \ 127 1.10 christos { WORDSIZE, ADDRSIZE, 8, bfd_arch_aarch64, NUMBER, \ 128 1.10 christos "aarch64", PRINT, 4, DEFAULT, compatible, scan, \ 129 1.10 christos bfd_arch_default_fill, NEXT, 0 } 130 1.9 christos 131 1.10 christos static const bfd_arch_info_type bfd_aarch64_arch_v8_r = 132 1.10 christos N (bfd_mach_aarch64_8R, "aarch64:armv8-r", 64, 64, false, NULL); 133 1.1 christos 134 1.1 christos static const bfd_arch_info_type bfd_aarch64_arch_ilp32 = 135 1.10 christos N (bfd_mach_aarch64_ilp32, "aarch64:ilp32", 32, 32, false, 136 1.9 christos &bfd_aarch64_arch_v8_r); 137 1.1 christos 138 1.10 christos static const bfd_arch_info_type bfd_aarch64_arch_llp64 = 139 1.10 christos N (bfd_mach_aarch64_llp64, "aarch64:llp64", 32, 64, LLP64_DEFAULT, 140 1.10 christos &bfd_aarch64_arch_ilp32); 141 1.10 christos 142 1.10 christos const bfd_arch_info_type bfd_aarch64_arch = 143 1.10 christos N (0, "aarch64", 64, 64, AARCH64_DEFAULT, &bfd_aarch64_arch_llp64); 144 1.1 christos 145 1.10 christos bool 146 1.1 christos bfd_is_aarch64_special_symbol_name (const char *name, int type) 147 1.1 christos { 148 1.1 christos if (!name || name[0] != '$') 149 1.10 christos return false; 150 1.1 christos if (name[1] == 'x' || name[1] == 'd') 151 1.1 christos type &= BFD_AARCH64_SPECIAL_SYM_TYPE_MAP; 152 1.1 christos else if (name[1] == 'm' || name[1] == 'f' || name[1] == 'p') 153 1.1 christos type &= BFD_AARCH64_SPECIAL_SYM_TYPE_TAG; 154 1.1 christos else 155 1.10 christos return false; 156 1.1 christos 157 1.1 christos return (type != 0 && (name[2] == 0 || name[2] == '.')); 158 1.1 christos } 159