X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Farchures.c;h=7ca1c0692636a746b49a325bd42e8c316ada075d;hb=87f8eb977e936160d4c332d88a8bce3db690521c;hp=3a8b0c06a63f2632d3c064a59e89900b8dfda420;hpb=c618de01c1b069e058af9df808d25bbab0f462dd;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/archures.c b/bfd/archures.c index 3a8b0c06a6..7ca1c06926 100644 --- a/bfd/archures.c +++ b/bfd/archures.c @@ -1,6 +1,7 @@ /* BFD library support routines for architectures. - Copyright (C) 1990-1991 Free Software Foundation, Inc. - Hacked by John Gilmore of Cygnus Support. + Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 97, 98, 1999, 2000 + Free Software Foundation, Inc. + Hacked by John Gilmore and Steve Chamberlain of Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -16,449 +17,1024 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -/*doc* -@section Architectures -BFD's idea of an architecture is implimented in @code{archures.c}. BFD -keeps two atoms in a bfd describing the architecture of the data -attatched to the bfd, the @code{enum bfd_architecture arch} field and -the @code{unsigned long machine} field. +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "bfd.h" +#include "sysdep.h" +#include "libbfd.h" +#include + +/* + +SECTION + Architectures + + BFD keeps one atom in a BFD describing the + architecture of the data attached to the BFD: a pointer to a + <>. + + Pointers to structures can be requested independently of a BFD + so that an architecture's information can be interrogated + without access to an open BFD. + + The architecture information is provided by each architecture package. + The set of default architectures is selected by the macro + <>. This is normally set up in the + @file{config/@var{target}.mt} file of your choice. If the name is not + defined, then all the architectures supported are included. + + When BFD starts up, all the architectures are called with an + initialize method. It is up to the architecture back end to + insert as many items into the list of architectures as it wants to; + generally this would be one for each machine and one for the + default case (an item with a machine field of 0). + + BFD's idea of an architecture is implemented in @file{archures.c}. */ -/*proto* bfd_architecture -This enum gives the object file's CPU -architecture, in a global sense. E.g. what processor family does it -belong to? There is another field, which indicates what processor -within the family is in use. The machine gives a number which -distingushes different versions of the architecture, containing for -example 2 and 3 for Intel i960 KA and i960 KB, and 68020 and 68030 for -Motorola 68020 and 68030. - -*+ -enum bfd_architecture -{ - bfd_arch_unknown, {* File arch not known *} - bfd_arch_obscure, {* Arch known, not one of these *} - bfd_arch_m68k, {* Motorola 68xxx *} - bfd_arch_vax, {* DEC Vax *} - bfd_arch_i960, {* Intel 960 *} - {* The order of the following is important. - lower number indicates a machine type that - only accepts a subset of the instructions - available to machines with higher numbers. - The exception is the "ca", which is - incompatible with all other machines except - "core". *} - -#define bfd_mach_i960_core 1 -#define bfd_mach_i960_ka_sa 2 -#define bfd_mach_i960_kb_sb 3 -#define bfd_mach_i960_mc 4 -#define bfd_mach_i960_xa 5 -#define bfd_mach_i960_ca 6 - - bfd_arch_a29k, {* AMD 29000 *} - bfd_arch_sparc, {* SPARC *} - bfd_arch_mips, {* MIPS Rxxxx *} - bfd_arch_i386, {* Intel 386 *} - bfd_arch_ns32k, {* National Semiconductor 32xxx *} - bfd_arch_tahoe, {* CCI/Harris Tahoe *} - bfd_arch_i860, {* Intel 860 *} - bfd_arch_romp, {* IBM ROMP RS/6000 *} - bfd_arch_alliant, {* Alliant *} - bfd_arch_convex, {* Convex *} - bfd_arch_m88k, {* Motorola 88xxx *} - bfd_arch_pyramid, {* Pyramid Technology *} - bfd_arch_h8_300, {* Hitachi H8/300 *} - bfd_arch_last - }; -*- - -stuff +/* + +SUBSECTION + bfd_architecture + +DESCRIPTION + This enum gives the object file's CPU architecture, in a + global sense---i.e., what processor family does it belong to? + Another field indicates which processor within + the family is in use. The machine gives a number which + distinguishes different versions of the architecture, + containing, for example, 2 and 3 for Intel i960 KA and i960 KB, + and 68020 and 68030 for Motorola 68020 and 68030. +.enum bfd_architecture +.{ +. bfd_arch_unknown, {* File arch not known *} +. bfd_arch_obscure, {* Arch known, not one of these *} +. bfd_arch_m68k, {* Motorola 68xxx *} +.#define bfd_mach_m68000 1 +.#define bfd_mach_m68008 2 +.#define bfd_mach_m68010 3 +.#define bfd_mach_m68020 4 +.#define bfd_mach_m68030 5 +.#define bfd_mach_m68040 6 +.#define bfd_mach_m68060 7 +.#define bfd_mach_cpu32 8 +. bfd_arch_vax, {* DEC Vax *} +. bfd_arch_i960, {* Intel 960 *} +. {* The order of the following is important. +. lower number indicates a machine type that +. only accepts a subset of the instructions +. available to machines with higher numbers. +. The exception is the "ca", which is +. incompatible with all other machines except +. "core". *} +. +.#define bfd_mach_i960_core 1 +.#define bfd_mach_i960_ka_sa 2 +.#define bfd_mach_i960_kb_sb 3 +.#define bfd_mach_i960_mc 4 +.#define bfd_mach_i960_xa 5 +.#define bfd_mach_i960_ca 6 +.#define bfd_mach_i960_jx 7 +.#define bfd_mach_i960_hx 8 +. +. bfd_arch_a29k, {* AMD 29000 *} +. bfd_arch_sparc, {* SPARC *} +.#define bfd_mach_sparc 1 +.{* The difference between v8plus and v9 is that v9 is a true 64 bit env. *} +.#define bfd_mach_sparc_sparclet 2 +.#define bfd_mach_sparc_sparclite 3 +.#define bfd_mach_sparc_v8plus 4 +.#define bfd_mach_sparc_v8plusa 5 {* with ultrasparc add'ns *} +.#define bfd_mach_sparc_sparclite_le 6 +.#define bfd_mach_sparc_v9 7 +.#define bfd_mach_sparc_v9a 8 {* with ultrasparc add'ns *} +.#define bfd_mach_sparc_v8plusb 9 {* with cheetah add'ns *} +.#define bfd_mach_sparc_v9b 10 {* with cheetah add'ns *} +.{* Nonzero if MACH has the v9 instruction set. *} +.#define bfd_mach_sparc_v9_p(mach) \ +. ((mach) >= bfd_mach_sparc_v8plus && (mach) <= bfd_mach_sparc_v9b \ +. && (mach) != bfd_mach_sparc_sparclite_le) +. bfd_arch_mips, {* MIPS Rxxxx *} +.#define bfd_mach_mips3000 3000 +.#define bfd_mach_mips3900 3900 +.#define bfd_mach_mips4000 4000 +.#define bfd_mach_mips4010 4010 +.#define bfd_mach_mips4100 4100 +.#define bfd_mach_mips4111 4111 +.#define bfd_mach_mips4300 4300 +.#define bfd_mach_mips4400 4400 +.#define bfd_mach_mips4600 4600 +.#define bfd_mach_mips4650 4650 +.#define bfd_mach_mips5000 5000 +.#define bfd_mach_mips6000 6000 +.#define bfd_mach_mips8000 8000 +.#define bfd_mach_mips10000 10000 +.#define bfd_mach_mips16 16 +.#define bfd_mach_mips32 32 +.#define bfd_mach_mips32_4k 3204113 {* 32, 04, octal 'K' *} +.#define bfd_mach_mips5 5 +.#define bfd_mach_mips64 64 +.#define bfd_mach_mips_sb1 12310201 {* octal 'SB', 01 *} +. bfd_arch_i386, {* Intel 386 *} +.#define bfd_mach_i386_i386 0 +.#define bfd_mach_i386_i8086 1 +.#define bfd_mach_i386_i386_intel_syntax 2 +.#define bfd_mach_x86_64 3 +.#define bfd_mach_x86_64_intel_syntax 4 +. bfd_arch_we32k, {* AT&T WE32xxx *} +. bfd_arch_tahoe, {* CCI/Harris Tahoe *} +. bfd_arch_i860, {* Intel 860 *} +. bfd_arch_i370, {* IBM 360/370 Mainframes *} +. bfd_arch_romp, {* IBM ROMP PC/RT *} +. bfd_arch_alliant, {* Alliant *} +. bfd_arch_convex, {* Convex *} +. bfd_arch_m88k, {* Motorola 88xxx *} +. bfd_arch_pyramid, {* Pyramid Technology *} +. bfd_arch_h8300, {* Hitachi H8/300 *} +.#define bfd_mach_h8300 1 +.#define bfd_mach_h8300h 2 +.#define bfd_mach_h8300s 3 +. bfd_arch_pdp11, {* DEC PDP-11 *} +. bfd_arch_powerpc, {* PowerPC *} +.#define bfd_mach_ppc 0 +.#define bfd_mach_ppc_403 403 +.#define bfd_mach_ppc_403gc 4030 +.#define bfd_mach_ppc_505 505 +.#define bfd_mach_ppc_601 601 +.#define bfd_mach_ppc_602 602 +.#define bfd_mach_ppc_603 603 +.#define bfd_mach_ppc_ec603e 6031 +.#define bfd_mach_ppc_604 604 +.#define bfd_mach_ppc_620 620 +.#define bfd_mach_ppc_630 630 +.#define bfd_mach_ppc_750 750 +.#define bfd_mach_ppc_860 860 +.#define bfd_mach_ppc_a35 35 +.#define bfd_mach_ppc_rs64ii 642 +.#define bfd_mach_ppc_rs64iii 643 +.#define bfd_mach_ppc_7400 7400 +. bfd_arch_rs6000, {* IBM RS/6000 *} +.#define bfd_mach_rs6k 0 +.#define bfd_mach_rs6k_rs1 6001 +.#define bfd_mach_rs6k_rsc 6003 +.#define bfd_mach_rs6k_rs2 6002 +. bfd_arch_hppa, {* HP PA RISC *} +. bfd_arch_d10v, {* Mitsubishi D10V *} +.#define bfd_mach_d10v 0 +.#define bfd_mach_d10v_ts2 2 +.#define bfd_mach_d10v_ts3 3 +. bfd_arch_d30v, {* Mitsubishi D30V *} +. bfd_arch_m68hc11, {* Motorola 68HC11 *} +. bfd_arch_m68hc12, {* Motorola 68HC12 *} +. bfd_arch_z8k, {* Zilog Z8000 *} +.#define bfd_mach_z8001 1 +.#define bfd_mach_z8002 2 +. bfd_arch_h8500, {* Hitachi H8/500 *} +. bfd_arch_sh, {* Hitachi SH *} +.#define bfd_mach_sh 0 +.#define bfd_mach_sh2 0x20 +.#define bfd_mach_sh_dsp 0x2d +.#define bfd_mach_sh3 0x30 +.#define bfd_mach_sh3_dsp 0x3d +.#define bfd_mach_sh3e 0x3e +.#define bfd_mach_sh4 0x40 +. bfd_arch_alpha, {* Dec Alpha *} +.#define bfd_mach_alpha_ev4 0x10 +.#define bfd_mach_alpha_ev5 0x20 +.#define bfd_mach_alpha_ev6 0x30 +. bfd_arch_arm, {* Advanced Risc Machines ARM *} +.#define bfd_mach_arm_2 1 +.#define bfd_mach_arm_2a 2 +.#define bfd_mach_arm_3 3 +.#define bfd_mach_arm_3M 4 +.#define bfd_mach_arm_4 5 +.#define bfd_mach_arm_4T 6 +.#define bfd_mach_arm_5 7 +.#define bfd_mach_arm_5T 8 +.#define bfd_mach_arm_5TE 9 +.#define bfd_mach_arm_XScale 10 +. bfd_arch_ns32k, {* National Semiconductors ns32000 *} +. bfd_arch_w65, {* WDC 65816 *} +. bfd_arch_tic30, {* Texas Instruments TMS320C30 *} +. bfd_arch_tic54x, {* Texas Instruments TMS320C54X *} +. bfd_arch_tic80, {* TI TMS320c80 (MVP) *} +. bfd_arch_v850, {* NEC V850 *} +.#define bfd_mach_v850 0 +.#define bfd_mach_v850e 'E' +.#define bfd_mach_v850ea 'A' +. bfd_arch_arc, {* ARC Cores *} +.#define bfd_mach_arc_5 0 +.#define bfd_mach_arc_6 1 +.#define bfd_mach_arc_7 2 +.#define bfd_mach_arc_8 3 +. bfd_arch_m32r, {* Mitsubishi M32R/D *} +.#define bfd_mach_m32r 0 {* backwards compatibility *} +.#define bfd_mach_m32rx 'x' +. bfd_arch_mn10200, {* Matsushita MN10200 *} +. bfd_arch_mn10300, {* Matsushita MN10300 *} +.#define bfd_mach_mn10300 300 +.#define bfd_mach_am33 330 +. bfd_arch_fr30, +.#define bfd_mach_fr30 0x46523330 +. bfd_arch_mcore, +. bfd_arch_ia64, {* HP/Intel ia64 *} +.#define bfd_mach_ia64_elf64 0 +.#define bfd_mach_ia64_elf32 1 +. bfd_arch_pj, +. bfd_arch_avr, {* Atmel AVR microcontrollers *} +.#define bfd_mach_avr1 1 +.#define bfd_mach_avr2 2 +.#define bfd_mach_avr3 3 +.#define bfd_mach_avr4 4 +.#define bfd_mach_avr5 5 +. bfd_arch_cris, {* Axis CRIS *} +. bfd_arch_s390, {* IBM s390 *} +.#define bfd_mach_s390_esa 0 +.#define bfd_mach_s390_esame 1 +. bfd_arch_last +. }; */ +/* +SUBSECTION + bfd_arch_info +DESCRIPTION + This structure contains information on architectures for use + within BFD. -/* $Id$ */ +. +.typedef struct bfd_arch_info +.{ +. int bits_per_word; +. int bits_per_address; +. int bits_per_byte; +. enum bfd_architecture arch; +. unsigned long mach; +. const char *arch_name; +. const char *printable_name; +. unsigned int section_align_power; +. {* True if this is the default machine for the architecture. *} +. boolean the_default; +. const struct bfd_arch_info * (*compatible) +. PARAMS ((const struct bfd_arch_info *a, +. const struct bfd_arch_info *b)); +. +. boolean (*scan) PARAMS ((const struct bfd_arch_info *, const char *)); +. +. const struct bfd_arch_info *next; +.} bfd_arch_info_type; +*/ -#include -#include "bfd.h" +extern const bfd_arch_info_type bfd_a29k_arch; +extern const bfd_arch_info_type bfd_alpha_arch; +extern const bfd_arch_info_type bfd_arc_arch; +extern const bfd_arch_info_type bfd_arm_arch; +extern const bfd_arch_info_type bfd_cris_arch; +extern const bfd_arch_info_type bfd_d10v_arch; +extern const bfd_arch_info_type bfd_d30v_arch; +extern const bfd_arch_info_type bfd_h8300_arch; +extern const bfd_arch_info_type bfd_h8500_arch; +extern const bfd_arch_info_type bfd_hppa_arch; +extern const bfd_arch_info_type bfd_i370_arch; +extern const bfd_arch_info_type bfd_i386_arch; +extern const bfd_arch_info_type bfd_i860_arch; +extern const bfd_arch_info_type bfd_i960_arch; +extern const bfd_arch_info_type bfd_m32r_arch; +extern const bfd_arch_info_type bfd_m68hc11_arch; +extern const bfd_arch_info_type bfd_m68hc12_arch; +extern const bfd_arch_info_type bfd_m68k_arch; +extern const bfd_arch_info_type bfd_m88k_arch; +extern const bfd_arch_info_type bfd_mips_arch; +extern const bfd_arch_info_type bfd_mn10200_arch; +extern const bfd_arch_info_type bfd_mn10300_arch; +extern const bfd_arch_info_type bfd_pdp11_arch; +extern const bfd_arch_info_type bfd_powerpc_arch; +extern const bfd_arch_info_type bfd_rs6000_arch; +extern const bfd_arch_info_type bfd_pj_arch; +extern const bfd_arch_info_type bfd_sh_arch; +extern const bfd_arch_info_type bfd_sparc_arch; +extern const bfd_arch_info_type bfd_tic30_arch; +extern const bfd_arch_info_type bfd_tic54x_arch; +extern const bfd_arch_info_type bfd_tic80_arch; +extern const bfd_arch_info_type bfd_vax_arch; +extern const bfd_arch_info_type bfd_we32k_arch; +extern const bfd_arch_info_type bfd_z8k_arch; +extern const bfd_arch_info_type bfd_ns32k_arch; +extern const bfd_arch_info_type bfd_w65_arch; +extern const bfd_arch_info_type bfd_v850_arch; +extern const bfd_arch_info_type bfd_fr30_arch; +extern const bfd_arch_info_type bfd_mcore_arch; +extern const bfd_arch_info_type bfd_avr_arch; +extern const bfd_arch_info_type bfd_ia64_arch; +extern const bfd_arch_info_type bfd_s390_arch; -static char *prt_num_mach (); -static boolean scan_num_mach (); -static char *prt_960_mach (); -static boolean scan_960_mach (); - -struct arch_print { - enum bfd_architecture arch; - char *astr; - char *(*mach_print)(); - boolean (*mach_scan)(); -} arch_print[] = { - - {bfd_arch_unknown, "unknown", prt_num_mach, scan_num_mach}, - {bfd_arch_obscure, "obscure", prt_num_mach, scan_num_mach}, - {bfd_arch_m68k, "m68k", prt_num_mach, scan_num_mach}, - {bfd_arch_vax, "vax", prt_num_mach, scan_num_mach}, - {bfd_arch_i960, "i960", prt_960_mach, scan_960_mach}, - {bfd_arch_a29k, "a29k", prt_num_mach, scan_num_mach}, - {bfd_arch_sparc, "sparc", prt_num_mach, scan_num_mach}, - {bfd_arch_mips, "mips", prt_num_mach, scan_num_mach}, - {bfd_arch_i386, "i386", prt_num_mach, scan_num_mach}, - {bfd_arch_ns32k, "ns32k", prt_num_mach, scan_num_mach}, - {bfd_arch_tahoe, "tahoe", prt_num_mach, scan_num_mach}, - {bfd_arch_i860, "i860", prt_num_mach, scan_num_mach}, - {bfd_arch_romp, "romp", prt_num_mach, scan_num_mach}, - {bfd_arch_alliant, "alliant", prt_num_mach, scan_num_mach}, - {bfd_arch_convex, "convex", prt_num_mach, scan_num_mach}, - {bfd_arch_m88k, "m88k", prt_num_mach, scan_num_mach}, - {bfd_arch_pyramid, "pyramid", prt_num_mach, scan_num_mach}, - {bfd_arch_h8_300, "H8/300", prt_num_mach, scan_num_mach}, - {bfd_arch_unknown, (char *)0, prt_num_mach, scan_num_mach}, +static const bfd_arch_info_type * const bfd_archures_list[] = { +#ifdef SELECT_ARCHITECTURES + SELECT_ARCHITECTURES, +#else + &bfd_a29k_arch, + &bfd_alpha_arch, + &bfd_arc_arch, + &bfd_arm_arch, + &bfd_cris_arch, + &bfd_d10v_arch, + &bfd_d30v_arch, + &bfd_h8300_arch, + &bfd_h8500_arch, + &bfd_hppa_arch, + &bfd_i370_arch, + &bfd_i386_arch, + &bfd_i860_arch, + &bfd_i960_arch, + &bfd_m32r_arch, + &bfd_m68hc11_arch, + &bfd_m68hc12_arch, + &bfd_m68k_arch, + &bfd_m88k_arch, + &bfd_mips_arch, + &bfd_mn10200_arch, + &bfd_mn10300_arch, + &bfd_pdp11_arch, + &bfd_powerpc_arch, + &bfd_rs6000_arch, + &bfd_sh_arch, + &bfd_sparc_arch, + &bfd_tic30_arch, + &bfd_tic54x_arch, + &bfd_tic80_arch, + &bfd_vax_arch, + &bfd_we32k_arch, + &bfd_z8k_arch, + &bfd_ns32k_arch, + &bfd_w65_arch, + &bfd_v850_arch, + &bfd_fr30_arch, + &bfd_mcore_arch, + &bfd_avr_arch, + &bfd_ia64_arch, + &bfd_s390_arch, +#endif + 0 }; -/*proto* bfd_prinable_arch_mach -Return a printable string representing the architecture and machine -type. The result is only good until the next call to -bfd_printable_arch_mach. -*; PROTO(CONST char *,bfd_printable_arch_mach, - (enum bfd_architecture arch, unsigned long machine)); +/* +FUNCTION + bfd_printable_name + +SYNOPSIS + const char *bfd_printable_name(bfd *abfd); + +DESCRIPTION + Return a printable string representing the architecture and machine + from the pointer to the architecture info structure. + */ -CONST char * -DEFUN(bfd_printable_arch_mach,(arch, machine), - enum bfd_architecture arch AND - unsigned long machine) +const char * +bfd_printable_name (abfd) + bfd *abfd; { - struct arch_print *ap; + return abfd->arch_info->printable_name; +} - for (ap = arch_print; ap->astr; ap++) { - if (ap->arch == arch) { - if (machine == 0) - return ap->astr; - return (*ap->mach_print)(ap, machine); +/* +FUNCTION + bfd_scan_arch + +SYNOPSIS + const bfd_arch_info_type *bfd_scan_arch(const char *string); + +DESCRIPTION + Figure out if BFD supports any cpu which could be described with + the name @var{string}. Return a pointer to an <> + structure if a machine is found, otherwise NULL. +*/ + +const bfd_arch_info_type * +bfd_scan_arch (string) + const char *string; +{ + const bfd_arch_info_type * const *app, *ap; + + /* Look through all the installed architectures. */ + for (app = bfd_archures_list; *app != NULL; app++) + { + for (ap = *app; ap != NULL; ap = ap->next) + { + if (ap->scan (ap, string)) + return ap; + } } - } - return "UNKNOWN!"; + + return NULL; } -static char * -prt_num_mach (ap, machine) - struct arch_print *ap; - unsigned long machine; +/* +FUNCTION + bfd_arch_list + +SYNOPSIS + const char **bfd_arch_list(void); + +DESCRIPTION + Return a freshly malloced NULL-terminated vector of the names + of all the valid BFD architectures. Do not modify the names. +*/ + +const char ** +bfd_arch_list () +{ + int vec_length = 0; + const char **name_ptr; + const char **name_list; + const bfd_arch_info_type * const *app; + + /* Determine the number of architectures. */ + vec_length = 0; + for (app = bfd_archures_list; *app != NULL; app++) + { + const bfd_arch_info_type *ap; + for (ap = *app; ap != NULL; ap = ap->next) + { + vec_length++; + } + } + + name_list = (const char **) + bfd_malloc ((vec_length + 1) * sizeof (char **)); + if (name_list == NULL) + return NULL; + + /* Point the list at each of the names. */ + name_ptr = name_list; + for (app = bfd_archures_list; *app != NULL; app++) + { + const bfd_arch_info_type *ap; + for (ap = *app; ap != NULL; ap = ap->next) + { + *name_ptr = ap->printable_name; + name_ptr++; + } + } + *name_ptr = NULL; + + return name_list; +} + +/* +FUNCTION + bfd_arch_get_compatible + +SYNOPSIS + const bfd_arch_info_type *bfd_arch_get_compatible( + const bfd *abfd, + const bfd *bbfd); + +DESCRIPTION + Determine whether two BFDs' + architectures and machine types are compatible. Calculates + the lowest common denominator between the two architectures + and machine types implied by the BFDs and returns a pointer to + an <> structure describing the compatible machine. +*/ + +const bfd_arch_info_type * +bfd_arch_get_compatible (abfd, bbfd) + const bfd *abfd; + const bfd *bbfd; { - static char result[20]; + /* If either architecture is unknown, then all we can do is assume + the user knows what he's doing. */ + if (abfd->arch_info->arch == bfd_arch_unknown) + return bbfd->arch_info; + if (bbfd->arch_info->arch == bfd_arch_unknown) + return abfd->arch_info; + + /* Otherwise architecture-specific code has to decide. */ + return abfd->arch_info->compatible (abfd->arch_info, bbfd->arch_info); +} + +/* +INTERNAL_DEFINITION + bfd_default_arch_struct + +DESCRIPTION + The <> is an item of + <> which has been initialized to a fairly + generic state. A BFD starts life by pointing to this + structure, until the correct back end has determined the real + architecture of the file. + +.extern const bfd_arch_info_type bfd_default_arch_struct; +*/ + +const bfd_arch_info_type bfd_default_arch_struct = { + 32, 32, 8, bfd_arch_unknown, 0, "unknown", "unknown", 2, true, + bfd_default_compatible, + bfd_default_scan, + 0, +}; + +/* +FUNCTION + bfd_set_arch_info + +SYNOPSIS + void bfd_set_arch_info(bfd *abfd, const bfd_arch_info_type *arg); - sprintf(result, "%s:%ld", ap->astr, (long) machine); - return result; +DESCRIPTION + Set the architecture info of @var{abfd} to @var{arg}. +*/ + +void +bfd_set_arch_info (abfd, arg) + bfd *abfd; + const bfd_arch_info_type *arg; +{ + abfd->arch_info = arg; } -/*proto* -*i bfd_scan_arch_mach -Scan a string and attempt to turn it into an archive and machine type combination. -*; PROTO(boolean, bfd_scan_arch_mach, - (CONST char *, enum bfd_architecture *, unsigned long *)); +/* +INTERNAL_FUNCTION + bfd_default_set_arch_mach + +SYNOPSIS + boolean bfd_default_set_arch_mach(bfd *abfd, + enum bfd_architecture arch, + unsigned long mach); + +DESCRIPTION + Set the architecture and machine type in BFD @var{abfd} + to @var{arch} and @var{mach}. Find the correct + pointer to a structure and insert it into the <> + pointer. */ boolean -DEFUN(bfd_scan_arch_mach,(string, archp, machinep), - CONST char *string AND - enum bfd_architecture *archp AND - unsigned long *machinep) +bfd_default_set_arch_mach (abfd, arch, mach) + bfd *abfd; + enum bfd_architecture arch; + unsigned long mach; { - struct arch_print *ap; - int len; - - /* First look for an architecture, possibly followed by machtype. */ - for (ap = arch_print; ap->astr; ap++) { - if (ap->astr[0] != string[0]) - continue; - len = strlen (ap->astr); - if (!strncmp (ap->astr, string, len)) { - /* We found the architecture, now see about the machine type */ - if (archp) - *archp = ap->arch; - if (string[len] != '\0') { - if (ap->mach_scan (string+len, ap, archp, machinep, 1)) - return true; - } - if (machinep) - *machinep = 0; - return true; - } - } + const bfd_arch_info_type * const *app, *ap; - /* Couldn't find an architecture -- try for just a machine type */ - for (ap = arch_print; ap->astr; ap++) { - if (ap->mach_scan (string, ap, archp, machinep, 0)) - return true; - } + for (app = bfd_archures_list; *app != NULL; app++) + { + for (ap = *app; ap != NULL; ap = ap->next) + { + if (ap->arch == arch + && (ap->mach == mach + || (mach == 0 && ap->the_default))) + { + abfd->arch_info = ap; + return true; + } + } + } + abfd->arch_info = &bfd_default_arch_struct; + bfd_set_error (bfd_error_bad_value); return false; } -static boolean -scan_num_mach (string, ap, archp, machinep, archspec) - char *string; - struct arch_print *ap; - enum bfd_architecture *archp; - unsigned long *machinep; - int archspec; +/* +FUNCTION + bfd_get_arch + +SYNOPSIS + enum bfd_architecture bfd_get_arch(bfd *abfd); + +DESCRIPTION + Return the enumerated type which describes the BFD @var{abfd}'s + architecture. +*/ + +enum bfd_architecture +bfd_get_arch (abfd) + bfd *abfd; +{ + return abfd->arch_info->arch; +} + +/* +FUNCTION + bfd_get_mach + +SYNOPSIS + unsigned long bfd_get_mach(bfd *abfd); + +DESCRIPTION + Return the long type which describes the BFD @var{abfd}'s + machine. +*/ + +unsigned long +bfd_get_mach (abfd) + bfd *abfd; +{ + return abfd->arch_info->mach; +} + +/* +FUNCTION + bfd_arch_bits_per_byte + +SYNOPSIS + unsigned int bfd_arch_bits_per_byte(bfd *abfd); + +DESCRIPTION + Return the number of bits in one of the BFD @var{abfd}'s + architecture's bytes. +*/ + +unsigned int +bfd_arch_bits_per_byte (abfd) + bfd *abfd; +{ + return abfd->arch_info->bits_per_byte; +} + +/* +FUNCTION + bfd_arch_bits_per_address + +SYNOPSIS + unsigned int bfd_arch_bits_per_address(bfd *abfd); + +DESCRIPTION + Return the number of bits in one of the BFD @var{abfd}'s + architecture's addresses. +*/ + +unsigned int +bfd_arch_bits_per_address (abfd) + bfd *abfd; +{ + return abfd->arch_info->bits_per_address; +} + +/* +INTERNAL_FUNCTION + bfd_default_compatible + +SYNOPSIS + const bfd_arch_info_type *bfd_default_compatible + (const bfd_arch_info_type *a, + const bfd_arch_info_type *b); + +DESCRIPTION + The default function for testing for compatibility. +*/ + +const bfd_arch_info_type * +bfd_default_compatible (a, b) + const bfd_arch_info_type *a; + const bfd_arch_info_type *b; +{ + if (a->arch != b->arch) + return NULL; + + if (a->mach > b->mach) + return a; + + if (b->mach > a->mach) + return b; + + return a; +} + +/* +INTERNAL_FUNCTION + bfd_default_scan + +SYNOPSIS + boolean bfd_default_scan(const struct bfd_arch_info *info, const char *string); + +DESCRIPTION + The default function for working out whether this is an + architecture hit and a machine hit. +*/ + +boolean +bfd_default_scan (info, string) + const struct bfd_arch_info *info; + const char *string; { + const char *ptr_src; + const char *ptr_tst; + unsigned long number; enum bfd_architecture arch; - unsigned long machine; - char achar; + const char *printable_name_colon; - if (archspec) { + /* Exact match of the architecture name (ARCH_NAME) and also the + default architecture? */ + if (strcasecmp (string, info->arch_name) == 0 + && info->the_default) + return true; - /* Architecture already specified, now go for machine type. */ - if (string[0] != ':') - return false; - /* We'll take any valid number that occupies the entire string */ - if (1 != sscanf (string+1, "%lu%c", &machine, &achar)) - return false; - arch = ap->arch; + /* Exact match of the machine name (PRINTABLE_NAME)? */ + if (strcasecmp (string, info->printable_name) == 0) + return true; - } else { + /* Given that printable_name contains no colon, attempt to match: + ARCH_NAME [ ":" ] PRINTABLE_NAME? */ + printable_name_colon = strchr (info->printable_name, ':'); + if (printable_name_colon == NULL) + { + int strlen_arch_name = strlen (info->arch_name); + if (strncasecmp (string, info->arch_name, strlen_arch_name) == 0) + { + if (string[strlen_arch_name] == ':') + { + if (strcasecmp (string + strlen_arch_name + 1, + info->printable_name) == 0) + return true; + } + else + { + if (strcasecmp (string + strlen_arch_name, + info->printable_name) == 0) + return true; + } + } + } - /* We couldn't identify an architecture prefix. Perhaps the entire - thing is a machine type. Be a lot picker. */ - if (1 != sscanf (string, "%lu%c", &machine, &achar)) - return false; - switch (machine) { + /* Given that PRINTABLE_NAME has the form: ":" ; + Attempt to match: ? */ + if (printable_name_colon != NULL) + { + int colon_index = printable_name_colon - info->printable_name; + if (strncasecmp (string, info->printable_name, colon_index) == 0 + && strcasecmp (string + colon_index, + info->printable_name + colon_index + 1) == 0) + return true; + } + + /* Given that PRINTABLE_NAME has the form: ":" ; Do not + attempt to match just , it could be ambigious. This test + is left until later. */ + + /* NOTE: The below is retained for compatibility only. Please do + not add to this code. */ + + /* See how much of the supplied string matches with the + architecture, eg the string m68k:68020 would match the 68k entry + up to the :, then we get left with the machine number. */ + + for (ptr_src = string, ptr_tst = info->arch_name; + *ptr_src && *ptr_tst; + ptr_src++, ptr_tst++) + { + if (*ptr_src != *ptr_tst) + break; + } + + /* Chewed up as much of the architecture as will match, skip any + colons. */ + if (*ptr_src == ':') + ptr_src++; + + if (*ptr_src == 0) + { + /* Nothing more, then only keep this one if it is the default + machine for this architecture. */ + return info->the_default; + } + + number = 0; + while (isdigit ((unsigned char) *ptr_src)) + { + number = number * 10 + *ptr_src - '0'; + ptr_src++; + } + + /* NOTE: The below is retained for compatibility only. + PLEASE DO NOT ADD TO THIS CODE. */ + + switch (number) + { + /* FIXME: These are needed to parse IEEE objects. */ + /* The following seven case's are here only for compatibility with + older binutils (at least IEEE objects from binutils 2.9.1 require + them). */ + case bfd_mach_m68000: + case bfd_mach_m68010: + case bfd_mach_m68020: + case bfd_mach_m68030: + case bfd_mach_m68040: + case bfd_mach_m68060: + case bfd_mach_cpu32: + arch = bfd_arch_m68k; + break; + case 68000: + arch = bfd_arch_m68k; + number = bfd_mach_m68000; + break; case 68010: + arch = bfd_arch_m68k; + number = bfd_mach_m68010; + break; case 68020: + arch = bfd_arch_m68k; + number = bfd_mach_m68020; + break; case 68030: + arch = bfd_arch_m68k; + number = bfd_mach_m68030; + break; case 68040: + arch = bfd_arch_m68k; + number = bfd_mach_m68040; + break; + case 68060: + arch = bfd_arch_m68k; + number = bfd_mach_m68060; + break; case 68332: - case 68050: arch = bfd_arch_m68k; break; - case 68000: arch = bfd_arch_m68k; machine = 0; break; + arch = bfd_arch_m68k; + number = bfd_mach_cpu32; + break; + + case 32000: + arch = bfd_arch_we32k; + break; + + case 3000: + arch = bfd_arch_mips; + number = bfd_mach_mips3000; + break; + + case 4000: + arch = bfd_arch_mips; + number = bfd_mach_mips4000; + break; - case 80960: - case 960: arch = bfd_arch_i960; machine = 0; break; + case 6000: + arch = bfd_arch_rs6000; + break; - case 386: - case 80386: arch = bfd_arch_i386; machine = 0; break; - case 486: arch = bfd_arch_i386; break; + case 7410: + arch = bfd_arch_sh; + number = bfd_mach_sh_dsp; + break; - case 29000: arch = bfd_arch_a29k; machine = 0; break; + case 7708: + arch = bfd_arch_sh; + number = bfd_mach_sh3; + break; - case 32016: - case 32032: - case 32132: - case 32232: - case 32332: - case 32432: - case 32532: arch = bfd_arch_ns32k; break; - case 32000: arch = bfd_arch_ns32k; machine = 0; break; + case 7729: + arch = bfd_arch_sh; + number = bfd_mach_sh3_dsp; + break; - case 860: - case 80860: arch = bfd_arch_i860; machine = 0; break; + case 7750: + arch = bfd_arch_sh; + number = bfd_mach_sh4; + break; - default: return false; + default: + return false; } - } - if (archp) - *archp = arch; - if (machinep) - *machinep = machine; + if (arch != info->arch) + return false; + + if (number != info->mach) + return false; + return true; } - -/* Intel 960 machine variants. */ -static char * -prt_960_mach (ap, machine) - struct arch_print *ap; - unsigned long machine; +/* +FUNCTION + bfd_get_arch_info + +SYNOPSIS + const bfd_arch_info_type * bfd_get_arch_info(bfd *abfd); + +DESCRIPTION + Return the architecture info struct in @var{abfd}. +*/ + +const bfd_arch_info_type * +bfd_get_arch_info (abfd) + bfd *abfd; { - static char result[20]; - char *str; - - switch (machine) { - case bfd_mach_i960_core: str = "core"; break; - case bfd_mach_i960_kb_sb: str = "kb"; break; - case bfd_mach_i960_mc: str = "mc"; break; - case bfd_mach_i960_xa: str = "xa"; break; - case bfd_mach_i960_ca: str = "ca"; break; - case bfd_mach_i960_ka_sa: str = "ka"; break; - default: - return prt_num_mach (ap, machine); - } - sprintf (result, "%s:%s", ap->astr, str); - return result; + return abfd->arch_info; } -static boolean -scan_960_mach (string, ap, archp, machinep, archspec) - char *string; - struct arch_print *ap; - enum bfd_architecture *archp; - unsigned long *machinep; - int archspec; +/* +FUNCTION + bfd_lookup_arch + +SYNOPSIS + const bfd_arch_info_type *bfd_lookup_arch + (enum bfd_architecture + arch, + unsigned long machine); + +DESCRIPTION + Look for the architecure info structure which matches the + arguments @var{arch} and @var{machine}. A machine of 0 matches the + machine/architecture structure which marks itself as the + default. +*/ + +const bfd_arch_info_type * +bfd_lookup_arch (arch, machine) + enum bfd_architecture arch; + unsigned long machine; { - unsigned long machine; + const bfd_arch_info_type * const *app, *ap; - if (!archspec) - return false; - if (string[0] != ':') - return false; - string++; - if (string[0] == '\0') - return false; - if (string[0] == 'c' && string[1] == 'o' && string[2] == 'r' && - string[3] == 'e' && string[4] == '\0') - machine = bfd_mach_i960_core; - else if (string[1] == '\0' || string[2] != '\0') /* rest are 2-char */ - return false; - else if (string[0] == 'k' && string[1] == 'b') - machine = bfd_mach_i960_kb_sb; - else if (string[0] == 's' && string[1] == 'b') - machine = bfd_mach_i960_kb_sb; - else if (string[0] == 'm' && string[1] == 'c') - machine = bfd_mach_i960_mc; - else if (string[0] == 'x' && string[1] == 'a') - machine = bfd_mach_i960_xa; - else if (string[0] == 'c' && string[1] == 'a') - machine = bfd_mach_i960_ca; - else if (string[0] == 'k' && string[1] == 'a') - machine = bfd_mach_i960_ka_sa; - else if (string[0] == 's' && string[1] == 'a') - machine = bfd_mach_i960_ka_sa; - else - return false; + for (app = bfd_archures_list; *app != NULL; app++) + { + for (ap = *app; ap != NULL; ap = ap->next) + { + if (ap->arch == arch + && (ap->mach == machine + || (machine == 0 && ap->the_default))) + return ap; + } + } - if (archp) - *archp = ap->arch; - if (machinep) - *machinep = machine; - return true; + return NULL; } +/* +FUNCTION + bfd_printable_arch_mach - -/*proto* -*i bfd_arch_compatible -This routine is used to determine whether two BFDs' architectures and machine types are -compatible. It calculates the lowest common denominator between the -two architectures and machine types implied by the bfds and sets the -objects pointed at by @var{archp} and @var{machine} if non NULL. +SYNOPSIS + const char *bfd_printable_arch_mach + (enum bfd_architecture arch, unsigned long machine); -This routine returns @code{true} if the bfds are of compatible type, -otherwise @code{false}. -*; PROTO(boolean, bfd_arch_compatible, - (bfd *abfd, - bfd *bbfd, - enum bfd_architecture *archp, - unsigned long *machinep)); -*-*/ +DESCRIPTION + Return a printable string representing the architecture and + machine type. -boolean -DEFUN(bfd_arch_compatible,(abfd, bbfd, archp, machinep), - bfd *abfd AND - bfd *bbfd AND - enum bfd_architecture *archp AND - unsigned long *machinep) + This routine is depreciated. +*/ + +const char * +bfd_printable_arch_mach (arch, machine) + enum bfd_architecture arch; + unsigned long machine; { - enum bfd_architecture archa, archb; - unsigned long macha, machb; - int pick_a; - - archa = bfd_get_architecture (abfd); - archb = bfd_get_architecture (bbfd); - macha = bfd_get_machine (abfd); - machb = bfd_get_machine (bbfd); - - if (archb == bfd_arch_unknown) - pick_a = 1; - else if (archa == bfd_arch_unknown) - pick_a = 0; - else if (archa != archb) - return false; /* Not compatible */ - else { - /* Architectures are the same. Check machine types. */ - if (macha == machb) /* Same machine type */ - pick_a = 1; - else if (machb == 0) /* B is default */ - pick_a = 1; - else if (macha == 0) /* A is default */ - pick_a = 0; - else switch (archa) { - /* If particular machine types of one architecture are not - compatible with each other, this is the place to put those tests - (returning false if incompatible). */ - - case bfd_arch_i960: - /* The i960 has two distinct subspecies which may not interbreed: - CORE CA - CORE KA KB MC - Any architecture on the same line is compatible, the one on - the right is the least restrictive. */ - /* So, if either is a ca then the other must be a be core or ca */ - if (macha == bfd_mach_i960_ca) { - if (machb != bfd_mach_i960_ca && - machb != bfd_mach_i960_core) { - return false; - } - pick_a = 1; - } - else if (machb == bfd_mach_i960_ca) { - if (macha != bfd_mach_i960_ca && - macha != bfd_mach_i960_core) { - return false; - } - pick_a = 0; - } - else { - /* This must be from the bottom row, so take the higest */ - pick_a = (macha > machb); - } - break; - - /* For these chips, as far as we care, "lower" numbers are included - by "higher" numbers, e.g. merge 68010 and 68020 into 68020, - 386 and 486 into 486, etc. This will need to change - if&when we care about things like 68332. */ - case bfd_arch_m68k: - case bfd_arch_ns32k: - case bfd_arch_i386: - pick_a = (macha > machb); - break; - - /* By default, pick first file's type, for lack of something better. */ - default: - pick_a = 1; - } - } - - /* Set result based on our pick */ - if (!pick_a) { - archa = archb; - macha = machb; - } - if (archp) - *archp = archa; - if (machinep) - *machinep = macha; + const bfd_arch_info_type *ap = bfd_lookup_arch (arch, machine); - return true; + if (ap) + return ap->printable_name; + return "UNKNOWN!"; } +/* +FUNCTION + bfd_octets_per_byte -/*proto* bfd_set_arch_mach -Set atch mach -*+ -#define bfd_set_arch_mach(abfd, arch, mach) \ - BFD_SEND (abfd, _bfd_set_arch_mach,\ - (abfd, arch, mach)) -*- +SYNOPSIS + unsigned int bfd_octets_per_byte(bfd *abfd); + +DESCRIPTION + Return the number of octets (8-bit quantities) per target byte + (minimum addressable unit). In most cases, this will be one, but some + DSP targets have 16, 32, or even 48 bits per byte. */ +unsigned int +bfd_octets_per_byte (abfd) + bfd *abfd; +{ + return bfd_arch_mach_octets_per_byte (bfd_get_arch (abfd), + bfd_get_mach (abfd)); +} -foo() { } +/* +FUNCTION + bfd_arch_mach_octets_per_byte +SYNOPSIS + unsigned int bfd_arch_mach_octets_per_byte(enum bfd_architecture arch, + unsigned long machine); +DESCRIPTION + See bfd_octets_per_byte. + This routine is provided for those cases where a bfd * is not + available +*/ + +unsigned int +bfd_arch_mach_octets_per_byte (arch, mach) + enum bfd_architecture arch; + unsigned long mach; +{ + const bfd_arch_info_type *ap = bfd_lookup_arch (arch, mach); + + if (ap) + return ap->bits_per_byte / 8; + return 1; +}