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