Home | History | Annotate | Line # | Download | only in bfd
cpu-aarch64.c revision 1.9.2.1
      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