|  | /* BFD support for the ARC processor | 
|  | Copyright (C) 1994-2022 Free Software Foundation, Inc. | 
|  | Contributed by Doug Evans (dje@cygnus.com). | 
|  |  | 
|  | This file is part of BFD, the Binary File Descriptor library. | 
|  |  | 
|  | This program is free software; you can redistribute it and/or modify | 
|  | it under the terms of the GNU General Public License as published by | 
|  | the Free Software Foundation; either version 3 of the License, or | 
|  | (at your option) any later version. | 
|  |  | 
|  | This program is distributed in the hope that it will be useful, | 
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | GNU General Public License for more details. | 
|  |  | 
|  | You should have received a copy of the GNU General Public License | 
|  | along with this program; if not, write to the Free Software | 
|  | Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, | 
|  | MA 02110-1301, USA.  */ | 
|  |  | 
|  | #include "sysdep.h" | 
|  | #include "bfd.h" | 
|  | #include "libbfd.h" | 
|  |  | 
|  | static const bfd_arch_info_type * | 
|  | arc_compatible (const bfd_arch_info_type *a, const bfd_arch_info_type *b); | 
|  |  | 
|  | #define ARC(mach, print_name, default_p, next) \ | 
|  | {					       \ | 
|  | 32,	/* Bits in a word.  */		\ | 
|  | 32,	/* Bits in an address.  */	\ | 
|  | 8,	/* Bits in a byte.  */		\ | 
|  | bfd_arch_arc,			\ | 
|  | mach,				\ | 
|  | "arc",				\ | 
|  | print_name,				\ | 
|  | 4, /* Section alignment power.  */	\ | 
|  | default_p,				\ | 
|  | arc_compatible,			\ | 
|  | bfd_default_scan,			\ | 
|  | bfd_arch_default_fill,		\ | 
|  | next,				\ | 
|  | 0 /* Maximum offset of a reloc from the start of an insn.  */ \ | 
|  | } | 
|  |  | 
|  | static const bfd_arch_info_type arch_info_struct[] = | 
|  | { | 
|  | ARC (bfd_mach_arc_arc600, "A6"    , false, &arch_info_struct[1]), | 
|  | ARC (bfd_mach_arc_arc601, "ARC601", false, &arch_info_struct[2]), | 
|  | ARC (bfd_mach_arc_arc700, "ARC700", false, &arch_info_struct[3]), | 
|  | ARC (bfd_mach_arc_arc700, "A7",     false, &arch_info_struct[4]), | 
|  | ARC (bfd_mach_arc_arcv2,  "ARCv2",  false, &arch_info_struct[5]), | 
|  | ARC (bfd_mach_arc_arcv2,  "EM",     false, &arch_info_struct[6]), | 
|  | ARC (bfd_mach_arc_arcv2,  "HS",     false, NULL), | 
|  | }; | 
|  |  | 
|  | const bfd_arch_info_type bfd_arc_arch = | 
|  | ARC (bfd_mach_arc_arc600, "ARC600", true, &arch_info_struct[0]); | 
|  |  | 
|  | /* ARC-specific "compatible" function.  The general rule is that if A and B are | 
|  | compatible, then this function should return architecture that is more | 
|  | "feature-rich", that is, can run both A and B.  ARCv2, EM and HS all has | 
|  | same mach number, so bfd_default_compatible assumes they are the same, and | 
|  | returns an A.  That causes issues with GDB, because GDB assumes that if | 
|  | machines are compatible, then "compatible ()" always returns same machine | 
|  | regardless of argument order.  As a result GDB gets confused because, for | 
|  | example, compatible (ARCv2, EM) returns ARCv2, but compatible (EM, ARCv2) | 
|  | returns EM, hence GDB is not sure if they are compatible and prints a | 
|  | warning.  */ | 
|  |  | 
|  | static const bfd_arch_info_type * | 
|  | arc_compatible (const bfd_arch_info_type *a, const bfd_arch_info_type *b) | 
|  | { | 
|  | const bfd_arch_info_type * const em = &arch_info_struct[5]; | 
|  | const bfd_arch_info_type * const hs = &arch_info_struct[6]; | 
|  |  | 
|  | /* Trivial case where a and b is the same instance.  Some callers already | 
|  | check this condition but some do not and get an invalid result.  */ | 
|  | if (a == b) | 
|  | return a; | 
|  |  | 
|  | /* If a & b are for different architecture we can do nothing.  */ | 
|  | if (a->arch != b->arch) | 
|  | return NULL; | 
|  |  | 
|  | if (a->bits_per_word != b->bits_per_word) | 
|  | return NULL; | 
|  |  | 
|  | /* ARCv2|EM and EM.  */ | 
|  | if ((a->mach == bfd_mach_arc_arcv2 && b == em) | 
|  | || (b->mach == bfd_mach_arc_arcv2 && a == em)) | 
|  | return em; | 
|  |  | 
|  | /* ARCv2|HS and HS.  */ | 
|  | if ((a->mach == bfd_mach_arc_arcv2 && b == hs) | 
|  | || (b->mach == bfd_mach_arc_arcv2 && a == hs)) | 
|  | return hs; | 
|  |  | 
|  | return bfd_default_compatible (a, b); | 
|  | } |