diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1997-05-29 09:30:28 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1997-05-29 09:30:28 +0000 |
commit | 5e8c4117fd51ae22bed414c7358df77884a216cf (patch) | |
tree | 11a6818390376768cc2c91b0c9a929723b71bebe | |
parent | 0939272cc89838d2549c2e7bcd4c5cf92eba738c (diff) |
Import of binutils-2.8.1 from Cygnus/FSF
169 files changed, 36271 insertions, 98 deletions
diff --git a/gnu/usr.bin/binutils/bfd/doc/aoutx.texi b/gnu/usr.bin/binutils/bfd/doc/aoutx.texi new file mode 100644 index 00000000000..a35fe9b7b88 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/aoutx.texi @@ -0,0 +1,211 @@ +@section a.out backends + +@* +@strong{Description}@* +BFD supports a number of different flavours of a.out format, +though the major differences are only the sizes of the +structures on disk, and the shape of the relocation +information. + +The support is split into a basic support file @file{aoutx.h} +and other files which derive functions from the base. One +derivation file is @file{aoutf1.h} (for a.out flavour 1), and +adds to the basic a.out functions support for sun3, sun4, 386 +and 29k a.out files, to create a target jump vector for a +specific target. + +This information is further split out into more specific files +for each machine, including @file{sunos.c} for sun3 and sun4, +@file{newsos3.c} for the Sony NEWS, and @file{demo64.c} for a +demonstration of a 64 bit a.out format. + +The base file @file{aoutx.h} defines general mechanisms for +reading and writing records to and from disk and various +other methods which BFD requires. It is included by +@file{aout32.c} and @file{aout64.c} to form the names +@code{aout_32_swap_exec_header_in}, @code{aout_64_swap_exec_header_in}, etc. + +As an example, this is what goes on to make the back end for a +sun4, from @file{aout32.c}: + +@example + #define ARCH_SIZE 32 + #include "aoutx.h" +@end example + +Which exports names: + +@example + ... + aout_32_canonicalize_reloc + aout_32_find_nearest_line + aout_32_get_lineno + aout_32_get_reloc_upper_bound + ... +@end example + +from @file{sunos.c}: + +@example + #define TARGET_NAME "a.out-sunos-big" + #define VECNAME sunos_big_vec + #include "aoutf1.h" +@end example + +requires all the names from @file{aout32.c}, and produces the jump vector + +@example + sunos_big_vec +@end example + +The file @file{host-aout.c} is a special case. It is for a large set +of hosts that use ``more or less standard'' a.out files, and +for which cross-debugging is not interesting. It uses the +standard 32-bit a.out support routines, but determines the +file offsets and addresses of the text, data, and BSS +sections, the machine architecture and machine type, and the +entry point address, in a host-dependent manner. Once these +values have been determined, generic code is used to handle +the object file. + +When porting it to run on a new system, you must supply: + +@example + HOST_PAGE_SIZE + HOST_SEGMENT_SIZE + HOST_MACHINE_ARCH (optional) + HOST_MACHINE_MACHINE (optional) + HOST_TEXT_START_ADDR + HOST_STACK_END_ADDR +@end example + +in the file @file{../include/sys/h-@var{XXX}.h} (for your host). These +values, plus the structures and macros defined in @file{a.out.h} on +your host system, will produce a BFD target that will access +ordinary a.out files on your host. To configure a new machine +to use @file{host-aout.c}, specify: + +@example + TDEFAULTS = -DDEFAULT_VECTOR=host_aout_big_vec + TDEPFILES= host-aout.o trad-core.o +@end example + +in the @file{config/@var{XXX}.mt} file, and modify @file{configure.in} +to use the +@file{@var{XXX}.mt} file (by setting "@code{bfd_target=XXX}") when your +configuration is selected. +@* +@subsection Relocations + +@* +@strong{Description}@* +The file @file{aoutx.h} provides for both the @emph{standard} +and @emph{extended} forms of a.out relocation records. + +The standard records contain only an +address, a symbol index, and a type field. The extended records +(used on 29ks and sparcs) also have a full integer for an +addend. +@* +@subsection Internal entry points + +@* +@strong{Description}@* +@file{aoutx.h} exports several routines for accessing the +contents of an a.out file, which are gathered and exported in +turn by various format specific files (eg sunos.c). +@* +@findex aout_@var{size}_swap_exec_header_in +@subsubsection @code{aout_@var{size}_swap_exec_header_in} +@strong{Synopsis} +@example +void aout_@var{size}_swap_exec_header_in, + (bfd *abfd, + struct external_exec *raw_bytes, + struct internal_exec *execp); +@end example +@strong{Description}@* +Swap the information in an executable header @var{raw_bytes} taken +from a raw byte stream memory image into the internal exec header +structure @var{execp}. +@* +@findex aout_@var{size}_swap_exec_header_out +@subsubsection @code{aout_@var{size}_swap_exec_header_out} +@strong{Synopsis} +@example +void aout_@var{size}_swap_exec_header_out + (bfd *abfd, + struct internal_exec *execp, + struct external_exec *raw_bytes); +@end example +@strong{Description}@* +Swap the information in an internal exec header structure +@var{execp} into the buffer @var{raw_bytes} ready for writing to disk. +@* +@findex aout_@var{size}_some_aout_object_p +@subsubsection @code{aout_@var{size}_some_aout_object_p} +@strong{Synopsis} +@example +const bfd_target *aout_@var{size}_some_aout_object_p + (bfd *abfd, + const bfd_target *(*callback_to_real_object_p)()); +@end example +@strong{Description}@* +Some a.out variant thinks that the file open in @var{abfd} +checking is an a.out file. Do some more checking, and set up +for access if it really is. Call back to the calling +environment's "finish up" function just before returning, to +handle any last-minute setup. +@* +@findex aout_@var{size}_mkobject +@subsubsection @code{aout_@var{size}_mkobject} +@strong{Synopsis} +@example +boolean aout_@var{size}_mkobject, (bfd *abfd); +@end example +@strong{Description}@* +Initialize BFD @var{abfd} for use with a.out files. +@* +@findex aout_@var{size}_machine_type +@subsubsection @code{aout_@var{size}_machine_type} +@strong{Synopsis} +@example +enum machine_type aout_@var{size}_machine_type + (enum bfd_architecture arch, + unsigned long machine)); + @end example +@strong{Description}@* +Keep track of machine architecture and machine type for +a.out's. Return the @code{machine_type} for a particular +architecture and machine, or @code{M_UNKNOWN} if that exact architecture +and machine can't be represented in a.out format. + +If the architecture is understood, machine type 0 (default) +is always understood. +@* +@findex aout_@var{size}_set_arch_mach +@subsubsection @code{aout_@var{size}_set_arch_mach} +@strong{Synopsis} +@example +boolean aout_@var{size}_set_arch_mach, + (bfd *, + enum bfd_architecture arch, + unsigned long machine)); + @end example +@strong{Description}@* +Set the architecture and the machine of the BFD @var{abfd} to the +values @var{arch} and @var{machine}. Verify that @var{abfd}'s format +can support the architecture required. +@* +@findex aout_@var{size}_new_section_hook +@subsubsection @code{aout_@var{size}_new_section_hook} +@strong{Synopsis} +@example +boolean aout_@var{size}_new_section_hook, + (bfd *abfd, + asection *newsect)); + @end example +@strong{Description}@* +Called by the BFD in response to a @code{bfd_make_section} +request. +@* diff --git a/gnu/usr.bin/binutils/bfd/doc/archive.texi b/gnu/usr.bin/binutils/bfd/doc/archive.texi new file mode 100644 index 00000000000..f8d6b89b939 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/archive.texi @@ -0,0 +1,95 @@ +@section Archives + +@* +@strong{Description}@* +An archive (or library) is just another BFD. It has a symbol +table, although there's not much a user program will do with it. + +The big difference between an archive BFD and an ordinary BFD +is that the archive doesn't have sections. Instead it has a +chain of BFDs that are considered its contents. These BFDs can +be manipulated like any other. The BFDs contained in an +archive opened for reading will all be opened for reading. You +may put either input or output BFDs into an archive opened for +output; they will be handled correctly when the archive is closed. + +Use @code{bfd_openr_next_archived_file} to step through +the contents of an archive opened for input. You don't +have to read the entire archive if you don't want +to! Read it until you find what you want. + +Archive contents of output BFDs are chained through the +@code{next} pointer in a BFD. The first one is findable through +the @code{archive_head} slot of the archive. Set it with +@code{bfd_set_archive_head} (q.v.). A given BFD may be in only one +open output archive at a time. + +As expected, the BFD archive code is more general than the +archive code of any given environment. BFD archives may +contain files of different formats (e.g., a.out and coff) and +even different architectures. You may even place archives +recursively into archives! + +This can cause unexpected confusion, since some archive +formats are more expressive than others. For instance, Intel +COFF archives can preserve long filenames; SunOS a.out archives +cannot. If you move a file from the first to the second +format and back again, the filename may be truncated. +Likewise, different a.out environments have different +conventions as to how they truncate filenames, whether they +preserve directory names in filenames, etc. When +interoperating with native tools, be sure your files are +homogeneous. + +Beware: most of these formats do not react well to the +presence of spaces in filenames. We do the best we can, but +can't always handle this case due to restrictions in the format of +archives. Many Unix utilities are braindead in regards to +spaces and such in filenames anyway, so this shouldn't be much +of a restriction. + +Archives are supported in BFD in @code{archive.c}. +@* +@findex bfd_get_next_mapent +@subsubsection @code{bfd_get_next_mapent} +@strong{Synopsis} +@example +symindex bfd_get_next_mapent(bfd *abfd, symindex previous, carsym **sym); +@end example +@strong{Description}@* +Step through archive @var{abfd}'s symbol table (if it +has one). Successively update @var{sym} with the next symbol's +information, returning that symbol's (internal) index into the +symbol table. + +Supply @code{BFD_NO_MORE_SYMBOLS} as the @var{previous} entry to get +the first one; returns @code{BFD_NO_MORE_SYMBOLS} when you've already +got the last one. + +A @code{carsym} is a canonical archive symbol. The only +user-visible element is its name, a null-terminated string. +@* +@findex bfd_set_archive_head +@subsubsection @code{bfd_set_archive_head} +@strong{Synopsis} +@example +boolean bfd_set_archive_head(bfd *output, bfd *new_head); +@end example +@strong{Description}@* +Set the head of the chain of +BFDs contained in the archive @var{output} to @var{new_head}. +@* +@findex bfd_openr_next_archived_file +@subsubsection @code{bfd_openr_next_archived_file} +@strong{Synopsis} +@example +bfd *bfd_openr_next_archived_file(bfd *archive, bfd *previous); +@end example +@strong{Description}@* +Provided a BFD, @var{archive}, containing an archive and NULL, open +an input BFD on the first contained element and returns that. +Subsequent calls should pass +the archive and the previous return value to return a created +BFD to the next contained element. NULL is returned when there +are no more. +@* diff --git a/gnu/usr.bin/binutils/bfd/doc/archures.texi b/gnu/usr.bin/binutils/bfd/doc/archures.texi new file mode 100644 index 00000000000..2dcc07476e8 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/archures.texi @@ -0,0 +1,307 @@ +@section Architectures +BFD keeps one atom in a BFD describing the +architecture of the data attached to the BFD: a pointer to a +@code{bfd_arch_info_type}. + +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 +@code{SELECT_ARCHITECTURES}. 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}. +@* +@subsection bfd_architecture + +@* +@strong{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. +@example +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 +#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_v9 6 +#define bfd_mach_sparc_v9a 7 /* with ultrasparc 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_v9a) + bfd_arch_mips, /* MIPS Rxxxx */ + bfd_arch_i386, /* Intel 386 */ +#define bfd_mach_i386_i386 0 +#define bfd_mach_i386_i8086 1 + bfd_arch_we32k, /* AT&T WE32xxx */ + bfd_arch_tahoe, /* CCI/Harris Tahoe */ + bfd_arch_i860, /* Intel 860 */ + 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_powerpc, /* PowerPC */ + bfd_arch_rs6000, /* IBM RS/6000 */ + bfd_arch_hppa, /* HP PA RISC */ + bfd_arch_d10v, /* Mitsubishi D10V */ + 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 */ + bfd_arch_alpha, /* Dec Alpha */ + bfd_arch_arm, /* Advanced Risc Machines ARM */ + bfd_arch_ns32k, /* National Semiconductors ns32000 */ + bfd_arch_w65, /* WDC 65816 */ + bfd_arch_m32r, /* Mitsubishi M32R/D */ + bfd_arch_mn10200, /* Matsushita MN10200 */ + bfd_arch_mn10300, /* Matsushita MN10300 */ + bfd_arch_last + @}; +@end example +@* +@subsection bfd_arch_info + +@* +@strong{Description}@* +This structure contains information on architectures for use +within BFD. +@example + +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; +@end example +@* +@findex bfd_printable_name +@subsubsection @code{bfd_printable_name} +@strong{Synopsis} +@example +const char *bfd_printable_name(bfd *abfd); +@end example +@strong{Description}@* +Return a printable string representing the architecture and machine +from the pointer to the architecture info structure. +@* +@findex bfd_scan_arch +@subsubsection @code{bfd_scan_arch} +@strong{Synopsis} +@example +const bfd_arch_info_type *bfd_scan_arch(const char *string); +@end example +@strong{Description}@* +Figure out if BFD supports any cpu which could be described with +the name @var{string}. Return a pointer to an @code{arch_info} +structure if a machine is found, otherwise NULL. +@* +@findex bfd_arch_get_compatible +@subsubsection @code{bfd_arch_get_compatible} +@strong{Synopsis} +@example +const bfd_arch_info_type *bfd_arch_get_compatible( + const bfd *abfd, + const bfd *bbfd); +@end example +@strong{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 @code{arch_info} structure describing the compatible machine. +@* +@findex bfd_default_arch_struct +@subsubsection @code{bfd_default_arch_struct} +@strong{Description}@* +The @code{bfd_default_arch_struct} is an item of +@code{bfd_arch_info_type} 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. +@example +extern const bfd_arch_info_type bfd_default_arch_struct; +@end example +@* +@findex bfd_set_arch_info +@subsubsection @code{bfd_set_arch_info} +@strong{Synopsis} +@example +void bfd_set_arch_info(bfd *abfd, const bfd_arch_info_type *arg); +@end example +@strong{Description}@* +Set the architecture info of @var{abfd} to @var{arg}. +@* +@findex bfd_default_set_arch_mach +@subsubsection @code{bfd_default_set_arch_mach} +@strong{Synopsis} +@example +boolean bfd_default_set_arch_mach(bfd *abfd, + enum bfd_architecture arch, + unsigned long mach); +@end example +@strong{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 @code{arch_info} +pointer. +@* +@findex bfd_get_arch +@subsubsection @code{bfd_get_arch} +@strong{Synopsis} +@example +enum bfd_architecture bfd_get_arch(bfd *abfd); +@end example +@strong{Description}@* +Return the enumerated type which describes the BFD @var{abfd}'s +architecture. +@* +@findex bfd_get_mach +@subsubsection @code{bfd_get_mach} +@strong{Synopsis} +@example +unsigned long bfd_get_mach(bfd *abfd); +@end example +@strong{Description}@* +Return the long type which describes the BFD @var{abfd}'s +machine. +@* +@findex bfd_arch_bits_per_byte +@subsubsection @code{bfd_arch_bits_per_byte} +@strong{Synopsis} +@example +unsigned int bfd_arch_bits_per_byte(bfd *abfd); +@end example +@strong{Description}@* +Return the number of bits in one of the BFD @var{abfd}'s +architecture's bytes. +@* +@findex bfd_arch_bits_per_address +@subsubsection @code{bfd_arch_bits_per_address} +@strong{Synopsis} +@example +unsigned int bfd_arch_bits_per_address(bfd *abfd); +@end example +@strong{Description}@* +Return the number of bits in one of the BFD @var{abfd}'s +architecture's addresses. +@* +@findex bfd_default_compatible +@subsubsection @code{bfd_default_compatible} +@strong{Synopsis} +@example +const bfd_arch_info_type *bfd_default_compatible + (const bfd_arch_info_type *a, + const bfd_arch_info_type *b); +@end example +@strong{Description}@* +The default function for testing for compatibility. +@* +@findex bfd_default_scan +@subsubsection @code{bfd_default_scan} +@strong{Synopsis} +@example +boolean bfd_default_scan(const struct bfd_arch_info *info, const char *string); +@end example +@strong{Description}@* +The default function for working out whether this is an +architecture hit and a machine hit. +@* +@findex bfd_get_arch_info +@subsubsection @code{bfd_get_arch_info} +@strong{Synopsis} +@example +const bfd_arch_info_type * bfd_get_arch_info(bfd *abfd); +@end example +@strong{Description}@* +Return the architecture info struct in @var{abfd}. +@* +@findex bfd_lookup_arch +@subsubsection @code{bfd_lookup_arch} +@strong{Synopsis} +@example +const bfd_arch_info_type *bfd_lookup_arch + (enum bfd_architecture + arch, + unsigned long machine); +@end example +@strong{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. +@* +@findex bfd_printable_arch_mach +@subsubsection @code{bfd_printable_arch_mach} +@strong{Synopsis} +@example +const char *bfd_printable_arch_mach + (enum bfd_architecture arch, unsigned long machine); +@end example +@strong{Description}@* +Return a printable string representing the architecture and +machine type. + +This routine is depreciated. +@* diff --git a/gnu/usr.bin/binutils/bfd/doc/bfd.info b/gnu/usr.bin/binutils/bfd/doc/bfd.info new file mode 100644 index 00000000000..f8ea24b8a6d --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/bfd.info @@ -0,0 +1,94 @@ +This is Info file bfd.info, produced by Makeinfo-1.64 from the input +file ./bfd.texinfo. + +START-INFO-DIR-ENTRY +* Bfd: (bfd). The Binary File Descriptor library. +END-INFO-DIR-ENTRY + + This file documents the BFD library. + + Copyright (C) 1991 Free Software Foundation, Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + + Permission is granted to copy and distribute modified versions of +this manual under the conditions for verbatim copying, subject to the +terms of the GNU General Public License, which includes the provision +that the entire resulting derived work is distributed under the terms +of a permission notice identical to this one. + + Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions. + + +Indirect: +bfd.info-1: 936 +bfd.info-2: 50487 +bfd.info-3: 91356 +bfd.info-4: 139850 +bfd.info-5: 181537 + +Tag Table: +(Indirect) +Node: Top936 +Node: Overview1201 +Node: History2251 +Node: How It Works3192 +Node: What BFD Version 2 Can Do4733 +Node: BFD information loss6047 +Node: Canonical format8570 +Node: BFD front end12931 +Node: Memory Usage31295 +Node: Initialization32518 +Node: Sections32890 +Node: Section Input33365 +Node: Section Output34717 +Node: typedef asection37178 +Node: section prototypes50487 +Node: Symbols56231 +Node: Reading Symbols57818 +Node: Writing Symbols58898 +Node: Mini Symbols60458 +Node: typedef asymbol61419 +Node: symbol handling functions66065 +Node: Archives70069 +Node: Formats73671 +Node: Relocations76452 +Node: typedef arelent77168 +Node: howto manager91356 +Node: Core Files106226 +Node: Targets107231 +Node: bfd_target109189 +Node: Architectures126860 +Node: Opening and Closing136295 +Node: Internal139850 +Node: File Caching144788 +Node: Linker Functions147532 +Node: Creating a Linker Hash Table149195 +Node: Adding Symbols to the Hash Table150918 +Node: Differing file formats151804 +Node: Adding symbols from an object file153533 +Node: Adding symbols from an archive155665 +Node: Performing the Final Link158060 +Node: Information provided by the linker159288 +Node: Relocating the section contents160420 +Node: Writing the symbol table162153 +Node: Hash Tables164740 +Node: Creating and Freeing a Hash Table165928 +Node: Looking Up or Entering a String167080 +Node: Traversing a Hash Table168318 +Node: Deriving a New Hash Table Type169092 +Node: Define the Derived Structures170144 +Node: Write the Derived Creation Routine171206 +Node: Write Other Derived Routines173884 +Node: BFD back ends175180 +Node: What to Put Where175399 +Node: aout175537 +Node: coff181537 +Node: elf206935 +Node: Index207760 + +End Tag Table diff --git a/gnu/usr.bin/binutils/bfd/doc/bfd.info-1 b/gnu/usr.bin/binutils/bfd/doc/bfd.info-1 new file mode 100644 index 00000000000..cb26d46ed74 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/bfd.info-1 @@ -0,0 +1,1306 @@ +This is Info file bfd.info, produced by Makeinfo-1.64 from the input +file ./bfd.texinfo. + +START-INFO-DIR-ENTRY +* Bfd: (bfd). The Binary File Descriptor library. +END-INFO-DIR-ENTRY + + This file documents the BFD library. + + Copyright (C) 1991 Free Software Foundation, Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + + Permission is granted to copy and distribute modified versions of +this manual under the conditions for verbatim copying, subject to the +terms of the GNU General Public License, which includes the provision +that the entire resulting derived work is distributed under the terms +of a permission notice identical to this one. + + Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions. + + +File: bfd.info, Node: Top, Next: Overview, Prev: (dir), Up: (dir) + + This file documents the binary file descriptor library libbfd. + +* Menu: + +* Overview:: Overview of BFD +* BFD front end:: BFD front end +* BFD back ends:: BFD back ends +* Index:: Index + + +File: bfd.info, Node: Overview, Next: BFD front end, Prev: Top, Up: Top + +Introduction +************ + + BFD is a package which allows applications to use the same routines +to operate on object files whatever the object file format. A new +object file format can be supported simply by creating a new BFD back +end and adding it to the library. + + BFD is split into two parts: the front end, and the back ends (one +for each object file format). + * The front end of BFD provides the interface to the user. It manages + memory and various canonical data structures. The front end also + decides which back end to use and when to call back end routines. + + * The back ends provide BFD its view of the real world. Each back + end provides a set of calls which the BFD front end can use to + maintain its canonical form. The back ends also may keep around + information for their own use, for greater efficiency. + +* Menu: + +* History:: History +* How It Works:: How It Works +* What BFD Version 2 Can Do:: What BFD Version 2 Can Do + + +File: bfd.info, Node: History, Next: How It Works, Prev: Overview, Up: Overview + +History +======= + + One spur behind BFD was the desire, on the part of the GNU 960 team +at Intel Oregon, for interoperability of applications on their COFF and +b.out file formats. Cygnus was providing GNU support for the team, and +was contracted to provide the required functionality. + + The name came from a conversation David Wallace was having with +Richard Stallman about the library: RMS said that it would be quite +hard--David said "BFD". Stallman was right, but the name stuck. + + At the same time, Ready Systems wanted much the same thing, but for +different object file formats: IEEE-695, Oasys, Srecords, a.out and 68k +coff. + + BFD was first implemented by members of Cygnus Support; Steve +Chamberlain (`sac@cygnus.com'), John Gilmore (`gnu@cygnus.com'), K. +Richard Pixley (`rich@cygnus.com') and David Henkel-Wallace +(`gumby@cygnus.com'). + + +File: bfd.info, Node: How It Works, Next: What BFD Version 2 Can Do, Prev: History, Up: Overview + +How To Use BFD +============== + + To use the library, include `bfd.h' and link with `libbfd.a'. + + BFD provides a common interface to the parts of an object file for a +calling application. + + When an application sucessfully opens a target file (object, +archive, or whatever), a pointer to an internal structure is returned. +This pointer points to a structure called `bfd', described in `bfd.h'. +Our convention is to call this pointer a BFD, and instances of it +within code `abfd'. All operations on the target object file are +applied as methods to the BFD. The mapping is defined within `bfd.h' +in a set of macros, all beginning with `bfd_' to reduce namespace +pollution. + + For example, this sequence does what you would probably expect: +return the number of sections in an object file attached to a BFD +`abfd'. + + #include "bfd.h" + + unsigned int number_of_sections(abfd) + bfd *abfd; + { + return bfd_count_sections(abfd); + } + + The abstraction used within BFD is that an object file has: + + * a header, + + * a number of sections containing raw data (*note Sections::.), + + * a set of relocations (*note Relocations::.), and + + * some symbol information (*note Symbols::.). + +Also, BFDs opened for archives have the additional attribute of an index +and contain subordinate BFDs. This approach is fine for a.out and coff, +but loses efficiency when applied to formats such as S-records and +IEEE-695. + + +File: bfd.info, Node: What BFD Version 2 Can Do, Prev: How It Works, Up: Overview + +What BFD Version 2 Can Do +========================= + + When an object file is opened, BFD subroutines automatically +determine the format of the input object file. They then build a +descriptor in memory with pointers to routines that will be used to +access elements of the object file's data structures. + + As different information from the the object files is required, BFD +reads from different sections of the file and processes them. For +example, a very common operation for the linker is processing symbol +tables. Each BFD back end provides a routine for converting between +the object file's representation of symbols and an internal canonical +format. When the linker asks for the symbol table of an object file, it +calls through a memory pointer to the routine from the relevant BFD +back end which reads and converts the table into a canonical form. The +linker then operates upon the canonical form. When the link is finished +and the linker writes the output file's symbol table, another BFD back +end routine is called to take the newly created symbol table and +convert it into the chosen output format. + +* Menu: + +* BFD information loss:: Information Loss +* Canonical format:: The BFD canonical object-file format + + +File: bfd.info, Node: BFD information loss, Next: Canonical format, Up: What BFD Version 2 Can Do + +Information Loss +---------------- + + *Information can be lost during output.* The output formats +supported by BFD do not provide identical facilities, and information +which can be described in one form has nowhere to go in another format. +One example of this is alignment information in `b.out'. There is +nowhere in an `a.out' format file to store alignment information on the +contained data, so when a file is linked from `b.out' and an `a.out' +image is produced, alignment information will not propagate to the +output file. (The linker will still use the alignment information +internally, so the link is performed correctly). + + Another example is COFF section names. COFF files may contain an +unlimited number of sections, each one with a textual section name. If +the target of the link is a format which does not have many sections +(e.g., `a.out') or has sections without names (e.g., the Oasys format), +the link cannot be done simply. You can circumvent this problem by +describing the desired input-to-output section mapping with the linker +command language. + + *Information can be lost during canonicalization.* The BFD internal +canonical form of the external formats is not exhaustive; there are +structures in input formats for which there is no direct representation +internally. This means that the BFD back ends cannot maintain all +possible data richness through the transformation between external to +internal and back to external formats. + + This limitation is only a problem when an application reads one +format and writes another. Each BFD back end is responsible for +maintaining as much data as possible, and the internal BFD canonical +form has structures which are opaque to the BFD core, and exported only +to the back ends. When a file is read in one format, the canonical form +is generated for BFD and the application. At the same time, the back +end saves away any information which may otherwise be lost. If the data +is then written back in the same format, the back end routine will be +able to use the canonical form provided by the BFD core as well as the +information it prepared earlier. Since there is a great deal of +commonality between back ends, there is no information lost when +linking or copying big endian COFF to little endian COFF, or `a.out' to +`b.out'. When a mixture of formats is linked, the information is only +lost from the files whose format differs from the destination. + + +File: bfd.info, Node: Canonical format, Prev: BFD information loss, Up: What BFD Version 2 Can Do + +The BFD canonical object-file format +------------------------------------ + + The greatest potential for loss of information occurs when there is +the least overlap between the information provided by the source +format, that stored by the canonical format, and that needed by the +destination format. A brief description of the canonical form may help +you understand which kinds of data you can count on preserving across +conversions. + +*files* + Information stored on a per-file basis includes target machine + architecture, particular implementation format type, a demand + pageable bit, and a write protected bit. Information like Unix + magic numbers is not stored here--only the magic numbers' meaning, + so a `ZMAGIC' file would have both the demand pageable bit and the + write protected text bit set. The byte order of the target is + stored on a per-file basis, so that big- and little-endian object + files may be used with one another. + +*sections* + Each section in the input file contains the name of the section, + the section's original address in the object file, size and + alignment information, various flags, and pointers into other BFD + data structures. + +*symbols* + Each symbol contains a pointer to the information for the object + file which originally defined it, its name, its value, and various + flag bits. When a BFD back end reads in a symbol table, it + relocates all symbols to make them relative to the base of the + section where they were defined. Doing this ensures that each + symbol points to its containing section. Each symbol also has a + varying amount of hidden private data for the BFD back end. Since + the symbol points to the original file, the private data format + for that symbol is accessible. `ld' can operate on a collection + of symbols of wildly different formats without problems. + + Normal global and simple local symbols are maintained on output, + so an output file (no matter its format) will retain symbols + pointing to functions and to global, static, and common variables. + Some symbol information is not worth retaining; in `a.out', type + information is stored in the symbol table as long symbol names. + This information would be useless to most COFF debuggers; the + linker has command line switches to allow users to throw it away. + + There is one word of type information within the symbol, so if the + format supports symbol type information within symbols (for + example, COFF, IEEE, Oasys) and the type is simple enough to fit + within one word (nearly everything but aggregates), the + information will be preserved. + +*relocation level* + Each canonical BFD relocation record contains a pointer to the + symbol to relocate to, the offset of the data to relocate, the + section the data is in, and a pointer to a relocation type + descriptor. Relocation is performed by passing messages through + the relocation type descriptor and the symbol pointer. Therefore, + relocations can be performed on output data using a relocation + method that is only available in one of the input formats. For + instance, Oasys provides a byte relocation format. A relocation + record requesting this relocation type would point indirectly to a + routine to perform this, so the relocation may be performed on a + byte being written to a 68k COFF file, even though 68k COFF has no + such relocation type. + +*line numbers* + Object formats can contain, for debugging purposes, some form of + mapping between symbols, source line numbers, and addresses in the + output file. These addresses have to be relocated along with the + symbol information. Each symbol with an associated list of line + number records points to the first record of the list. The head + of a line number list consists of a pointer to the symbol, which + allows finding out the address of the function whose line number + is being described. The rest of the list is made up of pairs: + offsets into the section and line numbers. Any format which can + simply derive this information can pass it successfully between + formats (COFF, IEEE and Oasys). + + +File: bfd.info, Node: BFD front end, Next: BFD back ends, Prev: Overview, Up: Top + +BFD front end +************* + +`typedef bfd' +============= + + A BFD has type `bfd'; objects of this type are the cornerstone of +any application using BFD. Using BFD consists of making references +though the BFD and to data in the BFD. + + Here is the structure that defines the type `bfd'. It contains the +major data about the file and pointers to the rest of the data. +. + struct _bfd + { + /* The filename the application opened the BFD with. */ + CONST char *filename; + + /* A pointer to the target jump table. */ + const struct bfd_target *xvec; + + /* To avoid dragging too many header files into every file that + includes ``bfd.h'', IOSTREAM has been declared as a "char + *", and MTIME as a "long". Their correct types, to which they + are cast when used, are "FILE *" and "time_t". The iostream + is the result of an fopen on the filename. However, if the + BFD_IN_MEMORY flag is set, then iostream is actually a pointer + to a bfd_in_memory struct. */ + PTR iostream; + + /* Is the file descriptor being cached? That is, can it be closed as + needed, and re-opened when accessed later? */ + + boolean cacheable; + + /* Marks whether there was a default target specified when the + BFD was opened. This is used to select which matching algorithm + to use to choose the back end. */ + + boolean target_defaulted; + + /* The caching routines use these to maintain a + least-recently-used list of BFDs */ + + struct _bfd *lru_prev, *lru_next; + + /* When a file is closed by the caching routines, BFD retains + state information on the file here: */ + + file_ptr where; + + /* and here: (``once'' means at least once) */ + + boolean opened_once; + + /* Set if we have a locally maintained mtime value, rather than + getting it from the file each time: */ + + boolean mtime_set; + + /* File modified time, if mtime_set is true: */ + + long mtime; + + /* Reserved for an unimplemented file locking extension.*/ + + int ifd; + + /* The format which belongs to the BFD. (object, core, etc.) */ + + bfd_format format; + + /* The direction the BFD was opened with*/ + + enum bfd_direction {no_direction = 0, + read_direction = 1, + write_direction = 2, + both_direction = 3} direction; + + /* Format_specific flags*/ + + flagword flags; + + /* Currently my_archive is tested before adding origin to + anything. I believe that this can become always an add of + origin, with origin set to 0 for non archive files. */ + + file_ptr origin; + + /* Remember when output has begun, to stop strange things + from happening. */ + boolean output_has_begun; + + /* Pointer to linked list of sections*/ + struct sec *sections; + + /* The number of sections */ + unsigned int section_count; + + /* Stuff only useful for object files: + The start address. */ + bfd_vma start_address; + + /* Used for input and output*/ + unsigned int symcount; + + /* Symbol table for output BFD (with symcount entries) */ + struct symbol_cache_entry **outsymbols; + + /* Pointer to structure which contains architecture information*/ + const struct bfd_arch_info *arch_info; + + /* Stuff only useful for archives:*/ + PTR arelt_data; + struct _bfd *my_archive; /* The containing archive BFD. */ + struct _bfd *next; /* The next BFD in the archive. */ + struct _bfd *archive_head; /* The first BFD in the archive. */ + boolean has_armap; + + /* A chain of BFD structures involved in a link. */ + struct _bfd *link_next; + + /* A field used by _bfd_generic_link_add_archive_symbols. This will + be used only for archive elements. */ + int archive_pass; + + /* Used by the back end to hold private data. */ + + union + { + struct aout_data_struct *aout_data; + struct artdata *aout_ar_data; + struct _oasys_data *oasys_obj_data; + struct _oasys_ar_data *oasys_ar_data; + struct coff_tdata *coff_obj_data; + struct pe_tdata *pe_obj_data; + struct xcoff_tdata *xcoff_obj_data; + struct ecoff_tdata *ecoff_obj_data; + struct ieee_data_struct *ieee_data; + struct ieee_ar_data_struct *ieee_ar_data; + struct srec_data_struct *srec_data; + struct ihex_data_struct *ihex_data; + struct tekhex_data_struct *tekhex_data; + struct elf_obj_tdata *elf_obj_data; + struct nlm_obj_tdata *nlm_obj_data; + struct bout_data_struct *bout_data; + struct sun_core_struct *sun_core_data; + struct trad_core_struct *trad_core_data; + struct som_data_struct *som_data; + struct hpux_core_struct *hpux_core_data; + struct hppabsd_core_struct *hppabsd_core_data; + struct sgi_core_struct *sgi_core_data; + struct lynx_core_struct *lynx_core_data; + struct osf_core_struct *osf_core_data; + struct cisco_core_struct *cisco_core_data; + struct versados_data_struct *versados_data; + struct netbsd_core_struct *netbsd_core_data; + PTR any; + } tdata; + + /* Used by the application to hold private data*/ + PTR usrdata; + + /* Where all the allocated stuff under this BFD goes. This is a + struct objalloc *, but we use PTR to avoid requiring the inclusion of + objalloc.h. */ + PTR memory; + }; + +Error reporting +=============== + + Most BFD functions return nonzero on success (check their individual +documentation for precise semantics). On an error, they call +`bfd_set_error' to set an error condition that callers can check by +calling `bfd_get_error'. If that returns `bfd_error_system_call', then +check `errno'. + + The easiest way to report a BFD error to the user is to use +`bfd_perror'. +Type `bfd_error_type' +--------------------- + +The values returned by `bfd_get_error' are defined by the enumerated +type `bfd_error_type'. +. + typedef enum bfd_error + { + bfd_error_no_error = 0, + bfd_error_system_call, + bfd_error_invalid_target, + bfd_error_wrong_format, + bfd_error_invalid_operation, + bfd_error_no_memory, + bfd_error_no_symbols, + bfd_error_no_armap, + bfd_error_no_more_archived_files, + bfd_error_malformed_archive, + bfd_error_file_not_recognized, + bfd_error_file_ambiguously_recognized, + bfd_error_no_contents, + bfd_error_nonrepresentable_section, + bfd_error_no_debug_section, + bfd_error_bad_value, + bfd_error_file_truncated, + bfd_error_file_too_big, + bfd_error_invalid_error_code + } bfd_error_type; + +`bfd_get_error' +............... + + *Synopsis* + bfd_error_type bfd_get_error (void); + *Description* +Return the current BFD error condition. +`bfd_set_error' +............... + +*Synopsis* + void bfd_set_error (bfd_error_type error_tag); + *Description* +Set the BFD error condition to be ERROR_TAG. +`bfd_errmsg' +............ + +*Synopsis* + CONST char *bfd_errmsg (bfd_error_type error_tag); + *Description* +Return a string describing the error ERROR_TAG, or the system error if +ERROR_TAG is `bfd_error_system_call'. +`bfd_perror' +............ + +*Synopsis* + void bfd_perror (CONST char *message); + *Description* +Print to the standard error stream a string describing the last BFD +error that occurred, or the last system error if the last BFD error was +a system call failure. If MESSAGE is non-NULL and non-empty, the error +string printed is preceded by MESSAGE, a colon, and a space. It is +followed by a newline. +BFD error handler +----------------- + +Some BFD functions want to print messages describing the problem. They +call a BFD error handler function. This function may be overriden by +the program. + + The BFD error handler acts like printf. +. + typedef void (*bfd_error_handler_type) PARAMS ((const char *, ...)); + +`bfd_set_error_handler' +....................... + + *Synopsis* + bfd_error_handler_type bfd_set_error_handler (bfd_error_handler_type); + *Description* +Set the BFD error handler function. Returns the previous function. +`bfd_set_error_program_name' +............................ + +*Synopsis* + void bfd_set_error_program_name (const char *); + *Description* +Set the program name to use when printing a BFD error. This is printed +before the error message followed by a colon and space. The string +must not be changed after it is passed to this function. +Symbols +======= + +`bfd_get_reloc_upper_bound' +........................... + +*Synopsis* + long bfd_get_reloc_upper_bound(bfd *abfd, asection *sect); + *Description* +Return the number of bytes required to store the relocation information +associated with section SECT attached to bfd ABFD. If an error occurs, +return -1. +`bfd_canonicalize_reloc' +........................ + +*Synopsis* + long bfd_canonicalize_reloc + (bfd *abfd, + asection *sec, + arelent **loc, + asymbol **syms); + *Description* +Call the back end associated with the open BFD ABFD and translate the +external form of the relocation information attached to SEC into the +internal canonical form. Place the table into memory at LOC, which has +been preallocated, usually by a call to `bfd_get_reloc_upper_bound'. +Returns the number of relocs, or -1 on error. + + The SYMS table is also needed for horrible internal magic reasons. +`bfd_set_reloc' +............... + +*Synopsis* + void bfd_set_reloc + (bfd *abfd, asection *sec, arelent **rel, unsigned int count) + *Description* +Set the relocation pointer and count within section SEC to the values +REL and COUNT. The argument ABFD is ignored. +`bfd_set_file_flags' +.................... + +*Synopsis* + boolean bfd_set_file_flags(bfd *abfd, flagword flags); + *Description* +Set the flag word in the BFD ABFD to the value FLAGS. + + Possible errors are: + * `bfd_error_wrong_format' - The target bfd was not of object format. + + * `bfd_error_invalid_operation' - The target bfd was open for + reading. + + * `bfd_error_invalid_operation' - The flag word contained a bit + which was not applicable to the type of file. E.g., an attempt + was made to set the `D_PAGED' bit on a BFD format which does not + support demand paging. +`bfd_set_start_address' +....................... + +*Synopsis* + boolean bfd_set_start_address(bfd *abfd, bfd_vma vma); + *Description* +Make VMA the entry point of output BFD ABFD. +*Returns* +Returns `true' on success, `false' otherwise. +`bfd_get_mtime' +............... + +*Synopsis* + long bfd_get_mtime(bfd *abfd); + *Description* +Return the file modification time (as read from the file system, or +from the archive header for archive members). +`bfd_get_size' +.............. + +*Synopsis* + long bfd_get_size(bfd *abfd); + *Description* +Return the file size (as read from file system) for the file associated +with BFD ABFD. + + The initial motivation for, and use of, this routine is not so we +can get the exact size of the object the BFD applies to, since that +might not be generally possible (archive members for example). It +would be ideal if someone could eventually modify it so that such +results were guaranteed. + + Instead, we want to ask questions like "is this NNN byte sized +object I'm about to try read from file offset YYY reasonable?" As as +example of where we might do this, some object formats use string +tables for which the first `sizeof(long)' bytes of the table contain +the size of the table itself, including the size bytes. If an +application tries to read what it thinks is one of these string tables, +without some way to validate the size, and for some reason the size is +wrong (byte swapping error, wrong location for the string table, etc.), +the only clue is likely to be a read error when it tries to read the +table, or a "virtual memory exhausted" error when it tries to allocate +15 bazillon bytes of space for the 15 bazillon byte table it is about +to read. This function at least allows us to answer the quesion, "is +the size reasonable?". +`bfd_get_gp_size' +................. + +*Synopsis* + int bfd_get_gp_size(bfd *abfd); + *Description* +Return the maximum size of objects to be optimized using the GP +register under MIPS ECOFF. This is typically set by the `-G' argument +to the compiler, assembler or linker. +`bfd_set_gp_size' +................. + +*Synopsis* + void bfd_set_gp_size(bfd *abfd, int i); + *Description* +Set the maximum size of objects to be optimized using the GP register +under ECOFF or MIPS ELF. This is typically set by the `-G' argument to +the compiler, assembler or linker. +`bfd_scan_vma' +.............. + +*Synopsis* + bfd_vma bfd_scan_vma(CONST char *string, CONST char **end, int base); + *Description* +Convert, like `strtoul', a numerical expression STRING into a `bfd_vma' +integer, and return that integer. (Though without as many bells and +whistles as `strtoul'.) The expression is assumed to be unsigned (i.e., +positive). If given a BASE, it is used as the base for conversion. A +base of 0 causes the function to interpret the string in hex if a +leading "0x" or "0X" is found, otherwise in octal if a leading zero is +found, otherwise in decimal. + + Overflow is not detected. +`bfd_copy_private_bfd_data' +........................... + +*Synopsis* + boolean bfd_copy_private_bfd_data(bfd *ibfd, bfd *obfd); + *Description* +Copy private BFD information from the BFD IBFD to the the BFD OBFD. +Return `true' on success, `false' on error. Possible error returns are: + + * `bfd_error_no_memory' - Not enough memory exists to create private + data for OBFD. + #define bfd_copy_private_bfd_data(ibfd, obfd) \ + BFD_SEND (obfd, _bfd_copy_private_bfd_data, \ + (ibfd, obfd)) + +`bfd_merge_private_bfd_data' +............................ + +*Synopsis* + boolean bfd_merge_private_bfd_data(bfd *ibfd, bfd *obfd); + *Description* +Merge private BFD information from the BFD IBFD to the the output file +BFD OBFD when linking. Return `true' on success, `false' on error. +Possible error returns are: + + * `bfd_error_no_memory' - Not enough memory exists to create private + data for OBFD. + #define bfd_merge_private_bfd_data(ibfd, obfd) \ + BFD_SEND (obfd, _bfd_merge_private_bfd_data, \ + (ibfd, obfd)) + +`bfd_set_private_flags' +....................... + +*Synopsis* + boolean bfd_set_private_flags(bfd *abfd, flagword flags); + *Description* +Set private BFD flag information in the BFD ABFD. Return `true' on +success, `false' on error. Possible error returns are: + + * `bfd_error_no_memory' - Not enough memory exists to create private + data for OBFD. + #define bfd_set_private_flags(abfd, flags) \ + BFD_SEND (abfd, _bfd_set_private_flags, \ + (abfd, flags)) + +`stuff' +....... + +*Description* +Stuff which should be documented: + #define bfd_sizeof_headers(abfd, reloc) \ + BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc)) + + #define bfd_find_nearest_line(abfd, sec, syms, off, file, func, line) \ + BFD_SEND (abfd, _bfd_find_nearest_line, (abfd, sec, syms, off, file, func, line)) + + /* Do these three do anything useful at all, for any back end? */ + #define bfd_debug_info_start(abfd) \ + BFD_SEND (abfd, _bfd_debug_info_start, (abfd)) + + #define bfd_debug_info_end(abfd) \ + BFD_SEND (abfd, _bfd_debug_info_end, (abfd)) + + #define bfd_debug_info_accumulate(abfd, section) \ + BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section)) + + + #define bfd_stat_arch_elt(abfd, stat) \ + BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat)) + + #define bfd_update_armap_timestamp(abfd) \ + BFD_SEND (abfd, _bfd_update_armap_timestamp, (abfd)) + + #define bfd_set_arch_mach(abfd, arch, mach)\ + BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach)) + + #define bfd_relax_section(abfd, section, link_info, again) \ + BFD_SEND (abfd, _bfd_relax_section, (abfd, section, link_info, again)) + + #define bfd_link_hash_table_create(abfd) \ + BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd)) + + #define bfd_link_add_symbols(abfd, info) \ + BFD_SEND (abfd, _bfd_link_add_symbols, (abfd, info)) + + #define bfd_final_link(abfd, info) \ + BFD_SEND (abfd, _bfd_final_link, (abfd, info)) + + #define bfd_free_cached_info(abfd) \ + BFD_SEND (abfd, _bfd_free_cached_info, (abfd)) + + #define bfd_get_dynamic_symtab_upper_bound(abfd) \ + BFD_SEND (abfd, _bfd_get_dynamic_symtab_upper_bound, (abfd)) + + #define bfd_print_private_bfd_data(abfd, file)\ + BFD_SEND (abfd, _bfd_print_private_bfd_data, (abfd, file)) + + #define bfd_canonicalize_dynamic_symtab(abfd, asymbols) \ + BFD_SEND (abfd, _bfd_canonicalize_dynamic_symtab, (abfd, asymbols)) + + #define bfd_get_dynamic_reloc_upper_bound(abfd) \ + BFD_SEND (abfd, _bfd_get_dynamic_reloc_upper_bound, (abfd)) + + #define bfd_canonicalize_dynamic_reloc(abfd, arels, asyms) \ + BFD_SEND (abfd, _bfd_canonicalize_dynamic_reloc, (abfd, arels, asyms)) + + extern bfd_byte *bfd_get_relocated_section_contents + PARAMS ((bfd *, struct bfd_link_info *, + struct bfd_link_order *, bfd_byte *, + boolean, asymbol **)); + +* Menu: + +* Memory Usage:: +* Initialization:: +* Sections:: +* Symbols:: +* Archives:: +* Formats:: +* Relocations:: +* Core Files:: +* Targets:: +* Architectures:: +* Opening and Closing:: +* Internal:: +* File Caching:: +* Linker Functions:: +* Hash Tables:: + + +File: bfd.info, Node: Memory Usage, Next: Initialization, Prev: BFD front end, Up: BFD front end + +Memory usage +============ + + BFD keeps all of its internal structures in obstacks. There is one +obstack per open BFD file, into which the current state is stored. When +a BFD is closed, the obstack is deleted, and so everything which has +been allocated by BFD for the closing file is thrown away. + + BFD does not free anything created by an application, but pointers +into `bfd' structures become invalid on a `bfd_close'; for example, +after a `bfd_close' the vector passed to `bfd_canonicalize_symtab' is +still around, since it has been allocated by the application, but the +data that it pointed to are lost. + + The general rule is to not close a BFD until all operations dependent +upon data from the BFD have been completed, or all the data from within +the file has been copied. To help with the management of memory, there +is a function (`bfd_alloc_size') which returns the number of bytes in +obstacks associated with the supplied BFD. This could be used to select +the greediest open BFD, close it to reclaim the memory, perform some +operation and reopen the BFD again, to get a fresh copy of the data +structures. + + +File: bfd.info, Node: Initialization, Next: Sections, Prev: Memory Usage, Up: BFD front end + +Initialization +============== + + These are the functions that handle initializing a BFD. +`bfd_init' +.......... + +*Synopsis* + void bfd_init(void); + *Description* +This routine must be called before any other BFD function to initialize +magical internal data structures. + +File: bfd.info, Node: Sections, Next: Symbols, Prev: Initialization, Up: BFD front end + +Sections +======== + +The raw data contained within a BFD is maintained through the section +abstraction. A single BFD may have any number of sections. It keeps +hold of them by pointing to the first; each one points to the next in +the list. + + Sections are supported in BFD in `section.c'. + +* Menu: + +* Section Input:: +* Section Output:: +* typedef asection:: +* section prototypes:: + + +File: bfd.info, Node: Section Input, Next: Section Output, Prev: Sections, Up: Sections + +Section input +------------- + +When a BFD is opened for reading, the section structures are created +and attached to the BFD. + + Each section has a name which describes the section in the outside +world--for example, `a.out' would contain at least three sections, +called `.text', `.data' and `.bss'. + + Names need not be unique; for example a COFF file may have several +sections named `.data'. + + Sometimes a BFD will contain more than the "natural" number of +sections. A back end may attach other sections containing constructor +data, or an application may add a section (using `bfd_make_section') to +the sections attached to an already open BFD. For example, the linker +creates an extra section `COMMON' for each input file's BFD to hold +information about common storage. + + The raw data is not necessarily read in when the section descriptor +is created. Some targets may leave the data in place until a +`bfd_get_section_contents' call is made. Other back ends may read in +all the data at once. For example, an S-record file has to be read +once to determine the size of the data. An IEEE-695 file doesn't +contain raw data in sections, but data and relocation expressions +intermixed, so the data area has to be parsed to get out the data and +relocations. + +File: bfd.info, Node: Section Output, Next: typedef asection, Prev: Section Input, Up: Sections + +Section output +-------------- + +To write a new object style BFD, the various sections to be written +have to be created. They are attached to the BFD in the same way as +input sections; data is written to the sections using +`bfd_set_section_contents'. + + Any program that creates or combines sections (e.g., the assembler +and linker) must use the `asection' fields `output_section' and +`output_offset' to indicate the file sections to which each section +must be written. (If the section is being created from scratch, +`output_section' should probably point to the section itself and +`output_offset' should probably be zero.) + + The data to be written comes from input sections attached (via +`output_section' pointers) to the output sections. The output section +structure can be considered a filter for the input section: the output +section determines the vma of the output data and the name, but the +input section determines the offset into the output section of the data +to be written. + + E.g., to create a section "O", starting at 0x100, 0x123 long, +containing two subsections, "A" at offset 0x0 (i.e., at vma 0x100) and +"B" at offset 0x20 (i.e., at vma 0x120) the `asection' structures would +look like: + + section name "A" + output_offset 0x00 + size 0x20 + output_section -----------> section name "O" + | vma 0x100 + section name "B" | size 0x123 + output_offset 0x20 | + size 0x103 | + output_section --------| + +Link orders +----------- + +The data within a section is stored in a "link_order". These are much +like the fixups in `gas'. The link_order abstraction allows a section +to grow and shrink within itself. + + A link_order knows how big it is, and which is the next link_order +and where the raw data for it is; it also points to a list of +relocations which apply to it. + + The link_order is used by the linker to perform relaxing on final +code. The compiler creates code which is as big as necessary to make +it work without relaxing, and the user can select whether to relax. +Sometimes relaxing takes a lot of time. The linker runs around the +relocations to see if any are attached to data which can be shrunk, if +so it does it on a link_order by link_order basis. + +File: bfd.info, Node: typedef asection, Next: section prototypes, Prev: Section Output, Up: Sections + +typedef asection +---------------- + +Here is the section structure: +. + typedef struct sec + { + /* The name of the section; the name isn't a copy, the pointer is + the same as that passed to bfd_make_section. */ + + CONST char *name; + + /* Which section is it; 0..nth. */ + + int index; + + /* The next section in the list belonging to the BFD, or NULL. */ + + struct sec *next; + + /* The field flags contains attributes of the section. Some + flags are read in from the object file, and some are + synthesized from other information. */ + + flagword flags; + + #define SEC_NO_FLAGS 0x000 + + /* Tells the OS to allocate space for this section when loading. + This is clear for a section containing debug information + only. */ + #define SEC_ALLOC 0x001 + + /* Tells the OS to load the section from the file when loading. + This is clear for a .bss section. */ + #define SEC_LOAD 0x002 + + /* The section contains data still to be relocated, so there is + some relocation information too. */ + #define SEC_RELOC 0x004 + + #if 0 /* Obsolete ? */ + #define SEC_BALIGN 0x008 + #endif + + /* A signal to the OS that the section contains read only + data. */ + #define SEC_READONLY 0x010 + + /* The section contains code only. */ + #define SEC_CODE 0x020 + + /* The section contains data only. */ + #define SEC_DATA 0x040 + + /* The section will reside in ROM. */ + #define SEC_ROM 0x080 + + /* The section contains constructor information. This section + type is used by the linker to create lists of constructors and + destructors used by `g++'. When a back end sees a symbol + which should be used in a constructor list, it creates a new + section for the type of name (e.g., `__CTOR_LIST__'), attaches + the symbol to it, and builds a relocation. To build the lists + of constructors, all the linker has to do is catenate all the + sections called `__CTOR_LIST__' and relocate the data + contained within - exactly the operations it would peform on + standard data. */ + #define SEC_CONSTRUCTOR 0x100 + + /* The section is a constuctor, and should be placed at the + end of the text, data, or bss section(?). */ + #define SEC_CONSTRUCTOR_TEXT 0x1100 + #define SEC_CONSTRUCTOR_DATA 0x2100 + #define SEC_CONSTRUCTOR_BSS 0x3100 + + /* The section has contents - a data section could be + `SEC_ALLOC' | `SEC_HAS_CONTENTS'; a debug section could be + `SEC_HAS_CONTENTS' */ + #define SEC_HAS_CONTENTS 0x200 + + /* An instruction to the linker to not output the section + even if it has information which would normally be written. */ + #define SEC_NEVER_LOAD 0x400 + + /* The section is a COFF shared library section. This flag is + only for the linker. If this type of section appears in + the input file, the linker must copy it to the output file + without changing the vma or size. FIXME: Although this + was originally intended to be general, it really is COFF + specific (and the flag was renamed to indicate this). It + might be cleaner to have some more general mechanism to + allow the back end to control what the linker does with + sections. */ + #define SEC_COFF_SHARED_LIBRARY 0x800 + + /* The section contains common symbols (symbols may be defined + multiple times, the value of a symbol is the amount of + space it requires, and the largest symbol value is the one + used). Most targets have exactly one of these (which we + translate to bfd_com_section_ptr), but ECOFF has two. */ + #define SEC_IS_COMMON 0x8000 + + /* The section contains only debugging information. For + example, this is set for ELF .debug and .stab sections. + strip tests this flag to see if a section can be + discarded. */ + #define SEC_DEBUGGING 0x10000 + + /* The contents of this section are held in memory pointed to + by the contents field. This is checked by + bfd_get_section_contents, and the data is retrieved from + memory if appropriate. */ + #define SEC_IN_MEMORY 0x20000 + + /* The contents of this section are to be excluded by the + linker for executable and shared objects unless those + objects are to be further relocated. */ + #define SEC_EXCLUDE 0x40000 + + /* The contents of this section are to be sorted by the + based on the address specified in the associated symbol + table. */ + #define SEC_SORT_ENTRIES 0x80000 + + /* When linking, duplicate sections of the same name should be + discarded, rather than being combined into a single section as + is usually done. This is similar to how common symbols are + handled. See SEC_LINK_DUPLICATES below. */ + #define SEC_LINK_ONCE 0x100000 + + /* If SEC_LINK_ONCE is set, this bitfield describes how the linker + should handle duplicate sections. */ + #define SEC_LINK_DUPLICATES 0x600000 + + /* This value for SEC_LINK_DUPLICATES means that duplicate + sections with the same name should simply be discarded. */ + #define SEC_LINK_DUPLICATES_DISCARD 0x0 + + /* This value for SEC_LINK_DUPLICATES means that the linker + should warn if there are any duplicate sections, although + it should still only link one copy. */ + #define SEC_LINK_DUPLICATES_ONE_ONLY 0x200000 + + /* This value for SEC_LINK_DUPLICATES means that the linker + should warn if any duplicate sections are a different size. */ + #define SEC_LINK_DUPLICATES_SAME_SIZE 0x400000 + + /* This value for SEC_LINK_DUPLICATES means that the linker + should warn if any duplicate sections contain different + contents. */ + #define SEC_LINK_DUPLICATES_SAME_CONTENTS 0x600000 + + /* This section was created by the linker as part of dynamic + relocation or other arcane processing. It is skipped when + going through the first-pass output, trusting that someone + else up the line will take care of it later. */ + #define SEC_LINKER_CREATED 0x800000 + + /* End of section flags. */ + + /* Some internal packed boolean fields. */ + + /* See the vma field. */ + unsigned int user_set_vma : 1; + + /* Whether relocations have been processed. */ + unsigned int reloc_done : 1; + + /* A mark flag used by some of the linker backends. */ + unsigned int linker_mark : 1; + + /* End of internal packed boolean fields. */ + + /* The virtual memory address of the section - where it will be + at run time. The symbols are relocated against this. The + user_set_vma flag is maintained by bfd; if it's not set, the + backend can assign addresses (for example, in `a.out', where + the default address for `.data' is dependent on the specific + target and various flags). */ + + bfd_vma vma; + + /* The load address of the section - where it would be in a + rom image; really only used for writing section header + information. */ + + bfd_vma lma; + + /* The size of the section in bytes, as it will be output. + contains a value even if the section has no contents (e.g., the + size of `.bss'). This will be filled in after relocation */ + + bfd_size_type _cooked_size; + + /* The original size on disk of the section, in bytes. Normally this + value is the same as the size, but if some relaxing has + been done, then this value will be bigger. */ + + bfd_size_type _raw_size; + + /* If this section is going to be output, then this value is the + offset into the output section of the first byte in the input + section. E.g., if this was going to start at the 100th byte in + the output section, this value would be 100. */ + + bfd_vma output_offset; + + /* The output section through which to map on output. */ + + struct sec *output_section; + + /* The alignment requirement of the section, as an exponent of 2 - + e.g., 3 aligns to 2^3 (or 8). */ + + unsigned int alignment_power; + + /* If an input section, a pointer to a vector of relocation + records for the data in this section. */ + + struct reloc_cache_entry *relocation; + + /* If an output section, a pointer to a vector of pointers to + relocation records for the data in this section. */ + + struct reloc_cache_entry **orelocation; + + /* The number of relocation records in one of the above */ + + unsigned reloc_count; + + /* Information below is back end specific - and not always used + or updated. */ + + /* File position of section data */ + + file_ptr filepos; + + /* File position of relocation info */ + + file_ptr rel_filepos; + + /* File position of line data */ + + file_ptr line_filepos; + + /* Pointer to data for applications */ + + PTR userdata; + + /* If the SEC_IN_MEMORY flag is set, this points to the actual + contents. */ + unsigned char *contents; + + /* Attached line number information */ + + alent *lineno; + + /* Number of line number records */ + + unsigned int lineno_count; + + /* When a section is being output, this value changes as more + linenumbers are written out */ + + file_ptr moving_line_filepos; + + /* What the section number is in the target world */ + + int target_index; + + PTR used_by_bfd; + + /* If this is a constructor section then here is a list of the + relocations created to relocate items within it. */ + + struct relent_chain *constructor_chain; + + /* The BFD which owns the section. */ + + bfd *owner; + + /* A symbol which points at this section only */ + struct symbol_cache_entry *symbol; + struct symbol_cache_entry **symbol_ptr_ptr; + + struct bfd_link_order *link_order_head; + struct bfd_link_order *link_order_tail; + } asection ; + + /* These sections are global, and are managed by BFD. The application + and target back end are not permitted to change the values in + these sections. New code should use the section_ptr macros rather + than referring directly to the const sections. The const sections + may eventually vanish. */ + #define BFD_ABS_SECTION_NAME "*ABS*" + #define BFD_UND_SECTION_NAME "*UND*" + #define BFD_COM_SECTION_NAME "*COM*" + #define BFD_IND_SECTION_NAME "*IND*" + + /* the absolute section */ + extern const asection bfd_abs_section; + #define bfd_abs_section_ptr ((asection *) &bfd_abs_section) + #define bfd_is_abs_section(sec) ((sec) == bfd_abs_section_ptr) + /* Pointer to the undefined section */ + extern const asection bfd_und_section; + #define bfd_und_section_ptr ((asection *) &bfd_und_section) + #define bfd_is_und_section(sec) ((sec) == bfd_und_section_ptr) + /* Pointer to the common section */ + extern const asection bfd_com_section; + #define bfd_com_section_ptr ((asection *) &bfd_com_section) + /* Pointer to the indirect section */ + extern const asection bfd_ind_section; + #define bfd_ind_section_ptr ((asection *) &bfd_ind_section) + #define bfd_is_ind_section(sec) ((sec) == bfd_ind_section_ptr) + + extern const struct symbol_cache_entry * const bfd_abs_symbol; + extern const struct symbol_cache_entry * const bfd_com_symbol; + extern const struct symbol_cache_entry * const bfd_und_symbol; + extern const struct symbol_cache_entry * const bfd_ind_symbol; + #define bfd_get_section_size_before_reloc(section) \ + (section->reloc_done ? (abort(),1): (section)->_raw_size) + #define bfd_get_section_size_after_reloc(section) \ + ((section->reloc_done) ? (section)->_cooked_size: (abort(),1)) + diff --git a/gnu/usr.bin/binutils/bfd/doc/bfd.info-2 b/gnu/usr.bin/binutils/bfd/doc/bfd.info-2 new file mode 100644 index 00000000000..36c5b800ab3 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/bfd.info-2 @@ -0,0 +1,1121 @@ +This is Info file bfd.info, produced by Makeinfo-1.64 from the input +file ./bfd.texinfo. + +START-INFO-DIR-ENTRY +* Bfd: (bfd). The Binary File Descriptor library. +END-INFO-DIR-ENTRY + + This file documents the BFD library. + + Copyright (C) 1991 Free Software Foundation, Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + + Permission is granted to copy and distribute modified versions of +this manual under the conditions for verbatim copying, subject to the +terms of the GNU General Public License, which includes the provision +that the entire resulting derived work is distributed under the terms +of a permission notice identical to this one. + + Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions. + + +File: bfd.info, Node: section prototypes, Prev: typedef asection, Up: Sections + +Section prototypes +------------------ + + These are the functions exported by the section handling part of BFD. +`bfd_get_section_by_name' +......................... + +*Synopsis* + asection *bfd_get_section_by_name(bfd *abfd, CONST char *name); + *Description* +Run through ABFD and return the one of the `asection's whose name +matches NAME, otherwise `NULL'. *Note Sections::, for more information. + + This should only be used in special cases; the normal way to process +all sections of a given name is to use `bfd_map_over_sections' and +`strcmp' on the name (or better yet, base it on the section flags or +something else) for each section. +`bfd_make_section_old_way' +.......................... + +*Synopsis* + asection *bfd_make_section_old_way(bfd *abfd, CONST char *name); + *Description* +Create a new empty section called NAME and attach it to the end of the +chain of sections for the BFD ABFD. An attempt to create a section with +a name which is already in use returns its pointer without changing the +section chain. + + It has the funny name since this is the way it used to be before it +was rewritten.... + + Possible errors are: + * `bfd_error_invalid_operation' - If output has already started for + this BFD. + + * `bfd_error_no_memory' - If memory allocation fails. +`bfd_make_section_anyway' +......................... + +*Synopsis* + asection *bfd_make_section_anyway(bfd *abfd, CONST char *name); + *Description* +Create a new empty section called NAME and attach it to the end of the +chain of sections for ABFD. Create a new section even if there is +already a section with that name. + + Return `NULL' and set `bfd_error' on error; possible errors are: + * `bfd_error_invalid_operation' - If output has already started for + ABFD. + + * `bfd_error_no_memory' - If memory allocation fails. +`bfd_make_section' +.................. + +*Synopsis* + asection *bfd_make_section(bfd *, CONST char *name); + *Description* +Like `bfd_make_section_anyway', but return `NULL' (without calling +bfd_set_error ()) without changing the section chain if there is +already a section named NAME. If there is an error, return `NULL' and +set `bfd_error'. +`bfd_set_section_flags' +....................... + +*Synopsis* + boolean bfd_set_section_flags(bfd *abfd, asection *sec, flagword flags); + *Description* +Set the attributes of the section SEC in the BFD ABFD to the value +FLAGS. Return `true' on success, `false' on error. Possible error +returns are: + + * `bfd_error_invalid_operation' - The section cannot have one or + more of the attributes requested. For example, a .bss section in + `a.out' may not have the `SEC_HAS_CONTENTS' field set. +`bfd_map_over_sections' +....................... + +*Synopsis* + void bfd_map_over_sections(bfd *abfd, + void (*func)(bfd *abfd, + asection *sect, + PTR obj), + PTR obj); + *Description* +Call the provided function FUNC for each section attached to the BFD +ABFD, passing OBJ as an argument. The function will be called as if by + + func(abfd, the_section, obj); + + This is the prefered method for iterating over sections; an +alternative would be to use a loop: + + section *p; + for (p = abfd->sections; p != NULL; p = p->next) + func(abfd, p, ...) + +`bfd_set_section_size' +...................... + +*Synopsis* + boolean bfd_set_section_size(bfd *abfd, asection *sec, bfd_size_type val); + *Description* +Set SEC to the size VAL. If the operation is ok, then `true' is +returned, else `false'. + + Possible error returns: + * `bfd_error_invalid_operation' - Writing has started to the BFD, so + setting the size is invalid. +`bfd_set_section_contents' +.......................... + +*Synopsis* + boolean bfd_set_section_contents + (bfd *abfd, + asection *section, + PTR data, + file_ptr offset, + bfd_size_type count); + *Description* +Sets the contents of the section SECTION in BFD ABFD to the data +starting in memory at DATA. The data is written to the output section +starting at offset OFFSET for COUNT bytes. + + Normally `true' is returned, else `false'. Possible error returns +are: + * `bfd_error_no_contents' - The output section does not have the + `SEC_HAS_CONTENTS' attribute, so nothing can be written to it. + + * and some more too This routine is front end to the back end +function `_bfd_set_section_contents'. +`bfd_get_section_contents' +.......................... + +*Synopsis* + boolean bfd_get_section_contents + (bfd *abfd, asection *section, PTR location, + file_ptr offset, bfd_size_type count); + *Description* +Read data from SECTION in BFD ABFD into memory starting at LOCATION. +The data is read at an offset of OFFSET from the start of the input +section, and is read for COUNT bytes. + + If the contents of a constructor with the `SEC_CONSTRUCTOR' flag set +are requested or if the section does not have the `SEC_HAS_CONTENTS' +flag set, then the LOCATION is filled with zeroes. If no errors occur, +`true' is returned, else `false'. +`bfd_copy_private_section_data' +............................... + +*Synopsis* + boolean bfd_copy_private_section_data(bfd *ibfd, asection *isec, bfd *obfd, asection *osec); + *Description* +Copy private section information from ISEC in the BFD IBFD to the +section OSEC in the BFD OBFD. Return `true' on success, `false' on +error. Possible error returns are: + + * `bfd_error_no_memory' - Not enough memory exists to create private + data for OSEC. + #define bfd_copy_private_section_data(ibfd, isection, obfd, osection) \ + BFD_SEND (obfd, _bfd_copy_private_section_data, \ + (ibfd, isection, obfd, osection)) + + +File: bfd.info, Node: Symbols, Next: Archives, Prev: Sections, Up: BFD front end + +Symbols +======= + +BFD tries to maintain as much symbol information as it can when it +moves information from file to file. BFD passes information to +applications though the `asymbol' structure. When the application +requests the symbol table, BFD reads the table in the native form and +translates parts of it into the internal format. To maintain more than +the information passed to applications, some targets keep some +information "behind the scenes" in a structure only the particular back +end knows about. For example, the coff back end keeps the original +symbol table structure as well as the canonical structure when a BFD is +read in. On output, the coff back end can reconstruct the output symbol +table so that no information is lost, even information unique to coff +which BFD doesn't know or understand. If a coff symbol table were read, +but were written through an a.out back end, all the coff specific +information would be lost. The symbol table of a BFD is not necessarily +read in until a canonicalize request is made. Then the BFD back end +fills in a table provided by the application with pointers to the +canonical information. To output symbols, the application provides BFD +with a table of pointers to pointers to `asymbol's. This allows +applications like the linker to output a symbol as it was read, since +the "behind the scenes" information will be still available. + +* Menu: + +* Reading Symbols:: +* Writing Symbols:: +* Mini Symbols:: +* typedef asymbol:: +* symbol handling functions:: + + +File: bfd.info, Node: Reading Symbols, Next: Writing Symbols, Prev: Symbols, Up: Symbols + +Reading symbols +--------------- + +There are two stages to reading a symbol table from a BFD: allocating +storage, and the actual reading process. This is an excerpt from an +application which reads the symbol table: + + long storage_needed; + asymbol **symbol_table; + long number_of_symbols; + long i; + + storage_needed = bfd_get_symtab_upper_bound (abfd); + + if (storage_needed < 0) + FAIL + + if (storage_needed == 0) { + return ; + } + symbol_table = (asymbol **) xmalloc (storage_needed); + ... + number_of_symbols = + bfd_canonicalize_symtab (abfd, symbol_table); + + if (number_of_symbols < 0) + FAIL + + for (i = 0; i < number_of_symbols; i++) { + process_symbol (symbol_table[i]); + } + + All storage for the symbols themselves is in an objalloc connected +to the BFD; it is freed when the BFD is closed. + +File: bfd.info, Node: Writing Symbols, Next: Mini Symbols, Prev: Reading Symbols, Up: Symbols + +Writing symbols +--------------- + +Writing of a symbol table is automatic when a BFD open for writing is +closed. The application attaches a vector of pointers to pointers to +symbols to the BFD being written, and fills in the symbol count. The +close and cleanup code reads through the table provided and performs +all the necessary operations. The BFD output code must always be +provided with an "owned" symbol: one which has come from another BFD, +or one which has been created using `bfd_make_empty_symbol'. Here is an +example showing the creation of a symbol table with only one element: + + #include "bfd.h" + main() + { + bfd *abfd; + asymbol *ptrs[2]; + asymbol *new; + + abfd = bfd_openw("foo","a.out-sunos-big"); + bfd_set_format(abfd, bfd_object); + new = bfd_make_empty_symbol(abfd); + new->name = "dummy_symbol"; + new->section = bfd_make_section_old_way(abfd, ".text"); + new->flags = BSF_GLOBAL; + new->value = 0x12345; + + ptrs[0] = new; + ptrs[1] = (asymbol *)0; + + bfd_set_symtab(abfd, ptrs, 1); + bfd_close(abfd); + } + + ./makesym + nm foo + 00012345 A dummy_symbol + + Many formats cannot represent arbitary symbol information; for +instance, the `a.out' object format does not allow an arbitary number +of sections. A symbol pointing to a section which is not one of +`.text', `.data' or `.bss' cannot be described. + +File: bfd.info, Node: Mini Symbols, Next: typedef asymbol, Prev: Writing Symbols, Up: Symbols + +Mini Symbols +------------ + +Mini symbols provide read-only access to the symbol table. They use +less memory space, but require more time to access. They can be useful +for tools like nm or objdump, which may have to handle symbol tables of +extremely large executables. + + The `bfd_read_minisymbols' function will read the symbols into +memory in an internal form. It will return a `void *' pointer to a +block of memory, a symbol count, and the size of each symbol. The +pointer is allocated using `malloc', and should be freed by the caller +when it is no longer needed. + + The function `bfd_minisymbol_to_symbol' will take a pointer to a +minisymbol, and a pointer to a structure returned by +`bfd_make_empty_symbol', and return a `asymbol' structure. The return +value may or may not be the same as the value from +`bfd_make_empty_symbol' which was passed in. + +File: bfd.info, Node: typedef asymbol, Next: symbol handling functions, Prev: Mini Symbols, Up: Symbols + +typedef asymbol +--------------- + +An `asymbol' has the form: +. + typedef struct symbol_cache_entry + { + /* A pointer to the BFD which owns the symbol. This information + is necessary so that a back end can work out what additional + information (invisible to the application writer) is carried + with the symbol. + + This field is *almost* redundant, since you can use section->owner + instead, except that some symbols point to the global sections + bfd_{abs,com,und}_section. This could be fixed by making + these globals be per-bfd (or per-target-flavor). FIXME. */ + + struct _bfd *the_bfd; /* Use bfd_asymbol_bfd(sym) to access this field. */ + + /* The text of the symbol. The name is left alone, and not copied; the + application may not alter it. */ + CONST char *name; + + /* The value of the symbol. This really should be a union of a + numeric value with a pointer, since some flags indicate that + a pointer to another symbol is stored here. */ + symvalue value; + + /* Attributes of a symbol: */ + + #define BSF_NO_FLAGS 0x00 + + /* The symbol has local scope; `static' in `C'. The value + is the offset into the section of the data. */ + #define BSF_LOCAL 0x01 + + /* The symbol has global scope; initialized data in `C'. The + value is the offset into the section of the data. */ + #define BSF_GLOBAL 0x02 + + /* The symbol has global scope and is exported. The value is + the offset into the section of the data. */ + #define BSF_EXPORT BSF_GLOBAL /* no real difference */ + + /* A normal C symbol would be one of: + `BSF_LOCAL', `BSF_FORT_COMM', `BSF_UNDEFINED' or + `BSF_GLOBAL' */ + + /* The symbol is a debugging record. The value has an arbitary + meaning. */ + #define BSF_DEBUGGING 0x08 + + /* The symbol denotes a function entry point. Used in ELF, + perhaps others someday. */ + #define BSF_FUNCTION 0x10 + + /* Used by the linker. */ + #define BSF_KEEP 0x20 + #define BSF_KEEP_G 0x40 + + /* A weak global symbol, overridable without warnings by + a regular global symbol of the same name. */ + #define BSF_WEAK 0x80 + + /* This symbol was created to point to a section, e.g. ELF's + STT_SECTION symbols. */ + #define BSF_SECTION_SYM 0x100 + + /* The symbol used to be a common symbol, but now it is + allocated. */ + #define BSF_OLD_COMMON 0x200 + + /* The default value for common data. */ + #define BFD_FORT_COMM_DEFAULT_VALUE 0 + + /* In some files the type of a symbol sometimes alters its + location in an output file - ie in coff a `ISFCN' symbol + which is also `C_EXT' symbol appears where it was + declared and not at the end of a section. This bit is set + by the target BFD part to convey this information. */ + + #define BSF_NOT_AT_END 0x400 + + /* Signal that the symbol is the label of constructor section. */ + #define BSF_CONSTRUCTOR 0x800 + + /* Signal that the symbol is a warning symbol. The name is a + warning. The name of the next symbol is the one to warn about; + if a reference is made to a symbol with the same name as the next + symbol, a warning is issued by the linker. */ + #define BSF_WARNING 0x1000 + + /* Signal that the symbol is indirect. This symbol is an indirect + pointer to the symbol with the same name as the next symbol. */ + #define BSF_INDIRECT 0x2000 + + /* BSF_FILE marks symbols that contain a file name. This is used + for ELF STT_FILE symbols. */ + #define BSF_FILE 0x4000 + + /* Symbol is from dynamic linking information. */ + #define BSF_DYNAMIC 0x8000 + + /* The symbol denotes a data object. Used in ELF, and perhaps + others someday. */ + #define BSF_OBJECT 0x10000 + + flagword flags; + + /* A pointer to the section to which this symbol is + relative. This will always be non NULL, there are special + sections for undefined and absolute symbols. */ + struct sec *section; + + /* Back end special data. */ + union + { + PTR p; + bfd_vma i; + } udata; + + } asymbol; + + +File: bfd.info, Node: symbol handling functions, Prev: typedef asymbol, Up: Symbols + +Symbol handling functions +------------------------- + +`bfd_get_symtab_upper_bound' +............................ + +*Description* +Return the number of bytes required to store a vector of pointers to +`asymbols' for all the symbols in the BFD ABFD, including a terminal +NULL pointer. If there are no symbols in the BFD, then return 0. If an +error occurs, return -1. + #define bfd_get_symtab_upper_bound(abfd) \ + BFD_SEND (abfd, _bfd_get_symtab_upper_bound, (abfd)) + +`bfd_is_local_label' +.................... + +*Synopsis* + boolean bfd_is_local_label(bfd *abfd, asymbol *sym); + *Description* +Return true if the given symbol SYM in the BFD ABFD is a compiler +generated local label, else return false. +`bfd_is_local_label_name' +......................... + +*Synopsis* + boolean bfd_is_local_label_name(bfd *abfd, const char *name); + *Description* +Return true if a symbol with the name NAME in the BFD ABFD is a +compiler generated local label, else return false. This just checks +whether the name has the form of a local label. + #define bfd_is_local_label_name(abfd, name) \ + BFD_SEND (abfd, _bfd_is_local_label_name, (abfd, name)) + +`bfd_canonicalize_symtab' +......................... + +*Description* +Read the symbols from the BFD ABFD, and fills in the vector LOCATION +with pointers to the symbols and a trailing NULL. Return the actual +number of symbol pointers, not including the NULL. + #define bfd_canonicalize_symtab(abfd, location) \ + BFD_SEND (abfd, _bfd_canonicalize_symtab,\ + (abfd, location)) + +`bfd_set_symtab' +................ + +*Synopsis* + boolean bfd_set_symtab (bfd *abfd, asymbol **location, unsigned int count); + *Description* +Arrange that when the output BFD ABFD is closed, the table LOCATION of +COUNT pointers to symbols will be written. +`bfd_print_symbol_vandf' +........................ + +*Synopsis* + void bfd_print_symbol_vandf(PTR file, asymbol *symbol); + *Description* +Print the value and flags of the SYMBOL supplied to the stream FILE. +`bfd_make_empty_symbol' +....................... + +*Description* +Create a new `asymbol' structure for the BFD ABFD and return a pointer +to it. + + This routine is necessary because each back end has private +information surrounding the `asymbol'. Building your own `asymbol' and +pointing to it will not create the private information, and will cause +problems later on. + #define bfd_make_empty_symbol(abfd) \ + BFD_SEND (abfd, _bfd_make_empty_symbol, (abfd)) + +`bfd_make_debug_symbol' +....................... + +*Description* +Create a new `asymbol' structure for the BFD ABFD, to be used as a +debugging symbol. Further details of its use have yet to be worked out. + #define bfd_make_debug_symbol(abfd,ptr,size) \ + BFD_SEND (abfd, _bfd_make_debug_symbol, (abfd, ptr, size)) + +`bfd_decode_symclass' +..................... + +*Description* +Return a character corresponding to the symbol class of SYMBOL, or '?' +for an unknown class. +*Synopsis* + int bfd_decode_symclass(asymbol *symbol); + +`bfd_symbol_info' +................. + + *Description* +Fill in the basic info about symbol that nm needs. Additional info may +be added by the back-ends after calling this function. +*Synopsis* + void bfd_symbol_info(asymbol *symbol, symbol_info *ret); + +`bfd_copy_private_symbol_data' +.............................. + + *Synopsis* + boolean bfd_copy_private_symbol_data(bfd *ibfd, asymbol *isym, bfd *obfd, asymbol *osym); + *Description* +Copy private symbol information from ISYM in the BFD IBFD to the symbol +OSYM in the BFD OBFD. Return `true' on success, `false' on error. +Possible error returns are: + + * `bfd_error_no_memory' - Not enough memory exists to create private + data for OSEC. + #define bfd_copy_private_symbol_data(ibfd, isymbol, obfd, osymbol) \ + BFD_SEND (obfd, _bfd_copy_private_symbol_data, \ + (ibfd, isymbol, obfd, osymbol)) + + +File: bfd.info, Node: Archives, Next: Formats, Prev: Symbols, Up: BFD front end + +Archives +======== + +*Description* +An archive (or library) is just another BFD. It has a symbol table, +although there's not much a user program will do with it. + + The big difference between an archive BFD and an ordinary BFD is +that the archive doesn't have sections. Instead it has a chain of BFDs +that are considered its contents. These BFDs can be manipulated like +any other. The BFDs contained in an archive opened for reading will +all be opened for reading. You may put either input or output BFDs +into an archive opened for output; they will be handled correctly when +the archive is closed. + + Use `bfd_openr_next_archived_file' to step through the contents of +an archive opened for input. You don't have to read the entire archive +if you don't want to! Read it until you find what you want. + + Archive contents of output BFDs are chained through the `next' +pointer in a BFD. The first one is findable through the `archive_head' +slot of the archive. Set it with `bfd_set_archive_head' (q.v.). A +given BFD may be in only one open output archive at a time. + + As expected, the BFD archive code is more general than the archive +code of any given environment. BFD archives may contain files of +different formats (e.g., a.out and coff) and even different +architectures. You may even place archives recursively into archives! + + This can cause unexpected confusion, since some archive formats are +more expressive than others. For instance, Intel COFF archives can +preserve long filenames; SunOS a.out archives cannot. If you move a +file from the first to the second format and back again, the filename +may be truncated. Likewise, different a.out environments have different +conventions as to how they truncate filenames, whether they preserve +directory names in filenames, etc. When interoperating with native +tools, be sure your files are homogeneous. + + Beware: most of these formats do not react well to the presence of +spaces in filenames. We do the best we can, but can't always handle +this case due to restrictions in the format of archives. Many Unix +utilities are braindead in regards to spaces and such in filenames +anyway, so this shouldn't be much of a restriction. + + Archives are supported in BFD in `archive.c'. +`bfd_get_next_mapent' +..................... + +*Synopsis* + symindex bfd_get_next_mapent(bfd *abfd, symindex previous, carsym **sym); + *Description* +Step through archive ABFD's symbol table (if it has one). Successively +update SYM with the next symbol's information, returning that symbol's +(internal) index into the symbol table. + + Supply `BFD_NO_MORE_SYMBOLS' as the PREVIOUS entry to get the first +one; returns `BFD_NO_MORE_SYMBOLS' when you've already got the last one. + + A `carsym' is a canonical archive symbol. The only user-visible +element is its name, a null-terminated string. +`bfd_set_archive_head' +...................... + +*Synopsis* + boolean bfd_set_archive_head(bfd *output, bfd *new_head); + *Description* +Set the head of the chain of BFDs contained in the archive OUTPUT to +NEW_HEAD. +`bfd_openr_next_archived_file' +.............................. + +*Synopsis* + bfd *bfd_openr_next_archived_file(bfd *archive, bfd *previous); + *Description* +Provided a BFD, ARCHIVE, containing an archive and NULL, open an input +BFD on the first contained element and returns that. Subsequent calls +should pass the archive and the previous return value to return a +created BFD to the next contained element. NULL is returned when there +are no more. + +File: bfd.info, Node: Formats, Next: Relocations, Prev: Archives, Up: BFD front end + +File formats +============ + +A format is a BFD concept of high level file contents type. The formats +supported by BFD are: + + * `bfd_object' The BFD may contain data, symbols, relocations and +debug info. + + * `bfd_archive' The BFD contains other BFDs and an optional index. + + * `bfd_core' The BFD contains the result of an executable core dump. +`bfd_check_format' +.................. + +*Synopsis* + boolean bfd_check_format(bfd *abfd, bfd_format format); + *Description* +Verify if the file attached to the BFD ABFD is compatible with the +format FORMAT (i.e., one of `bfd_object', `bfd_archive' or `bfd_core'). + + If the BFD has been set to a specific target before the call, only +the named target and format combination is checked. If the target has +not been set, or has been set to `default', then all the known target +backends is interrogated to determine a match. If the default target +matches, it is used. If not, exactly one target must recognize the +file, or an error results. + + The function returns `true' on success, otherwise `false' with one +of the following error codes: + + * `bfd_error_invalid_operation' - if `format' is not one of + `bfd_object', `bfd_archive' or `bfd_core'. + + * `bfd_error_system_call' - if an error occured during a read - even + some file mismatches can cause bfd_error_system_calls. + + * `file_not_recognised' - none of the backends recognised the file + format. + + * `bfd_error_file_ambiguously_recognized' - more than one backend + recognised the file format. +`bfd_check_format_matches' +.......................... + +*Synopsis* + boolean bfd_check_format_matches(bfd *abfd, bfd_format format, char ***matching); + *Description* +Like `bfd_check_format', except when it returns false with `bfd_errno' +set to `bfd_error_file_ambiguously_recognized'. In that case, if +MATCHING is not NULL, it will be filled in with a NULL-terminated list +of the names of the formats that matched, allocated with `malloc'. +Then the user may choose a format and try again. + + When done with the list that MATCHING points to, the caller should +free it. +`bfd_set_format' +................ + +*Synopsis* + boolean bfd_set_format(bfd *abfd, bfd_format format); + *Description* +This function sets the file format of the BFD ABFD to the format +FORMAT. If the target set in the BFD does not support the format +requested, the format is invalid, or the BFD is not open for writing, +then an error occurs. +`bfd_format_string' +................... + +*Synopsis* + CONST char *bfd_format_string(bfd_format format); + *Description* +Return a pointer to a const string `invalid', `object', `archive', +`core', or `unknown', depending upon the value of FORMAT. + +File: bfd.info, Node: Relocations, Next: Core Files, Prev: Formats, Up: BFD front end + +Relocations +=========== + +BFD maintains relocations in much the same way it maintains symbols: +they are left alone until required, then read in en-mass and translated +into an internal form. A common routine `bfd_perform_relocation' acts +upon the canonical form to do the fixup. + + Relocations are maintained on a per section basis, while symbols are +maintained on a per BFD basis. + + All that a back end has to do to fit the BFD interface is to create +a `struct reloc_cache_entry' for each relocation in a particular +section, and fill in the right bits of the structures. + +* Menu: + +* typedef arelent:: +* howto manager:: + + +File: bfd.info, Node: typedef arelent, Next: howto manager, Prev: Relocations, Up: Relocations + +typedef arelent +--------------- + +This is the structure of a relocation entry: +. + typedef enum bfd_reloc_status + { + /* No errors detected */ + bfd_reloc_ok, + + /* The relocation was performed, but there was an overflow. */ + bfd_reloc_overflow, + + /* The address to relocate was not within the section supplied. */ + bfd_reloc_outofrange, + + /* Used by special functions */ + bfd_reloc_continue, + + /* Unsupported relocation size requested. */ + bfd_reloc_notsupported, + + /* Unused */ + bfd_reloc_other, + + /* The symbol to relocate against was undefined. */ + bfd_reloc_undefined, + + /* The relocation was performed, but may not be ok - presently + generated only when linking i960 coff files with i960 b.out + symbols. If this type is returned, the error_message argument + to bfd_perform_relocation will be set. */ + bfd_reloc_dangerous + } + bfd_reloc_status_type; + + + typedef struct reloc_cache_entry + { + /* A pointer into the canonical table of pointers */ + struct symbol_cache_entry **sym_ptr_ptr; + + /* offset in section */ + bfd_size_type address; + + /* addend for relocation value */ + bfd_vma addend; + + /* Pointer to how to perform the required relocation */ + reloc_howto_type *howto; + + } arelent; + *Description* +Here is a description of each of the fields within an `arelent': + + * `sym_ptr_ptr' The symbol table pointer points to a pointer to the +symbol associated with the relocation request. It is the pointer into +the table returned by the back end's `get_symtab' action. *Note +Symbols::. The symbol is referenced through a pointer to a pointer so +that tools like the linker can fix up all the symbols of the same name +by modifying only one pointer. The relocation routine looks in the +symbol and uses the base of the section the symbol is attached to and +the value of the symbol as the initial relocation offset. If the symbol +pointer is zero, then the section provided is looked up. + + * `address' The `address' field gives the offset in bytes from the +base of the section data which owns the relocation record to the first +byte of relocatable information. The actual data relocated will be +relative to this point; for example, a relocation type which modifies +the bottom two bytes of a four byte word would not touch the first byte +pointed to in a big endian world. + + * `addend' The `addend' is a value provided by the back end to be +added (!) to the relocation offset. Its interpretation is dependent upon +the howto. For example, on the 68k the code: + + char foo[]; + main() + { + return foo[0x12345678]; + } + + Could be compiled into: + + linkw fp,#-4 + moveb @#12345678,d0 + extbl d0 + unlk fp + rts + + This could create a reloc pointing to `foo', but leave the offset in +the data, something like: + + RELOCATION RECORDS FOR [.text]: + offset type value + 00000006 32 _foo + + 00000000 4e56 fffc ; linkw fp,#-4 + 00000004 1039 1234 5678 ; moveb @#12345678,d0 + 0000000a 49c0 ; extbl d0 + 0000000c 4e5e ; unlk fp + 0000000e 4e75 ; rts + + Using coff and an 88k, some instructions don't have enough space in +them to represent the full address range, and pointers have to be +loaded in two parts. So you'd get something like: + + or.u r13,r0,hi16(_foo+0x12345678) + ld.b r2,r13,lo16(_foo+0x12345678) + jmp r1 + + This should create two relocs, both pointing to `_foo', and with +0x12340000 in their addend field. The data would consist of: + + RELOCATION RECORDS FOR [.text]: + offset type value + 00000002 HVRT16 _foo+0x12340000 + 00000006 LVRT16 _foo+0x12340000 + + 00000000 5da05678 ; or.u r13,r0,0x5678 + 00000004 1c4d5678 ; ld.b r2,r13,0x5678 + 00000008 f400c001 ; jmp r1 + + The relocation routine digs out the value from the data, adds it to +the addend to get the original offset, and then adds the value of +`_foo'. Note that all 32 bits have to be kept around somewhere, to cope +with carry from bit 15 to bit 16. + + One further example is the sparc and the a.out format. The sparc has +a similar problem to the 88k, in that some instructions don't have room +for an entire offset, but on the sparc the parts are created in odd +sized lumps. The designers of the a.out format chose to not use the +data within the section for storing part of the offset; all the offset +is kept within the reloc. Anything in the data should be ignored. + + save %sp,-112,%sp + sethi %hi(_foo+0x12345678),%g2 + ldsb [%g2+%lo(_foo+0x12345678)],%i0 + ret + restore + + Both relocs contain a pointer to `foo', and the offsets contain junk. + + RELOCATION RECORDS FOR [.text]: + offset type value + 00000004 HI22 _foo+0x12345678 + 00000008 LO10 _foo+0x12345678 + + 00000000 9de3bf90 ; save %sp,-112,%sp + 00000004 05000000 ; sethi %hi(_foo+0),%g2 + 00000008 f048a000 ; ldsb [%g2+%lo(_foo+0)],%i0 + 0000000c 81c7e008 ; ret + 00000010 81e80000 ; restore + + * `howto' The `howto' field can be imagined as a relocation +instruction. It is a pointer to a structure which contains information +on what to do with all of the other information in the reloc record and +data section. A back end would normally have a relocation instruction +set and turn relocations into pointers to the correct structure on +input - but it would be possible to create each howto field on demand. +`enum complain_overflow' +........................ + +Indicates what sort of overflow checking should be done when performing +a relocation. +. + enum complain_overflow + { + /* Do not complain on overflow. */ + complain_overflow_dont, + + /* Complain if the bitfield overflows, whether it is considered + as signed or unsigned. */ + complain_overflow_bitfield, + + /* Complain if the value overflows when considered as signed + number. */ + complain_overflow_signed, + + /* Complain if the value overflows when considered as an + unsigned number. */ + complain_overflow_unsigned + }; + +`reloc_howto_type' +.................. + + The `reloc_howto_type' is a structure which contains all the +information that libbfd needs to know to tie up a back end's data. +.struct symbol_cache_entry; /* Forward declaration */ + + struct reloc_howto_struct + { + /* The type field has mainly a documentary use - the back end can + do what it wants with it, though normally the back end's + external idea of what a reloc number is stored + in this field. For example, a PC relative word relocation + in a coff environment has the type 023 - because that's + what the outside world calls a R_PCRWORD reloc. */ + unsigned int type; + + /* The value the final relocation is shifted right by. This drops + unwanted data from the relocation. */ + unsigned int rightshift; + + /* The size of the item to be relocated. This is *not* a + power-of-two measure. To get the number of bytes operated + on by a type of relocation, use bfd_get_reloc_size. */ + int size; + + /* The number of bits in the item to be relocated. This is used + when doing overflow checking. */ + unsigned int bitsize; + + /* Notes that the relocation is relative to the location in the + data section of the addend. The relocation function will + subtract from the relocation value the address of the location + being relocated. */ + boolean pc_relative; + + /* The bit position of the reloc value in the destination. + The relocated value is left shifted by this amount. */ + unsigned int bitpos; + + /* What type of overflow error should be checked for when + relocating. */ + enum complain_overflow complain_on_overflow; + + /* If this field is non null, then the supplied function is + called rather than the normal function. This allows really + strange relocation methods to be accomodated (e.g., i960 callj + instructions). */ + bfd_reloc_status_type (*special_function) + PARAMS ((bfd *abfd, + arelent *reloc_entry, + struct symbol_cache_entry *symbol, + PTR data, + asection *input_section, + bfd *output_bfd, + char **error_message)); + + /* The textual name of the relocation type. */ + char *name; + + /* When performing a partial link, some formats must modify the + relocations rather than the data - this flag signals this.*/ + boolean partial_inplace; + + /* The src_mask selects which parts of the read in data + are to be used in the relocation sum. E.g., if this was an 8 bit + bit of data which we read and relocated, this would be + 0x000000ff. When we have relocs which have an addend, such as + sun4 extended relocs, the value in the offset part of a + relocating field is garbage so we never use it. In this case + the mask would be 0x00000000. */ + bfd_vma src_mask; + + /* The dst_mask selects which parts of the instruction are replaced + into the instruction. In most cases src_mask == dst_mask, + except in the above special case, where dst_mask would be + 0x000000ff, and src_mask would be 0x00000000. */ + bfd_vma dst_mask; + + /* When some formats create PC relative instructions, they leave + the value of the pc of the place being relocated in the offset + slot of the instruction, so that a PC relative relocation can + be made just by adding in an ordinary offset (e.g., sun3 a.out). + Some formats leave the displacement part of an instruction + empty (e.g., m88k bcs); this flag signals the fact.*/ + boolean pcrel_offset; + + }; + +`The HOWTO Macro' +................. + + *Description* +The HOWTO define is horrible and will go away. + #define HOWTO(C, R,S,B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \ + {(unsigned)C,R,S,B, P, BI, O,SF,NAME,INPLACE,MASKSRC,MASKDST,PC} + +*Description* +And will be replaced with the totally magic way. But for the moment, we +are compatible, so do it this way. + #define NEWHOWTO( FUNCTION, NAME,SIZE,REL,IN) HOWTO(0,0,SIZE,0,REL,0,complain_overflow_dont,FUNCTION, NAME,false,0,0,IN) + +*Description* +Helper routine to turn a symbol into a relocation value. + #define HOWTO_PREPARE(relocation, symbol) \ + { \ + if (symbol != (asymbol *)NULL) { \ + if (bfd_is_com_section (symbol->section)) { \ + relocation = 0; \ + } \ + else { \ + relocation = symbol->value; \ + } \ + } \ + } + +`bfd_get_reloc_size' +.................... + +*Synopsis* + int bfd_get_reloc_size (reloc_howto_type *); + *Description* +For a reloc_howto_type that operates on a fixed number of bytes, this +returns the number of bytes operated on. +`arelent_chain' +............... + +*Description* +How relocs are tied together in an `asection': + typedef struct relent_chain { + arelent relent; + struct relent_chain *next; + } arelent_chain; + +`bfd_perform_relocation' +........................ + +*Synopsis* + bfd_reloc_status_type + bfd_perform_relocation + (bfd *abfd, + arelent *reloc_entry, + PTR data, + asection *input_section, + bfd *output_bfd, + char **error_message); + *Description* +If OUTPUT_BFD is supplied to this function, the generated image will be +relocatable; the relocations are copied to the output file after they +have been changed to reflect the new state of the world. There are two +ways of reflecting the results of partial linkage in an output file: by +modifying the output data in place, and by modifying the relocation +record. Some native formats (e.g., basic a.out and basic coff) have no +way of specifying an addend in the relocation type, so the addend has +to go in the output data. This is no big deal since in these formats +the output data slot will always be big enough for the addend. Complex +reloc types with addends were invented to solve just this problem. The +ERROR_MESSAGE argument is set to an error message if this return +`bfd_reloc_dangerous'. +`bfd_install_relocation' +........................ + +*Synopsis* + bfd_reloc_status_type + bfd_install_relocation + (bfd *abfd, + arelent *reloc_entry, + PTR data, bfd_vma data_start, + asection *input_section, + char **error_message); + *Description* +This looks remarkably like `bfd_perform_relocation', except it does not +expect that the section contents have been filled in. I.e., it's +suitable for use when creating, rather than applying a relocation. + + For now, this function should be considered reserved for the +assembler. diff --git a/gnu/usr.bin/binutils/bfd/doc/bfd.info-3 b/gnu/usr.bin/binutils/bfd/doc/bfd.info-3 new file mode 100644 index 00000000000..8d51c9c2c59 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/bfd.info-3 @@ -0,0 +1,1322 @@ +This is Info file bfd.info, produced by Makeinfo-1.64 from the input +file ./bfd.texinfo. + +START-INFO-DIR-ENTRY +* Bfd: (bfd). The Binary File Descriptor library. +END-INFO-DIR-ENTRY + + This file documents the BFD library. + + Copyright (C) 1991 Free Software Foundation, Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + + Permission is granted to copy and distribute modified versions of +this manual under the conditions for verbatim copying, subject to the +terms of the GNU General Public License, which includes the provision +that the entire resulting derived work is distributed under the terms +of a permission notice identical to this one. + + Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions. + + +File: bfd.info, Node: howto manager, Prev: typedef arelent, Up: Relocations + +The howto manager +================= + +When an application wants to create a relocation, but doesn't know what +the target machine might call it, it can find out by using this bit of +code. +`bfd_reloc_code_type' +..................... + +*Description* +The insides of a reloc code. The idea is that, eventually, there will +be one enumerator for every type of relocation we ever do. Pass one of +these values to `bfd_reloc_type_lookup', and it'll return a howto +pointer. + + This does mean that the application must determine the correct +enumerator value; you can't get a howto pointer from a random set of +attributes. +Here are the possible values for `enum bfd_reloc_code_real': + + - : BFD_RELOC_64 + - : BFD_RELOC_32 + - : BFD_RELOC_26 + - : BFD_RELOC_24 + - : BFD_RELOC_16 + - : BFD_RELOC_14 + - : BFD_RELOC_8 + Basic absolute relocations of N bits. + + - : BFD_RELOC_64_PCREL + - : BFD_RELOC_32_PCREL + - : BFD_RELOC_24_PCREL + - : BFD_RELOC_16_PCREL + - : BFD_RELOC_12_PCREL + - : BFD_RELOC_8_PCREL + PC-relative relocations. Sometimes these are relative to the + address of the relocation itself; sometimes they are relative to + the start of the section containing the relocation. It depends on + the specific target. + + The 24-bit relocation is used in some Intel 960 configurations. + + - : BFD_RELOC_32_GOT_PCREL + - : BFD_RELOC_16_GOT_PCREL + - : BFD_RELOC_8_GOT_PCREL + - : BFD_RELOC_32_GOTOFF + - : BFD_RELOC_16_GOTOFF + - : BFD_RELOC_LO16_GOTOFF + - : BFD_RELOC_HI16_GOTOFF + - : BFD_RELOC_HI16_S_GOTOFF + - : BFD_RELOC_8_GOTOFF + - : BFD_RELOC_32_PLT_PCREL + - : BFD_RELOC_24_PLT_PCREL + - : BFD_RELOC_16_PLT_PCREL + - : BFD_RELOC_8_PLT_PCREL + - : BFD_RELOC_32_PLTOFF + - : BFD_RELOC_16_PLTOFF + - : BFD_RELOC_LO16_PLTOFF + - : BFD_RELOC_HI16_PLTOFF + - : BFD_RELOC_HI16_S_PLTOFF + - : BFD_RELOC_8_PLTOFF + For ELF. + + - : BFD_RELOC_68K_GLOB_DAT + - : BFD_RELOC_68K_JMP_SLOT + - : BFD_RELOC_68K_RELATIVE + Relocations used by 68K ELF. + + - : BFD_RELOC_32_BASEREL + - : BFD_RELOC_16_BASEREL + - : BFD_RELOC_LO16_BASEREL + - : BFD_RELOC_HI16_BASEREL + - : BFD_RELOC_HI16_S_BASEREL + - : BFD_RELOC_8_BASEREL + - : BFD_RELOC_RVA + Linkage-table relative. + + - : BFD_RELOC_8_FFnn + Absolute 8-bit relocation, but used to form an address like 0xFFnn. + + - : BFD_RELOC_32_PCREL_S2 + - : BFD_RELOC_16_PCREL_S2 + - : BFD_RELOC_23_PCREL_S2 + These PC-relative relocations are stored as word displacements - + i.e., byte displacements shifted right two bits. The 30-bit word + displacement (<<32_PCREL_S2>> - 32 bits, shifted 2) is used on the + SPARC. (SPARC tools generally refer to this as <<WDISP30>>.) The + signed 16-bit displacement is used on the MIPS, and the 23-bit + displacement is used on the Alpha. + + - : BFD_RELOC_HI22 + - : BFD_RELOC_LO10 + High 22 bits and low 10 bits of 32-bit value, placed into lower + bits of the target word. These are used on the SPARC. + + - : BFD_RELOC_GPREL16 + - : BFD_RELOC_GPREL32 + For systems that allocate a Global Pointer register, these are + displacements off that register. These relocation types are + handled specially, because the value the register will have is + decided relatively late. + + - : BFD_RELOC_I960_CALLJ + Reloc types used for i960/b.out. + + - : BFD_RELOC_NONE + - : BFD_RELOC_SPARC_WDISP22 + - : BFD_RELOC_SPARC22 + - : BFD_RELOC_SPARC13 + - : BFD_RELOC_SPARC_GOT10 + - : BFD_RELOC_SPARC_GOT13 + - : BFD_RELOC_SPARC_GOT22 + - : BFD_RELOC_SPARC_PC10 + - : BFD_RELOC_SPARC_PC22 + - : BFD_RELOC_SPARC_WPLT30 + - : BFD_RELOC_SPARC_COPY + - : BFD_RELOC_SPARC_GLOB_DAT + - : BFD_RELOC_SPARC_JMP_SLOT + - : BFD_RELOC_SPARC_RELATIVE + - : BFD_RELOC_SPARC_UA32 + SPARC ELF relocations. There is probably some overlap with other + relocation types already defined. + + - : BFD_RELOC_SPARC_BASE13 + - : BFD_RELOC_SPARC_BASE22 + I think these are specific to SPARC a.out (e.g., Sun 4). + + - : BFD_RELOC_SPARC_64 + - : BFD_RELOC_SPARC_10 + - : BFD_RELOC_SPARC_11 + - : BFD_RELOC_SPARC_OLO10 + - : BFD_RELOC_SPARC_HH22 + - : BFD_RELOC_SPARC_HM10 + - : BFD_RELOC_SPARC_LM22 + - : BFD_RELOC_SPARC_PC_HH22 + - : BFD_RELOC_SPARC_PC_HM10 + - : BFD_RELOC_SPARC_PC_LM22 + - : BFD_RELOC_SPARC_WDISP16 + - : BFD_RELOC_SPARC_WDISP19 + - : BFD_RELOC_SPARC_GLOB_JMP + - : BFD_RELOC_SPARC_7 + - : BFD_RELOC_SPARC_6 + - : BFD_RELOC_SPARC_5 + Some relocations we're using for SPARC V9 - subject to change. + + - : BFD_RELOC_ALPHA_GPDISP_HI16 + Alpha ECOFF and ELF relocations. Some of these treat the symbol or + "addend" in some special way. For GPDISP_HI16 ("gpdisp") + relocations, the symbol is ignored when writing; when reading, it + will be the absolute section symbol. The addend is the + displacement in bytes of the "lda" instruction from the "ldah" + instruction (which is at the address of this reloc). + + - : BFD_RELOC_ALPHA_GPDISP_LO16 + For GPDISP_LO16 ("ignore") relocations, the symbol is handled as + with GPDISP_HI16 relocs. The addend is ignored when writing the + relocations out, and is filled in with the file's GP value on + reading, for convenience. + + - : BFD_RELOC_ALPHA_GPDISP + The ELF GPDISP relocation is exactly the same as the GPDISP_HI16 + relocation except that there is no accompanying GPDISP_LO16 + relocation. + + - : BFD_RELOC_ALPHA_LITERAL + - : BFD_RELOC_ALPHA_ELF_LITERAL + - : BFD_RELOC_ALPHA_LITUSE + The Alpha LITERAL/LITUSE relocs are produced by a symbol reference; + the assembler turns it into a LDQ instruction to load the address + of the symbol, and then fills in a register in the real + instruction. + + The LITERAL reloc, at the LDQ instruction, refers to the .lita + section symbol. The addend is ignored when writing, but is filled + in with the file's GP value on reading, for convenience, as with + the GPDISP_LO16 reloc. + + The ELF_LITERAL reloc is somewhere between 16_GOTOFF and + GPDISP_LO16. It should refer to the symbol to be referenced, as + with 16_GOTOFF, but it generates output not based on the position + within the .got section, but relative to the GP value chosen for + the file during the final link stage. + + The LITUSE reloc, on the instruction using the loaded address, + gives information to the linker that it might be able to use to + optimize away some literal section references. The symbol is + ignored (read as the absolute section symbol), and the "addend" + indicates the type of instruction using the register: 1 - "memory" + fmt insn 2 - byte-manipulation (byte offset reg) 3 - jsr (target + of branch) + + The GNU linker currently doesn't do any of this optimizing. + + - : BFD_RELOC_ALPHA_HINT + The HINT relocation indicates a value that should be filled into + the "hint" field of a jmp/jsr/ret instruction, for possible branch- + prediction logic which may be provided on some processors. + + - : BFD_RELOC_ALPHA_LINKAGE + The LINKAGE relocation outputs a linkage pair in the object file, + which is filled by the linker. + + - : BFD_RELOC_ALPHA_CODEADDR + The CODEADDR relocation outputs a STO_CA in the object file, which + is filled by the linker. + + - : BFD_RELOC_MIPS_JMP + Bits 27..2 of the relocation address shifted right 2 bits; simple + reloc otherwise. + + - : BFD_RELOC_MIPS16_JMP + The MIPS16 jump instruction. + + - : BFD_RELOC_MIPS16_GPREL + MIPS16 GP relative reloc. + + - : BFD_RELOC_HI16 + High 16 bits of 32-bit value; simple reloc. + + - : BFD_RELOC_HI16_S + High 16 bits of 32-bit value but the low 16 bits will be sign + extended and added to form the final result. If the low 16 bits + form a negative number, we need to add one to the high value to + compensate for the borrow when the low bits are added. + + - : BFD_RELOC_LO16 + Low 16 bits. + + - : BFD_RELOC_PCREL_HI16_S + Like BFD_RELOC_HI16_S, but PC relative. + + - : BFD_RELOC_PCREL_LO16 + Like BFD_RELOC_LO16, but PC relative. + + - : BFD_RELOC_MIPS_GPREL + Relocation relative to the global pointer. + + - : BFD_RELOC_MIPS_LITERAL + Relocation against a MIPS literal section. + + - : BFD_RELOC_MIPS_GOT16 + - : BFD_RELOC_MIPS_CALL16 + - : BFD_RELOC_MIPS_GPREL32 + - : BFD_RELOC_MIPS_GOT_HI16 + - : BFD_RELOC_MIPS_GOT_LO16 + - : BFD_RELOC_MIPS_CALL_HI16 + - : BFD_RELOC_MIPS_CALL_LO16 + MIPS ELF relocations. + + - : BFD_RELOC_386_GOT32 + - : BFD_RELOC_386_PLT32 + - : BFD_RELOC_386_COPY + - : BFD_RELOC_386_GLOB_DAT + - : BFD_RELOC_386_JUMP_SLOT + - : BFD_RELOC_386_RELATIVE + - : BFD_RELOC_386_GOTOFF + - : BFD_RELOC_386_GOTPC + i386/elf relocations + + - : BFD_RELOC_NS32K_IMM_8 + - : BFD_RELOC_NS32K_IMM_16 + - : BFD_RELOC_NS32K_IMM_32 + - : BFD_RELOC_NS32K_IMM_8_PCREL + - : BFD_RELOC_NS32K_IMM_16_PCREL + - : BFD_RELOC_NS32K_IMM_32_PCREL + - : BFD_RELOC_NS32K_DISP_8 + - : BFD_RELOC_NS32K_DISP_16 + - : BFD_RELOC_NS32K_DISP_32 + - : BFD_RELOC_NS32K_DISP_8_PCREL + - : BFD_RELOC_NS32K_DISP_16_PCREL + - : BFD_RELOC_NS32K_DISP_32_PCREL + ns32k relocations + + - : BFD_RELOC_PPC_B26 + - : BFD_RELOC_PPC_BA26 + - : BFD_RELOC_PPC_TOC16 + - : BFD_RELOC_PPC_B16 + - : BFD_RELOC_PPC_B16_BRTAKEN + - : BFD_RELOC_PPC_B16_BRNTAKEN + - : BFD_RELOC_PPC_BA16 + - : BFD_RELOC_PPC_BA16_BRTAKEN + - : BFD_RELOC_PPC_BA16_BRNTAKEN + - : BFD_RELOC_PPC_COPY + - : BFD_RELOC_PPC_GLOB_DAT + - : BFD_RELOC_PPC_JMP_SLOT + - : BFD_RELOC_PPC_RELATIVE + - : BFD_RELOC_PPC_LOCAL24PC + - : BFD_RELOC_PPC_EMB_NADDR32 + - : BFD_RELOC_PPC_EMB_NADDR16 + - : BFD_RELOC_PPC_EMB_NADDR16_LO + - : BFD_RELOC_PPC_EMB_NADDR16_HI + - : BFD_RELOC_PPC_EMB_NADDR16_HA + - : BFD_RELOC_PPC_EMB_SDAI16 + - : BFD_RELOC_PPC_EMB_SDA2I16 + - : BFD_RELOC_PPC_EMB_SDA2REL + - : BFD_RELOC_PPC_EMB_SDA21 + - : BFD_RELOC_PPC_EMB_MRKREF + - : BFD_RELOC_PPC_EMB_RELSEC16 + - : BFD_RELOC_PPC_EMB_RELST_LO + - : BFD_RELOC_PPC_EMB_RELST_HI + - : BFD_RELOC_PPC_EMB_RELST_HA + - : BFD_RELOC_PPC_EMB_BIT_FLD + - : BFD_RELOC_PPC_EMB_RELSDA + Power(rs6000) and PowerPC relocations. + + - : BFD_RELOC_CTOR + The type of reloc used to build a contructor table - at the moment + probably a 32 bit wide absolute relocation, but the target can + choose. It generally does map to one of the other relocation + types. + + - : BFD_RELOC_ARM_PCREL_BRANCH + ARM 26 bit pc-relative branch. The lowest two bits must be zero + and are not stored in the instruction. + + - : BFD_RELOC_ARM_IMMEDIATE + - : BFD_RELOC_ARM_OFFSET_IMM + - : BFD_RELOC_ARM_SHIFT_IMM + - : BFD_RELOC_ARM_SWI + - : BFD_RELOC_ARM_MULTI + - : BFD_RELOC_ARM_CP_OFF_IMM + - : BFD_RELOC_ARM_ADR_IMM + - : BFD_RELOC_ARM_LDR_IMM + - : BFD_RELOC_ARM_LITERAL + - : BFD_RELOC_ARM_IN_POOL + - : BFD_RELOC_ARM_OFFSET_IMM8 + - : BFD_RELOC_ARM_HWLITERAL + - : BFD_RELOC_ARM_THUMB_ADD + - : BFD_RELOC_ARM_THUMB_IMM + - : BFD_RELOC_ARM_THUMB_SHIFT + - : BFD_RELOC_ARM_THUMB_OFFSET + These relocs are only used within the ARM assembler. They are not + (at present) written to any object files. + + - : BFD_RELOC_SH_PCDISP8BY2 + - : BFD_RELOC_SH_PCDISP12BY2 + - : BFD_RELOC_SH_IMM4 + - : BFD_RELOC_SH_IMM4BY2 + - : BFD_RELOC_SH_IMM4BY4 + - : BFD_RELOC_SH_IMM8 + - : BFD_RELOC_SH_IMM8BY2 + - : BFD_RELOC_SH_IMM8BY4 + - : BFD_RELOC_SH_PCRELIMM8BY2 + - : BFD_RELOC_SH_PCRELIMM8BY4 + - : BFD_RELOC_SH_SWITCH16 + - : BFD_RELOC_SH_SWITCH32 + - : BFD_RELOC_SH_USES + - : BFD_RELOC_SH_COUNT + - : BFD_RELOC_SH_ALIGN + - : BFD_RELOC_SH_CODE + - : BFD_RELOC_SH_DATA + - : BFD_RELOC_SH_LABEL + Hitachi SH relocs. Not all of these appear in object files. + + - : BFD_RELOC_D10V_10_PCREL_R + Mitsubishi D10V relocs. This is a 10-bit reloc with the right 2 + bits assumed to be 0. + + - : BFD_RELOC_D10V_10_PCREL_L + Mitsubishi D10V relocs. This is a 10-bit reloc with the right 2 + bits assumed to be 0. This is the same as the previous reloc + except it is in the left container, i.e., shifted left 15 bits. + + - : BFD_RELOC_D10V_18 + This is an 18-bit reloc with the right 2 bits assumed to be 0. + + - : BFD_RELOC_D10V_18_PCREL + This is an 18-bit reloc with the right 2 bits assumed to be 0. + + - : BFD_RELOC_M32R_24 + Mitsubishi M32R relocs. This is a 24 bit absolute address. + + - : BFD_RELOC_M32R_10_PCREL + This is a 10-bit pc-relative reloc with the right 2 bits assumed + to be 0. + + - : BFD_RELOC_M32R_18_PCREL + This is an 18-bit reloc with the right 2 bits assumed to be 0. + + - : BFD_RELOC_M32R_26_PCREL + This is a 26-bit reloc with the right 2 bits assumed to be 0. + + - : BFD_RELOC_M32R_HI16_ULO + This is a 16-bit reloc containing the high 16 bits of an address + used when the lower 16 bits are treated as unsigned. + + - : BFD_RELOC_M32R_HI16_SLO + This is a 16-bit reloc containing the high 16 bits of an address + used when the lower 16 bits are treated as signed. + + - : BFD_RELOC_M32R_LO16 + This is a 16-bit reloc containing the lower 16 bits of an address. + + - : BFD_RELOC_M32R_SDA16 + This is a 16-bit reloc containing the small data area offset for + use in add3, load, and store instructions. + + - : BFD_RELOC_MN10300_32_PCREL + This is a 32bit pcrel reloc for the mn10300, offset by two bytes + in the instruction. + + - : BFD_RELOC_MN10300_16_PCREL + This is a 16bit pcrel reloc for the mn10300, offset by two bytes + in the instruction. + . + typedef enum bfd_reloc_code_real bfd_reloc_code_real_type; + +`bfd_reloc_type_lookup' +....................... + + *Synopsis* + reloc_howto_type * + bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code); + *Description* +Return a pointer to a howto structure which, when invoked, will perform +the relocation CODE on data from the architecture noted. +`bfd_default_reloc_type_lookup' +............................... + +*Synopsis* + reloc_howto_type *bfd_default_reloc_type_lookup + (bfd *abfd, bfd_reloc_code_real_type code); + *Description* +Provides a default relocation lookup routine for any architecture. +`bfd_get_reloc_code_name' +......................... + +*Synopsis* + const char *bfd_get_reloc_code_name (bfd_reloc_code_real_type code); + *Description* +Provides a printable name for the supplied relocation code. Useful +mainly for printing error messages. +`bfd_generic_relax_section' +........................... + +*Synopsis* + boolean bfd_generic_relax_section + (bfd *abfd, + asection *section, + struct bfd_link_info *, + boolean *); + *Description* +Provides default handling for relaxing for back ends which don't do +relaxing - i.e., does nothing. +`bfd_generic_get_relocated_section_contents' +............................................ + +*Synopsis* + bfd_byte * + bfd_generic_get_relocated_section_contents (bfd *abfd, + struct bfd_link_info *link_info, + struct bfd_link_order *link_order, + bfd_byte *data, + boolean relocateable, + asymbol **symbols); + *Description* +Provides default handling of relocation effort for back ends which +can't be bothered to do it efficiently. + +File: bfd.info, Node: Core Files, Next: Targets, Prev: Relocations, Up: BFD front end + +Core files +========== + +*Description* +These are functions pertaining to core files. +`bfd_core_file_failing_command' +............................... + +*Synopsis* + CONST char *bfd_core_file_failing_command(bfd *abfd); + *Description* +Return a read-only string explaining which program was running when it +failed and produced the core file ABFD. +`bfd_core_file_failing_signal' +.............................. + +*Synopsis* + int bfd_core_file_failing_signal(bfd *abfd); + *Description* +Returns the signal number which caused the core dump which generated +the file the BFD ABFD is attached to. +`core_file_matches_executable_p' +................................ + +*Synopsis* + boolean core_file_matches_executable_p + (bfd *core_bfd, bfd *exec_bfd); + *Description* +Return `true' if the core file attached to CORE_BFD was generated by a +run of the executable file attached to EXEC_BFD, `false' otherwise. + +File: bfd.info, Node: Targets, Next: Architectures, Prev: Core Files, Up: BFD front end + +Targets +======= + +*Description* +Each port of BFD to a different machine requries the creation of a +target back end. All the back end provides to the root part of BFD is a +structure containing pointers to functions which perform certain low +level operations on files. BFD translates the applications's requests +through a pointer into calls to the back end routines. + + When a file is opened with `bfd_openr', its format and target are +unknown. BFD uses various mechanisms to determine how to interpret the +file. The operations performed are: + + * Create a BFD by calling the internal routine `_bfd_new_bfd', then + call `bfd_find_target' with the target string supplied to + `bfd_openr' and the new BFD pointer. + + * If a null target string was provided to `bfd_find_target', look up + the environment variable `GNUTARGET' and use that as the target + string. + + * If the target string is still `NULL', or the target string is + `default', then use the first item in the target vector as the + target type, and set `target_defaulted' in the BFD to cause + `bfd_check_format' to loop through all the targets. *Note + bfd_target::. *Note Formats::. + + * Otherwise, inspect the elements in the target vector one by one, + until a match on target name is found. When found, use it. + + * Otherwise return the error `bfd_error_invalid_target' to + `bfd_openr'. + + * `bfd_openr' attempts to open the file using `bfd_open_file', and + returns the BFD. Once the BFD has been opened and the target +selected, the file format may be determined. This is done by calling +`bfd_check_format' on the BFD with a suggested format. If +`target_defaulted' has been set, each possible target type is tried to +see if it recognizes the specified format. `bfd_check_format' returns +`true' when the caller guesses right. + +* Menu: + +* bfd_target:: + + +File: bfd.info, Node: bfd_target, Prev: Targets, Up: Targets + +bfd_target +---------- + +*Description* +This structure contains everything that BFD knows about a target. It +includes things like its byte order, name, and which routines to call +to do various operations. + + Every BFD points to a target structure with its `xvec' member. + + The macros below are used to dispatch to functions through the +`bfd_target' vector. They are used in a number of macros further down +in `bfd.h', and are also used when calling various routines by hand +inside the BFD implementation. The ARGLIST argument must be +parenthesized; it contains all the arguments to the called function. + + They make the documentation (more) unpleasant to read, so if someone +wants to fix this and not break the above, please do. + #define BFD_SEND(bfd, message, arglist) \ + ((*((bfd)->xvec->message)) arglist) + + #ifdef DEBUG_BFD_SEND + #undef BFD_SEND + #define BFD_SEND(bfd, message, arglist) \ + (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \ + ((*((bfd)->xvec->message)) arglist) : \ + (bfd_assert (__FILE__,__LINE__), NULL)) + #endif + For operations which index on the BFD format: + #define BFD_SEND_FMT(bfd, message, arglist) \ + (((bfd)->xvec->message[(int)((bfd)->format)]) arglist) + + #ifdef DEBUG_BFD_SEND + #undef BFD_SEND_FMT + #define BFD_SEND_FMT(bfd, message, arglist) \ + (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \ + (((bfd)->xvec->message[(int)((bfd)->format)]) arglist) : \ + (bfd_assert (__FILE__,__LINE__), NULL)) + #endif + This is the structure which defines the type of BFD this is. The +`xvec' member of the struct `bfd' itself points here. Each module that +implements access to a different target under BFD, defines one of these. + + FIXME, these names should be rationalised with the names of the +entry points which call them. Too bad we can't have one macro to define +them both! + enum bfd_flavour { + bfd_target_unknown_flavour, + bfd_target_aout_flavour, + bfd_target_coff_flavour, + bfd_target_ecoff_flavour, + bfd_target_elf_flavour, + bfd_target_ieee_flavour, + bfd_target_nlm_flavour, + bfd_target_oasys_flavour, + bfd_target_tekhex_flavour, + bfd_target_srec_flavour, + bfd_target_ihex_flavour, + bfd_target_som_flavour, + bfd_target_os9k_flavour, + bfd_target_versados_flavour, + bfd_target_msdos_flavour, + bfd_target_evax_flavour + }; + + enum bfd_endian { BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN }; + + /* Forward declaration. */ + typedef struct bfd_link_info _bfd_link_info; + + typedef struct bfd_target + { + Identifies the kind of target, e.g., SunOS4, Ultrix, etc. + char *name; + The "flavour" of a back end is a general indication about the +contents of a file. + enum bfd_flavour flavour; + The order of bytes within the data area of a file. + enum bfd_endian byteorder; + The order of bytes within the header parts of a file. + enum bfd_endian header_byteorder; + A mask of all the flags which an executable may have set - from the +set `BFD_NO_FLAGS', `HAS_RELOC', ...`D_PAGED'. + flagword object_flags; + A mask of all the flags which a section may have set - from the set +`SEC_NO_FLAGS', `SEC_ALLOC', ...`SET_NEVER_LOAD'. + flagword section_flags; + The character normally found at the front of a symbol (if any), +perhaps `_'. + char symbol_leading_char; + The pad character for file names within an archive header. + char ar_pad_char; + The maximum number of characters in an archive header. + unsigned short ar_max_namelen; + Entries for byte swapping for data. These are different from the +other entry points, since they don't take a BFD asthe first argument. +Certain other handlers could do the same. + bfd_vma (*bfd_getx64) PARAMS ((const bfd_byte *)); + bfd_signed_vma (*bfd_getx_signed_64) PARAMS ((const bfd_byte *)); + void (*bfd_putx64) PARAMS ((bfd_vma, bfd_byte *)); + bfd_vma (*bfd_getx32) PARAMS ((const bfd_byte *)); + bfd_signed_vma (*bfd_getx_signed_32) PARAMS ((const bfd_byte *)); + void (*bfd_putx32) PARAMS ((bfd_vma, bfd_byte *)); + bfd_vma (*bfd_getx16) PARAMS ((const bfd_byte *)); + bfd_signed_vma (*bfd_getx_signed_16) PARAMS ((const bfd_byte *)); + void (*bfd_putx16) PARAMS ((bfd_vma, bfd_byte *)); + Byte swapping for the headers + bfd_vma (*bfd_h_getx64) PARAMS ((const bfd_byte *)); + bfd_signed_vma (*bfd_h_getx_signed_64) PARAMS ((const bfd_byte *)); + void (*bfd_h_putx64) PARAMS ((bfd_vma, bfd_byte *)); + bfd_vma (*bfd_h_getx32) PARAMS ((const bfd_byte *)); + bfd_signed_vma (*bfd_h_getx_signed_32) PARAMS ((const bfd_byte *)); + void (*bfd_h_putx32) PARAMS ((bfd_vma, bfd_byte *)); + bfd_vma (*bfd_h_getx16) PARAMS ((const bfd_byte *)); + bfd_signed_vma (*bfd_h_getx_signed_16) PARAMS ((const bfd_byte *)); + void (*bfd_h_putx16) PARAMS ((bfd_vma, bfd_byte *)); + Format dependent routines: these are vectors of entry points within +the target vector structure, one for each format to check. + + Check the format of a file being read. Return a `bfd_target *' or +zero. + const struct bfd_target *(*_bfd_check_format[bfd_type_end]) PARAMS ((bfd *)); + Set the format of a file being written. + boolean (*_bfd_set_format[bfd_type_end]) PARAMS ((bfd *)); + Write cached information into a file being written, at `bfd_close'. + boolean (*_bfd_write_contents[bfd_type_end]) PARAMS ((bfd *)); + The general target vector. + + /* Generic entry points. */ + #define BFD_JUMP_TABLE_GENERIC(NAME)\ + CAT(NAME,_close_and_cleanup),\ + CAT(NAME,_bfd_free_cached_info),\ + CAT(NAME,_new_section_hook),\ + CAT(NAME,_get_section_contents),\ + CAT(NAME,_get_section_contents_in_window) + + /* Called when the BFD is being closed to do any necessary cleanup. */ + boolean (*_close_and_cleanup) PARAMS ((bfd *)); + /* Ask the BFD to free all cached information. */ + boolean (*_bfd_free_cached_info) PARAMS ((bfd *)); + /* Called when a new section is created. */ + boolean (*_new_section_hook) PARAMS ((bfd *, sec_ptr)); + /* Read the contents of a section. */ + boolean (*_bfd_get_section_contents) PARAMS ((bfd *, sec_ptr, PTR, + file_ptr, bfd_size_type)); + boolean (*_bfd_get_section_contents_in_window) + PARAMS ((bfd *, sec_ptr, bfd_window *, + file_ptr, bfd_size_type)); + + /* Entry points to copy private data. */ + #define BFD_JUMP_TABLE_COPY(NAME)\ + CAT(NAME,_bfd_copy_private_bfd_data),\ + CAT(NAME,_bfd_merge_private_bfd_data),\ + CAT(NAME,_bfd_copy_private_section_data),\ + CAT(NAME,_bfd_copy_private_symbol_data),\ + CAT(NAME,_bfd_set_private_flags),\ + CAT(NAME,_bfd_print_private_bfd_data)\ + /* Called to copy BFD general private data from one object file + to another. */ + boolean (*_bfd_copy_private_bfd_data) PARAMS ((bfd *, bfd *)); + /* Called to merge BFD general private data from one object file + to a common output file when linking. */ + boolean (*_bfd_merge_private_bfd_data) PARAMS ((bfd *, bfd *)); + /* Called to copy BFD private section data from one object file + to another. */ + boolean (*_bfd_copy_private_section_data) PARAMS ((bfd *, sec_ptr, + bfd *, sec_ptr)); + /* Called to copy BFD private symbol data from one symbol + to another. */ + boolean (*_bfd_copy_private_symbol_data) PARAMS ((bfd *, asymbol *, + bfd *, asymbol *)); + /* Called to set private backend flags */ + boolean (*_bfd_set_private_flags) PARAMS ((bfd *, flagword)); + + /* Called to print private BFD data */ + boolean (*_bfd_print_private_bfd_data) PARAMS ((bfd *, PTR)); + + /* Core file entry points. */ + #define BFD_JUMP_TABLE_CORE(NAME)\ + CAT(NAME,_core_file_failing_command),\ + CAT(NAME,_core_file_failing_signal),\ + CAT(NAME,_core_file_matches_executable_p) + char * (*_core_file_failing_command) PARAMS ((bfd *)); + int (*_core_file_failing_signal) PARAMS ((bfd *)); + boolean (*_core_file_matches_executable_p) PARAMS ((bfd *, bfd *)); + + /* Archive entry points. */ + #define BFD_JUMP_TABLE_ARCHIVE(NAME)\ + CAT(NAME,_slurp_armap),\ + CAT(NAME,_slurp_extended_name_table),\ + CAT(NAME,_construct_extended_name_table),\ + CAT(NAME,_truncate_arname),\ + CAT(NAME,_write_armap),\ + CAT(NAME,_read_ar_hdr),\ + CAT(NAME,_openr_next_archived_file),\ + CAT(NAME,_get_elt_at_index),\ + CAT(NAME,_generic_stat_arch_elt),\ + CAT(NAME,_update_armap_timestamp) + boolean (*_bfd_slurp_armap) PARAMS ((bfd *)); + boolean (*_bfd_slurp_extended_name_table) PARAMS ((bfd *)); + boolean (*_bfd_construct_extended_name_table) + PARAMS ((bfd *, char **, bfd_size_type *, const char **)); + void (*_bfd_truncate_arname) PARAMS ((bfd *, CONST char *, char *)); + boolean (*write_armap) PARAMS ((bfd *arch, + unsigned int elength, + struct orl *map, + unsigned int orl_count, + int stridx)); + PTR (*_bfd_read_ar_hdr_fn) PARAMS ((bfd *)); + bfd * (*openr_next_archived_file) PARAMS ((bfd *arch, bfd *prev)); + #define bfd_get_elt_at_index(b,i) BFD_SEND(b, _bfd_get_elt_at_index, (b,i)) + bfd * (*_bfd_get_elt_at_index) PARAMS ((bfd *, symindex)); + int (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *)); + boolean (*_bfd_update_armap_timestamp) PARAMS ((bfd *)); + + /* Entry points used for symbols. */ + #define BFD_JUMP_TABLE_SYMBOLS(NAME)\ + CAT(NAME,_get_symtab_upper_bound),\ + CAT(NAME,_get_symtab),\ + CAT(NAME,_make_empty_symbol),\ + CAT(NAME,_print_symbol),\ + CAT(NAME,_get_symbol_info),\ + CAT(NAME,_bfd_is_local_label_name),\ + CAT(NAME,_get_lineno),\ + CAT(NAME,_find_nearest_line),\ + CAT(NAME,_bfd_make_debug_symbol),\ + CAT(NAME,_read_minisymbols),\ + CAT(NAME,_minisymbol_to_symbol) + long (*_bfd_get_symtab_upper_bound) PARAMS ((bfd *)); + long (*_bfd_canonicalize_symtab) PARAMS ((bfd *, + struct symbol_cache_entry **)); + struct symbol_cache_entry * + (*_bfd_make_empty_symbol) PARAMS ((bfd *)); + void (*_bfd_print_symbol) PARAMS ((bfd *, PTR, + struct symbol_cache_entry *, + bfd_print_symbol_type)); + #define bfd_print_symbol(b,p,s,e) BFD_SEND(b, _bfd_print_symbol, (b,p,s,e)) + void (*_bfd_get_symbol_info) PARAMS ((bfd *, + struct symbol_cache_entry *, + symbol_info *)); + #define bfd_get_symbol_info(b,p,e) BFD_SEND(b, _bfd_get_symbol_info, (b,p,e)) + boolean (*_bfd_is_local_label_name) PARAMS ((bfd *, const char *)); + + alent * (*_get_lineno) PARAMS ((bfd *, struct symbol_cache_entry *)); + boolean (*_bfd_find_nearest_line) PARAMS ((bfd *abfd, + struct sec *section, struct symbol_cache_entry **symbols, + bfd_vma offset, CONST char **file, CONST char **func, + unsigned int *line)); + /* Back-door to allow format-aware applications to create debug symbols + while using BFD for everything else. Currently used by the assembler + when creating COFF files. */ + asymbol * (*_bfd_make_debug_symbol) PARAMS (( + bfd *abfd, + void *ptr, + unsigned long size)); + #define bfd_read_minisymbols(b, d, m, s) \ + BFD_SEND (b, _read_minisymbols, (b, d, m, s)) + long (*_read_minisymbols) PARAMS ((bfd *, boolean, PTR *, + unsigned int *)); + #define bfd_minisymbol_to_symbol(b, d, m, f) \ + BFD_SEND (b, _minisymbol_to_symbol, (b, d, m, f)) + asymbol *(*_minisymbol_to_symbol) PARAMS ((bfd *, boolean, const PTR, + asymbol *)); + + /* Routines for relocs. */ + #define BFD_JUMP_TABLE_RELOCS(NAME)\ + CAT(NAME,_get_reloc_upper_bound),\ + CAT(NAME,_canonicalize_reloc),\ + CAT(NAME,_bfd_reloc_type_lookup) + long (*_get_reloc_upper_bound) PARAMS ((bfd *, sec_ptr)); + long (*_bfd_canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **, + struct symbol_cache_entry **)); + /* See documentation on reloc types. */ + reloc_howto_type * + (*reloc_type_lookup) PARAMS ((bfd *abfd, + bfd_reloc_code_real_type code)); + + /* Routines used when writing an object file. */ + #define BFD_JUMP_TABLE_WRITE(NAME)\ + CAT(NAME,_set_arch_mach),\ + CAT(NAME,_set_section_contents) + boolean (*_bfd_set_arch_mach) PARAMS ((bfd *, enum bfd_architecture, + unsigned long)); + boolean (*_bfd_set_section_contents) PARAMS ((bfd *, sec_ptr, PTR, + file_ptr, bfd_size_type)); + + /* Routines used by the linker. */ + #define BFD_JUMP_TABLE_LINK(NAME)\ + CAT(NAME,_sizeof_headers),\ + CAT(NAME,_bfd_get_relocated_section_contents),\ + CAT(NAME,_bfd_relax_section),\ + CAT(NAME,_bfd_link_hash_table_create),\ + CAT(NAME,_bfd_link_add_symbols),\ + CAT(NAME,_bfd_final_link),\ + CAT(NAME,_bfd_link_split_section) + int (*_bfd_sizeof_headers) PARAMS ((bfd *, boolean)); + bfd_byte * (*_bfd_get_relocated_section_contents) PARAMS ((bfd *, + struct bfd_link_info *, struct bfd_link_order *, + bfd_byte *data, boolean relocateable, + struct symbol_cache_entry **)); + + boolean (*_bfd_relax_section) PARAMS ((bfd *, struct sec *, + struct bfd_link_info *, boolean *again)); + + /* Create a hash table for the linker. Different backends store + different information in this table. */ + struct bfd_link_hash_table *(*_bfd_link_hash_table_create) PARAMS ((bfd *)); + + /* Add symbols from this object file into the hash table. */ + boolean (*_bfd_link_add_symbols) PARAMS ((bfd *, struct bfd_link_info *)); + + /* Do a link based on the link_order structures attached to each + section of the BFD. */ + boolean (*_bfd_final_link) PARAMS ((bfd *, struct bfd_link_info *)); + + /* Should this section be split up into smaller pieces during linking. */ + boolean (*_bfd_link_split_section) PARAMS ((bfd *, struct sec *)); + + /* Routines to handle dynamic symbols and relocs. */ + #define BFD_JUMP_TABLE_DYNAMIC(NAME)\ + CAT(NAME,_get_dynamic_symtab_upper_bound),\ + CAT(NAME,_canonicalize_dynamic_symtab),\ + CAT(NAME,_get_dynamic_reloc_upper_bound),\ + CAT(NAME,_canonicalize_dynamic_reloc) + /* Get the amount of memory required to hold the dynamic symbols. */ + long (*_bfd_get_dynamic_symtab_upper_bound) PARAMS ((bfd *)); + /* Read in the dynamic symbols. */ + long (*_bfd_canonicalize_dynamic_symtab) + PARAMS ((bfd *, struct symbol_cache_entry **)); + /* Get the amount of memory required to hold the dynamic relocs. */ + long (*_bfd_get_dynamic_reloc_upper_bound) PARAMS ((bfd *)); + /* Read in the dynamic relocs. */ + long (*_bfd_canonicalize_dynamic_reloc) + PARAMS ((bfd *, arelent **, struct symbol_cache_entry **)); + Data for use by back-end routines, which isn't generic enough to +belong in this structure. + PTR backend_data; + } bfd_target; + +`bfd_set_default_target' +........................ + +*Synopsis* + boolean bfd_set_default_target (const char *name); + *Description* +Set the default target vector to use when recognizing a BFD. This +takes the name of the target, which may be a BFD target name or a +configuration triplet. +`bfd_find_target' +................. + +*Synopsis* + const bfd_target *bfd_find_target(CONST char *target_name, bfd *abfd); + *Description* +Return a pointer to the transfer vector for the object target named +TARGET_NAME. If TARGET_NAME is `NULL', choose the one in the +environment variable `GNUTARGET'; if that is null or not defined, then +choose the first entry in the target list. Passing in the string +"default" or setting the environment variable to "default" will cause +the first entry in the target list to be returned, and +"target_defaulted" will be set in the BFD. This causes +`bfd_check_format' to loop over all the targets to find the one that +matches the file being read. +`bfd_target_list' +................. + +*Synopsis* + const char **bfd_target_list(void); + *Description* +Return a freshly malloced NULL-terminated vector of the names of all +the valid BFD targets. Do not modify the names. + +File: bfd.info, Node: Architectures, Next: Opening and Closing, Prev: Targets, Up: BFD front end + +Architectures +============= + +BFD keeps one atom in a BFD describing the architecture of the data +attached to the BFD: a pointer to a `bfd_arch_info_type'. + + 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 +`SELECT_ARCHITECTURES'. This is normally set up in the +`config/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 `archures.c'. +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 */ + 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_v9 6 + #define bfd_mach_sparc_v9a 7 /* with ultrasparc 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_v9a) + bfd_arch_mips, /* MIPS Rxxxx */ + bfd_arch_i386, /* Intel 386 */ + #define bfd_mach_i386_i386 0 + #define bfd_mach_i386_i8086 1 + bfd_arch_we32k, /* AT&T WE32xxx */ + bfd_arch_tahoe, /* CCI/Harris Tahoe */ + bfd_arch_i860, /* Intel 860 */ + 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_powerpc, /* PowerPC */ + bfd_arch_rs6000, /* IBM RS/6000 */ + bfd_arch_hppa, /* HP PA RISC */ + bfd_arch_d10v, /* Mitsubishi D10V */ + 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 */ + bfd_arch_alpha, /* Dec Alpha */ + bfd_arch_arm, /* Advanced Risc Machines ARM */ + bfd_arch_ns32k, /* National Semiconductors ns32000 */ + bfd_arch_w65, /* WDC 65816 */ + bfd_arch_m32r, /* Mitsubishi M32R/D */ + bfd_arch_mn10200, /* Matsushita MN10200 */ + bfd_arch_mn10300, /* Matsushita MN10300 */ + bfd_arch_last + }; + +bfd_arch_info +------------- + +*Description* +This structure contains information on architectures for use within BFD. + + 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; + +`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. +`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 STRING. Return a pointer to an `arch_info' structure if a machine +is found, otherwise NULL. +`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 `arch_info' structure describing the compatible machine. +`bfd_default_arch_struct' +......................... + +*Description* +The `bfd_default_arch_struct' is an item of `bfd_arch_info_type' 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; + +`bfd_set_arch_info' +................... + +*Synopsis* + void bfd_set_arch_info(bfd *abfd, const bfd_arch_info_type *arg); + *Description* +Set the architecture info of ABFD to ARG. +`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 ABFD to ARCH and MACH. +Find the correct pointer to a structure and insert it into the +`arch_info' pointer. +`bfd_get_arch' +.............. + +*Synopsis* + enum bfd_architecture bfd_get_arch(bfd *abfd); + *Description* +Return the enumerated type which describes the BFD ABFD's architecture. +`bfd_get_mach' +.............. + +*Synopsis* + unsigned long bfd_get_mach(bfd *abfd); + *Description* +Return the long type which describes the BFD ABFD's machine. +`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 ABFD's architecture's bytes. +`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 ABFD's architecture's +addresses. +`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. +`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. +`bfd_get_arch_info' +................... + +*Synopsis* + const bfd_arch_info_type * bfd_get_arch_info(bfd *abfd); + *Description* +Return the architecture info struct in ABFD. +`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 +ARCH and MACHINE. A machine of 0 matches the machine/architecture +structure which marks itself as the default. +`bfd_printable_arch_mach' +......................... + +*Synopsis* + const char *bfd_printable_arch_mach + (enum bfd_architecture arch, unsigned long machine); + *Description* +Return a printable string representing the architecture and machine +type. + + This routine is depreciated. + +File: bfd.info, Node: Opening and Closing, Next: Internal, Prev: Architectures, Up: BFD front end + +Opening and closing BFDs +======================== + +`bfd_openr' +........... + +*Synopsis* + bfd *bfd_openr(CONST char *filename, CONST char *target); + *Description* +Open the file FILENAME (using `fopen') with the target TARGET. Return +a pointer to the created BFD. + + Calls `bfd_find_target', so TARGET is interpreted as by that +function. + + If `NULL' is returned then an error has occured. Possible errors +are `bfd_error_no_memory', `bfd_error_invalid_target' or `system_call' +error. +`bfd_fdopenr' +............. + +*Synopsis* + bfd *bfd_fdopenr(CONST char *filename, CONST char *target, int fd); + *Description* +`bfd_fdopenr' is to `bfd_fopenr' much like `fdopen' is to `fopen'. It +opens a BFD on a file already described by the FD supplied. + + When the file is later `bfd_close'd, the file descriptor will be +closed. + + If the caller desires that this file descriptor be cached by BFD +(opened as needed, closed as needed to free descriptors for other +opens), with the supplied FD used as an initial file descriptor (but +subject to closure at any time), call bfd_set_cacheable(bfd, 1) on the +returned BFD. The default is to assume no cacheing; the file +descriptor will remain open until `bfd_close', and will not be affected +by BFD operations on other files. + + Possible errors are `bfd_error_no_memory', +`bfd_error_invalid_target' and `bfd_error_system_call'. +`bfd_openstreamr' +................. + +*Synopsis* + bfd *bfd_openstreamr(const char *, const char *, PTR); + *Description* +Open a BFD for read access on an existing stdio stream. When the BFD +is passed to `bfd_close', the stream will be closed. +`bfd_openw' +........... + +*Synopsis* + bfd *bfd_openw(CONST char *filename, CONST char *target); + *Description* +Create a BFD, associated with file FILENAME, using the file format +TARGET, and return a pointer to it. + + Possible errors are `bfd_error_system_call', `bfd_error_no_memory', +`bfd_error_invalid_target'. +`bfd_close' +........... + +*Synopsis* + boolean bfd_close(bfd *abfd); + *Description* +Close a BFD. If the BFD was open for writing, then pending operations +are completed and the file written out and closed. If the created file +is executable, then `chmod' is called to mark it as such. + + All memory attached to the BFD is released. + + The file descriptor associated with the BFD is closed (even if it +was passed in to BFD by `bfd_fdopenr'). +*Returns* +`true' is returned if all is ok, otherwise `false'. +`bfd_close_all_done' +.................... + +*Synopsis* + boolean bfd_close_all_done(bfd *); + *Description* +Close a BFD. Differs from `bfd_close' since it does not complete any +pending operations. This routine would be used if the application had +just used BFD for swapping and didn't want to use any of the writing +code. + + If the created file is executable, then `chmod' is called to mark it +as such. + + All memory attached to the BFD is released. +*Returns* +`true' is returned if all is ok, otherwise `false'. +`bfd_create' +............ + +*Synopsis* + bfd *bfd_create(CONST char *filename, bfd *templ); + *Description* +Create a new BFD in the manner of `bfd_openw', but without opening a +file. The new BFD takes the target from the target used by TEMPLATE. The +format is always set to `bfd_object'. +`bfd_alloc' +........... + +*Synopsis* + PTR bfd_alloc (bfd *abfd, size_t wanted); + *Description* +Allocate a block of WANTED bytes of memory attached to `abfd' and +return a pointer to it. diff --git a/gnu/usr.bin/binutils/bfd/doc/bfd.info-4 b/gnu/usr.bin/binutils/bfd/doc/bfd.info-4 new file mode 100644 index 00000000000..430d0df0ba6 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/bfd.info-4 @@ -0,0 +1,1023 @@ +This is Info file bfd.info, produced by Makeinfo-1.64 from the input +file ./bfd.texinfo. + +START-INFO-DIR-ENTRY +* Bfd: (bfd). The Binary File Descriptor library. +END-INFO-DIR-ENTRY + + This file documents the BFD library. + + Copyright (C) 1991 Free Software Foundation, Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + + Permission is granted to copy and distribute modified versions of +this manual under the conditions for verbatim copying, subject to the +terms of the GNU General Public License, which includes the provision +that the entire resulting derived work is distributed under the terms +of a permission notice identical to this one. + + Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions. + + +File: bfd.info, Node: Internal, Next: File Caching, Prev: Opening and Closing, Up: BFD front end + +Internal functions +================== + +*Description* +These routines are used within BFD. They are not intended for export, +but are documented here for completeness. +`bfd_write_bigendian_4byte_int' +............................... + +*Synopsis* + void bfd_write_bigendian_4byte_int(bfd *abfd, int i); + *Description* +Write a 4 byte integer I to the output BFD ABFD, in big endian order +regardless of what else is going on. This is useful in archives. +`bfd_put_size' +.............. + +`bfd_get_size' +.............. + +*Description* +These macros as used for reading and writing raw data in sections; each +access (except for bytes) is vectored through the target format of the +BFD and mangled accordingly. The mangling performs any necessary endian +translations and removes alignment restrictions. Note that types +accepted and returned by these macros are identical so they can be +swapped around in macros--for example, `libaout.h' defines `GET_WORD' +to either `bfd_get_32' or `bfd_get_64'. + + In the put routines, VAL must be a `bfd_vma'. If we are on a system +without prototypes, the caller is responsible for making sure that is +true, with a cast if necessary. We don't cast them in the macro +definitions because that would prevent `lint' or `gcc -Wall' from +detecting sins such as passing a pointer. To detect calling these with +less than a `bfd_vma', use `gcc -Wconversion' on a host with 64 bit +`bfd_vma''s. + + /* Byte swapping macros for user section data. */ + + #define bfd_put_8(abfd, val, ptr) \ + (*((unsigned char *)(ptr)) = (unsigned char)(val)) + #define bfd_put_signed_8 \ + bfd_put_8 + #define bfd_get_8(abfd, ptr) \ + (*(unsigned char *)(ptr)) + #define bfd_get_signed_8(abfd, ptr) \ + ((*(unsigned char *)(ptr) ^ 0x80) - 0x80) + + #define bfd_put_16(abfd, val, ptr) \ + BFD_SEND(abfd, bfd_putx16, ((val),(ptr))) + #define bfd_put_signed_16 \ + bfd_put_16 + #define bfd_get_16(abfd, ptr) \ + BFD_SEND(abfd, bfd_getx16, (ptr)) + #define bfd_get_signed_16(abfd, ptr) \ + BFD_SEND (abfd, bfd_getx_signed_16, (ptr)) + + #define bfd_put_32(abfd, val, ptr) \ + BFD_SEND(abfd, bfd_putx32, ((val),(ptr))) + #define bfd_put_signed_32 \ + bfd_put_32 + #define bfd_get_32(abfd, ptr) \ + BFD_SEND(abfd, bfd_getx32, (ptr)) + #define bfd_get_signed_32(abfd, ptr) \ + BFD_SEND(abfd, bfd_getx_signed_32, (ptr)) + + #define bfd_put_64(abfd, val, ptr) \ + BFD_SEND(abfd, bfd_putx64, ((val), (ptr))) + #define bfd_put_signed_64 \ + bfd_put_64 + #define bfd_get_64(abfd, ptr) \ + BFD_SEND(abfd, bfd_getx64, (ptr)) + #define bfd_get_signed_64(abfd, ptr) \ + BFD_SEND(abfd, bfd_getx_signed_64, (ptr)) + +`bfd_h_put_size' +................ + +*Description* +These macros have the same function as their `bfd_get_x' bretheren, +except that they are used for removing information for the header +records of object files. Believe it or not, some object files keep +their header records in big endian order and their data in little +endian order. + + /* Byte swapping macros for file header data. */ + + #define bfd_h_put_8(abfd, val, ptr) \ + bfd_put_8 (abfd, val, ptr) + #define bfd_h_put_signed_8(abfd, val, ptr) \ + bfd_put_8 (abfd, val, ptr) + #define bfd_h_get_8(abfd, ptr) \ + bfd_get_8 (abfd, ptr) + #define bfd_h_get_signed_8(abfd, ptr) \ + bfd_get_signed_8 (abfd, ptr) + + #define bfd_h_put_16(abfd, val, ptr) \ + BFD_SEND(abfd, bfd_h_putx16,(val,ptr)) + #define bfd_h_put_signed_16 \ + bfd_h_put_16 + #define bfd_h_get_16(abfd, ptr) \ + BFD_SEND(abfd, bfd_h_getx16,(ptr)) + #define bfd_h_get_signed_16(abfd, ptr) \ + BFD_SEND(abfd, bfd_h_getx_signed_16, (ptr)) + + #define bfd_h_put_32(abfd, val, ptr) \ + BFD_SEND(abfd, bfd_h_putx32,(val,ptr)) + #define bfd_h_put_signed_32 \ + bfd_h_put_32 + #define bfd_h_get_32(abfd, ptr) \ + BFD_SEND(abfd, bfd_h_getx32,(ptr)) + #define bfd_h_get_signed_32(abfd, ptr) \ + BFD_SEND(abfd, bfd_h_getx_signed_32, (ptr)) + + #define bfd_h_put_64(abfd, val, ptr) \ + BFD_SEND(abfd, bfd_h_putx64,(val, ptr)) + #define bfd_h_put_signed_64 \ + bfd_h_put_64 + #define bfd_h_get_64(abfd, ptr) \ + BFD_SEND(abfd, bfd_h_getx64,(ptr)) + #define bfd_h_get_signed_64(abfd, ptr) \ + BFD_SEND(abfd, bfd_h_getx_signed_64, (ptr)) + +`bfd_log2' +.......... + +*Synopsis* + unsigned int bfd_log2(bfd_vma x); + *Description* +Return the log base 2 of the value supplied, rounded up. E.g., an X of +1025 returns 11. + +File: bfd.info, Node: File Caching, Next: Linker Functions, Prev: Internal, Up: BFD front end + +File caching +============ + +The file caching mechanism is embedded within BFD and allows the +application to open as many BFDs as it wants without regard to the +underlying operating system's file descriptor limit (often as low as 20 +open files). The module in `cache.c' maintains a least recently used +list of `BFD_CACHE_MAX_OPEN' files, and exports the name +`bfd_cache_lookup', which runs around and makes sure that the required +BFD is open. If not, then it chooses a file to close, closes it and +opens the one wanted, returning its file handle. +`BFD_CACHE_MAX_OPEN macro' +.......................... + +*Description* +The maximum number of files which the cache will keep open at one time. + #define BFD_CACHE_MAX_OPEN 10 + +`bfd_last_cache' +................ + +*Synopsis* + extern bfd *bfd_last_cache; + *Description* +Zero, or a pointer to the topmost BFD on the chain. This is used by +the `bfd_cache_lookup' macro in `libbfd.h' to determine when it can +avoid a function call. +`bfd_cache_lookup' +.................. + +*Description* +Check to see if the required BFD is the same as the last one looked up. +If so, then it can use the stream in the BFD with impunity, since it +can't have changed since the last lookup; otherwise, it has to perform +the complicated lookup function. + #define bfd_cache_lookup(x) \ + ((x)==bfd_last_cache? \ + (FILE*)(bfd_last_cache->iostream): \ + bfd_cache_lookup_worker(x)) + +`bfd_cache_init' +................ + +*Synopsis* + boolean bfd_cache_init (bfd *abfd); + *Description* +Add a newly opened BFD to the cache. +`bfd_cache_close' +................. + +*Synopsis* + boolean bfd_cache_close (bfd *abfd); + *Description* +Remove the BFD ABFD from the cache. If the attached file is open, then +close it too. +*Returns* +`false' is returned if closing the file fails, `true' is returned if +all is well. +`bfd_open_file' +............... + +*Synopsis* + FILE* bfd_open_file(bfd *abfd); + *Description* +Call the OS to open a file for ABFD. Return the `FILE *' (possibly +`NULL') that results from this operation. Set up the BFD so that +future accesses know the file is open. If the `FILE *' returned is +`NULL', then it won't have been put in the cache, so it won't have to +be removed from it. +`bfd_cache_lookup_worker' +......................... + +*Synopsis* + FILE *bfd_cache_lookup_worker(bfd *abfd); + *Description* +Called when the macro `bfd_cache_lookup' fails to find a quick answer. +Find a file descriptor for ABFD. If necessary, it open it. If there +are already more than `BFD_CACHE_MAX_OPEN' files open, it tries to +close one first, to avoid running out of file descriptors. + +File: bfd.info, Node: Linker Functions, Next: Hash Tables, Prev: File Caching, Up: BFD front end + +Linker Functions +================ + +The linker uses three special entry points in the BFD target vector. +It is not necessary to write special routines for these entry points +when creating a new BFD back end, since generic versions are provided. +However, writing them can speed up linking and make it use +significantly less runtime memory. + + The first routine creates a hash table used by the other routines. +The second routine adds the symbols from an object file to the hash +table. The third routine takes all the object files and links them +together to create the output file. These routines are designed so +that the linker proper does not need to know anything about the symbols +in the object files that it is linking. The linker merely arranges the +sections as directed by the linker script and lets BFD handle the +details of symbols and relocs. + + The second routine and third routines are passed a pointer to a +`struct bfd_link_info' structure (defined in `bfdlink.h') which holds +information relevant to the link, including the linker hash table +(which was created by the first routine) and a set of callback +functions to the linker proper. + + The generic linker routines are in `linker.c', and use the header +file `genlink.h'. As of this writing, the only back ends which have +implemented versions of these routines are a.out (in `aoutx.h') and +ECOFF (in `ecoff.c'). The a.out routines are used as examples +throughout this section. + +* Menu: + +* Creating a Linker Hash Table:: +* Adding Symbols to the Hash Table:: +* Performing the Final Link:: + + +File: bfd.info, Node: Creating a Linker Hash Table, Next: Adding Symbols to the Hash Table, Prev: Linker Functions, Up: Linker Functions + +Creating a linker hash table +---------------------------- + +The linker routines must create a hash table, which must be derived +from `struct bfd_link_hash_table' described in `bfdlink.c'. *Note Hash +Tables:: for information on how to create a derived hash table. This +entry point is called using the target vector of the linker output file. + + The `_bfd_link_hash_table_create' entry point must allocate and +initialize an instance of the desired hash table. If the back end does +not require any additional information to be stored with the entries in +the hash table, the entry point may simply create a `struct +bfd_link_hash_table'. Most likely, however, some additional +information will be needed. + + For example, with each entry in the hash table the a.out linker +keeps the index the symbol has in the final output file (this index +number is used so that when doing a relocateable link the symbol index +used in the output file can be quickly filled in when copying over a +reloc). The a.out linker code defines the required structures and +functions for a hash table derived from `struct bfd_link_hash_table'. +The a.out linker hash table is created by the function +`NAME(aout,link_hash_table_create)'; it simply allocates space for the +hash table, initializes it, and returns a pointer to it. + + When writing the linker routines for a new back end, you will +generally not know exactly which fields will be required until you have +finished. You should simply create a new hash table which defines no +additional fields, and then simply add fields as they become necessary. + +File: bfd.info, Node: Adding Symbols to the Hash Table, Next: Performing the Final Link, Prev: Creating a Linker Hash Table, Up: Linker Functions + +Adding symbols to the hash table +-------------------------------- + +The linker proper will call the `_bfd_link_add_symbols' entry point for +each object file or archive which is to be linked (typically these are +the files named on the command line, but some may also come from the +linker script). The entry point is responsible for examining the file. +For an object file, BFD must add any relevant symbol information to +the hash table. For an archive, BFD must determine which elements of +the archive should be used and adding them to the link. + + The a.out version of this entry point is +`NAME(aout,link_add_symbols)'. + +* Menu: + +* Differing file formats:: +* Adding symbols from an object file:: +* Adding symbols from an archive:: + + +File: bfd.info, Node: Differing file formats, Next: Adding symbols from an object file, Prev: Adding Symbols to the Hash Table, Up: Adding Symbols to the Hash Table + +Differing file formats +...................... + +Normally all the files involved in a link will be of the same format, +but it is also possible to link together different format object files, +and the back end must support that. The `_bfd_link_add_symbols' entry +point is called via the target vector of the file to be added. This +has an important consequence: the function may not assume that the hash +table is the type created by the corresponding +`_bfd_link_hash_table_create' vector. All the `_bfd_link_add_symbols' +function can assume about the hash table is that it is derived from +`struct bfd_link_hash_table'. + + Sometimes the `_bfd_link_add_symbols' function must store some +information in the hash table entry to be used by the `_bfd_final_link' +function. In such a case the `creator' field of the hash table must be +checked to make sure that the hash table was created by an object file +of the same format. + + The `_bfd_final_link' routine must be prepared to handle a hash +entry without any extra information added by the +`_bfd_link_add_symbols' function. A hash entry without extra +information will also occur when the linker script directs the linker +to create a symbol. Note that, regardless of how a hash table entry is +added, all the fields will be initialized to some sort of null value by +the hash table entry initialization function. + + See `ecoff_link_add_externals' for an example of how to check the +`creator' field before saving information (in this case, the ECOFF +external symbol debugging information) in a hash table entry. + +File: bfd.info, Node: Adding symbols from an object file, Next: Adding symbols from an archive, Prev: Differing file formats, Up: Adding Symbols to the Hash Table + +Adding symbols from an object file +.................................. + +When the `_bfd_link_add_symbols' routine is passed an object file, it +must add all externally visible symbols in that object file to the hash +table. The actual work of adding the symbol to the hash table is +normally handled by the function `_bfd_generic_link_add_one_symbol'. +The `_bfd_link_add_symbols' routine is responsible for reading all the +symbols from the object file and passing the correct information to +`_bfd_generic_link_add_one_symbol'. + + The `_bfd_link_add_symbols' routine should not use +`bfd_canonicalize_symtab' to read the symbols. The point of providing +this routine is to avoid the overhead of converting the symbols into +generic `asymbol' structures. + + `_bfd_generic_link_add_one_symbol' handles the details of combining +common symbols, warning about multiple definitions, and so forth. It +takes arguments which describe the symbol to add, notably symbol flags, +a section, and an offset. The symbol flags include such things as +`BSF_WEAK' or `BSF_INDIRECT'. The section is a section in the object +file, or something like `bfd_und_section_ptr' for an undefined symbol +or `bfd_com_section_ptr' for a common symbol. + + If the `_bfd_final_link' routine is also going to need to read the +symbol information, the `_bfd_link_add_symbols' routine should save it +somewhere attached to the object file BFD. However, the information +should only be saved if the `keep_memory' field of the `info' argument +is true, so that the `-no-keep-memory' linker switch is effective. + + The a.out function which adds symbols from an object file is +`aout_link_add_object_symbols', and most of the interesting work is in +`aout_link_add_symbols'. The latter saves pointers to the hash tables +entries created by `_bfd_generic_link_add_one_symbol' indexed by symbol +number, so that the `_bfd_final_link' routine does not have to call the +hash table lookup routine to locate the entry. + +File: bfd.info, Node: Adding symbols from an archive, Prev: Adding symbols from an object file, Up: Adding Symbols to the Hash Table + +Adding symbols from an archive +.............................. + +When the `_bfd_link_add_symbols' routine is passed an archive, it must +look through the symbols defined by the archive and decide which +elements of the archive should be included in the link. For each such +element it must call the `add_archive_element' linker callback, and it +must add the symbols from the object file to the linker hash table. + + In most cases the work of looking through the symbols in the archive +should be done by the `_bfd_generic_link_add_archive_symbols' function. +This function builds a hash table from the archive symbol table and +looks through the list of undefined symbols to see which elements +should be included. `_bfd_generic_link_add_archive_symbols' is passed +a function to call to make the final decision about adding an archive +element to the link and to do the actual work of adding the symbols to +the linker hash table. + + The function passed to `_bfd_generic_link_add_archive_symbols' must +read the symbols of the archive element and decide whether the archive +element should be included in the link. If the element is to be +included, the `add_archive_element' linker callback routine must be +called with the element as an argument, and the elements symbols must +be added to the linker hash table just as though the element had itself +been passed to the `_bfd_link_add_symbols' function. + + When the a.out `_bfd_link_add_symbols' function receives an archive, +it calls `_bfd_generic_link_add_archive_symbols' passing +`aout_link_check_archive_element' as the function argument. +`aout_link_check_archive_element' calls `aout_link_check_ar_symbols'. +If the latter decides to add the element (an element is only added if +it provides a real, non-common, definition for a previously undefined +or common symbol) it calls the `add_archive_element' callback and then +`aout_link_check_archive_element' calls `aout_link_add_symbols' to +actually add the symbols to the linker hash table. + + The ECOFF back end is unusual in that it does not normally call +`_bfd_generic_link_add_archive_symbols', because ECOFF archives already +contain a hash table of symbols. The ECOFF back end searches the +archive itself to avoid the overhead of creating a new hash table. + +File: bfd.info, Node: Performing the Final Link, Prev: Adding Symbols to the Hash Table, Up: Linker Functions + +Performing the final link +------------------------- + +When all the input files have been processed, the linker calls the +`_bfd_final_link' entry point of the output BFD. This routine is +responsible for producing the final output file, which has several +aspects. It must relocate the contents of the input sections and copy +the data into the output sections. It must build an output symbol +table including any local symbols from the input files and the global +symbols from the hash table. When producing relocateable output, it +must modify the input relocs and write them into the output file. +There may also be object format dependent work to be done. + + The linker will also call the `write_object_contents' entry point +when the BFD is closed. The two entry points must work together in +order to produce the correct output file. + + The details of how this works are inevitably dependent upon the +specific object file format. The a.out `_bfd_final_link' routine is +`NAME(aout,final_link)'. + +* Menu: + +* Information provided by the linker:: +* Relocating the section contents:: +* Writing the symbol table:: + + +File: bfd.info, Node: Information provided by the linker, Next: Relocating the section contents, Prev: Performing the Final Link, Up: Performing the Final Link + +Information provided by the linker +.................................. + +Before the linker calls the `_bfd_final_link' entry point, it sets up +some data structures for the function to use. + + The `input_bfds' field of the `bfd_link_info' structure will point +to a list of all the input files included in the link. These files are +linked through the `link_next' field of the `bfd' structure. + + Each section in the output file will have a list of `link_order' +structures attached to the `link_order_head' field (the `link_order' +structure is defined in `bfdlink.h'). These structures describe how to +create the contents of the output section in terms of the contents of +various input sections, fill constants, and, eventually, other types of +information. They also describe relocs that must be created by the BFD +backend, but do not correspond to any input file; this is used to +support -Ur, which builds constructors while generating a relocateable +object file. + +File: bfd.info, Node: Relocating the section contents, Next: Writing the symbol table, Prev: Information provided by the linker, Up: Performing the Final Link + +Relocating the section contents +............................... + +The `_bfd_final_link' function should look through the `link_order' +structures attached to each section of the output file. Each +`link_order' structure should either be handled specially, or it should +be passed to the function `_bfd_default_link_order' which will do the +right thing (`_bfd_default_link_order' is defined in `linker.c'). + + For efficiency, a `link_order' of type `bfd_indirect_link_order' +whose associated section belongs to a BFD of the same format as the +output BFD must be handled specially. This type of `link_order' +describes part of an output section in terms of a section belonging to +one of the input files. The `_bfd_final_link' function should read the +contents of the section and any associated relocs, apply the relocs to +the section contents, and write out the modified section contents. If +performing a relocateable link, the relocs themselves must also be +modified and written out. + + The functions `_bfd_relocate_contents' and +`_bfd_final_link_relocate' provide some general support for performing +the actual relocations, notably overflow checking. Their arguments +include information about the symbol the relocation is against and a +`reloc_howto_type' argument which describes the relocation to perform. +These functions are defined in `reloc.c'. + + The a.out function which handles reading, relocating, and writing +section contents is `aout_link_input_section'. The actual relocation +is done in `aout_link_input_section_std' and +`aout_link_input_section_ext'. + +File: bfd.info, Node: Writing the symbol table, Prev: Relocating the section contents, Up: Performing the Final Link + +Writing the symbol table +........................ + +The `_bfd_final_link' function must gather all the symbols in the input +files and write them out. It must also write out all the symbols in +the global hash table. This must be controlled by the `strip' and +`discard' fields of the `bfd_link_info' structure. + + The local symbols of the input files will not have been entered into +the linker hash table. The `_bfd_final_link' routine must consider +each input file and include the symbols in the output file. It may be +convenient to do this when looking through the `link_order' structures, +or it may be done by stepping through the `input_bfds' list. + + The `_bfd_final_link' routine must also traverse the global hash +table to gather all the externally visible symbols. It is possible +that most of the externally visible symbols may be written out when +considering the symbols of each input file, but it is still necessary +to traverse the hash table since the linker script may have defined +some symbols that are not in any of the input files. + + The `strip' field of the `bfd_link_info' structure controls which +symbols are written out. The possible values are listed in +`bfdlink.h'. If the value is `strip_some', then the `keep_hash' field +of the `bfd_link_info' structure is a hash table of symbols to keep; +each symbol should be looked up in this hash table, and only symbols +which are present should be included in the output file. + + If the `strip' field of the `bfd_link_info' structure permits local +symbols to be written out, the `discard' field is used to further +controls which local symbols are included in the output file. If the +value is `discard_l', then all local symbols which begin with a certain +prefix are discarded; this is controlled by the +`bfd_is_local_label_name' entry point. + + The a.out backend handles symbols by calling +`aout_link_write_symbols' on each input BFD and then traversing the +global hash table with the function `aout_link_write_other_symbol'. It +builds a string table while writing out the symbols, which is written +to the output file at the end of `NAME(aout,final_link)'. +`bfd_link_split_section' +........................ + +*Synopsis* + boolean bfd_link_split_section(bfd *abfd, asection *sec); + *Description* +Return nonzero if SEC should be split during a reloceatable or final +link. + #define bfd_link_split_section(abfd, sec) \ + BFD_SEND (abfd, _bfd_link_split_section, (abfd, sec)) + + +File: bfd.info, Node: Hash Tables, Prev: Linker Functions, Up: BFD front end + +Hash Tables +=========== + +BFD provides a simple set of hash table functions. Routines are +provided to initialize a hash table, to free a hash table, to look up a +string in a hash table and optionally create an entry for it, and to +traverse a hash table. There is currently no routine to delete an +string from a hash table. + + The basic hash table does not permit any data to be stored with a +string. However, a hash table is designed to present a base class from +which other types of hash tables may be derived. These derived types +may store additional information with the string. Hash tables were +implemented in this way, rather than simply providing a data pointer in +a hash table entry, because they were designed for use by the linker +back ends. The linker may create thousands of hash table entries, and +the overhead of allocating private data and storing and following +pointers becomes noticeable. + + The basic hash table code is in `hash.c'. + +* Menu: + +* Creating and Freeing a Hash Table:: +* Looking Up or Entering a String:: +* Traversing a Hash Table:: +* Deriving a New Hash Table Type:: + + +File: bfd.info, Node: Creating and Freeing a Hash Table, Next: Looking Up or Entering a String, Prev: Hash Tables, Up: Hash Tables + +Creating and freeing a hash table +--------------------------------- + +To create a hash table, create an instance of a `struct bfd_hash_table' +(defined in `bfd.h') and call `bfd_hash_table_init' (if you know +approximately how many entries you will need, the function +`bfd_hash_table_init_n', which takes a SIZE argument, may be used). +`bfd_hash_table_init' returns `false' if some sort of error occurs. + + The function `bfd_hash_table_init' take as an argument a function to +use to create new entries. For a basic hash table, use the function +`bfd_hash_newfunc'. *Note Deriving a New Hash Table Type:: for why you +would want to use a different value for this argument. + + `bfd_hash_table_init' will create an objalloc which will be used to +allocate new entries. You may allocate memory on this objalloc using +`bfd_hash_allocate'. + + Use `bfd_hash_table_free' to free up all the memory that has been +allocated for a hash table. This will not free up the `struct +bfd_hash_table' itself, which you must provide. + +File: bfd.info, Node: Looking Up or Entering a String, Next: Traversing a Hash Table, Prev: Creating and Freeing a Hash Table, Up: Hash Tables + +Looking up or entering a string +------------------------------- + +The function `bfd_hash_lookup' is used both to look up a string in the +hash table and to create a new entry. + + If the CREATE argument is `false', `bfd_hash_lookup' will look up a +string. If the string is found, it will returns a pointer to a `struct +bfd_hash_entry'. If the string is not found in the table +`bfd_hash_lookup' will return `NULL'. You should not modify any of the +fields in the returns `struct bfd_hash_entry'. + + If the CREATE argument is `true', the string will be entered into +the hash table if it is not already there. Either way a pointer to a +`struct bfd_hash_entry' will be returned, either to the existing +structure or to a newly created one. In this case, a `NULL' return +means that an error occurred. + + If the CREATE argument is `true', and a new entry is created, the +COPY argument is used to decide whether to copy the string onto the +hash table objalloc or not. If COPY is passed as `false', you must be +careful not to deallocate or modify the string as long as the hash table +exists. + +File: bfd.info, Node: Traversing a Hash Table, Next: Deriving a New Hash Table Type, Prev: Looking Up or Entering a String, Up: Hash Tables + +Traversing a hash table +----------------------- + +The function `bfd_hash_traverse' may be used to traverse a hash table, +calling a function on each element. The traversal is done in a random +order. + + `bfd_hash_traverse' takes as arguments a function and a generic +`void *' pointer. The function is called with a hash table entry (a +`struct bfd_hash_entry *') and the generic pointer passed to +`bfd_hash_traverse'. The function must return a `boolean' value, which +indicates whether to continue traversing the hash table. If the +function returns `false', `bfd_hash_traverse' will stop the traversal +and return immediately. + +File: bfd.info, Node: Deriving a New Hash Table Type, Prev: Traversing a Hash Table, Up: Hash Tables + +Deriving a new hash table type +------------------------------ + +Many uses of hash tables want to store additional information which +each entry in the hash table. Some also find it convenient to store +additional information with the hash table itself. This may be done +using a derived hash table. + + Since C is not an object oriented language, creating a derived hash +table requires sticking together some boilerplate routines with a few +differences specific to the type of hash table you want to create. + + An example of a derived hash table is the linker hash table. The +structures for this are defined in `bfdlink.h'. The functions are in +`linker.c'. + + You may also derive a hash table from an already derived hash table. +For example, the a.out linker backend code uses a hash table derived +from the linker hash table. + +* Menu: + +* Define the Derived Structures:: +* Write the Derived Creation Routine:: +* Write Other Derived Routines:: + + +File: bfd.info, Node: Define the Derived Structures, Next: Write the Derived Creation Routine, Prev: Deriving a New Hash Table Type, Up: Deriving a New Hash Table Type + +Define the derived structures +............................. + +You must define a structure for an entry in the hash table, and a +structure for the hash table itself. + + The first field in the structure for an entry in the hash table must +be of the type used for an entry in the hash table you are deriving +from. If you are deriving from a basic hash table this is `struct +bfd_hash_entry', which is defined in `bfd.h'. The first field in the +structure for the hash table itself must be of the type of the hash +table you are deriving from itself. If you are deriving from a basic +hash table, this is `struct bfd_hash_table'. + + For example, the linker hash table defines `struct +bfd_link_hash_entry' (in `bfdlink.h'). The first field, `root', is of +type `struct bfd_hash_entry'. Similarly, the first field in `struct +bfd_link_hash_table', `table', is of type `struct bfd_hash_table'. + +File: bfd.info, Node: Write the Derived Creation Routine, Next: Write Other Derived Routines, Prev: Define the Derived Structures, Up: Deriving a New Hash Table Type + +Write the derived creation routine +.................................. + +You must write a routine which will create and initialize an entry in +the hash table. This routine is passed as the function argument to +`bfd_hash_table_init'. + + In order to permit other hash tables to be derived from the hash +table you are creating, this routine must be written in a standard way. + + The first argument to the creation routine is a pointer to a hash +table entry. This may be `NULL', in which case the routine should +allocate the right amount of space. Otherwise the space has already +been allocated by a hash table type derived from this one. + + After allocating space, the creation routine must call the creation +routine of the hash table type it is derived from, passing in a pointer +to the space it just allocated. This will initialize any fields used +by the base hash table. + + Finally the creation routine must initialize any local fields for +the new hash table type. + + Here is a boilerplate example of a creation routine. FUNCTION_NAME +is the name of the routine. ENTRY_TYPE is the type of an entry in the +hash table you are creating. BASE_NEWFUNC is the name of the creation +routine of the hash table type your hash table is derived from. +.struct bfd_hash_entry * + FUNCTION_NAME (entry, table, string) + struct bfd_hash_entry *entry; + struct bfd_hash_table *table; + const char *string; + { + struct ENTRY_TYPE *ret = (ENTRY_TYPE *) entry; + + /* Allocate the structure if it has not already been allocated by a + derived class. */ + if (ret == (ENTRY_TYPE *) NULL) + { + ret = ((ENTRY_TYPE *) + bfd_hash_allocate (table, sizeof (ENTRY_TYPE))); + if (ret == (ENTRY_TYPE *) NULL) + return NULL; + } + + /* Call the allocation method of the base class. */ + ret = ((ENTRY_TYPE *) + BASE_NEWFUNC ((struct bfd_hash_entry *) ret, table, string)); + + /* Initialize the local fields here. */ + + return (struct bfd_hash_entry *) ret; + } + *Description* +The creation routine for the linker hash table, which is in `linker.c', +looks just like this example. FUNCTION_NAME is +`_bfd_link_hash_newfunc'. ENTRY_TYPE is `struct bfd_link_hash_entry'. +BASE_NEWFUNC is `bfd_hash_newfunc', the creation routine for a basic +hash table. + + `_bfd_link_hash_newfunc' also initializes the local fields in a +linker hash table entry: `type', `written' and `next'. + +File: bfd.info, Node: Write Other Derived Routines, Prev: Write the Derived Creation Routine, Up: Deriving a New Hash Table Type + +Write other derived routines +............................ + +You will want to write other routines for your new hash table, as well. + + You will want an initialization routine which calls the +initialization routine of the hash table you are deriving from and +initializes any other local fields. For the linker hash table, this is +`_bfd_link_hash_table_init' in `linker.c'. + + You will want a lookup routine which calls the lookup routine of the +hash table you are deriving from and casts the result. The linker hash +table uses `bfd_link_hash_lookup' in `linker.c' (this actually takes an +additional argument which it uses to decide how to return the looked up +value). + + You may want a traversal routine. This should just call the +traversal routine of the hash table you are deriving from with +appropriate casts. The linker hash table uses `bfd_link_hash_traverse' +in `linker.c'. + + These routines may simply be defined as macros. For example, the +a.out backend linker hash table, which is derived from the linker hash +table, uses macros for the lookup and traversal routines. These are +`aout_link_hash_lookup' and `aout_link_hash_traverse' in aoutx.h. + +File: bfd.info, Node: BFD back ends, Next: Index, Prev: BFD front end, Up: Top + +BFD back ends +************* + +* Menu: + +* What to Put Where:: +* aout :: a.out backends +* coff :: coff backends +* elf :: elf backends + + +File: bfd.info, Node: What to Put Where, Next: aout, Prev: BFD back ends, Up: BFD back ends + + All of BFD lives in one directory. + + +File: bfd.info, Node: aout, Next: coff, Prev: What to Put Where, Up: BFD back ends + +a.out backends +============== + +*Description* +BFD supports a number of different flavours of a.out format, though the +major differences are only the sizes of the structures on disk, and the +shape of the relocation information. + + The support is split into a basic support file `aoutx.h' and other +files which derive functions from the base. One derivation file is +`aoutf1.h' (for a.out flavour 1), and adds to the basic a.out functions +support for sun3, sun4, 386 and 29k a.out files, to create a target +jump vector for a specific target. + + This information is further split out into more specific files for +each machine, including `sunos.c' for sun3 and sun4, `newsos3.c' for +the Sony NEWS, and `demo64.c' for a demonstration of a 64 bit a.out +format. + + The base file `aoutx.h' defines general mechanisms for reading and +writing records to and from disk and various other methods which BFD +requires. It is included by `aout32.c' and `aout64.c' to form the names +`aout_32_swap_exec_header_in', `aout_64_swap_exec_header_in', etc. + + As an example, this is what goes on to make the back end for a sun4, +from `aout32.c': + + #define ARCH_SIZE 32 + #include "aoutx.h" + + Which exports names: + + ... + aout_32_canonicalize_reloc + aout_32_find_nearest_line + aout_32_get_lineno + aout_32_get_reloc_upper_bound + ... + + from `sunos.c': + + #define TARGET_NAME "a.out-sunos-big" + #define VECNAME sunos_big_vec + #include "aoutf1.h" + + requires all the names from `aout32.c', and produces the jump vector + + sunos_big_vec + + The file `host-aout.c' is a special case. It is for a large set of +hosts that use "more or less standard" a.out files, and for which +cross-debugging is not interesting. It uses the standard 32-bit a.out +support routines, but determines the file offsets and addresses of the +text, data, and BSS sections, the machine architecture and machine +type, and the entry point address, in a host-dependent manner. Once +these values have been determined, generic code is used to handle the +object file. + + When porting it to run on a new system, you must supply: + + HOST_PAGE_SIZE + HOST_SEGMENT_SIZE + HOST_MACHINE_ARCH (optional) + HOST_MACHINE_MACHINE (optional) + HOST_TEXT_START_ADDR + HOST_STACK_END_ADDR + + in the file `../include/sys/h-XXX.h' (for your host). These values, +plus the structures and macros defined in `a.out.h' on your host +system, will produce a BFD target that will access ordinary a.out files +on your host. To configure a new machine to use `host-aout.c', specify: + + TDEFAULTS = -DDEFAULT_VECTOR=host_aout_big_vec + TDEPFILES= host-aout.o trad-core.o + + in the `config/XXX.mt' file, and modify `configure.in' to use the +`XXX.mt' file (by setting "`bfd_target=XXX'") when your configuration +is selected. +Relocations +----------- + +*Description* +The file `aoutx.h' provides for both the *standard* and *extended* +forms of a.out relocation records. + + The standard records contain only an address, a symbol index, and a +type field. The extended records (used on 29ks and sparcs) also have a +full integer for an addend. +Internal entry points +--------------------- + +*Description* +`aoutx.h' exports several routines for accessing the contents of an +a.out file, which are gathered and exported in turn by various format +specific files (eg sunos.c). +`aout_SIZE_swap_exec_header_in' +............................... + +*Synopsis* + void aout_SIZE_swap_exec_header_in, + (bfd *abfd, + struct external_exec *raw_bytes, + struct internal_exec *execp); + *Description* +Swap the information in an executable header RAW_BYTES taken from a raw +byte stream memory image into the internal exec header structure EXECP. +`aout_SIZE_swap_exec_header_out' +................................ + +*Synopsis* + void aout_SIZE_swap_exec_header_out + (bfd *abfd, + struct internal_exec *execp, + struct external_exec *raw_bytes); + *Description* +Swap the information in an internal exec header structure EXECP into +the buffer RAW_BYTES ready for writing to disk. +`aout_SIZE_some_aout_object_p' +.............................. + +*Synopsis* + const bfd_target *aout_SIZE_some_aout_object_p + (bfd *abfd, + const bfd_target *(*callback_to_real_object_p)()); + *Description* +Some a.out variant thinks that the file open in ABFD checking is an +a.out file. Do some more checking, and set up for access if it really +is. Call back to the calling environment's "finish up" function just +before returning, to handle any last-minute setup. +`aout_SIZE_mkobject' +.................... + +*Synopsis* + boolean aout_SIZE_mkobject, (bfd *abfd); + *Description* +Initialize BFD ABFD for use with a.out files. +`aout_SIZE_machine_type' +........................ + +*Synopsis* + enum machine_type aout_SIZE_machine_type + (enum bfd_architecture arch, + unsigned long machine)); + *Description* +Keep track of machine architecture and machine type for a.out's. Return +the `machine_type' for a particular architecture and machine, or +`M_UNKNOWN' if that exact architecture and machine can't be represented +in a.out format. + + If the architecture is understood, machine type 0 (default) is +always understood. +`aout_SIZE_set_arch_mach' +......................... + +*Synopsis* + boolean aout_SIZE_set_arch_mach, + (bfd *, + enum bfd_architecture arch, + unsigned long machine)); + *Description* +Set the architecture and the machine of the BFD ABFD to the values ARCH +and MACHINE. Verify that ABFD's format can support the architecture +required. +`aout_SIZE_new_section_hook' +............................ + +*Synopsis* + boolean aout_SIZE_new_section_hook, + (bfd *abfd, + asection *newsect)); + *Description* +Called by the BFD in response to a `bfd_make_section' request. diff --git a/gnu/usr.bin/binutils/bfd/doc/bfd.info-5 b/gnu/usr.bin/binutils/bfd/doc/bfd.info-5 new file mode 100644 index 00000000000..86acfab2e46 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/bfd.info-5 @@ -0,0 +1,991 @@ +This is Info file bfd.info, produced by Makeinfo-1.64 from the input +file ./bfd.texinfo. + +START-INFO-DIR-ENTRY +* Bfd: (bfd). The Binary File Descriptor library. +END-INFO-DIR-ENTRY + + This file documents the BFD library. + + Copyright (C) 1991 Free Software Foundation, Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + + Permission is granted to copy and distribute modified versions of +this manual under the conditions for verbatim copying, subject to the +terms of the GNU General Public License, which includes the provision +that the entire resulting derived work is distributed under the terms +of a permission notice identical to this one. + + Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions. + + +File: bfd.info, Node: coff, Next: elf, Prev: aout, Up: BFD back ends + +coff backends +============= + +BFD supports a number of different flavours of coff format. The major +differences between formats are the sizes and alignments of fields in +structures on disk, and the occasional extra field. + + Coff in all its varieties is implemented with a few common files and +a number of implementation specific files. For example, The 88k bcs +coff format is implemented in the file `coff-m88k.c'. This file +`#include's `coff/m88k.h' which defines the external structure of the +coff format for the 88k, and `coff/internal.h' which defines the +internal structure. `coff-m88k.c' also defines the relocations used by +the 88k format *Note Relocations::. + + The Intel i960 processor version of coff is implemented in +`coff-i960.c'. This file has the same structure as `coff-m88k.c', +except that it includes `coff/i960.h' rather than `coff-m88k.h'. +Porting to a new version of coff +-------------------------------- + +The recommended method is to select from the existing implementations +the version of coff which is most like the one you want to use. For +example, we'll say that i386 coff is the one you select, and that your +coff flavour is called foo. Copy `i386coff.c' to `foocoff.c', copy +`../include/coff/i386.h' to `../include/coff/foo.h', and add the lines +to `targets.c' and `Makefile.in' so that your new back end is used. +Alter the shapes of the structures in `../include/coff/foo.h' so that +they match what you need. You will probably also have to add `#ifdef's +to the code in `coff/internal.h' and `coffcode.h' if your version of +coff is too wild. + + You can verify that your new BFD backend works quite simply by +building `objdump' from the `binutils' directory, and making sure that +its version of what's going on and your host system's idea (assuming it +has the pretty standard coff dump utility, usually called `att-dump' or +just `dump') are the same. Then clean up your code, and send what +you've done to Cygnus. Then your stuff will be in the next release, and +you won't have to keep integrating it. +How the coff backend works +-------------------------- + +File layout +........... + +The Coff backend is split into generic routines that are applicable to +any Coff target and routines that are specific to a particular target. +The target-specific routines are further split into ones which are +basically the same for all Coff targets except that they use the +external symbol format or use different values for certain constants. + + The generic routines are in `coffgen.c'. These routines work for +any Coff target. They use some hooks into the target specific code; +the hooks are in a `bfd_coff_backend_data' structure, one of which +exists for each target. + + The essentially similar target-specific routines are in +`coffcode.h'. This header file includes executable C code. The +various Coff targets first include the appropriate Coff header file, +make any special defines that are needed, and then include `coffcode.h'. + + Some of the Coff targets then also have additional routines in the +target source file itself. + + For example, `coff-i960.c' includes `coff/internal.h' and +`coff/i960.h'. It then defines a few constants, such as `I960', and +includes `coffcode.h'. Since the i960 has complex relocation types, +`coff-i960.c' also includes some code to manipulate the i960 relocs. +This code is not in `coffcode.h' because it would not be used by any +other target. +Bit twiddling +............. + +Each flavour of coff supported in BFD has its own header file +describing the external layout of the structures. There is also an +internal description of the coff layout, in `coff/internal.h'. A major +function of the coff backend is swapping the bytes and twiddling the +bits to translate the external form of the structures into the normal +internal form. This is all performed in the `bfd_swap'_thing_direction +routines. Some elements are different sizes between different versions +of coff; it is the duty of the coff version specific include file to +override the definitions of various packing routines in `coffcode.h'. +E.g., the size of line number entry in coff is sometimes 16 bits, and +sometimes 32 bits. `#define'ing `PUT_LNSZ_LNNO' and `GET_LNSZ_LNNO' +will select the correct one. No doubt, some day someone will find a +version of coff which has a varying field size not catered to at the +moment. To port BFD, that person will have to add more `#defines'. +Three of the bit twiddling routines are exported to `gdb'; +`coff_swap_aux_in', `coff_swap_sym_in' and `coff_swap_linno_in'. `GDB' +reads the symbol table on its own, but uses BFD to fix things up. More +of the bit twiddlers are exported for `gas'; `coff_swap_aux_out', +`coff_swap_sym_out', `coff_swap_lineno_out', `coff_swap_reloc_out', +`coff_swap_filehdr_out', `coff_swap_aouthdr_out', +`coff_swap_scnhdr_out'. `Gas' currently keeps track of all the symbol +table and reloc drudgery itself, thereby saving the internal BFD +overhead, but uses BFD to swap things on the way out, making cross +ports much safer. Doing so also allows BFD (and thus the linker) to +use the same header files as `gas', which makes one avenue to disaster +disappear. +Symbol reading +.............. + +The simple canonical form for symbols used by BFD is not rich enough to +keep all the information available in a coff symbol table. The back end +gets around this problem by keeping the original symbol table around, +"behind the scenes". + + When a symbol table is requested (through a call to +`bfd_canonicalize_symtab'), a request gets through to +`coff_get_normalized_symtab'. This reads the symbol table from the coff +file and swaps all the structures inside into the internal form. It +also fixes up all the pointers in the table (represented in the file by +offsets from the first symbol in the table) into physical pointers to +elements in the new internal table. This involves some work since the +meanings of fields change depending upon context: a field that is a +pointer to another structure in the symbol table at one moment may be +the size in bytes of a structure at the next. Another pass is made +over the table. All symbols which mark file names (`C_FILE' symbols) +are modified so that the internal string points to the value in the +auxent (the real filename) rather than the normal text associated with +the symbol (`".file"'). + + At this time the symbol names are moved around. Coff stores all +symbols less than nine characters long physically within the symbol +table; longer strings are kept at the end of the file in the string +table. This pass moves all strings into memory and replaces them with +pointers to the strings. + + The symbol table is massaged once again, this time to create the +canonical table used by the BFD application. Each symbol is inspected +in turn, and a decision made (using the `sclass' field) about the +various flags to set in the `asymbol'. *Note Symbols::. The generated +canonical table shares strings with the hidden internal symbol table. + + Any linenumbers are read from the coff file too, and attached to the +symbols which own the functions the linenumbers belong to. +Symbol writing +.............. + +Writing a symbol to a coff file which didn't come from a coff file will +lose any debugging information. The `asymbol' structure remembers the +BFD from which the symbol was taken, and on output the back end makes +sure that the same destination target as source target is present. + + When the symbols have come from a coff file then all the debugging +information is preserved. + + Symbol tables are provided for writing to the back end in a vector +of pointers to pointers. This allows applications like the linker to +accumulate and output large symbol tables without having to do too much +byte copying. + + This function runs through the provided symbol table and patches +each symbol marked as a file place holder (`C_FILE') to point to the +next file place holder in the list. It also marks each `offset' field +in the list with the offset from the first symbol of the current symbol. + + Another function of this procedure is to turn the canonical value +form of BFD into the form used by coff. Internally, BFD expects symbol +values to be offsets from a section base; so a symbol physically at +0x120, but in a section starting at 0x100, would have the value 0x20. +Coff expects symbols to contain their final value, so symbols have +their values changed at this point to reflect their sum with their +owning section. This transformation uses the `output_section' field of +the `asymbol''s `asection' *Note Sections::. + + * `coff_mangle_symbols' This routine runs though the provided symbol +table and uses the offsets generated by the previous pass and the +pointers generated when the symbol table was read in to create the +structured hierachy required by coff. It changes each pointer to a +symbol into the index into the symbol table of the asymbol. + + * `coff_write_symbols' This routine runs through the symbol table +and patches up the symbols from their internal form into the coff way, +calls the bit twiddlers, and writes out the table to the file. +`coff_symbol_type' +.................. + +*Description* +The hidden information for an `asymbol' is described in a +`combined_entry_type': +. + typedef struct coff_ptr_struct + { + + /* Remembers the offset from the first symbol in the file for + this symbol. Generated by coff_renumber_symbols. */ + unsigned int offset; + + /* Should the value of this symbol be renumbered. Used for + XCOFF C_BSTAT symbols. Set by coff_slurp_symbol_table. */ + unsigned int fix_value : 1; + + /* Should the tag field of this symbol be renumbered. + Created by coff_pointerize_aux. */ + unsigned int fix_tag : 1; + + /* Should the endidx field of this symbol be renumbered. + Created by coff_pointerize_aux. */ + unsigned int fix_end : 1; + + /* Should the x_csect.x_scnlen field be renumbered. + Created by coff_pointerize_aux. */ + unsigned int fix_scnlen : 1; + + /* Fix up an XCOFF C_BINCL/C_EINCL symbol. The value is the + index into the line number entries. Set by + coff_slurp_symbol_table. */ + unsigned int fix_line : 1; + + /* The container for the symbol structure as read and translated + from the file. */ + + union { + union internal_auxent auxent; + struct internal_syment syment; + } u; + } combined_entry_type; + + + /* Each canonical asymbol really looks like this: */ + + typedef struct coff_symbol_struct + { + /* The actual symbol which the rest of BFD works with */ + asymbol symbol; + + /* A pointer to the hidden information for this symbol */ + combined_entry_type *native; + + /* A pointer to the linenumber information for this symbol */ + struct lineno_cache_entry *lineno; + + /* Have the line numbers been relocated yet ? */ + boolean done_lineno; + } coff_symbol_type; + +`bfd_coff_backend_data' +....................... + + Special entry points for gdb to swap in coff symbol table parts: + typedef struct + { + void (*_bfd_coff_swap_aux_in) PARAMS (( + bfd *abfd, + PTR ext, + int type, + int class, + int indaux, + int numaux, + PTR in)); + + void (*_bfd_coff_swap_sym_in) PARAMS (( + bfd *abfd , + PTR ext, + PTR in)); + + void (*_bfd_coff_swap_lineno_in) PARAMS (( + bfd *abfd, + PTR ext, + PTR in)); + Special entry points for gas to swap out coff parts: + unsigned int (*_bfd_coff_swap_aux_out) PARAMS (( + bfd *abfd, + PTR in, + int type, + int class, + int indaux, + int numaux, + PTR ext)); + + unsigned int (*_bfd_coff_swap_sym_out) PARAMS (( + bfd *abfd, + PTR in, + PTR ext)); + + unsigned int (*_bfd_coff_swap_lineno_out) PARAMS (( + bfd *abfd, + PTR in, + PTR ext)); + + unsigned int (*_bfd_coff_swap_reloc_out) PARAMS (( + bfd *abfd, + PTR src, + PTR dst)); + + unsigned int (*_bfd_coff_swap_filehdr_out) PARAMS (( + bfd *abfd, + PTR in, + PTR out)); + + unsigned int (*_bfd_coff_swap_aouthdr_out) PARAMS (( + bfd *abfd, + PTR in, + PTR out)); + + unsigned int (*_bfd_coff_swap_scnhdr_out) PARAMS (( + bfd *abfd, + PTR in, + PTR out)); + Special entry points for generic COFF routines to call target +dependent COFF routines: + unsigned int _bfd_filhsz; + unsigned int _bfd_aoutsz; + unsigned int _bfd_scnhsz; + unsigned int _bfd_symesz; + unsigned int _bfd_auxesz; + unsigned int _bfd_relsz; + unsigned int _bfd_linesz; + boolean _bfd_coff_long_filenames; + boolean _bfd_coff_long_section_names; + unsigned int _bfd_coff_default_section_alignment_power; + void (*_bfd_coff_swap_filehdr_in) PARAMS (( + bfd *abfd, + PTR ext, + PTR in)); + void (*_bfd_coff_swap_aouthdr_in) PARAMS (( + bfd *abfd, + PTR ext, + PTR in)); + void (*_bfd_coff_swap_scnhdr_in) PARAMS (( + bfd *abfd, + PTR ext, + PTR in)); + void (*_bfd_coff_swap_reloc_in) PARAMS (( + bfd *abfd, + PTR ext, + PTR in)); + boolean (*_bfd_coff_bad_format_hook) PARAMS (( + bfd *abfd, + PTR internal_filehdr)); + boolean (*_bfd_coff_set_arch_mach_hook) PARAMS (( + bfd *abfd, + PTR internal_filehdr)); + PTR (*_bfd_coff_mkobject_hook) PARAMS (( + bfd *abfd, + PTR internal_filehdr, + PTR internal_aouthdr)); + flagword (*_bfd_styp_to_sec_flags_hook) PARAMS (( + bfd *abfd, + PTR internal_scnhdr, + const char *name)); + void (*_bfd_set_alignment_hook) PARAMS (( + bfd *abfd, + asection *sec, + PTR internal_scnhdr)); + boolean (*_bfd_coff_slurp_symbol_table) PARAMS (( + bfd *abfd)); + boolean (*_bfd_coff_symname_in_debug) PARAMS (( + bfd *abfd, + struct internal_syment *sym)); + boolean (*_bfd_coff_pointerize_aux_hook) PARAMS (( + bfd *abfd, + combined_entry_type *table_base, + combined_entry_type *symbol, + unsigned int indaux, + combined_entry_type *aux)); + boolean (*_bfd_coff_print_aux) PARAMS (( + bfd *abfd, + FILE *file, + combined_entry_type *table_base, + combined_entry_type *symbol, + combined_entry_type *aux, + unsigned int indaux)); + void (*_bfd_coff_reloc16_extra_cases) PARAMS (( + bfd *abfd, + struct bfd_link_info *link_info, + struct bfd_link_order *link_order, + arelent *reloc, + bfd_byte *data, + unsigned int *src_ptr, + unsigned int *dst_ptr)); + int (*_bfd_coff_reloc16_estimate) PARAMS (( + bfd *abfd, + asection *input_section, + arelent *r, + unsigned int shrink, + struct bfd_link_info *link_info)); + boolean (*_bfd_coff_sym_is_global) PARAMS (( + bfd *abfd, + struct internal_syment *)); + boolean (*_bfd_coff_compute_section_file_positions) PARAMS (( + bfd *abfd)); + boolean (*_bfd_coff_start_final_link) PARAMS (( + bfd *output_bfd, + struct bfd_link_info *info)); + boolean (*_bfd_coff_relocate_section) PARAMS (( + bfd *output_bfd, + struct bfd_link_info *info, + bfd *input_bfd, + asection *input_section, + bfd_byte *contents, + struct internal_reloc *relocs, + struct internal_syment *syms, + asection **sections)); + reloc_howto_type *(*_bfd_coff_rtype_to_howto) PARAMS (( + bfd *abfd, + asection *sec, + struct internal_reloc *rel, + struct coff_link_hash_entry *h, + struct internal_syment *sym, + bfd_vma *addendp)); + boolean (*_bfd_coff_adjust_symndx) PARAMS (( + bfd *obfd, + struct bfd_link_info *info, + bfd *ibfd, + asection *sec, + struct internal_reloc *reloc, + boolean *adjustedp)); + boolean (*_bfd_coff_link_add_one_symbol) PARAMS (( + struct bfd_link_info *info, + bfd *abfd, + const char *name, + flagword flags, + asection *section, + bfd_vma value, + const char *string, + boolean copy, + boolean collect, + struct bfd_link_hash_entry **hashp)); + + } bfd_coff_backend_data; + + #define coff_backend_info(abfd) ((bfd_coff_backend_data *) (abfd)->xvec->backend_data) + + #define bfd_coff_swap_aux_in(a,e,t,c,ind,num,i) \ + ((coff_backend_info (a)->_bfd_coff_swap_aux_in) (a,e,t,c,ind,num,i)) + + #define bfd_coff_swap_sym_in(a,e,i) \ + ((coff_backend_info (a)->_bfd_coff_swap_sym_in) (a,e,i)) + + #define bfd_coff_swap_lineno_in(a,e,i) \ + ((coff_backend_info ( a)->_bfd_coff_swap_lineno_in) (a,e,i)) + + #define bfd_coff_swap_reloc_out(abfd, i, o) \ + ((coff_backend_info (abfd)->_bfd_coff_swap_reloc_out) (abfd, i, o)) + + #define bfd_coff_swap_lineno_out(abfd, i, o) \ + ((coff_backend_info (abfd)->_bfd_coff_swap_lineno_out) (abfd, i, o)) + + #define bfd_coff_swap_aux_out(a,i,t,c,ind,num,o) \ + ((coff_backend_info (a)->_bfd_coff_swap_aux_out) (a,i,t,c,ind,num,o)) + + #define bfd_coff_swap_sym_out(abfd, i,o) \ + ((coff_backend_info (abfd)->_bfd_coff_swap_sym_out) (abfd, i, o)) + + #define bfd_coff_swap_scnhdr_out(abfd, i,o) \ + ((coff_backend_info (abfd)->_bfd_coff_swap_scnhdr_out) (abfd, i, o)) + + #define bfd_coff_swap_filehdr_out(abfd, i,o) \ + ((coff_backend_info (abfd)->_bfd_coff_swap_filehdr_out) (abfd, i, o)) + + #define bfd_coff_swap_aouthdr_out(abfd, i,o) \ + ((coff_backend_info (abfd)->_bfd_coff_swap_aouthdr_out) (abfd, i, o)) + + #define bfd_coff_filhsz(abfd) (coff_backend_info (abfd)->_bfd_filhsz) + #define bfd_coff_aoutsz(abfd) (coff_backend_info (abfd)->_bfd_aoutsz) + #define bfd_coff_scnhsz(abfd) (coff_backend_info (abfd)->_bfd_scnhsz) + #define bfd_coff_symesz(abfd) (coff_backend_info (abfd)->_bfd_symesz) + #define bfd_coff_auxesz(abfd) (coff_backend_info (abfd)->_bfd_auxesz) + #define bfd_coff_relsz(abfd) (coff_backend_info (abfd)->_bfd_relsz) + #define bfd_coff_linesz(abfd) (coff_backend_info (abfd)->_bfd_linesz) + #define bfd_coff_long_filenames(abfd) (coff_backend_info (abfd)->_bfd_coff_long_filenames) + #define bfd_coff_long_section_names(abfd) \ + (coff_backend_info (abfd)->_bfd_coff_long_section_names) + #define bfd_coff_default_section_alignment_power(abfd) \ + (coff_backend_info (abfd)->_bfd_coff_default_section_alignment_power) + #define bfd_coff_swap_filehdr_in(abfd, i,o) \ + ((coff_backend_info (abfd)->_bfd_coff_swap_filehdr_in) (abfd, i, o)) + + #define bfd_coff_swap_aouthdr_in(abfd, i,o) \ + ((coff_backend_info (abfd)->_bfd_coff_swap_aouthdr_in) (abfd, i, o)) + + #define bfd_coff_swap_scnhdr_in(abfd, i,o) \ + ((coff_backend_info (abfd)->_bfd_coff_swap_scnhdr_in) (abfd, i, o)) + + #define bfd_coff_swap_reloc_in(abfd, i, o) \ + ((coff_backend_info (abfd)->_bfd_coff_swap_reloc_in) (abfd, i, o)) + + #define bfd_coff_bad_format_hook(abfd, filehdr) \ + ((coff_backend_info (abfd)->_bfd_coff_bad_format_hook) (abfd, filehdr)) + + #define bfd_coff_set_arch_mach_hook(abfd, filehdr)\ + ((coff_backend_info (abfd)->_bfd_coff_set_arch_mach_hook) (abfd, filehdr)) + #define bfd_coff_mkobject_hook(abfd, filehdr, aouthdr)\ + ((coff_backend_info (abfd)->_bfd_coff_mkobject_hook) (abfd, filehdr, aouthdr)) + + #define bfd_coff_styp_to_sec_flags_hook(abfd, scnhdr, name)\ + ((coff_backend_info (abfd)->_bfd_styp_to_sec_flags_hook) (abfd, scnhdr, name)) + + #define bfd_coff_set_alignment_hook(abfd, sec, scnhdr)\ + ((coff_backend_info (abfd)->_bfd_set_alignment_hook) (abfd, sec, scnhdr)) + + #define bfd_coff_slurp_symbol_table(abfd)\ + ((coff_backend_info (abfd)->_bfd_coff_slurp_symbol_table) (abfd)) + + #define bfd_coff_symname_in_debug(abfd, sym)\ + ((coff_backend_info (abfd)->_bfd_coff_symname_in_debug) (abfd, sym)) + + #define bfd_coff_print_aux(abfd, file, base, symbol, aux, indaux)\ + ((coff_backend_info (abfd)->_bfd_coff_print_aux)\ + (abfd, file, base, symbol, aux, indaux)) + + #define bfd_coff_reloc16_extra_cases(abfd, link_info, link_order, reloc, data, src_ptr, dst_ptr)\ + ((coff_backend_info (abfd)->_bfd_coff_reloc16_extra_cases)\ + (abfd, link_info, link_order, reloc, data, src_ptr, dst_ptr)) + + #define bfd_coff_reloc16_estimate(abfd, section, reloc, shrink, link_info)\ + ((coff_backend_info (abfd)->_bfd_coff_reloc16_estimate)\ + (abfd, section, reloc, shrink, link_info)) + + #define bfd_coff_sym_is_global(abfd, sym)\ + ((coff_backend_info (abfd)->_bfd_coff_sym_is_global)\ + (abfd, sym)) + + #define bfd_coff_compute_section_file_positions(abfd)\ + ((coff_backend_info (abfd)->_bfd_coff_compute_section_file_positions)\ + (abfd)) + + #define bfd_coff_start_final_link(obfd, info)\ + ((coff_backend_info (obfd)->_bfd_coff_start_final_link)\ + (obfd, info)) + #define bfd_coff_relocate_section(obfd,info,ibfd,o,con,rel,isyms,secs)\ + ((coff_backend_info (ibfd)->_bfd_coff_relocate_section)\ + (obfd, info, ibfd, o, con, rel, isyms, secs)) + #define bfd_coff_rtype_to_howto(abfd, sec, rel, h, sym, addendp)\ + ((coff_backend_info (abfd)->_bfd_coff_rtype_to_howto)\ + (abfd, sec, rel, h, sym, addendp)) + #define bfd_coff_adjust_symndx(obfd, info, ibfd, sec, rel, adjustedp)\ + ((coff_backend_info (abfd)->_bfd_coff_adjust_symndx)\ + (obfd, info, ibfd, sec, rel, adjustedp)) + #define bfd_coff_link_add_one_symbol(info,abfd,name,flags,section,value,string,cp,coll,hashp)\ + ((coff_backend_info (abfd)->_bfd_coff_link_add_one_symbol)\ + (info, abfd, name, flags, section, value, string, cp, coll, hashp)) + +Writing relocations +................... + + To write relocations, the back end steps though the canonical +relocation table and create an `internal_reloc'. The symbol index to +use is removed from the `offset' field in the symbol table supplied. +The address comes directly from the sum of the section base address and +the relocation offset; the type is dug directly from the howto field. +Then the `internal_reloc' is swapped into the shape of an +`external_reloc' and written out to disk. +Reading linenumbers +................... + +Creating the linenumber table is done by reading in the entire coff +linenumber table, and creating another table for internal use. + + A coff linenumber table is structured so that each function is +marked as having a line number of 0. Each line within the function is +an offset from the first line in the function. The base of the line +number information for the table is stored in the symbol associated +with the function. + + The information is copied from the external to the internal table, +and each symbol which marks a function is marked by pointing its... + + How does this work ? +Reading relocations +................... + +Coff relocations are easily transformed into the internal BFD form +(`arelent'). + + Reading a coff relocation table is done in the following stages: + + * Read the entire coff relocation table into memory. + + * Process each relocation in turn; first swap it from the external + to the internal form. + + * Turn the symbol referenced in the relocation's symbol index into a + pointer into the canonical symbol table. This table is the same + as the one returned by a call to `bfd_canonicalize_symtab'. The + back end will call that routine and save the result if a + canonicalization hasn't been done. + + * The reloc index is turned into a pointer to a howto structure, in + a back end specific way. For instance, the 386 and 960 use the + `r_type' to directly produce an index into a howto table vector; + the 88k subtracts a number from the `r_type' field and creates an + addend field. + +File: bfd.info, Node: elf, Prev: coff, Up: BFD back ends + +ELF backends +============ + +BFD support for ELF formats is being worked on. Currently, the best +supported back ends are for sparc and i386 (running svr4 or Solaris 2). + + Documentation of the internals of the support code still needs to be +written. The code is changing quickly enough that we haven't bothered +yet. +`bfd_elf_find_section' +...................... + +*Synopsis* + struct elf_internal_shdr *bfd_elf_find_section (bfd *abfd, char *name); + *Description* +Helper functions for GDB to locate the string tables. Since BFD hides +string tables from callers, GDB needs to use an internal hook to find +them. Sun's .stabstr, in particular, isn't even pointed to by the +.stab section, so ordinary mechanisms wouldn't work to find it, even if +we had some. + +File: bfd.info, Node: Index, Prev: BFD back ends, Up: Top + +Index +***** + +* Menu: + +* _bfd_final_link_relocate: Relocating the section contents. +* _bfd_generic_link_add_archive_symbols: Adding symbols from an archive. +* _bfd_generic_link_add_one_symbol: Adding symbols from an object file. +* _bfd_link_add_symbols in target vector: Adding Symbols to the Hash Table. +* _bfd_link_final_link in target vector: Performing the Final Link. +* _bfd_link_hash_table_create in target vector: Creating a Linker Hash Table. +* _bfd_relocate_contents: Relocating the section contents. +* aout_SIZE_machine_type: aout. +* aout_SIZE_mkobject: aout. +* aout_SIZE_new_section_hook: aout. +* aout_SIZE_set_arch_mach: aout. +* aout_SIZE_some_aout_object_p: aout. +* aout_SIZE_swap_exec_header_in: aout. +* aout_SIZE_swap_exec_header_out: aout. +* arelent_chain: typedef arelent. +* BFD: Overview. +* BFD canonical format: Canonical format. +* bfd_alloc: Opening and Closing. +* bfd_arch_bits_per_address: Architectures. +* bfd_arch_bits_per_byte: Architectures. +* bfd_arch_get_compatible: Architectures. +* bfd_cache_close: File Caching. +* bfd_cache_init: File Caching. +* bfd_cache_lookup: File Caching. +* bfd_cache_lookup_worker: File Caching. +* BFD_CACHE_MAX_OPEN macro: File Caching. +* bfd_canonicalize_reloc: BFD front end. +* bfd_canonicalize_symtab: symbol handling functions. +* bfd_check_format: Formats. +* bfd_check_format_matches: Formats. +* bfd_close: Opening and Closing. +* bfd_close_all_done: Opening and Closing. +* bfd_coff_backend_data: coff. +* bfd_copy_private_bfd_data: BFD front end. +* bfd_copy_private_section_data: section prototypes. +* bfd_copy_private_symbol_data: symbol handling functions. +* bfd_core_file_failing_command: Core Files. +* bfd_core_file_failing_signal: Core Files. +* bfd_create: Opening and Closing. +* bfd_decode_symclass: symbol handling functions. +* bfd_default_arch_struct: Architectures. +* bfd_default_compatible: Architectures. +* bfd_default_reloc_type_lookup: howto manager. +* bfd_default_scan: Architectures. +* bfd_default_set_arch_mach: Architectures. +* bfd_elf_find_section: elf. +* bfd_errmsg: BFD front end. +* bfd_fdopenr: Opening and Closing. +* bfd_find_target: bfd_target. +* bfd_format_string: Formats. +* bfd_generic_get_relocated_section_contents: howto manager. +* bfd_generic_relax_section: howto manager. +* bfd_get_arch: Architectures. +* bfd_get_arch_info: Architectures. +* bfd_get_error: BFD front end. +* bfd_get_gp_size: BFD front end. +* bfd_get_mach: Architectures. +* bfd_get_mtime: BFD front end. +* bfd_get_next_mapent: Archives. +* bfd_get_reloc_code_name: howto manager. +* bfd_get_reloc_size: typedef arelent. +* bfd_get_reloc_upper_bound: BFD front end. +* bfd_get_section_by_name: section prototypes. +* bfd_get_section_contents: section prototypes. +* bfd_get_size <1>: Internal. +* bfd_get_size: BFD front end. +* bfd_get_symtab_upper_bound: symbol handling functions. +* bfd_h_put_size: Internal. +* bfd_hash_allocate: Creating and Freeing a Hash Table. +* bfd_hash_lookup: Looking Up or Entering a String. +* bfd_hash_newfunc: Creating and Freeing a Hash Table. +* bfd_hash_table_free: Creating and Freeing a Hash Table. +* bfd_hash_table_init: Creating and Freeing a Hash Table. +* bfd_hash_table_init_n: Creating and Freeing a Hash Table. +* bfd_hash_traverse: Traversing a Hash Table. +* bfd_init: Initialization. +* bfd_install_relocation: typedef arelent. +* bfd_is_local_label: symbol handling functions. +* bfd_is_local_label_name: symbol handling functions. +* bfd_last_cache: File Caching. +* bfd_link_split_section: Writing the symbol table. +* bfd_log2: Internal. +* bfd_lookup_arch: Architectures. +* bfd_make_debug_symbol: symbol handling functions. +* bfd_make_empty_symbol: symbol handling functions. +* bfd_make_section: section prototypes. +* bfd_make_section_anyway: section prototypes. +* bfd_make_section_old_way: section prototypes. +* bfd_map_over_sections: section prototypes. +* bfd_merge_private_bfd_data: BFD front end. +* bfd_open_file: File Caching. +* bfd_openr: Opening and Closing. +* bfd_openr_next_archived_file: Archives. +* bfd_openstreamr: Opening and Closing. +* bfd_openw: Opening and Closing. +* bfd_perform_relocation: typedef arelent. +* bfd_perror: BFD front end. +* bfd_print_symbol_vandf: symbol handling functions. +* bfd_printable_arch_mach: Architectures. +* bfd_printable_name: Architectures. +* bfd_put_size: Internal. +* BFD_RELOC_12_PCREL: howto manager. +* BFD_RELOC_14: howto manager. +* BFD_RELOC_16: howto manager. +* BFD_RELOC_16_BASEREL: howto manager. +* BFD_RELOC_16_GOT_PCREL: howto manager. +* BFD_RELOC_16_GOTOFF: howto manager. +* BFD_RELOC_16_PCREL: howto manager. +* BFD_RELOC_16_PCREL_S2: howto manager. +* BFD_RELOC_16_PLT_PCREL: howto manager. +* BFD_RELOC_16_PLTOFF: howto manager. +* BFD_RELOC_23_PCREL_S2: howto manager. +* BFD_RELOC_24: howto manager. +* BFD_RELOC_24_PCREL: howto manager. +* BFD_RELOC_24_PLT_PCREL: howto manager. +* BFD_RELOC_26: howto manager. +* BFD_RELOC_32: howto manager. +* BFD_RELOC_32_BASEREL: howto manager. +* BFD_RELOC_32_GOT_PCREL: howto manager. +* BFD_RELOC_32_GOTOFF: howto manager. +* BFD_RELOC_32_PCREL: howto manager. +* BFD_RELOC_32_PCREL_S2: howto manager. +* BFD_RELOC_32_PLT_PCREL: howto manager. +* BFD_RELOC_32_PLTOFF: howto manager. +* BFD_RELOC_386_COPY: howto manager. +* BFD_RELOC_386_GLOB_DAT: howto manager. +* BFD_RELOC_386_GOT32: howto manager. +* BFD_RELOC_386_GOTOFF: howto manager. +* BFD_RELOC_386_GOTPC: howto manager. +* BFD_RELOC_386_JUMP_SLOT: howto manager. +* BFD_RELOC_386_PLT32: howto manager. +* BFD_RELOC_386_RELATIVE: howto manager. +* BFD_RELOC_64: howto manager. +* BFD_RELOC_64_PCREL: howto manager. +* BFD_RELOC_68K_GLOB_DAT: howto manager. +* BFD_RELOC_68K_JMP_SLOT: howto manager. +* BFD_RELOC_68K_RELATIVE: howto manager. +* BFD_RELOC_8: howto manager. +* BFD_RELOC_8_BASEREL: howto manager. +* BFD_RELOC_8_FFnn: howto manager. +* BFD_RELOC_8_GOT_PCREL: howto manager. +* BFD_RELOC_8_GOTOFF: howto manager. +* BFD_RELOC_8_PCREL: howto manager. +* BFD_RELOC_8_PLT_PCREL: howto manager. +* BFD_RELOC_8_PLTOFF: howto manager. +* BFD_RELOC_ALPHA_CODEADDR: howto manager. +* BFD_RELOC_ALPHA_ELF_LITERAL: howto manager. +* BFD_RELOC_ALPHA_GPDISP: howto manager. +* BFD_RELOC_ALPHA_GPDISP_HI16: howto manager. +* BFD_RELOC_ALPHA_GPDISP_LO16: howto manager. +* BFD_RELOC_ALPHA_HINT: howto manager. +* BFD_RELOC_ALPHA_LINKAGE: howto manager. +* BFD_RELOC_ALPHA_LITERAL: howto manager. +* BFD_RELOC_ALPHA_LITUSE: howto manager. +* BFD_RELOC_ARM_ADR_IMM: howto manager. +* BFD_RELOC_ARM_CP_OFF_IMM: howto manager. +* BFD_RELOC_ARM_HWLITERAL: howto manager. +* BFD_RELOC_ARM_IMMEDIATE: howto manager. +* BFD_RELOC_ARM_IN_POOL: howto manager. +* BFD_RELOC_ARM_LDR_IMM: howto manager. +* BFD_RELOC_ARM_LITERAL: howto manager. +* BFD_RELOC_ARM_MULTI: howto manager. +* BFD_RELOC_ARM_OFFSET_IMM: howto manager. +* BFD_RELOC_ARM_OFFSET_IMM8: howto manager. +* BFD_RELOC_ARM_PCREL_BRANCH: howto manager. +* BFD_RELOC_ARM_SHIFT_IMM: howto manager. +* BFD_RELOC_ARM_SWI: howto manager. +* BFD_RELOC_ARM_THUMB_ADD: howto manager. +* BFD_RELOC_ARM_THUMB_IMM: howto manager. +* BFD_RELOC_ARM_THUMB_OFFSET: howto manager. +* BFD_RELOC_ARM_THUMB_SHIFT: howto manager. +* bfd_reloc_code_type: howto manager. +* BFD_RELOC_CTOR: howto manager. +* BFD_RELOC_D10V_10_PCREL_L: howto manager. +* BFD_RELOC_D10V_10_PCREL_R: howto manager. +* BFD_RELOC_D10V_18: howto manager. +* BFD_RELOC_D10V_18_PCREL: howto manager. +* BFD_RELOC_GPREL16: howto manager. +* BFD_RELOC_GPREL32: howto manager. +* BFD_RELOC_HI16: howto manager. +* BFD_RELOC_HI16_BASEREL: howto manager. +* BFD_RELOC_HI16_GOTOFF: howto manager. +* BFD_RELOC_HI16_PLTOFF: howto manager. +* BFD_RELOC_HI16_S: howto manager. +* BFD_RELOC_HI16_S_BASEREL: howto manager. +* BFD_RELOC_HI16_S_GOTOFF: howto manager. +* BFD_RELOC_HI16_S_PLTOFF: howto manager. +* BFD_RELOC_HI22: howto manager. +* BFD_RELOC_I960_CALLJ: howto manager. +* BFD_RELOC_LO10: howto manager. +* BFD_RELOC_LO16: howto manager. +* BFD_RELOC_LO16_BASEREL: howto manager. +* BFD_RELOC_LO16_GOTOFF: howto manager. +* BFD_RELOC_LO16_PLTOFF: howto manager. +* BFD_RELOC_M32R_10_PCREL: howto manager. +* BFD_RELOC_M32R_18_PCREL: howto manager. +* BFD_RELOC_M32R_24: howto manager. +* BFD_RELOC_M32R_26_PCREL: howto manager. +* BFD_RELOC_M32R_HI16_SLO: howto manager. +* BFD_RELOC_M32R_HI16_ULO: howto manager. +* BFD_RELOC_M32R_LO16: howto manager. +* BFD_RELOC_M32R_SDA16: howto manager. +* BFD_RELOC_MIPS16_GPREL: howto manager. +* BFD_RELOC_MIPS16_JMP: howto manager. +* BFD_RELOC_MIPS_CALL16: howto manager. +* BFD_RELOC_MIPS_CALL_HI16: howto manager. +* BFD_RELOC_MIPS_CALL_LO16: howto manager. +* BFD_RELOC_MIPS_GOT16: howto manager. +* BFD_RELOC_MIPS_GOT_HI16: howto manager. +* BFD_RELOC_MIPS_GOT_LO16: howto manager. +* BFD_RELOC_MIPS_GPREL: howto manager. +* BFD_RELOC_MIPS_GPREL32: howto manager. +* BFD_RELOC_MIPS_JMP: howto manager. +* BFD_RELOC_MIPS_LITERAL: howto manager. +* BFD_RELOC_MN10300_16_PCREL: howto manager. +* BFD_RELOC_MN10300_32_PCREL: howto manager. +* BFD_RELOC_NONE: howto manager. +* BFD_RELOC_NS32K_DISP_16: howto manager. +* BFD_RELOC_NS32K_DISP_16_PCREL: howto manager. +* BFD_RELOC_NS32K_DISP_32: howto manager. +* BFD_RELOC_NS32K_DISP_32_PCREL: howto manager. +* BFD_RELOC_NS32K_DISP_8: howto manager. +* BFD_RELOC_NS32K_DISP_8_PCREL: howto manager. +* BFD_RELOC_NS32K_IMM_16: howto manager. +* BFD_RELOC_NS32K_IMM_16_PCREL: howto manager. +* BFD_RELOC_NS32K_IMM_32: howto manager. +* BFD_RELOC_NS32K_IMM_32_PCREL: howto manager. +* BFD_RELOC_NS32K_IMM_8: howto manager. +* BFD_RELOC_NS32K_IMM_8_PCREL: howto manager. +* BFD_RELOC_PCREL_HI16_S: howto manager. +* BFD_RELOC_PCREL_LO16: howto manager. +* BFD_RELOC_PPC_B16: howto manager. +* BFD_RELOC_PPC_B16_BRNTAKEN: howto manager. +* BFD_RELOC_PPC_B16_BRTAKEN: howto manager. +* BFD_RELOC_PPC_B26: howto manager. +* BFD_RELOC_PPC_BA16: howto manager. +* BFD_RELOC_PPC_BA16_BRNTAKEN: howto manager. +* BFD_RELOC_PPC_BA16_BRTAKEN: howto manager. +* BFD_RELOC_PPC_BA26: howto manager. +* BFD_RELOC_PPC_COPY: howto manager. +* BFD_RELOC_PPC_EMB_BIT_FLD: howto manager. +* BFD_RELOC_PPC_EMB_MRKREF: howto manager. +* BFD_RELOC_PPC_EMB_NADDR16: howto manager. +* BFD_RELOC_PPC_EMB_NADDR16_HA: howto manager. +* BFD_RELOC_PPC_EMB_NADDR16_HI: howto manager. +* BFD_RELOC_PPC_EMB_NADDR16_LO: howto manager. +* BFD_RELOC_PPC_EMB_NADDR32: howto manager. +* BFD_RELOC_PPC_EMB_RELSDA: howto manager. +* BFD_RELOC_PPC_EMB_RELSEC16: howto manager. +* BFD_RELOC_PPC_EMB_RELST_HA: howto manager. +* BFD_RELOC_PPC_EMB_RELST_HI: howto manager. +* BFD_RELOC_PPC_EMB_RELST_LO: howto manager. +* BFD_RELOC_PPC_EMB_SDA21: howto manager. +* BFD_RELOC_PPC_EMB_SDA2I16: howto manager. +* BFD_RELOC_PPC_EMB_SDA2REL: howto manager. +* BFD_RELOC_PPC_EMB_SDAI16: howto manager. +* BFD_RELOC_PPC_GLOB_DAT: howto manager. +* BFD_RELOC_PPC_JMP_SLOT: howto manager. +* BFD_RELOC_PPC_LOCAL24PC: howto manager. +* BFD_RELOC_PPC_RELATIVE: howto manager. +* BFD_RELOC_PPC_TOC16: howto manager. +* BFD_RELOC_RVA: howto manager. +* BFD_RELOC_SH_ALIGN: howto manager. +* BFD_RELOC_SH_CODE: howto manager. +* BFD_RELOC_SH_COUNT: howto manager. +* BFD_RELOC_SH_DATA: howto manager. +* BFD_RELOC_SH_IMM4: howto manager. +* BFD_RELOC_SH_IMM4BY2: howto manager. +* BFD_RELOC_SH_IMM4BY4: howto manager. +* BFD_RELOC_SH_IMM8: howto manager. +* BFD_RELOC_SH_IMM8BY2: howto manager. +* BFD_RELOC_SH_IMM8BY4: howto manager. +* BFD_RELOC_SH_LABEL: howto manager. +* BFD_RELOC_SH_PCDISP12BY2: howto manager. +* BFD_RELOC_SH_PCDISP8BY2: howto manager. +* BFD_RELOC_SH_PCRELIMM8BY2: howto manager. +* BFD_RELOC_SH_PCRELIMM8BY4: howto manager. +* BFD_RELOC_SH_SWITCH16: howto manager. +* BFD_RELOC_SH_SWITCH32: howto manager. +* BFD_RELOC_SH_USES: howto manager. +* BFD_RELOC_SPARC13: howto manager. +* BFD_RELOC_SPARC22: howto manager. +* BFD_RELOC_SPARC_10: howto manager. +* BFD_RELOC_SPARC_11: howto manager. +* BFD_RELOC_SPARC_5: howto manager. +* BFD_RELOC_SPARC_6: howto manager. +* BFD_RELOC_SPARC_64: howto manager. +* BFD_RELOC_SPARC_7: howto manager. +* BFD_RELOC_SPARC_BASE13: howto manager. +* BFD_RELOC_SPARC_BASE22: howto manager. +* BFD_RELOC_SPARC_COPY: howto manager. +* BFD_RELOC_SPARC_GLOB_DAT: howto manager. +* BFD_RELOC_SPARC_GLOB_JMP: howto manager. +* BFD_RELOC_SPARC_GOT10: howto manager. +* BFD_RELOC_SPARC_GOT13: howto manager. +* BFD_RELOC_SPARC_GOT22: howto manager. +* BFD_RELOC_SPARC_HH22: howto manager. +* BFD_RELOC_SPARC_HM10: howto manager. +* BFD_RELOC_SPARC_JMP_SLOT: howto manager. +* BFD_RELOC_SPARC_LM22: howto manager. +* BFD_RELOC_SPARC_OLO10: howto manager. +* BFD_RELOC_SPARC_PC10: howto manager. +* BFD_RELOC_SPARC_PC22: howto manager. +* BFD_RELOC_SPARC_PC_HH22: howto manager. +* BFD_RELOC_SPARC_PC_HM10: howto manager. +* BFD_RELOC_SPARC_PC_LM22: howto manager. +* BFD_RELOC_SPARC_RELATIVE: howto manager. +* BFD_RELOC_SPARC_UA32: howto manager. +* BFD_RELOC_SPARC_WDISP16: howto manager. +* BFD_RELOC_SPARC_WDISP19: howto manager. +* BFD_RELOC_SPARC_WDISP22: howto manager. +* BFD_RELOC_SPARC_WPLT30: howto manager. +* bfd_reloc_type_lookup: howto manager. +* bfd_scan_arch: Architectures. +* bfd_scan_vma: BFD front end. +* bfd_set_arch_info: Architectures. +* bfd_set_archive_head: Archives. +* bfd_set_default_target: bfd_target. +* bfd_set_error: BFD front end. +* bfd_set_error_handler: BFD front end. +* bfd_set_error_program_name: BFD front end. +* bfd_set_file_flags: BFD front end. +* bfd_set_format: Formats. +* bfd_set_gp_size: BFD front end. +* bfd_set_private_flags: BFD front end. +* bfd_set_reloc: BFD front end. +* bfd_set_section_contents: section prototypes. +* bfd_set_section_flags: section prototypes. +* bfd_set_section_size: section prototypes. +* bfd_set_start_address: BFD front end. +* bfd_set_symtab: symbol handling functions. +* bfd_symbol_info: symbol handling functions. +* bfd_target_list: bfd_target. +* bfd_write_bigendian_4byte_int: Internal. +* coff_symbol_type: coff. +* core_file_matches_executable_p: Core Files. +* Hash tables: Hash Tables. +* internal object-file format: Canonical format. +* Linker: Linker Functions. +* stuff: BFD front end. +* target vector (_bfd_final_link): Performing the Final Link. +* target vector (_bfd_link_add_symbols): Adding Symbols to the Hash Table. +* target vector (_bfd_link_hash_table_create): Creating a Linker Hash Table. +* The HOWTO Macro: typedef arelent. +* what is it?: Overview. + + diff --git a/gnu/usr.bin/binutils/bfd/doc/bfd.texi b/gnu/usr.bin/binutils/bfd/doc/bfd.texi new file mode 100644 index 00000000000..ea0ca9e56dc --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/bfd.texi @@ -0,0 +1,585 @@ +@section @code{typedef bfd} +A BFD has type @code{bfd}; objects of this type are the +cornerstone of any application using BFD. Using BFD +consists of making references though the BFD and to data in the BFD. + +Here is the structure that defines the type @code{bfd}. It +contains the major data about the file and pointers +to the rest of the data. +@* +. +@example +struct _bfd +@{ + /* The filename the application opened the BFD with. */ + CONST char *filename; + + /* A pointer to the target jump table. */ + const struct bfd_target *xvec; + + /* To avoid dragging too many header files into every file that + includes `@code{bfd.h}', IOSTREAM has been declared as a "char + *", and MTIME as a "long". Their correct types, to which they + are cast when used, are "FILE *" and "time_t". The iostream + is the result of an fopen on the filename. However, if the + BFD_IN_MEMORY flag is set, then iostream is actually a pointer + to a bfd_in_memory struct. */ + PTR iostream; + + /* Is the file descriptor being cached? That is, can it be closed as + needed, and re-opened when accessed later? */ + + boolean cacheable; + + /* Marks whether there was a default target specified when the + BFD was opened. This is used to select which matching algorithm + to use to choose the back end. */ + + boolean target_defaulted; + + /* The caching routines use these to maintain a + least-recently-used list of BFDs */ + + struct _bfd *lru_prev, *lru_next; + + /* When a file is closed by the caching routines, BFD retains + state information on the file here: */ + + file_ptr where; + + /* and here: (``once'' means at least once) */ + + boolean opened_once; + + /* Set if we have a locally maintained mtime value, rather than + getting it from the file each time: */ + + boolean mtime_set; + + /* File modified time, if mtime_set is true: */ + + long mtime; + + /* Reserved for an unimplemented file locking extension.*/ + + int ifd; + + /* The format which belongs to the BFD. (object, core, etc.) */ + + bfd_format format; + + /* The direction the BFD was opened with*/ + + enum bfd_direction @{no_direction = 0, + read_direction = 1, + write_direction = 2, + both_direction = 3@} direction; + + /* Format_specific flags*/ + + flagword flags; + + /* Currently my_archive is tested before adding origin to + anything. I believe that this can become always an add of + origin, with origin set to 0 for non archive files. */ + + file_ptr origin; + + /* Remember when output has begun, to stop strange things + from happening. */ + boolean output_has_begun; + + /* Pointer to linked list of sections*/ + struct sec *sections; + + /* The number of sections */ + unsigned int section_count; + + /* Stuff only useful for object files: + The start address. */ + bfd_vma start_address; + + /* Used for input and output*/ + unsigned int symcount; + + /* Symbol table for output BFD (with symcount entries) */ + struct symbol_cache_entry **outsymbols; + + /* Pointer to structure which contains architecture information*/ + const struct bfd_arch_info *arch_info; + + /* Stuff only useful for archives:*/ + PTR arelt_data; + struct _bfd *my_archive; /* The containing archive BFD. */ + struct _bfd *next; /* The next BFD in the archive. */ + struct _bfd *archive_head; /* The first BFD in the archive. */ + boolean has_armap; + + /* A chain of BFD structures involved in a link. */ + struct _bfd *link_next; + + /* A field used by _bfd_generic_link_add_archive_symbols. This will + be used only for archive elements. */ + int archive_pass; + + /* Used by the back end to hold private data. */ + + union + @{ + struct aout_data_struct *aout_data; + struct artdata *aout_ar_data; + struct _oasys_data *oasys_obj_data; + struct _oasys_ar_data *oasys_ar_data; + struct coff_tdata *coff_obj_data; + struct pe_tdata *pe_obj_data; + struct xcoff_tdata *xcoff_obj_data; + struct ecoff_tdata *ecoff_obj_data; + struct ieee_data_struct *ieee_data; + struct ieee_ar_data_struct *ieee_ar_data; + struct srec_data_struct *srec_data; + struct ihex_data_struct *ihex_data; + struct tekhex_data_struct *tekhex_data; + struct elf_obj_tdata *elf_obj_data; + struct nlm_obj_tdata *nlm_obj_data; + struct bout_data_struct *bout_data; + struct sun_core_struct *sun_core_data; + struct trad_core_struct *trad_core_data; + struct som_data_struct *som_data; + struct hpux_core_struct *hpux_core_data; + struct hppabsd_core_struct *hppabsd_core_data; + struct sgi_core_struct *sgi_core_data; + struct lynx_core_struct *lynx_core_data; + struct osf_core_struct *osf_core_data; + struct cisco_core_struct *cisco_core_data; + struct versados_data_struct *versados_data; + struct netbsd_core_struct *netbsd_core_data; + PTR any; + @} tdata; + + /* Used by the application to hold private data*/ + PTR usrdata; + + /* Where all the allocated stuff under this BFD goes. This is a + struct objalloc *, but we use PTR to avoid requiring the inclusion of + objalloc.h. */ + PTR memory; +@}; + +@end example +@section Error reporting +Most BFD functions return nonzero on success (check their +individual documentation for precise semantics). On an error, +they call @code{bfd_set_error} to set an error condition that callers +can check by calling @code{bfd_get_error}. +If that returns @code{bfd_error_system_call}, then check +@code{errno}. + +The easiest way to report a BFD error to the user is to +use @code{bfd_perror}. +@* +@subsection Type @code{bfd_error_type} +The values returned by @code{bfd_get_error} are defined by the +enumerated type @code{bfd_error_type}. +@* +. +@example +typedef enum bfd_error +@{ + bfd_error_no_error = 0, + bfd_error_system_call, + bfd_error_invalid_target, + bfd_error_wrong_format, + bfd_error_invalid_operation, + bfd_error_no_memory, + bfd_error_no_symbols, + bfd_error_no_armap, + bfd_error_no_more_archived_files, + bfd_error_malformed_archive, + bfd_error_file_not_recognized, + bfd_error_file_ambiguously_recognized, + bfd_error_no_contents, + bfd_error_nonrepresentable_section, + bfd_error_no_debug_section, + bfd_error_bad_value, + bfd_error_file_truncated, + bfd_error_file_too_big, + bfd_error_invalid_error_code +@} bfd_error_type; + +@end example +@findex bfd_get_error +@subsubsection @code{bfd_get_error} +@strong{Synopsis} +@example +bfd_error_type bfd_get_error (void); +@end example +@strong{Description}@* +Return the current BFD error condition. +@* +@findex bfd_set_error +@subsubsection @code{bfd_set_error} +@strong{Synopsis} +@example +void bfd_set_error (bfd_error_type error_tag); +@end example +@strong{Description}@* +Set the BFD error condition to be @var{error_tag}. +@* +@findex bfd_errmsg +@subsubsection @code{bfd_errmsg} +@strong{Synopsis} +@example +CONST char *bfd_errmsg (bfd_error_type error_tag); +@end example +@strong{Description}@* +Return a string describing the error @var{error_tag}, or +the system error if @var{error_tag} is @code{bfd_error_system_call}. +@* +@findex bfd_perror +@subsubsection @code{bfd_perror} +@strong{Synopsis} +@example +void bfd_perror (CONST char *message); +@end example +@strong{Description}@* +Print to the standard error stream a string describing the +last BFD error that occurred, or the last system error if +the last BFD error was a system call failure. If @var{message} +is non-NULL and non-empty, the error string printed is preceded +by @var{message}, a colon, and a space. It is followed by a newline. +@* +@subsection BFD error handler +Some BFD functions want to print messages describing the +problem. They call a BFD error handler function. This +function may be overriden by the program. + +The BFD error handler acts like printf. +@* +. +@example +typedef void (*bfd_error_handler_type) PARAMS ((const char *, ...)); + +@end example +@findex bfd_set_error_handler +@subsubsection @code{bfd_set_error_handler} +@strong{Synopsis} +@example +bfd_error_handler_type bfd_set_error_handler (bfd_error_handler_type); +@end example +@strong{Description}@* +Set the BFD error handler function. Returns the previous +function. +@* +@findex bfd_set_error_program_name +@subsubsection @code{bfd_set_error_program_name} +@strong{Synopsis} +@example +void bfd_set_error_program_name (const char *); +@end example +@strong{Description}@* +Set the program name to use when printing a BFD error. This +is printed before the error message followed by a colon and +space. The string must not be changed after it is passed to +this function. +@* +@section Symbols + +@* +@findex bfd_get_reloc_upper_bound +@subsubsection @code{bfd_get_reloc_upper_bound} +@strong{Synopsis} +@example +long bfd_get_reloc_upper_bound(bfd *abfd, asection *sect); +@end example +@strong{Description}@* +Return the number of bytes required to store the +relocation information associated with section @var{sect} +attached to bfd @var{abfd}. If an error occurs, return -1. +@* +@findex bfd_canonicalize_reloc +@subsubsection @code{bfd_canonicalize_reloc} +@strong{Synopsis} +@example +long bfd_canonicalize_reloc + (bfd *abfd, + asection *sec, + arelent **loc, + asymbol **syms); +@end example +@strong{Description}@* +Call the back end associated with the open BFD +@var{abfd} and translate the external form of the relocation +information attached to @var{sec} into the internal canonical +form. Place the table into memory at @var{loc}, which has +been preallocated, usually by a call to +@code{bfd_get_reloc_upper_bound}. Returns the number of relocs, or +-1 on error. + +The @var{syms} table is also needed for horrible internal magic +reasons. +@* +@findex bfd_set_reloc +@subsubsection @code{bfd_set_reloc} +@strong{Synopsis} +@example +void bfd_set_reloc + (bfd *abfd, asection *sec, arelent **rel, unsigned int count) +@end example +@strong{Description}@* +Set the relocation pointer and count within +section @var{sec} to the values @var{rel} and @var{count}. +The argument @var{abfd} is ignored. +@* +@findex bfd_set_file_flags +@subsubsection @code{bfd_set_file_flags} +@strong{Synopsis} +@example +boolean bfd_set_file_flags(bfd *abfd, flagword flags); +@end example +@strong{Description}@* +Set the flag word in the BFD @var{abfd} to the value @var{flags}. + +Possible errors are: +@itemize @bullet + +@item +@code{bfd_error_wrong_format} - The target bfd was not of object format. +@item +@code{bfd_error_invalid_operation} - The target bfd was open for reading. +@item +@code{bfd_error_invalid_operation} - +The flag word contained a bit which was not applicable to the +type of file. E.g., an attempt was made to set the @code{D_PAGED} bit +on a BFD format which does not support demand paging. +@end itemize +@* +@findex bfd_set_start_address +@subsubsection @code{bfd_set_start_address} +@strong{Synopsis} +@example +boolean bfd_set_start_address(bfd *abfd, bfd_vma vma); +@end example +@strong{Description}@* +Make @var{vma} the entry point of output BFD @var{abfd}. +@* +@strong{Returns}@* +Returns @code{true} on success, @code{false} otherwise. +@* +@findex bfd_get_mtime +@subsubsection @code{bfd_get_mtime} +@strong{Synopsis} +@example +long bfd_get_mtime(bfd *abfd); +@end example +@strong{Description}@* +Return the file modification time (as read from the file system, or +from the archive header for archive members). +@* +@findex bfd_get_size +@subsubsection @code{bfd_get_size} +@strong{Synopsis} +@example +long bfd_get_size(bfd *abfd); +@end example +@strong{Description}@* +Return the file size (as read from file system) for the file +associated with BFD @var{abfd}. + +The initial motivation for, and use of, this routine is not +so we can get the exact size of the object the BFD applies to, since +that might not be generally possible (archive members for example). +It would be ideal if someone could eventually modify +it so that such results were guaranteed. + +Instead, we want to ask questions like "is this NNN byte sized +object I'm about to try read from file offset YYY reasonable?" +As as example of where we might do this, some object formats +use string tables for which the first @code{sizeof(long)} bytes of the +table contain the size of the table itself, including the size bytes. +If an application tries to read what it thinks is one of these +string tables, without some way to validate the size, and for +some reason the size is wrong (byte swapping error, wrong location +for the string table, etc.), the only clue is likely to be a read +error when it tries to read the table, or a "virtual memory +exhausted" error when it tries to allocate 15 bazillon bytes +of space for the 15 bazillon byte table it is about to read. +This function at least allows us to answer the quesion, "is the +size reasonable?". +@* +@findex bfd_get_gp_size +@subsubsection @code{bfd_get_gp_size} +@strong{Synopsis} +@example +int bfd_get_gp_size(bfd *abfd); +@end example +@strong{Description}@* +Return the maximum size of objects to be optimized using the GP +register under MIPS ECOFF. This is typically set by the @code{-G} +argument to the compiler, assembler or linker. +@* +@findex bfd_set_gp_size +@subsubsection @code{bfd_set_gp_size} +@strong{Synopsis} +@example +void bfd_set_gp_size(bfd *abfd, int i); +@end example +@strong{Description}@* +Set the maximum size of objects to be optimized using the GP +register under ECOFF or MIPS ELF. This is typically set by +the @code{-G} argument to the compiler, assembler or linker. +@* +@findex bfd_scan_vma +@subsubsection @code{bfd_scan_vma} +@strong{Synopsis} +@example +bfd_vma bfd_scan_vma(CONST char *string, CONST char **end, int base); +@end example +@strong{Description}@* +Convert, like @code{strtoul}, a numerical expression +@var{string} into a @code{bfd_vma} integer, and return that integer. +(Though without as many bells and whistles as @code{strtoul}.) +The expression is assumed to be unsigned (i.e., positive). +If given a @var{base}, it is used as the base for conversion. +A base of 0 causes the function to interpret the string +in hex if a leading "0x" or "0X" is found, otherwise +in octal if a leading zero is found, otherwise in decimal. + +Overflow is not detected. +@* +@findex bfd_copy_private_bfd_data +@subsubsection @code{bfd_copy_private_bfd_data} +@strong{Synopsis} +@example +boolean bfd_copy_private_bfd_data(bfd *ibfd, bfd *obfd); +@end example +@strong{Description}@* +Copy private BFD information from the BFD @var{ibfd} to the +the BFD @var{obfd}. Return @code{true} on success, @code{false} on error. +Possible error returns are: + +@itemize @bullet + +@item +@code{bfd_error_no_memory} - +Not enough memory exists to create private data for @var{obfd}. +@end itemize +@example +#define bfd_copy_private_bfd_data(ibfd, obfd) \ + BFD_SEND (obfd, _bfd_copy_private_bfd_data, \ + (ibfd, obfd)) +@end example +@* +@findex bfd_merge_private_bfd_data +@subsubsection @code{bfd_merge_private_bfd_data} +@strong{Synopsis} +@example +boolean bfd_merge_private_bfd_data(bfd *ibfd, bfd *obfd); +@end example +@strong{Description}@* +Merge private BFD information from the BFD @var{ibfd} to the +the output file BFD @var{obfd} when linking. Return @code{true} +on success, @code{false} on error. Possible error returns are: + +@itemize @bullet + +@item +@code{bfd_error_no_memory} - +Not enough memory exists to create private data for @var{obfd}. +@end itemize +@example +#define bfd_merge_private_bfd_data(ibfd, obfd) \ + BFD_SEND (obfd, _bfd_merge_private_bfd_data, \ + (ibfd, obfd)) +@end example +@* +@findex bfd_set_private_flags +@subsubsection @code{bfd_set_private_flags} +@strong{Synopsis} +@example +boolean bfd_set_private_flags(bfd *abfd, flagword flags); +@end example +@strong{Description}@* +Set private BFD flag information in the BFD @var{abfd}. +Return @code{true} on success, @code{false} on error. Possible error +returns are: + +@itemize @bullet + +@item +@code{bfd_error_no_memory} - +Not enough memory exists to create private data for @var{obfd}. +@end itemize +@example +#define bfd_set_private_flags(abfd, flags) \ + BFD_SEND (abfd, _bfd_set_private_flags, \ + (abfd, flags)) +@end example +@* +@findex stuff +@subsubsection @code{stuff} +@strong{Description}@* +Stuff which should be documented: +@example +#define bfd_sizeof_headers(abfd, reloc) \ + BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc)) + +#define bfd_find_nearest_line(abfd, sec, syms, off, file, func, line) \ + BFD_SEND (abfd, _bfd_find_nearest_line, (abfd, sec, syms, off, file, func, line)) + + /* Do these three do anything useful at all, for any back end? */ +#define bfd_debug_info_start(abfd) \ + BFD_SEND (abfd, _bfd_debug_info_start, (abfd)) + +#define bfd_debug_info_end(abfd) \ + BFD_SEND (abfd, _bfd_debug_info_end, (abfd)) + +#define bfd_debug_info_accumulate(abfd, section) \ + BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section)) + + +#define bfd_stat_arch_elt(abfd, stat) \ + BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat)) + +#define bfd_update_armap_timestamp(abfd) \ + BFD_SEND (abfd, _bfd_update_armap_timestamp, (abfd)) + +#define bfd_set_arch_mach(abfd, arch, mach)\ + BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach)) + +#define bfd_relax_section(abfd, section, link_info, again) \ + BFD_SEND (abfd, _bfd_relax_section, (abfd, section, link_info, again)) + +#define bfd_link_hash_table_create(abfd) \ + BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd)) + +#define bfd_link_add_symbols(abfd, info) \ + BFD_SEND (abfd, _bfd_link_add_symbols, (abfd, info)) + +#define bfd_final_link(abfd, info) \ + BFD_SEND (abfd, _bfd_final_link, (abfd, info)) + +#define bfd_free_cached_info(abfd) \ + BFD_SEND (abfd, _bfd_free_cached_info, (abfd)) + +#define bfd_get_dynamic_symtab_upper_bound(abfd) \ + BFD_SEND (abfd, _bfd_get_dynamic_symtab_upper_bound, (abfd)) + +#define bfd_print_private_bfd_data(abfd, file)\ + BFD_SEND (abfd, _bfd_print_private_bfd_data, (abfd, file)) + +#define bfd_canonicalize_dynamic_symtab(abfd, asymbols) \ + BFD_SEND (abfd, _bfd_canonicalize_dynamic_symtab, (abfd, asymbols)) + +#define bfd_get_dynamic_reloc_upper_bound(abfd) \ + BFD_SEND (abfd, _bfd_get_dynamic_reloc_upper_bound, (abfd)) + +#define bfd_canonicalize_dynamic_reloc(abfd, arels, asyms) \ + BFD_SEND (abfd, _bfd_canonicalize_dynamic_reloc, (abfd, arels, asyms)) + +extern bfd_byte *bfd_get_relocated_section_contents + PARAMS ((bfd *, struct bfd_link_info *, + struct bfd_link_order *, bfd_byte *, + boolean, asymbol **)); + +@end example +@* diff --git a/gnu/usr.bin/binutils/bfd/doc/cache.texi b/gnu/usr.bin/binutils/bfd/doc/cache.texi new file mode 100644 index 00000000000..badda349839 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/cache.texi @@ -0,0 +1,95 @@ +@section File caching +The file caching mechanism is embedded within BFD and allows +the application to open as many BFDs as it wants without +regard to the underlying operating system's file descriptor +limit (often as low as 20 open files). The module in +@code{cache.c} maintains a least recently used list of +@code{BFD_CACHE_MAX_OPEN} files, and exports the name +@code{bfd_cache_lookup}, which runs around and makes sure that +the required BFD is open. If not, then it chooses a file to +close, closes it and opens the one wanted, returning its file +handle. +@* +@findex BFD_CACHE_MAX_OPEN macro +@subsubsection @code{BFD_CACHE_MAX_OPEN macro} +@strong{Description}@* +The maximum number of files which the cache will keep open at +one time. +@example +#define BFD_CACHE_MAX_OPEN 10 +@end example +@* +@findex bfd_last_cache +@subsubsection @code{bfd_last_cache} +@strong{Synopsis} +@example +extern bfd *bfd_last_cache; +@end example +@strong{Description}@* +Zero, or a pointer to the topmost BFD on the chain. This is +used by the @code{bfd_cache_lookup} macro in @file{libbfd.h} to +determine when it can avoid a function call. +@* +@findex bfd_cache_lookup +@subsubsection @code{bfd_cache_lookup} +@strong{Description}@* +Check to see if the required BFD is the same as the last one +looked up. If so, then it can use the stream in the BFD with +impunity, since it can't have changed since the last lookup; +otherwise, it has to perform the complicated lookup function. +@example +#define bfd_cache_lookup(x) \ + ((x)==bfd_last_cache? \ + (FILE*)(bfd_last_cache->iostream): \ + bfd_cache_lookup_worker(x)) +@end example +@* +@findex bfd_cache_init +@subsubsection @code{bfd_cache_init} +@strong{Synopsis} +@example +boolean bfd_cache_init (bfd *abfd); +@end example +@strong{Description}@* +Add a newly opened BFD to the cache. +@* +@findex bfd_cache_close +@subsubsection @code{bfd_cache_close} +@strong{Synopsis} +@example +boolean bfd_cache_close (bfd *abfd); +@end example +@strong{Description}@* +Remove the BFD @var{abfd} from the cache. If the attached file is open, +then close it too. +@* +@strong{Returns}@* +@code{false} is returned if closing the file fails, @code{true} is +returned if all is well. +@* +@findex bfd_open_file +@subsubsection @code{bfd_open_file} +@strong{Synopsis} +@example +FILE* bfd_open_file(bfd *abfd); +@end example +@strong{Description}@* +Call the OS to open a file for @var{abfd}. Return the @code{FILE *} +(possibly @code{NULL}) that results from this operation. Set up the +BFD so that future accesses know the file is open. If the @code{FILE *} +returned is @code{NULL}, then it won't have been put in the +cache, so it won't have to be removed from it. +@* +@findex bfd_cache_lookup_worker +@subsubsection @code{bfd_cache_lookup_worker} +@strong{Synopsis} +@example +FILE *bfd_cache_lookup_worker(bfd *abfd); +@end example +@strong{Description}@* +Called when the macro @code{bfd_cache_lookup} fails to find a +quick answer. Find a file descriptor for @var{abfd}. If +necessary, it open it. If there are already more than +@code{BFD_CACHE_MAX_OPEN} files open, it tries to close one first, to +avoid running out of file descriptors. +@* diff --git a/gnu/usr.bin/binutils/bfd/doc/coffcode.texi b/gnu/usr.bin/binutils/bfd/doc/coffcode.texi new file mode 100644 index 00000000000..5c3d546bef7 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/coffcode.texi @@ -0,0 +1,627 @@ +@section coff backends +BFD supports a number of different flavours of coff format. +The major differences between formats are the sizes and +alignments of fields in structures on disk, and the occasional +extra field. + +Coff in all its varieties is implemented with a few common +files and a number of implementation specific files. For +example, The 88k bcs coff format is implemented in the file +@file{coff-m88k.c}. This file @code{#include}s +@file{coff/m88k.h} which defines the external structure of the +coff format for the 88k, and @file{coff/internal.h} which +defines the internal structure. @file{coff-m88k.c} also +defines the relocations used by the 88k format +@xref{Relocations}. + +The Intel i960 processor version of coff is implemented in +@file{coff-i960.c}. This file has the same structure as +@file{coff-m88k.c}, except that it includes @file{coff/i960.h} +rather than @file{coff-m88k.h}. +@* +@subsection Porting to a new version of coff +The recommended method is to select from the existing +implementations the version of coff which is most like the one +you want to use. For example, we'll say that i386 coff is +the one you select, and that your coff flavour is called foo. +Copy @file{i386coff.c} to @file{foocoff.c}, copy +@file{../include/coff/i386.h} to @file{../include/coff/foo.h}, +and add the lines to @file{targets.c} and @file{Makefile.in} +so that your new back end is used. Alter the shapes of the +structures in @file{../include/coff/foo.h} so that they match +what you need. You will probably also have to add +@code{#ifdef}s to the code in @file{coff/internal.h} and +@file{coffcode.h} if your version of coff is too wild. + +You can verify that your new BFD backend works quite simply by +building @file{objdump} from the @file{binutils} directory, +and making sure that its version of what's going on and your +host system's idea (assuming it has the pretty standard coff +dump utility, usually called @code{att-dump} or just +@code{dump}) are the same. Then clean up your code, and send +what you've done to Cygnus. Then your stuff will be in the +next release, and you won't have to keep integrating it. +@* +@subsection How the coff backend works + +@* +@subsubsection File layout +The Coff backend is split into generic routines that are +applicable to any Coff target and routines that are specific +to a particular target. The target-specific routines are +further split into ones which are basically the same for all +Coff targets except that they use the external symbol format +or use different values for certain constants. + +The generic routines are in @file{coffgen.c}. These routines +work for any Coff target. They use some hooks into the target +specific code; the hooks are in a @code{bfd_coff_backend_data} +structure, one of which exists for each target. + +The essentially similar target-specific routines are in +@file{coffcode.h}. This header file includes executable C code. +The various Coff targets first include the appropriate Coff +header file, make any special defines that are needed, and +then include @file{coffcode.h}. + +Some of the Coff targets then also have additional routines in +the target source file itself. + +For example, @file{coff-i960.c} includes +@file{coff/internal.h} and @file{coff/i960.h}. It then +defines a few constants, such as @code{I960}, and includes +@file{coffcode.h}. Since the i960 has complex relocation +types, @file{coff-i960.c} also includes some code to +manipulate the i960 relocs. This code is not in +@file{coffcode.h} because it would not be used by any other +target. +@* +@subsubsection Bit twiddling +Each flavour of coff supported in BFD has its own header file +describing the external layout of the structures. There is also +an internal description of the coff layout, in +@file{coff/internal.h}. A major function of the +coff backend is swapping the bytes and twiddling the bits to +translate the external form of the structures into the normal +internal form. This is all performed in the +@code{bfd_swap}_@i{thing}_@i{direction} routines. Some +elements are different sizes between different versions of +coff; it is the duty of the coff version specific include file +to override the definitions of various packing routines in +@file{coffcode.h}. E.g., the size of line number entry in coff is +sometimes 16 bits, and sometimes 32 bits. @code{#define}ing +@code{PUT_LNSZ_LNNO} and @code{GET_LNSZ_LNNO} will select the +correct one. No doubt, some day someone will find a version of +coff which has a varying field size not catered to at the +moment. To port BFD, that person will have to add more @code{#defines}. +Three of the bit twiddling routines are exported to +@code{gdb}; @code{coff_swap_aux_in}, @code{coff_swap_sym_in} +and @code{coff_swap_linno_in}. @code{GDB} reads the symbol +table on its own, but uses BFD to fix things up. More of the +bit twiddlers are exported for @code{gas}; +@code{coff_swap_aux_out}, @code{coff_swap_sym_out}, +@code{coff_swap_lineno_out}, @code{coff_swap_reloc_out}, +@code{coff_swap_filehdr_out}, @code{coff_swap_aouthdr_out}, +@code{coff_swap_scnhdr_out}. @code{Gas} currently keeps track +of all the symbol table and reloc drudgery itself, thereby +saving the internal BFD overhead, but uses BFD to swap things +on the way out, making cross ports much safer. Doing so also +allows BFD (and thus the linker) to use the same header files +as @code{gas}, which makes one avenue to disaster disappear. +@* +@subsubsection Symbol reading +The simple canonical form for symbols used by BFD is not rich +enough to keep all the information available in a coff symbol +table. The back end gets around this problem by keeping the original +symbol table around, "behind the scenes". + +When a symbol table is requested (through a call to +@code{bfd_canonicalize_symtab}), a request gets through to +@code{coff_get_normalized_symtab}. This reads the symbol table from +the coff file and swaps all the structures inside into the +internal form. It also fixes up all the pointers in the table +(represented in the file by offsets from the first symbol in +the table) into physical pointers to elements in the new +internal table. This involves some work since the meanings of +fields change depending upon context: a field that is a +pointer to another structure in the symbol table at one moment +may be the size in bytes of a structure at the next. Another +pass is made over the table. All symbols which mark file names +(@code{C_FILE} symbols) are modified so that the internal +string points to the value in the auxent (the real filename) +rather than the normal text associated with the symbol +(@code{".file"}). + +At this time the symbol names are moved around. Coff stores +all symbols less than nine characters long physically +within the symbol table; longer strings are kept at the end of +the file in the string table. This pass moves all strings +into memory and replaces them with pointers to the strings. + +The symbol table is massaged once again, this time to create +the canonical table used by the BFD application. Each symbol +is inspected in turn, and a decision made (using the +@code{sclass} field) about the various flags to set in the +@code{asymbol}. @xref{Symbols}. The generated canonical table +shares strings with the hidden internal symbol table. + +Any linenumbers are read from the coff file too, and attached +to the symbols which own the functions the linenumbers belong to. +@* +@subsubsection Symbol writing +Writing a symbol to a coff file which didn't come from a coff +file will lose any debugging information. The @code{asymbol} +structure remembers the BFD from which the symbol was taken, and on +output the back end makes sure that the same destination target as +source target is present. + +When the symbols have come from a coff file then all the +debugging information is preserved. + +Symbol tables are provided for writing to the back end in a +vector of pointers to pointers. This allows applications like +the linker to accumulate and output large symbol tables +without having to do too much byte copying. + +This function runs through the provided symbol table and +patches each symbol marked as a file place holder +(@code{C_FILE}) to point to the next file place holder in the +list. It also marks each @code{offset} field in the list with +the offset from the first symbol of the current symbol. + +Another function of this procedure is to turn the canonical +value form of BFD into the form used by coff. Internally, BFD +expects symbol values to be offsets from a section base; so a +symbol physically at 0x120, but in a section starting at +0x100, would have the value 0x20. Coff expects symbols to +contain their final value, so symbols have their values +changed at this point to reflect their sum with their owning +section. This transformation uses the +@code{output_section} field of the @code{asymbol}'s +@code{asection} @xref{Sections}. + +@itemize @bullet + +@item +@code{coff_mangle_symbols} +@end itemize +This routine runs though the provided symbol table and uses +the offsets generated by the previous pass and the pointers +generated when the symbol table was read in to create the +structured hierachy required by coff. It changes each pointer +to a symbol into the index into the symbol table of the asymbol. + +@itemize @bullet + +@item +@code{coff_write_symbols} +@end itemize +This routine runs through the symbol table and patches up the +symbols from their internal form into the coff way, calls the +bit twiddlers, and writes out the table to the file. +@* +@findex coff_symbol_type +@subsubsection @code{coff_symbol_type} +@strong{Description}@* +The hidden information for an @code{asymbol} is described in a +@code{combined_entry_type}: +@* +. +@example +typedef struct coff_ptr_struct +@{ + + /* Remembers the offset from the first symbol in the file for + this symbol. Generated by coff_renumber_symbols. */ +unsigned int offset; + + /* Should the value of this symbol be renumbered. Used for + XCOFF C_BSTAT symbols. Set by coff_slurp_symbol_table. */ +unsigned int fix_value : 1; + + /* Should the tag field of this symbol be renumbered. + Created by coff_pointerize_aux. */ +unsigned int fix_tag : 1; + + /* Should the endidx field of this symbol be renumbered. + Created by coff_pointerize_aux. */ +unsigned int fix_end : 1; + + /* Should the x_csect.x_scnlen field be renumbered. + Created by coff_pointerize_aux. */ +unsigned int fix_scnlen : 1; + + /* Fix up an XCOFF C_BINCL/C_EINCL symbol. The value is the + index into the line number entries. Set by + coff_slurp_symbol_table. */ +unsigned int fix_line : 1; + + /* The container for the symbol structure as read and translated + from the file. */ + +union @{ + union internal_auxent auxent; + struct internal_syment syment; + @} u; +@} combined_entry_type; + + +/* Each canonical asymbol really looks like this: */ + +typedef struct coff_symbol_struct +@{ + /* The actual symbol which the rest of BFD works with */ +asymbol symbol; + + /* A pointer to the hidden information for this symbol */ +combined_entry_type *native; + + /* A pointer to the linenumber information for this symbol */ +struct lineno_cache_entry *lineno; + + /* Have the line numbers been relocated yet ? */ +boolean done_lineno; +@} coff_symbol_type; +@end example +@findex bfd_coff_backend_data +@subsubsection @code{bfd_coff_backend_data} +Special entry points for gdb to swap in coff symbol table parts: +@example +typedef struct +@{ + void (*_bfd_coff_swap_aux_in) PARAMS (( + bfd *abfd, + PTR ext, + int type, + int class, + int indaux, + int numaux, + PTR in)); + + void (*_bfd_coff_swap_sym_in) PARAMS (( + bfd *abfd , + PTR ext, + PTR in)); + + void (*_bfd_coff_swap_lineno_in) PARAMS (( + bfd *abfd, + PTR ext, + PTR in)); + +@end example +Special entry points for gas to swap out coff parts: +@example + unsigned int (*_bfd_coff_swap_aux_out) PARAMS (( + bfd *abfd, + PTR in, + int type, + int class, + int indaux, + int numaux, + PTR ext)); + + unsigned int (*_bfd_coff_swap_sym_out) PARAMS (( + bfd *abfd, + PTR in, + PTR ext)); + + unsigned int (*_bfd_coff_swap_lineno_out) PARAMS (( + bfd *abfd, + PTR in, + PTR ext)); + + unsigned int (*_bfd_coff_swap_reloc_out) PARAMS (( + bfd *abfd, + PTR src, + PTR dst)); + + unsigned int (*_bfd_coff_swap_filehdr_out) PARAMS (( + bfd *abfd, + PTR in, + PTR out)); + + unsigned int (*_bfd_coff_swap_aouthdr_out) PARAMS (( + bfd *abfd, + PTR in, + PTR out)); + + unsigned int (*_bfd_coff_swap_scnhdr_out) PARAMS (( + bfd *abfd, + PTR in, + PTR out)); + +@end example +Special entry points for generic COFF routines to call target +dependent COFF routines: +@example + unsigned int _bfd_filhsz; + unsigned int _bfd_aoutsz; + unsigned int _bfd_scnhsz; + unsigned int _bfd_symesz; + unsigned int _bfd_auxesz; + unsigned int _bfd_relsz; + unsigned int _bfd_linesz; + boolean _bfd_coff_long_filenames; + boolean _bfd_coff_long_section_names; + unsigned int _bfd_coff_default_section_alignment_power; + void (*_bfd_coff_swap_filehdr_in) PARAMS (( + bfd *abfd, + PTR ext, + PTR in)); + void (*_bfd_coff_swap_aouthdr_in) PARAMS (( + bfd *abfd, + PTR ext, + PTR in)); + void (*_bfd_coff_swap_scnhdr_in) PARAMS (( + bfd *abfd, + PTR ext, + PTR in)); + void (*_bfd_coff_swap_reloc_in) PARAMS (( + bfd *abfd, + PTR ext, + PTR in)); + boolean (*_bfd_coff_bad_format_hook) PARAMS (( + bfd *abfd, + PTR internal_filehdr)); + boolean (*_bfd_coff_set_arch_mach_hook) PARAMS (( + bfd *abfd, + PTR internal_filehdr)); + PTR (*_bfd_coff_mkobject_hook) PARAMS (( + bfd *abfd, + PTR internal_filehdr, + PTR internal_aouthdr)); + flagword (*_bfd_styp_to_sec_flags_hook) PARAMS (( + bfd *abfd, + PTR internal_scnhdr, + const char *name)); + void (*_bfd_set_alignment_hook) PARAMS (( + bfd *abfd, + asection *sec, + PTR internal_scnhdr)); + boolean (*_bfd_coff_slurp_symbol_table) PARAMS (( + bfd *abfd)); + boolean (*_bfd_coff_symname_in_debug) PARAMS (( + bfd *abfd, + struct internal_syment *sym)); + boolean (*_bfd_coff_pointerize_aux_hook) PARAMS (( + bfd *abfd, + combined_entry_type *table_base, + combined_entry_type *symbol, + unsigned int indaux, + combined_entry_type *aux)); + boolean (*_bfd_coff_print_aux) PARAMS (( + bfd *abfd, + FILE *file, + combined_entry_type *table_base, + combined_entry_type *symbol, + combined_entry_type *aux, + unsigned int indaux)); + void (*_bfd_coff_reloc16_extra_cases) PARAMS (( + bfd *abfd, + struct bfd_link_info *link_info, + struct bfd_link_order *link_order, + arelent *reloc, + bfd_byte *data, + unsigned int *src_ptr, + unsigned int *dst_ptr)); + int (*_bfd_coff_reloc16_estimate) PARAMS (( + bfd *abfd, + asection *input_section, + arelent *r, + unsigned int shrink, + struct bfd_link_info *link_info)); + boolean (*_bfd_coff_sym_is_global) PARAMS (( + bfd *abfd, + struct internal_syment *)); + boolean (*_bfd_coff_compute_section_file_positions) PARAMS (( + bfd *abfd)); + boolean (*_bfd_coff_start_final_link) PARAMS (( + bfd *output_bfd, + struct bfd_link_info *info)); + boolean (*_bfd_coff_relocate_section) PARAMS (( + bfd *output_bfd, + struct bfd_link_info *info, + bfd *input_bfd, + asection *input_section, + bfd_byte *contents, + struct internal_reloc *relocs, + struct internal_syment *syms, + asection **sections)); + reloc_howto_type *(*_bfd_coff_rtype_to_howto) PARAMS (( + bfd *abfd, + asection *sec, + struct internal_reloc *rel, + struct coff_link_hash_entry *h, + struct internal_syment *sym, + bfd_vma *addendp)); + boolean (*_bfd_coff_adjust_symndx) PARAMS (( + bfd *obfd, + struct bfd_link_info *info, + bfd *ibfd, + asection *sec, + struct internal_reloc *reloc, + boolean *adjustedp)); + boolean (*_bfd_coff_link_add_one_symbol) PARAMS (( + struct bfd_link_info *info, + bfd *abfd, + const char *name, + flagword flags, + asection *section, + bfd_vma value, + const char *string, + boolean copy, + boolean collect, + struct bfd_link_hash_entry **hashp)); + +@} bfd_coff_backend_data; + +#define coff_backend_info(abfd) ((bfd_coff_backend_data *) (abfd)->xvec->backend_data) + +#define bfd_coff_swap_aux_in(a,e,t,c,ind,num,i) \ + ((coff_backend_info (a)->_bfd_coff_swap_aux_in) (a,e,t,c,ind,num,i)) + +#define bfd_coff_swap_sym_in(a,e,i) \ + ((coff_backend_info (a)->_bfd_coff_swap_sym_in) (a,e,i)) + +#define bfd_coff_swap_lineno_in(a,e,i) \ + ((coff_backend_info ( a)->_bfd_coff_swap_lineno_in) (a,e,i)) + +#define bfd_coff_swap_reloc_out(abfd, i, o) \ + ((coff_backend_info (abfd)->_bfd_coff_swap_reloc_out) (abfd, i, o)) + +#define bfd_coff_swap_lineno_out(abfd, i, o) \ + ((coff_backend_info (abfd)->_bfd_coff_swap_lineno_out) (abfd, i, o)) + +#define bfd_coff_swap_aux_out(a,i,t,c,ind,num,o) \ + ((coff_backend_info (a)->_bfd_coff_swap_aux_out) (a,i,t,c,ind,num,o)) + +#define bfd_coff_swap_sym_out(abfd, i,o) \ + ((coff_backend_info (abfd)->_bfd_coff_swap_sym_out) (abfd, i, o)) + +#define bfd_coff_swap_scnhdr_out(abfd, i,o) \ + ((coff_backend_info (abfd)->_bfd_coff_swap_scnhdr_out) (abfd, i, o)) + +#define bfd_coff_swap_filehdr_out(abfd, i,o) \ + ((coff_backend_info (abfd)->_bfd_coff_swap_filehdr_out) (abfd, i, o)) + +#define bfd_coff_swap_aouthdr_out(abfd, i,o) \ + ((coff_backend_info (abfd)->_bfd_coff_swap_aouthdr_out) (abfd, i, o)) + +#define bfd_coff_filhsz(abfd) (coff_backend_info (abfd)->_bfd_filhsz) +#define bfd_coff_aoutsz(abfd) (coff_backend_info (abfd)->_bfd_aoutsz) +#define bfd_coff_scnhsz(abfd) (coff_backend_info (abfd)->_bfd_scnhsz) +#define bfd_coff_symesz(abfd) (coff_backend_info (abfd)->_bfd_symesz) +#define bfd_coff_auxesz(abfd) (coff_backend_info (abfd)->_bfd_auxesz) +#define bfd_coff_relsz(abfd) (coff_backend_info (abfd)->_bfd_relsz) +#define bfd_coff_linesz(abfd) (coff_backend_info (abfd)->_bfd_linesz) +#define bfd_coff_long_filenames(abfd) (coff_backend_info (abfd)->_bfd_coff_long_filenames) +#define bfd_coff_long_section_names(abfd) \ + (coff_backend_info (abfd)->_bfd_coff_long_section_names) +#define bfd_coff_default_section_alignment_power(abfd) \ + (coff_backend_info (abfd)->_bfd_coff_default_section_alignment_power) +#define bfd_coff_swap_filehdr_in(abfd, i,o) \ + ((coff_backend_info (abfd)->_bfd_coff_swap_filehdr_in) (abfd, i, o)) + +#define bfd_coff_swap_aouthdr_in(abfd, i,o) \ + ((coff_backend_info (abfd)->_bfd_coff_swap_aouthdr_in) (abfd, i, o)) + +#define bfd_coff_swap_scnhdr_in(abfd, i,o) \ + ((coff_backend_info (abfd)->_bfd_coff_swap_scnhdr_in) (abfd, i, o)) + +#define bfd_coff_swap_reloc_in(abfd, i, o) \ + ((coff_backend_info (abfd)->_bfd_coff_swap_reloc_in) (abfd, i, o)) + +#define bfd_coff_bad_format_hook(abfd, filehdr) \ + ((coff_backend_info (abfd)->_bfd_coff_bad_format_hook) (abfd, filehdr)) + +#define bfd_coff_set_arch_mach_hook(abfd, filehdr)\ + ((coff_backend_info (abfd)->_bfd_coff_set_arch_mach_hook) (abfd, filehdr)) +#define bfd_coff_mkobject_hook(abfd, filehdr, aouthdr)\ + ((coff_backend_info (abfd)->_bfd_coff_mkobject_hook) (abfd, filehdr, aouthdr)) + +#define bfd_coff_styp_to_sec_flags_hook(abfd, scnhdr, name)\ + ((coff_backend_info (abfd)->_bfd_styp_to_sec_flags_hook) (abfd, scnhdr, name)) + +#define bfd_coff_set_alignment_hook(abfd, sec, scnhdr)\ + ((coff_backend_info (abfd)->_bfd_set_alignment_hook) (abfd, sec, scnhdr)) + +#define bfd_coff_slurp_symbol_table(abfd)\ + ((coff_backend_info (abfd)->_bfd_coff_slurp_symbol_table) (abfd)) + +#define bfd_coff_symname_in_debug(abfd, sym)\ + ((coff_backend_info (abfd)->_bfd_coff_symname_in_debug) (abfd, sym)) + +#define bfd_coff_print_aux(abfd, file, base, symbol, aux, indaux)\ + ((coff_backend_info (abfd)->_bfd_coff_print_aux)\ + (abfd, file, base, symbol, aux, indaux)) + +#define bfd_coff_reloc16_extra_cases(abfd, link_info, link_order, reloc, data, src_ptr, dst_ptr)\ + ((coff_backend_info (abfd)->_bfd_coff_reloc16_extra_cases)\ + (abfd, link_info, link_order, reloc, data, src_ptr, dst_ptr)) + +#define bfd_coff_reloc16_estimate(abfd, section, reloc, shrink, link_info)\ + ((coff_backend_info (abfd)->_bfd_coff_reloc16_estimate)\ + (abfd, section, reloc, shrink, link_info)) + +#define bfd_coff_sym_is_global(abfd, sym)\ + ((coff_backend_info (abfd)->_bfd_coff_sym_is_global)\ + (abfd, sym)) + +#define bfd_coff_compute_section_file_positions(abfd)\ + ((coff_backend_info (abfd)->_bfd_coff_compute_section_file_positions)\ + (abfd)) + +#define bfd_coff_start_final_link(obfd, info)\ + ((coff_backend_info (obfd)->_bfd_coff_start_final_link)\ + (obfd, info)) +#define bfd_coff_relocate_section(obfd,info,ibfd,o,con,rel,isyms,secs)\ + ((coff_backend_info (ibfd)->_bfd_coff_relocate_section)\ + (obfd, info, ibfd, o, con, rel, isyms, secs)) +#define bfd_coff_rtype_to_howto(abfd, sec, rel, h, sym, addendp)\ + ((coff_backend_info (abfd)->_bfd_coff_rtype_to_howto)\ + (abfd, sec, rel, h, sym, addendp)) +#define bfd_coff_adjust_symndx(obfd, info, ibfd, sec, rel, adjustedp)\ + ((coff_backend_info (abfd)->_bfd_coff_adjust_symndx)\ + (obfd, info, ibfd, sec, rel, adjustedp)) +#define bfd_coff_link_add_one_symbol(info,abfd,name,flags,section,value,string,cp,coll,hashp)\ + ((coff_backend_info (abfd)->_bfd_coff_link_add_one_symbol)\ + (info, abfd, name, flags, section, value, string, cp, coll, hashp)) + +@end example +@subsubsection Writing relocations +To write relocations, the back end steps though the +canonical relocation table and create an +@code{internal_reloc}. The symbol index to use is removed from +the @code{offset} field in the symbol table supplied. The +address comes directly from the sum of the section base +address and the relocation offset; the type is dug directly +from the howto field. Then the @code{internal_reloc} is +swapped into the shape of an @code{external_reloc} and written +out to disk. +@* +@subsubsection Reading linenumbers +Creating the linenumber table is done by reading in the entire +coff linenumber table, and creating another table for internal use. + +A coff linenumber table is structured so that each function +is marked as having a line number of 0. Each line within the +function is an offset from the first line in the function. The +base of the line number information for the table is stored in +the symbol associated with the function. + +The information is copied from the external to the internal +table, and each symbol which marks a function is marked by +pointing its... + +How does this work ? +@* +@subsubsection Reading relocations +Coff relocations are easily transformed into the internal BFD form +(@code{arelent}). + +Reading a coff relocation table is done in the following stages: + +@itemize @bullet + +@item +Read the entire coff relocation table into memory. + +@item +Process each relocation in turn; first swap it from the +external to the internal form. + +@item +Turn the symbol referenced in the relocation's symbol index +into a pointer into the canonical symbol table. +This table is the same as the one returned by a call to +@code{bfd_canonicalize_symtab}. The back end will call that +routine and save the result if a canonicalization hasn't been done. + +@item +The reloc index is turned into a pointer to a howto +structure, in a back end specific way. For instance, the 386 +and 960 use the @code{r_type} to directly produce an index +into a howto table vector; the 88k subtracts a number from the +@code{r_type} field and creates an addend field. +@end itemize +@* diff --git a/gnu/usr.bin/binutils/bfd/doc/core.texi b/gnu/usr.bin/binutils/bfd/doc/core.texi new file mode 100644 index 00000000000..841daa920f8 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/core.texi @@ -0,0 +1,38 @@ +@section Core files + +@* +@strong{Description}@* +These are functions pertaining to core files. +@* +@findex bfd_core_file_failing_command +@subsubsection @code{bfd_core_file_failing_command} +@strong{Synopsis} +@example +CONST char *bfd_core_file_failing_command(bfd *abfd); +@end example +@strong{Description}@* +Return a read-only string explaining which program was running +when it failed and produced the core file @var{abfd}. +@* +@findex bfd_core_file_failing_signal +@subsubsection @code{bfd_core_file_failing_signal} +@strong{Synopsis} +@example +int bfd_core_file_failing_signal(bfd *abfd); +@end example +@strong{Description}@* +Returns the signal number which caused the core dump which +generated the file the BFD @var{abfd} is attached to. +@* +@findex core_file_matches_executable_p +@subsubsection @code{core_file_matches_executable_p} +@strong{Synopsis} +@example +boolean core_file_matches_executable_p + (bfd *core_bfd, bfd *exec_bfd); +@end example +@strong{Description}@* +Return @code{true} if the core file attached to @var{core_bfd} +was generated by a run of the executable file attached to +@var{exec_bfd}, @code{false} otherwise. +@* diff --git a/gnu/usr.bin/binutils/bfd/doc/elf.texi b/gnu/usr.bin/binutils/bfd/doc/elf.texi new file mode 100644 index 00000000000..673654c51ac --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/elf.texi @@ -0,0 +1,22 @@ +@section ELF backends +BFD support for ELF formats is being worked on. +Currently, the best supported back ends are for sparc and i386 +(running svr4 or Solaris 2). + +Documentation of the internals of the support code still needs +to be written. The code is changing quickly enough that we +haven't bothered yet. +@* +@findex bfd_elf_find_section +@subsubsection @code{bfd_elf_find_section} +@strong{Synopsis} +@example +struct elf_internal_shdr *bfd_elf_find_section (bfd *abfd, char *name); +@end example +@strong{Description}@* +Helper functions for GDB to locate the string tables. +Since BFD hides string tables from callers, GDB needs to use an +internal hook to find them. Sun's .stabstr, in particular, +isn't even pointed to by the .stab section, so ordinary +mechanisms wouldn't work to find it, even if we had some. +@* diff --git a/gnu/usr.bin/binutils/bfd/doc/elfcode.texi b/gnu/usr.bin/binutils/bfd/doc/elfcode.texi new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/elfcode.texi diff --git a/gnu/usr.bin/binutils/bfd/doc/format.texi b/gnu/usr.bin/binutils/bfd/doc/format.texi new file mode 100644 index 00000000000..d30a41b7ce2 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/format.texi @@ -0,0 +1,108 @@ +@section File formats +A format is a BFD concept of high level file contents type. The +formats supported by BFD are: + +@itemize @bullet + +@item +@code{bfd_object} +@end itemize +The BFD may contain data, symbols, relocations and debug info. + +@itemize @bullet + +@item +@code{bfd_archive} +@end itemize +The BFD contains other BFDs and an optional index. + +@itemize @bullet + +@item +@code{bfd_core} +@end itemize +The BFD contains the result of an executable core dump. +@* +@findex bfd_check_format +@subsubsection @code{bfd_check_format} +@strong{Synopsis} +@example +boolean bfd_check_format(bfd *abfd, bfd_format format); +@end example +@strong{Description}@* +Verify if the file attached to the BFD @var{abfd} is compatible +with the format @var{format} (i.e., one of @code{bfd_object}, +@code{bfd_archive} or @code{bfd_core}). + +If the BFD has been set to a specific target before the +call, only the named target and format combination is +checked. If the target has not been set, or has been set to +@code{default}, then all the known target backends is +interrogated to determine a match. If the default target +matches, it is used. If not, exactly one target must recognize +the file, or an error results. + +The function returns @code{true} on success, otherwise @code{false} +with one of the following error codes: + +@itemize @bullet + +@item +@code{bfd_error_invalid_operation} - +if @code{format} is not one of @code{bfd_object}, @code{bfd_archive} or +@code{bfd_core}. + +@item +@code{bfd_error_system_call} - +if an error occured during a read - even some file mismatches +can cause bfd_error_system_calls. + +@item +@code{file_not_recognised} - +none of the backends recognised the file format. + +@item +@code{bfd_error_file_ambiguously_recognized} - +more than one backend recognised the file format. +@end itemize +@* +@findex bfd_check_format_matches +@subsubsection @code{bfd_check_format_matches} +@strong{Synopsis} +@example +boolean bfd_check_format_matches(bfd *abfd, bfd_format format, char ***matching); +@end example +@strong{Description}@* +Like @code{bfd_check_format}, except when it returns false with +@code{bfd_errno} set to @code{bfd_error_file_ambiguously_recognized}. In that +case, if @var{matching} is not NULL, it will be filled in with +a NULL-terminated list of the names of the formats that matched, +allocated with @code{malloc}. +Then the user may choose a format and try again. + +When done with the list that @var{matching} points to, the caller +should free it. +@* +@findex bfd_set_format +@subsubsection @code{bfd_set_format} +@strong{Synopsis} +@example +boolean bfd_set_format(bfd *abfd, bfd_format format); +@end example +@strong{Description}@* +This function sets the file format of the BFD @var{abfd} to the +format @var{format}. If the target set in the BFD does not +support the format requested, the format is invalid, or the BFD +is not open for writing, then an error occurs. +@* +@findex bfd_format_string +@subsubsection @code{bfd_format_string} +@strong{Synopsis} +@example +CONST char *bfd_format_string(bfd_format format); +@end example +@strong{Description}@* +Return a pointer to a const string +@code{invalid}, @code{object}, @code{archive}, @code{core}, or @code{unknown}, +depending upon the value of @var{format}. +@* diff --git a/gnu/usr.bin/binutils/bfd/doc/hash.texi b/gnu/usr.bin/binutils/bfd/doc/hash.texi new file mode 100644 index 00000000000..4147ce4f8cf --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/hash.texi @@ -0,0 +1,244 @@ +@section Hash Tables +@cindex Hash tables +BFD provides a simple set of hash table functions. Routines +are provided to initialize a hash table, to free a hash table, +to look up a string in a hash table and optionally create an +entry for it, and to traverse a hash table. There is +currently no routine to delete an string from a hash table. + +The basic hash table does not permit any data to be stored +with a string. However, a hash table is designed to present a +base class from which other types of hash tables may be +derived. These derived types may store additional information +with the string. Hash tables were implemented in this way, +rather than simply providing a data pointer in a hash table +entry, because they were designed for use by the linker back +ends. The linker may create thousands of hash table entries, +and the overhead of allocating private data and storing and +following pointers becomes noticeable. + +The basic hash table code is in @code{hash.c}. + +@menu +* Creating and Freeing a Hash Table:: +* Looking Up or Entering a String:: +* Traversing a Hash Table:: +* Deriving a New Hash Table Type:: +@end menu +@* +@node Creating and Freeing a Hash Table, Looking Up or Entering a String, Hash Tables, Hash Tables +@subsection Creating and freeing a hash table +@findex bfd_hash_table_init +@findex bfd_hash_table_init_n +To create a hash table, create an instance of a @code{struct +bfd_hash_table} (defined in @code{bfd.h}) and call +@code{bfd_hash_table_init} (if you know approximately how many +entries you will need, the function @code{bfd_hash_table_init_n}, +which takes a @var{size} argument, may be used). +@code{bfd_hash_table_init} returns @code{false} if some sort of +error occurs. + +@findex bfd_hash_newfunc +The function @code{bfd_hash_table_init} take as an argument a +function to use to create new entries. For a basic hash +table, use the function @code{bfd_hash_newfunc}. @xref{Deriving +a New Hash Table Type} for why you would want to use a +different value for this argument. + +@findex bfd_hash_allocate +@code{bfd_hash_table_init} will create an objalloc which will be +used to allocate new entries. You may allocate memory on this +objalloc using @code{bfd_hash_allocate}. + +@findex bfd_hash_table_free +Use @code{bfd_hash_table_free} to free up all the memory that has +been allocated for a hash table. This will not free up the +@code{struct bfd_hash_table} itself, which you must provide. +@* +@node Looking Up or Entering a String, Traversing a Hash Table, Creating and Freeing a Hash Table, Hash Tables +@subsection Looking up or entering a string +@findex bfd_hash_lookup +The function @code{bfd_hash_lookup} is used both to look up a +string in the hash table and to create a new entry. + +If the @var{create} argument is @code{false}, @code{bfd_hash_lookup} +will look up a string. If the string is found, it will +returns a pointer to a @code{struct bfd_hash_entry}. If the +string is not found in the table @code{bfd_hash_lookup} will +return @code{NULL}. You should not modify any of the fields in +the returns @code{struct bfd_hash_entry}. + +If the @var{create} argument is @code{true}, the string will be +entered into the hash table if it is not already there. +Either way a pointer to a @code{struct bfd_hash_entry} will be +returned, either to the existing structure or to a newly +created one. In this case, a @code{NULL} return means that an +error occurred. + +If the @var{create} argument is @code{true}, and a new entry is +created, the @var{copy} argument is used to decide whether to +copy the string onto the hash table objalloc or not. If +@var{copy} is passed as @code{false}, you must be careful not to +deallocate or modify the string as long as the hash table +exists. +@* +@node Traversing a Hash Table, Deriving a New Hash Table Type, Looking Up or Entering a String, Hash Tables +@subsection Traversing a hash table +@findex bfd_hash_traverse +The function @code{bfd_hash_traverse} may be used to traverse a +hash table, calling a function on each element. The traversal +is done in a random order. + +@code{bfd_hash_traverse} takes as arguments a function and a +generic @code{void *} pointer. The function is called with a +hash table entry (a @code{struct bfd_hash_entry *}) and the +generic pointer passed to @code{bfd_hash_traverse}. The function +must return a @code{boolean} value, which indicates whether to +continue traversing the hash table. If the function returns +@code{false}, @code{bfd_hash_traverse} will stop the traversal and +return immediately. +@* +@node Deriving a New Hash Table Type, , Traversing a Hash Table, Hash Tables +@subsection Deriving a new hash table type +Many uses of hash tables want to store additional information +which each entry in the hash table. Some also find it +convenient to store additional information with the hash table +itself. This may be done using a derived hash table. + +Since C is not an object oriented language, creating a derived +hash table requires sticking together some boilerplate +routines with a few differences specific to the type of hash +table you want to create. + +An example of a derived hash table is the linker hash table. +The structures for this are defined in @code{bfdlink.h}. The +functions are in @code{linker.c}. + +You may also derive a hash table from an already derived hash +table. For example, the a.out linker backend code uses a hash +table derived from the linker hash table. + +@menu +* Define the Derived Structures:: +* Write the Derived Creation Routine:: +* Write Other Derived Routines:: +@end menu +@* +@node Define the Derived Structures, Write the Derived Creation Routine, Deriving a New Hash Table Type, Deriving a New Hash Table Type +@subsubsection Define the derived structures +You must define a structure for an entry in the hash table, +and a structure for the hash table itself. + +The first field in the structure for an entry in the hash +table must be of the type used for an entry in the hash table +you are deriving from. If you are deriving from a basic hash +table this is @code{struct bfd_hash_entry}, which is defined in +@code{bfd.h}. The first field in the structure for the hash +table itself must be of the type of the hash table you are +deriving from itself. If you are deriving from a basic hash +table, this is @code{struct bfd_hash_table}. + +For example, the linker hash table defines @code{struct +bfd_link_hash_entry} (in @code{bfdlink.h}). The first field, +@code{root}, is of type @code{struct bfd_hash_entry}. Similarly, +the first field in @code{struct bfd_link_hash_table}, @code{table}, +is of type @code{struct bfd_hash_table}. +@* +@node Write the Derived Creation Routine, Write Other Derived Routines, Define the Derived Structures, Deriving a New Hash Table Type +@subsubsection Write the derived creation routine +You must write a routine which will create and initialize an +entry in the hash table. This routine is passed as the +function argument to @code{bfd_hash_table_init}. + +In order to permit other hash tables to be derived from the +hash table you are creating, this routine must be written in a +standard way. + +The first argument to the creation routine is a pointer to a +hash table entry. This may be @code{NULL}, in which case the +routine should allocate the right amount of space. Otherwise +the space has already been allocated by a hash table type +derived from this one. + +After allocating space, the creation routine must call the +creation routine of the hash table type it is derived from, +passing in a pointer to the space it just allocated. This +will initialize any fields used by the base hash table. + +Finally the creation routine must initialize any local fields +for the new hash table type. + +Here is a boilerplate example of a creation routine. +@var{function_name} is the name of the routine. +@var{entry_type} is the type of an entry in the hash table you +are creating. @var{base_newfunc} is the name of the creation +routine of the hash table type your hash table is derived +from. +@* +.struct bfd_hash_entry * +@example +@var{function_name} (entry, table, string) + struct bfd_hash_entry *entry; + struct bfd_hash_table *table; + const char *string; +@{ + struct @var{entry_type} *ret = (@var{entry_type} *) entry; + + /* Allocate the structure if it has not already been allocated by a + derived class. */ + if (ret == (@var{entry_type} *) NULL) + @{ + ret = ((@var{entry_type} *) + bfd_hash_allocate (table, sizeof (@var{entry_type}))); + if (ret == (@var{entry_type} *) NULL) + return NULL; + @} + + /* Call the allocation method of the base class. */ + ret = ((@var{entry_type} *) + @var{base_newfunc} ((struct bfd_hash_entry *) ret, table, string)); + + /* Initialize the local fields here. */ + + return (struct bfd_hash_entry *) ret; +@} +@end example +@strong{Description}@* +The creation routine for the linker hash table, which is in +@code{linker.c}, looks just like this example. +@var{function_name} is @code{_bfd_link_hash_newfunc}. +@var{entry_type} is @code{struct bfd_link_hash_entry}. +@var{base_newfunc} is @code{bfd_hash_newfunc}, the creation +routine for a basic hash table. + +@code{_bfd_link_hash_newfunc} also initializes the local fields +in a linker hash table entry: @code{type}, @code{written} and +@code{next}. +@* +@node Write Other Derived Routines, , Write the Derived Creation Routine, Deriving a New Hash Table Type +@subsubsection Write other derived routines +You will want to write other routines for your new hash table, +as well. + +You will want an initialization routine which calls the +initialization routine of the hash table you are deriving from +and initializes any other local fields. For the linker hash +table, this is @code{_bfd_link_hash_table_init} in @code{linker.c}. + +You will want a lookup routine which calls the lookup routine +of the hash table you are deriving from and casts the result. +The linker hash table uses @code{bfd_link_hash_lookup} in +@code{linker.c} (this actually takes an additional argument which +it uses to decide how to return the looked up value). + +You may want a traversal routine. This should just call the +traversal routine of the hash table you are deriving from with +appropriate casts. The linker hash table uses +@code{bfd_link_hash_traverse} in @code{linker.c}. + +These routines may simply be defined as macros. For example, +the a.out backend linker hash table, which is derived from the +linker hash table, uses macros for the lookup and traversal +routines. These are @code{aout_link_hash_lookup} and +@code{aout_link_hash_traverse} in aoutx.h. +@* diff --git a/gnu/usr.bin/binutils/bfd/doc/init.texi b/gnu/usr.bin/binutils/bfd/doc/init.texi new file mode 100644 index 00000000000..2902eac316c --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/init.texi @@ -0,0 +1,13 @@ +@section Initialization +These are the functions that handle initializing a BFD. +@* +@findex bfd_init +@subsubsection @code{bfd_init} +@strong{Synopsis} +@example +void bfd_init(void); +@end example +@strong{Description}@* +This routine must be called before any other BFD function to +initialize magical internal data structures. +@* diff --git a/gnu/usr.bin/binutils/bfd/doc/libbfd.texi b/gnu/usr.bin/binutils/bfd/doc/libbfd.texi new file mode 100644 index 00000000000..002e2f430fe --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/libbfd.texi @@ -0,0 +1,142 @@ +@section Internal functions + +@* +@strong{Description}@* +These routines are used within BFD. +They are not intended for export, but are documented here for +completeness. +@* +@findex bfd_write_bigendian_4byte_int +@subsubsection @code{bfd_write_bigendian_4byte_int} +@strong{Synopsis} +@example +void bfd_write_bigendian_4byte_int(bfd *abfd, int i); +@end example +@strong{Description}@* +Write a 4 byte integer @var{i} to the output BFD @var{abfd}, in big +endian order regardless of what else is going on. This is useful in +archives. +@* +@findex bfd_put_size +@subsubsection @code{bfd_put_size} +@findex bfd_get_size +@subsubsection @code{bfd_get_size} +@strong{Description}@* +These macros as used for reading and writing raw data in +sections; each access (except for bytes) is vectored through +the target format of the BFD and mangled accordingly. The +mangling performs any necessary endian translations and +removes alignment restrictions. Note that types accepted and +returned by these macros are identical so they can be swapped +around in macros---for example, @file{libaout.h} defines @code{GET_WORD} +to either @code{bfd_get_32} or @code{bfd_get_64}. + +In the put routines, @var{val} must be a @code{bfd_vma}. If we are on a +system without prototypes, the caller is responsible for making +sure that is true, with a cast if necessary. We don't cast +them in the macro definitions because that would prevent @code{lint} +or @code{gcc -Wall} from detecting sins such as passing a pointer. +To detect calling these with less than a @code{bfd_vma}, use +@code{gcc -Wconversion} on a host with 64 bit @code{bfd_vma}'s. +@example + + /* Byte swapping macros for user section data. */ + +#define bfd_put_8(abfd, val, ptr) \ + (*((unsigned char *)(ptr)) = (unsigned char)(val)) +#define bfd_put_signed_8 \ + bfd_put_8 +#define bfd_get_8(abfd, ptr) \ + (*(unsigned char *)(ptr)) +#define bfd_get_signed_8(abfd, ptr) \ + ((*(unsigned char *)(ptr) ^ 0x80) - 0x80) + +#define bfd_put_16(abfd, val, ptr) \ + BFD_SEND(abfd, bfd_putx16, ((val),(ptr))) +#define bfd_put_signed_16 \ + bfd_put_16 +#define bfd_get_16(abfd, ptr) \ + BFD_SEND(abfd, bfd_getx16, (ptr)) +#define bfd_get_signed_16(abfd, ptr) \ + BFD_SEND (abfd, bfd_getx_signed_16, (ptr)) + +#define bfd_put_32(abfd, val, ptr) \ + BFD_SEND(abfd, bfd_putx32, ((val),(ptr))) +#define bfd_put_signed_32 \ + bfd_put_32 +#define bfd_get_32(abfd, ptr) \ + BFD_SEND(abfd, bfd_getx32, (ptr)) +#define bfd_get_signed_32(abfd, ptr) \ + BFD_SEND(abfd, bfd_getx_signed_32, (ptr)) + +#define bfd_put_64(abfd, val, ptr) \ + BFD_SEND(abfd, bfd_putx64, ((val), (ptr))) +#define bfd_put_signed_64 \ + bfd_put_64 +#define bfd_get_64(abfd, ptr) \ + BFD_SEND(abfd, bfd_getx64, (ptr)) +#define bfd_get_signed_64(abfd, ptr) \ + BFD_SEND(abfd, bfd_getx_signed_64, (ptr)) + +@end example +@* +@findex bfd_h_put_size +@subsubsection @code{bfd_h_put_size} +@strong{Description}@* +These macros have the same function as their @code{bfd_get_x} +bretheren, except that they are used for removing information +for the header records of object files. Believe it or not, +some object files keep their header records in big endian +order and their data in little endian order. +@example + + /* Byte swapping macros for file header data. */ + +#define bfd_h_put_8(abfd, val, ptr) \ + bfd_put_8 (abfd, val, ptr) +#define bfd_h_put_signed_8(abfd, val, ptr) \ + bfd_put_8 (abfd, val, ptr) +#define bfd_h_get_8(abfd, ptr) \ + bfd_get_8 (abfd, ptr) +#define bfd_h_get_signed_8(abfd, ptr) \ + bfd_get_signed_8 (abfd, ptr) + +#define bfd_h_put_16(abfd, val, ptr) \ + BFD_SEND(abfd, bfd_h_putx16,(val,ptr)) +#define bfd_h_put_signed_16 \ + bfd_h_put_16 +#define bfd_h_get_16(abfd, ptr) \ + BFD_SEND(abfd, bfd_h_getx16,(ptr)) +#define bfd_h_get_signed_16(abfd, ptr) \ + BFD_SEND(abfd, bfd_h_getx_signed_16, (ptr)) + +#define bfd_h_put_32(abfd, val, ptr) \ + BFD_SEND(abfd, bfd_h_putx32,(val,ptr)) +#define bfd_h_put_signed_32 \ + bfd_h_put_32 +#define bfd_h_get_32(abfd, ptr) \ + BFD_SEND(abfd, bfd_h_getx32,(ptr)) +#define bfd_h_get_signed_32(abfd, ptr) \ + BFD_SEND(abfd, bfd_h_getx_signed_32, (ptr)) + +#define bfd_h_put_64(abfd, val, ptr) \ + BFD_SEND(abfd, bfd_h_putx64,(val, ptr)) +#define bfd_h_put_signed_64 \ + bfd_h_put_64 +#define bfd_h_get_64(abfd, ptr) \ + BFD_SEND(abfd, bfd_h_getx64,(ptr)) +#define bfd_h_get_signed_64(abfd, ptr) \ + BFD_SEND(abfd, bfd_h_getx_signed_64, (ptr)) + +@end example +@* +@findex bfd_log2 +@subsubsection @code{bfd_log2} +@strong{Synopsis} +@example +unsigned int bfd_log2(bfd_vma x); +@end example +@strong{Description}@* +Return the log base 2 of the value supplied, rounded up. E.g., an +@var{x} of 1025 returns 11. +@* diff --git a/gnu/usr.bin/binutils/bfd/doc/linker.texi b/gnu/usr.bin/binutils/bfd/doc/linker.texi new file mode 100644 index 00000000000..5cd6268e77a --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/linker.texi @@ -0,0 +1,365 @@ +@section Linker Functions +@cindex Linker +The linker uses three special entry points in the BFD target +vector. It is not necessary to write special routines for +these entry points when creating a new BFD back end, since +generic versions are provided. However, writing them can +speed up linking and make it use significantly less runtime +memory. + +The first routine creates a hash table used by the other +routines. The second routine adds the symbols from an object +file to the hash table. The third routine takes all the +object files and links them together to create the output +file. These routines are designed so that the linker proper +does not need to know anything about the symbols in the object +files that it is linking. The linker merely arranges the +sections as directed by the linker script and lets BFD handle +the details of symbols and relocs. + +The second routine and third routines are passed a pointer to +a @code{struct bfd_link_info} structure (defined in +@code{bfdlink.h}) which holds information relevant to the link, +including the linker hash table (which was created by the +first routine) and a set of callback functions to the linker +proper. + +The generic linker routines are in @code{linker.c}, and use the +header file @code{genlink.h}. As of this writing, the only back +ends which have implemented versions of these routines are +a.out (in @code{aoutx.h}) and ECOFF (in @code{ecoff.c}). The a.out +routines are used as examples throughout this section. + +@menu +* Creating a Linker Hash Table:: +* Adding Symbols to the Hash Table:: +* Performing the Final Link:: +@end menu +@* +@node Creating a Linker Hash Table, Adding Symbols to the Hash Table, Linker Functions, Linker Functions +@subsection Creating a linker hash table +@cindex _bfd_link_hash_table_create in target vector +@cindex target vector (_bfd_link_hash_table_create) +The linker routines must create a hash table, which must be +derived from @code{struct bfd_link_hash_table} described in +@code{bfdlink.c}. @xref{Hash Tables} for information on how to +create a derived hash table. This entry point is called using +the target vector of the linker output file. + +The @code{_bfd_link_hash_table_create} entry point must allocate +and initialize an instance of the desired hash table. If the +back end does not require any additional information to be +stored with the entries in the hash table, the entry point may +simply create a @code{struct bfd_link_hash_table}. Most likely, +however, some additional information will be needed. + +For example, with each entry in the hash table the a.out +linker keeps the index the symbol has in the final output file +(this index number is used so that when doing a relocateable +link the symbol index used in the output file can be quickly +filled in when copying over a reloc). The a.out linker code +defines the required structures and functions for a hash table +derived from @code{struct bfd_link_hash_table}. The a.out linker +hash table is created by the function +@code{NAME(aout,link_hash_table_create)}; it simply allocates +space for the hash table, initializes it, and returns a +pointer to it. + +When writing the linker routines for a new back end, you will +generally not know exactly which fields will be required until +you have finished. You should simply create a new hash table +which defines no additional fields, and then simply add fields +as they become necessary. +@* +@node Adding Symbols to the Hash Table, Performing the Final Link, Creating a Linker Hash Table, Linker Functions +@subsection Adding symbols to the hash table +@cindex _bfd_link_add_symbols in target vector +@cindex target vector (_bfd_link_add_symbols) +The linker proper will call the @code{_bfd_link_add_symbols} +entry point for each object file or archive which is to be +linked (typically these are the files named on the command +line, but some may also come from the linker script). The +entry point is responsible for examining the file. For an +object file, BFD must add any relevant symbol information to +the hash table. For an archive, BFD must determine which +elements of the archive should be used and adding them to the +link. + +The a.out version of this entry point is +@code{NAME(aout,link_add_symbols)}. + +@menu +* Differing file formats:: +* Adding symbols from an object file:: +* Adding symbols from an archive:: +@end menu +@* +@node Differing file formats, Adding symbols from an object file, Adding Symbols to the Hash Table, Adding Symbols to the Hash Table +@subsubsection Differing file formats +Normally all the files involved in a link will be of the same +format, but it is also possible to link together different +format object files, and the back end must support that. The +@code{_bfd_link_add_symbols} entry point is called via the target +vector of the file to be added. This has an important +consequence: the function may not assume that the hash table +is the type created by the corresponding +@code{_bfd_link_hash_table_create} vector. All the +@code{_bfd_link_add_symbols} function can assume about the hash +table is that it is derived from @code{struct +bfd_link_hash_table}. + +Sometimes the @code{_bfd_link_add_symbols} function must store +some information in the hash table entry to be used by the +@code{_bfd_final_link} function. In such a case the @code{creator} +field of the hash table must be checked to make sure that the +hash table was created by an object file of the same format. + +The @code{_bfd_final_link} routine must be prepared to handle a +hash entry without any extra information added by the +@code{_bfd_link_add_symbols} function. A hash entry without +extra information will also occur when the linker script +directs the linker to create a symbol. Note that, regardless +of how a hash table entry is added, all the fields will be +initialized to some sort of null value by the hash table entry +initialization function. + +See @code{ecoff_link_add_externals} for an example of how to +check the @code{creator} field before saving information (in this +case, the ECOFF external symbol debugging information) in a +hash table entry. +@* +@node Adding symbols from an object file, Adding symbols from an archive, Differing file formats, Adding Symbols to the Hash Table +@subsubsection Adding symbols from an object file +When the @code{_bfd_link_add_symbols} routine is passed an object +file, it must add all externally visible symbols in that +object file to the hash table. The actual work of adding the +symbol to the hash table is normally handled by the function +@code{_bfd_generic_link_add_one_symbol}. The +@code{_bfd_link_add_symbols} routine is responsible for reading +all the symbols from the object file and passing the correct +information to @code{_bfd_generic_link_add_one_symbol}. + +The @code{_bfd_link_add_symbols} routine should not use +@code{bfd_canonicalize_symtab} to read the symbols. The point of +providing this routine is to avoid the overhead of converting +the symbols into generic @code{asymbol} structures. + +@findex _bfd_generic_link_add_one_symbol +@code{_bfd_generic_link_add_one_symbol} handles the details of +combining common symbols, warning about multiple definitions, +and so forth. It takes arguments which describe the symbol to +add, notably symbol flags, a section, and an offset. The +symbol flags include such things as @code{BSF_WEAK} or +@code{BSF_INDIRECT}. The section is a section in the object +file, or something like @code{bfd_und_section_ptr} for an undefined +symbol or @code{bfd_com_section_ptr} for a common symbol. + +If the @code{_bfd_final_link} routine is also going to need to +read the symbol information, the @code{_bfd_link_add_symbols} +routine should save it somewhere attached to the object file +BFD. However, the information should only be saved if the +@code{keep_memory} field of the @code{info} argument is true, so +that the @code{-no-keep-memory} linker switch is effective. + +The a.out function which adds symbols from an object file is +@code{aout_link_add_object_symbols}, and most of the interesting +work is in @code{aout_link_add_symbols}. The latter saves +pointers to the hash tables entries created by +@code{_bfd_generic_link_add_one_symbol} indexed by symbol number, +so that the @code{_bfd_final_link} routine does not have to call +the hash table lookup routine to locate the entry. +@* +@node Adding symbols from an archive, , Adding symbols from an object file, Adding Symbols to the Hash Table +@subsubsection Adding symbols from an archive +When the @code{_bfd_link_add_symbols} routine is passed an +archive, it must look through the symbols defined by the +archive and decide which elements of the archive should be +included in the link. For each such element it must call the +@code{add_archive_element} linker callback, and it must add the +symbols from the object file to the linker hash table. + +@findex _bfd_generic_link_add_archive_symbols +In most cases the work of looking through the symbols in the +archive should be done by the +@code{_bfd_generic_link_add_archive_symbols} function. This +function builds a hash table from the archive symbol table and +looks through the list of undefined symbols to see which +elements should be included. +@code{_bfd_generic_link_add_archive_symbols} is passed a function +to call to make the final decision about adding an archive +element to the link and to do the actual work of adding the +symbols to the linker hash table. + +The function passed to +@code{_bfd_generic_link_add_archive_symbols} must read the +symbols of the archive element and decide whether the archive +element should be included in the link. If the element is to +be included, the @code{add_archive_element} linker callback +routine must be called with the element as an argument, and +the elements symbols must be added to the linker hash table +just as though the element had itself been passed to the +@code{_bfd_link_add_symbols} function. + +When the a.out @code{_bfd_link_add_symbols} function receives an +archive, it calls @code{_bfd_generic_link_add_archive_symbols} +passing @code{aout_link_check_archive_element} as the function +argument. @code{aout_link_check_archive_element} calls +@code{aout_link_check_ar_symbols}. If the latter decides to add +the element (an element is only added if it provides a real, +non-common, definition for a previously undefined or common +symbol) it calls the @code{add_archive_element} callback and then +@code{aout_link_check_archive_element} calls +@code{aout_link_add_symbols} to actually add the symbols to the +linker hash table. + +The ECOFF back end is unusual in that it does not normally +call @code{_bfd_generic_link_add_archive_symbols}, because ECOFF +archives already contain a hash table of symbols. The ECOFF +back end searches the archive itself to avoid the overhead of +creating a new hash table. +@* +@node Performing the Final Link, , Adding Symbols to the Hash Table, Linker Functions +@subsection Performing the final link +@cindex _bfd_link_final_link in target vector +@cindex target vector (_bfd_final_link) +When all the input files have been processed, the linker calls +the @code{_bfd_final_link} entry point of the output BFD. This +routine is responsible for producing the final output file, +which has several aspects. It must relocate the contents of +the input sections and copy the data into the output sections. +It must build an output symbol table including any local +symbols from the input files and the global symbols from the +hash table. When producing relocateable output, it must +modify the input relocs and write them into the output file. +There may also be object format dependent work to be done. + +The linker will also call the @code{write_object_contents} entry +point when the BFD is closed. The two entry points must work +together in order to produce the correct output file. + +The details of how this works are inevitably dependent upon +the specific object file format. The a.out +@code{_bfd_final_link} routine is @code{NAME(aout,final_link)}. + +@menu +* Information provided by the linker:: +* Relocating the section contents:: +* Writing the symbol table:: +@end menu +@* +@node Information provided by the linker, Relocating the section contents, Performing the Final Link, Performing the Final Link +@subsubsection Information provided by the linker +Before the linker calls the @code{_bfd_final_link} entry point, +it sets up some data structures for the function to use. + +The @code{input_bfds} field of the @code{bfd_link_info} structure +will point to a list of all the input files included in the +link. These files are linked through the @code{link_next} field +of the @code{bfd} structure. + +Each section in the output file will have a list of +@code{link_order} structures attached to the @code{link_order_head} +field (the @code{link_order} structure is defined in +@code{bfdlink.h}). These structures describe how to create the +contents of the output section in terms of the contents of +various input sections, fill constants, and, eventually, other +types of information. They also describe relocs that must be +created by the BFD backend, but do not correspond to any input +file; this is used to support -Ur, which builds constructors +while generating a relocateable object file. +@* +@node Relocating the section contents, Writing the symbol table, Information provided by the linker, Performing the Final Link +@subsubsection Relocating the section contents +The @code{_bfd_final_link} function should look through the +@code{link_order} structures attached to each section of the +output file. Each @code{link_order} structure should either be +handled specially, or it should be passed to the function +@code{_bfd_default_link_order} which will do the right thing +(@code{_bfd_default_link_order} is defined in @code{linker.c}). + +For efficiency, a @code{link_order} of type +@code{bfd_indirect_link_order} whose associated section belongs +to a BFD of the same format as the output BFD must be handled +specially. This type of @code{link_order} describes part of an +output section in terms of a section belonging to one of the +input files. The @code{_bfd_final_link} function should read the +contents of the section and any associated relocs, apply the +relocs to the section contents, and write out the modified +section contents. If performing a relocateable link, the +relocs themselves must also be modified and written out. + +@findex _bfd_relocate_contents +@findex _bfd_final_link_relocate +The functions @code{_bfd_relocate_contents} and +@code{_bfd_final_link_relocate} provide some general support for +performing the actual relocations, notably overflow checking. +Their arguments include information about the symbol the +relocation is against and a @code{reloc_howto_type} argument +which describes the relocation to perform. These functions +are defined in @code{reloc.c}. + +The a.out function which handles reading, relocating, and +writing section contents is @code{aout_link_input_section}. The +actual relocation is done in @code{aout_link_input_section_std} +and @code{aout_link_input_section_ext}. +@* +@node Writing the symbol table, , Relocating the section contents, Performing the Final Link +@subsubsection Writing the symbol table +The @code{_bfd_final_link} function must gather all the symbols +in the input files and write them out. It must also write out +all the symbols in the global hash table. This must be +controlled by the @code{strip} and @code{discard} fields of the +@code{bfd_link_info} structure. + +The local symbols of the input files will not have been +entered into the linker hash table. The @code{_bfd_final_link} +routine must consider each input file and include the symbols +in the output file. It may be convenient to do this when +looking through the @code{link_order} structures, or it may be +done by stepping through the @code{input_bfds} list. + +The @code{_bfd_final_link} routine must also traverse the global +hash table to gather all the externally visible symbols. It +is possible that most of the externally visible symbols may be +written out when considering the symbols of each input file, +but it is still necessary to traverse the hash table since the +linker script may have defined some symbols that are not in +any of the input files. + +The @code{strip} field of the @code{bfd_link_info} structure +controls which symbols are written out. The possible values +are listed in @code{bfdlink.h}. If the value is @code{strip_some}, +then the @code{keep_hash} field of the @code{bfd_link_info} +structure is a hash table of symbols to keep; each symbol +should be looked up in this hash table, and only symbols which +are present should be included in the output file. + +If the @code{strip} field of the @code{bfd_link_info} structure +permits local symbols to be written out, the @code{discard} field +is used to further controls which local symbols are included +in the output file. If the value is @code{discard_l}, then all +local symbols which begin with a certain prefix are discarded; +this is controlled by the @code{bfd_is_local_label_name} entry point. + +The a.out backend handles symbols by calling +@code{aout_link_write_symbols} on each input BFD and then +traversing the global hash table with the function +@code{aout_link_write_other_symbol}. It builds a string table +while writing out the symbols, which is written to the output +file at the end of @code{NAME(aout,final_link)}. +@* +@findex bfd_link_split_section +@subsubsection @code{bfd_link_split_section} +@strong{Synopsis} +@example +boolean bfd_link_split_section(bfd *abfd, asection *sec); +@end example +@strong{Description}@* +Return nonzero if @var{sec} should be split during a +reloceatable or final link. +@example +#define bfd_link_split_section(abfd, sec) \ + BFD_SEND (abfd, _bfd_link_split_section, (abfd, sec)) + +@end example +@* diff --git a/gnu/usr.bin/binutils/bfd/doc/makefile.vms b/gnu/usr.bin/binutils/bfd/doc/makefile.vms new file mode 100644 index 00000000000..a0857c0caaf --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/makefile.vms @@ -0,0 +1,5 @@ +CFLAGS = /noopt/include=([],[-],[-.-.include]) +LDFLAGS = /nomap +LDLIBS = ,sys$$library:vaxcrtl.olb/lib + +all: chew.exe diff --git a/gnu/usr.bin/binutils/bfd/doc/opncls.texi b/gnu/usr.bin/binutils/bfd/doc/opncls.texi new file mode 100644 index 00000000000..07456d8dbc5 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/opncls.texi @@ -0,0 +1,128 @@ +@section Opening and closing BFDs + +@* +@findex bfd_openr +@subsubsection @code{bfd_openr} +@strong{Synopsis} +@example +bfd *bfd_openr(CONST char *filename, CONST char *target); +@end example +@strong{Description}@* +Open the file @var{filename} (using @code{fopen}) with the target +@var{target}. Return a pointer to the created BFD. + +Calls @code{bfd_find_target}, so @var{target} is interpreted as by +that function. + +If @code{NULL} is returned then an error has occured. Possible errors +are @code{bfd_error_no_memory}, @code{bfd_error_invalid_target} or @code{system_call} error. +@* +@findex bfd_fdopenr +@subsubsection @code{bfd_fdopenr} +@strong{Synopsis} +@example +bfd *bfd_fdopenr(CONST char *filename, CONST char *target, int fd); +@end example +@strong{Description}@* +@code{bfd_fdopenr} is to @code{bfd_fopenr} much like @code{fdopen} is to @code{fopen}. +It opens a BFD on a file already described by the @var{fd} +supplied. + +When the file is later @code{bfd_close}d, the file descriptor will be closed. + +If the caller desires that this file descriptor be cached by BFD +(opened as needed, closed as needed to free descriptors for +other opens), with the supplied @var{fd} used as an initial +file descriptor (but subject to closure at any time), call +bfd_set_cacheable(bfd, 1) on the returned BFD. The default is to +assume no cacheing; the file descriptor will remain open until +@code{bfd_close}, and will not be affected by BFD operations on other +files. + +Possible errors are @code{bfd_error_no_memory}, @code{bfd_error_invalid_target} and @code{bfd_error_system_call}. +@* +@findex bfd_openstreamr +@subsubsection @code{bfd_openstreamr} +@strong{Synopsis} +@example +bfd *bfd_openstreamr(const char *, const char *, PTR); +@end example +@strong{Description}@* +Open a BFD for read access on an existing stdio stream. When +the BFD is passed to @code{bfd_close}, the stream will be closed. +@* +@findex bfd_openw +@subsubsection @code{bfd_openw} +@strong{Synopsis} +@example +bfd *bfd_openw(CONST char *filename, CONST char *target); +@end example +@strong{Description}@* +Create a BFD, associated with file @var{filename}, using the +file format @var{target}, and return a pointer to it. + +Possible errors are @code{bfd_error_system_call}, @code{bfd_error_no_memory}, +@code{bfd_error_invalid_target}. +@* +@findex bfd_close +@subsubsection @code{bfd_close} +@strong{Synopsis} +@example +boolean bfd_close(bfd *abfd); +@end example +@strong{Description}@* +Close a BFD. If the BFD was open for writing, +then pending operations are completed and the file written out +and closed. If the created file is executable, then +@code{chmod} is called to mark it as such. + +All memory attached to the BFD is released. + +The file descriptor associated with the BFD is closed (even +if it was passed in to BFD by @code{bfd_fdopenr}). +@* +@strong{Returns}@* +@code{true} is returned if all is ok, otherwise @code{false}. +@* +@findex bfd_close_all_done +@subsubsection @code{bfd_close_all_done} +@strong{Synopsis} +@example +boolean bfd_close_all_done(bfd *); +@end example +@strong{Description}@* +Close a BFD. Differs from @code{bfd_close} +since it does not complete any pending operations. This +routine would be used if the application had just used BFD for +swapping and didn't want to use any of the writing code. + +If the created file is executable, then @code{chmod} is called +to mark it as such. + +All memory attached to the BFD is released. +@* +@strong{Returns}@* +@code{true} is returned if all is ok, otherwise @code{false}. +@* +@findex bfd_create +@subsubsection @code{bfd_create} +@strong{Synopsis} +@example +bfd *bfd_create(CONST char *filename, bfd *templ); +@end example +@strong{Description}@* +Create a new BFD in the manner of +@code{bfd_openw}, but without opening a file. The new BFD +takes the target from the target used by @var{template}. The +format is always set to @code{bfd_object}. +@* +@findex bfd_alloc +@subsubsection @code{bfd_alloc} +@strong{Synopsis} +@example +PTR bfd_alloc (bfd *abfd, size_t wanted); +@end example +@strong{Description}@* +Allocate a block of @var{wanted} bytes of memory attached to +@code{abfd} and return a pointer to it. +@* diff --git a/gnu/usr.bin/binutils/bfd/doc/reloc.texi b/gnu/usr.bin/binutils/bfd/doc/reloc.texi new file mode 100644 index 00000000000..63c079e8726 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/reloc.texi @@ -0,0 +1,914 @@ +@section Relocations +BFD maintains relocations in much the same way it maintains +symbols: they are left alone until required, then read in +en-mass and translated into an internal form. A common +routine @code{bfd_perform_relocation} acts upon the +canonical form to do the fixup. + +Relocations are maintained on a per section basis, +while symbols are maintained on a per BFD basis. + +All that a back end has to do to fit the BFD interface is to create +a @code{struct reloc_cache_entry} for each relocation +in a particular section, and fill in the right bits of the structures. + +@menu +* typedef arelent:: +* howto manager:: +@end menu +@* + +@node typedef arelent, howto manager, Relocations, Relocations +@subsection typedef arelent +This is the structure of a relocation entry: +@* +. +@example +typedef enum bfd_reloc_status +@{ + /* No errors detected */ + bfd_reloc_ok, + + /* The relocation was performed, but there was an overflow. */ + bfd_reloc_overflow, + + /* The address to relocate was not within the section supplied. */ + bfd_reloc_outofrange, + + /* Used by special functions */ + bfd_reloc_continue, + + /* Unsupported relocation size requested. */ + bfd_reloc_notsupported, + + /* Unused */ + bfd_reloc_other, + + /* The symbol to relocate against was undefined. */ + bfd_reloc_undefined, + + /* The relocation was performed, but may not be ok - presently + generated only when linking i960 coff files with i960 b.out + symbols. If this type is returned, the error_message argument + to bfd_perform_relocation will be set. */ + bfd_reloc_dangerous + @} + bfd_reloc_status_type; + + +typedef struct reloc_cache_entry +@{ + /* A pointer into the canonical table of pointers */ + struct symbol_cache_entry **sym_ptr_ptr; + + /* offset in section */ + bfd_size_type address; + + /* addend for relocation value */ + bfd_vma addend; + + /* Pointer to how to perform the required relocation */ + reloc_howto_type *howto; + +@} arelent; +@end example +@strong{Description}@* +Here is a description of each of the fields within an @code{arelent}: + +@itemize @bullet + +@item +@code{sym_ptr_ptr} +@end itemize +The symbol table pointer points to a pointer to the symbol +associated with the relocation request. It is +the pointer into the table returned by the back end's +@code{get_symtab} action. @xref{Symbols}. The symbol is referenced +through a pointer to a pointer so that tools like the linker +can fix up all the symbols of the same name by modifying only +one pointer. The relocation routine looks in the symbol and +uses the base of the section the symbol is attached to and the +value of the symbol as the initial relocation offset. If the +symbol pointer is zero, then the section provided is looked up. + +@itemize @bullet + +@item +@code{address} +@end itemize +The @code{address} field gives the offset in bytes from the base of +the section data which owns the relocation record to the first +byte of relocatable information. The actual data relocated +will be relative to this point; for example, a relocation +type which modifies the bottom two bytes of a four byte word +would not touch the first byte pointed to in a big endian +world. + +@itemize @bullet + +@item +@code{addend} +@end itemize +The @code{addend} is a value provided by the back end to be added (!) +to the relocation offset. Its interpretation is dependent upon +the howto. For example, on the 68k the code: + +@example + char foo[]; + main() + @{ + return foo[0x12345678]; + @} +@end example + +Could be compiled into: + +@example + linkw fp,#-4 + moveb @@#12345678,d0 + extbl d0 + unlk fp + rts +@end example + +This could create a reloc pointing to @code{foo}, but leave the +offset in the data, something like: + +@example +RELOCATION RECORDS FOR [.text]: +offset type value +00000006 32 _foo + +00000000 4e56 fffc ; linkw fp,#-4 +00000004 1039 1234 5678 ; moveb @@#12345678,d0 +0000000a 49c0 ; extbl d0 +0000000c 4e5e ; unlk fp +0000000e 4e75 ; rts +@end example + +Using coff and an 88k, some instructions don't have enough +space in them to represent the full address range, and +pointers have to be loaded in two parts. So you'd get something like: + +@example + or.u r13,r0,hi16(_foo+0x12345678) + ld.b r2,r13,lo16(_foo+0x12345678) + jmp r1 +@end example + +This should create two relocs, both pointing to @code{_foo}, and with +0x12340000 in their addend field. The data would consist of: + +@example +RELOCATION RECORDS FOR [.text]: +offset type value +00000002 HVRT16 _foo+0x12340000 +00000006 LVRT16 _foo+0x12340000 + +00000000 5da05678 ; or.u r13,r0,0x5678 +00000004 1c4d5678 ; ld.b r2,r13,0x5678 +00000008 f400c001 ; jmp r1 +@end example + +The relocation routine digs out the value from the data, adds +it to the addend to get the original offset, and then adds the +value of @code{_foo}. Note that all 32 bits have to be kept around +somewhere, to cope with carry from bit 15 to bit 16. + +One further example is the sparc and the a.out format. The +sparc has a similar problem to the 88k, in that some +instructions don't have room for an entire offset, but on the +sparc the parts are created in odd sized lumps. The designers of +the a.out format chose to not use the data within the section +for storing part of the offset; all the offset is kept within +the reloc. Anything in the data should be ignored. + +@example + save %sp,-112,%sp + sethi %hi(_foo+0x12345678),%g2 + ldsb [%g2+%lo(_foo+0x12345678)],%i0 + ret + restore +@end example + +Both relocs contain a pointer to @code{foo}, and the offsets +contain junk. + +@example +RELOCATION RECORDS FOR [.text]: +offset type value +00000004 HI22 _foo+0x12345678 +00000008 LO10 _foo+0x12345678 + +00000000 9de3bf90 ; save %sp,-112,%sp +00000004 05000000 ; sethi %hi(_foo+0),%g2 +00000008 f048a000 ; ldsb [%g2+%lo(_foo+0)],%i0 +0000000c 81c7e008 ; ret +00000010 81e80000 ; restore +@end example + +@itemize @bullet + +@item +@code{howto} +@end itemize +The @code{howto} field can be imagined as a +relocation instruction. It is a pointer to a structure which +contains information on what to do with all of the other +information in the reloc record and data section. A back end +would normally have a relocation instruction set and turn +relocations into pointers to the correct structure on input - +but it would be possible to create each howto field on demand. +@* +@subsubsection @code{enum complain_overflow} +Indicates what sort of overflow checking should be done when +performing a relocation. +@* +. +@example +enum complain_overflow +@{ + /* Do not complain on overflow. */ + complain_overflow_dont, + + /* Complain if the bitfield overflows, whether it is considered + as signed or unsigned. */ + complain_overflow_bitfield, + + /* Complain if the value overflows when considered as signed + number. */ + complain_overflow_signed, + + /* Complain if the value overflows when considered as an + unsigned number. */ + complain_overflow_unsigned +@}; +@end example +@subsubsection @code{reloc_howto_type} +The @code{reloc_howto_type} is a structure which contains all the +information that libbfd needs to know to tie up a back end's data. +@* +.struct symbol_cache_entry; /* Forward declaration */ +@example + +struct reloc_howto_struct +@{ + /* The type field has mainly a documentary use - the back end can + do what it wants with it, though normally the back end's + external idea of what a reloc number is stored + in this field. For example, a PC relative word relocation + in a coff environment has the type 023 - because that's + what the outside world calls a R_PCRWORD reloc. */ + unsigned int type; + + /* The value the final relocation is shifted right by. This drops + unwanted data from the relocation. */ + unsigned int rightshift; + + /* The size of the item to be relocated. This is *not* a + power-of-two measure. To get the number of bytes operated + on by a type of relocation, use bfd_get_reloc_size. */ + int size; + + /* The number of bits in the item to be relocated. This is used + when doing overflow checking. */ + unsigned int bitsize; + + /* Notes that the relocation is relative to the location in the + data section of the addend. The relocation function will + subtract from the relocation value the address of the location + being relocated. */ + boolean pc_relative; + + /* The bit position of the reloc value in the destination. + The relocated value is left shifted by this amount. */ + unsigned int bitpos; + + /* What type of overflow error should be checked for when + relocating. */ + enum complain_overflow complain_on_overflow; + + /* If this field is non null, then the supplied function is + called rather than the normal function. This allows really + strange relocation methods to be accomodated (e.g., i960 callj + instructions). */ + bfd_reloc_status_type (*special_function) + PARAMS ((bfd *abfd, + arelent *reloc_entry, + struct symbol_cache_entry *symbol, + PTR data, + asection *input_section, + bfd *output_bfd, + char **error_message)); + + /* The textual name of the relocation type. */ + char *name; + + /* When performing a partial link, some formats must modify the + relocations rather than the data - this flag signals this.*/ + boolean partial_inplace; + + /* The src_mask selects which parts of the read in data + are to be used in the relocation sum. E.g., if this was an 8 bit + bit of data which we read and relocated, this would be + 0x000000ff. When we have relocs which have an addend, such as + sun4 extended relocs, the value in the offset part of a + relocating field is garbage so we never use it. In this case + the mask would be 0x00000000. */ + bfd_vma src_mask; + + /* The dst_mask selects which parts of the instruction are replaced + into the instruction. In most cases src_mask == dst_mask, + except in the above special case, where dst_mask would be + 0x000000ff, and src_mask would be 0x00000000. */ + bfd_vma dst_mask; + + /* When some formats create PC relative instructions, they leave + the value of the pc of the place being relocated in the offset + slot of the instruction, so that a PC relative relocation can + be made just by adding in an ordinary offset (e.g., sun3 a.out). + Some formats leave the displacement part of an instruction + empty (e.g., m88k bcs); this flag signals the fact.*/ + boolean pcrel_offset; + +@}; +@end example +@findex The HOWTO Macro +@subsubsection @code{The HOWTO Macro} +@strong{Description}@* +The HOWTO define is horrible and will go away. +@example +#define HOWTO(C, R,S,B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \ + @{(unsigned)C,R,S,B, P, BI, O,SF,NAME,INPLACE,MASKSRC,MASKDST,PC@} +@end example +@* +@strong{Description}@* +And will be replaced with the totally magic way. But for the +moment, we are compatible, so do it this way. +@example +#define NEWHOWTO( FUNCTION, NAME,SIZE,REL,IN) HOWTO(0,0,SIZE,0,REL,0,complain_overflow_dont,FUNCTION, NAME,false,0,0,IN) + +@end example +@* +@strong{Description}@* +Helper routine to turn a symbol into a relocation value. +@example +#define HOWTO_PREPARE(relocation, symbol) \ + @{ \ + if (symbol != (asymbol *)NULL) @{ \ + if (bfd_is_com_section (symbol->section)) @{ \ + relocation = 0; \ + @} \ + else @{ \ + relocation = symbol->value; \ + @} \ + @} \ +@} +@end example +@* +@findex bfd_get_reloc_size +@subsubsection @code{bfd_get_reloc_size} +@strong{Synopsis} +@example +int bfd_get_reloc_size (reloc_howto_type *); +@end example +@strong{Description}@* +For a reloc_howto_type that operates on a fixed number of bytes, +this returns the number of bytes operated on. +@* +@findex arelent_chain +@subsubsection @code{arelent_chain} +@strong{Description}@* +How relocs are tied together in an @code{asection}: +@example +typedef struct relent_chain @{ + arelent relent; + struct relent_chain *next; +@} arelent_chain; +@end example +@* +@findex bfd_perform_relocation +@subsubsection @code{bfd_perform_relocation} +@strong{Synopsis} +@example +bfd_reloc_status_type +bfd_perform_relocation + (bfd *abfd, + arelent *reloc_entry, + PTR data, + asection *input_section, + bfd *output_bfd, + char **error_message); +@end example +@strong{Description}@* +If @var{output_bfd} is supplied to this function, the +generated image will be relocatable; the relocations are +copied to the output file after they have been changed to +reflect the new state of the world. There are two ways of +reflecting the results of partial linkage in an output file: +by modifying the output data in place, and by modifying the +relocation record. Some native formats (e.g., basic a.out and +basic coff) have no way of specifying an addend in the +relocation type, so the addend has to go in the output data. +This is no big deal since in these formats the output data +slot will always be big enough for the addend. Complex reloc +types with addends were invented to solve just this problem. +The @var{error_message} argument is set to an error message if +this return @code{bfd_reloc_dangerous}. +@* +@findex bfd_install_relocation +@subsubsection @code{bfd_install_relocation} +@strong{Synopsis} +@example +bfd_reloc_status_type +bfd_install_relocation + (bfd *abfd, + arelent *reloc_entry, + PTR data, bfd_vma data_start, + asection *input_section, + char **error_message); +@end example +@strong{Description}@* +This looks remarkably like @code{bfd_perform_relocation}, except it +does not expect that the section contents have been filled in. +I.e., it's suitable for use when creating, rather than applying +a relocation. + +For now, this function should be considered reserved for the +assembler. +@* + +@node howto manager, , typedef arelent, Relocations +@section The howto manager +When an application wants to create a relocation, but doesn't +know what the target machine might call it, it can find out by +using this bit of code. +@* +@findex bfd_reloc_code_type +@subsubsection @code{bfd_reloc_code_type} +@strong{Description}@* +The insides of a reloc code. The idea is that, eventually, there +will be one enumerator for every type of relocation we ever do. +Pass one of these values to @code{bfd_reloc_type_lookup}, and it'll +return a howto pointer. + +This does mean that the application must determine the correct +enumerator value; you can't get a howto pointer from a random set +of attributes. +@* +Here are the possible values for @code{enum bfd_reloc_code_real}: + +@deffn {} BFD_RELOC_64 +@deffnx {} BFD_RELOC_32 +@deffnx {} BFD_RELOC_26 +@deffnx {} BFD_RELOC_24 +@deffnx {} BFD_RELOC_16 +@deffnx {} BFD_RELOC_14 +@deffnx {} BFD_RELOC_8 +Basic absolute relocations of N bits. +@end deffn +@deffn {} BFD_RELOC_64_PCREL +@deffnx {} BFD_RELOC_32_PCREL +@deffnx {} BFD_RELOC_24_PCREL +@deffnx {} BFD_RELOC_16_PCREL +@deffnx {} BFD_RELOC_12_PCREL +@deffnx {} BFD_RELOC_8_PCREL +PC-relative relocations. Sometimes these are relative to the address +of the relocation itself; sometimes they are relative to the start of +the section containing the relocation. It depends on the specific target. + +The 24-bit relocation is used in some Intel 960 configurations. +@end deffn +@deffn {} BFD_RELOC_32_GOT_PCREL +@deffnx {} BFD_RELOC_16_GOT_PCREL +@deffnx {} BFD_RELOC_8_GOT_PCREL +@deffnx {} BFD_RELOC_32_GOTOFF +@deffnx {} BFD_RELOC_16_GOTOFF +@deffnx {} BFD_RELOC_LO16_GOTOFF +@deffnx {} BFD_RELOC_HI16_GOTOFF +@deffnx {} BFD_RELOC_HI16_S_GOTOFF +@deffnx {} BFD_RELOC_8_GOTOFF +@deffnx {} BFD_RELOC_32_PLT_PCREL +@deffnx {} BFD_RELOC_24_PLT_PCREL +@deffnx {} BFD_RELOC_16_PLT_PCREL +@deffnx {} BFD_RELOC_8_PLT_PCREL +@deffnx {} BFD_RELOC_32_PLTOFF +@deffnx {} BFD_RELOC_16_PLTOFF +@deffnx {} BFD_RELOC_LO16_PLTOFF +@deffnx {} BFD_RELOC_HI16_PLTOFF +@deffnx {} BFD_RELOC_HI16_S_PLTOFF +@deffnx {} BFD_RELOC_8_PLTOFF +For ELF. +@end deffn +@deffn {} BFD_RELOC_68K_GLOB_DAT +@deffnx {} BFD_RELOC_68K_JMP_SLOT +@deffnx {} BFD_RELOC_68K_RELATIVE +Relocations used by 68K ELF. +@end deffn +@deffn {} BFD_RELOC_32_BASEREL +@deffnx {} BFD_RELOC_16_BASEREL +@deffnx {} BFD_RELOC_LO16_BASEREL +@deffnx {} BFD_RELOC_HI16_BASEREL +@deffnx {} BFD_RELOC_HI16_S_BASEREL +@deffnx {} BFD_RELOC_8_BASEREL +@deffnx {} BFD_RELOC_RVA +Linkage-table relative. +@end deffn +@deffn {} BFD_RELOC_8_FFnn +Absolute 8-bit relocation, but used to form an address like 0xFFnn. +@end deffn +@deffn {} BFD_RELOC_32_PCREL_S2 +@deffnx {} BFD_RELOC_16_PCREL_S2 +@deffnx {} BFD_RELOC_23_PCREL_S2 +These PC-relative relocations are stored as word displacements -- +i.e., byte displacements shifted right two bits. The 30-bit word +displacement (<<32_PCREL_S2>> -- 32 bits, shifted 2) is used on the +SPARC. (SPARC tools generally refer to this as <<WDISP30>>.) The +signed 16-bit displacement is used on the MIPS, and the 23-bit +displacement is used on the Alpha. +@end deffn +@deffn {} BFD_RELOC_HI22 +@deffnx {} BFD_RELOC_LO10 +High 22 bits and low 10 bits of 32-bit value, placed into lower bits of +the target word. These are used on the SPARC. +@end deffn +@deffn {} BFD_RELOC_GPREL16 +@deffnx {} BFD_RELOC_GPREL32 +For systems that allocate a Global Pointer register, these are +displacements off that register. These relocation types are +handled specially, because the value the register will have is +decided relatively late. +@end deffn +@deffn {} BFD_RELOC_I960_CALLJ +Reloc types used for i960/b.out. +@end deffn +@deffn {} BFD_RELOC_NONE +@deffnx {} BFD_RELOC_SPARC_WDISP22 +@deffnx {} BFD_RELOC_SPARC22 +@deffnx {} BFD_RELOC_SPARC13 +@deffnx {} BFD_RELOC_SPARC_GOT10 +@deffnx {} BFD_RELOC_SPARC_GOT13 +@deffnx {} BFD_RELOC_SPARC_GOT22 +@deffnx {} BFD_RELOC_SPARC_PC10 +@deffnx {} BFD_RELOC_SPARC_PC22 +@deffnx {} BFD_RELOC_SPARC_WPLT30 +@deffnx {} BFD_RELOC_SPARC_COPY +@deffnx {} BFD_RELOC_SPARC_GLOB_DAT +@deffnx {} BFD_RELOC_SPARC_JMP_SLOT +@deffnx {} BFD_RELOC_SPARC_RELATIVE +@deffnx {} BFD_RELOC_SPARC_UA32 +SPARC ELF relocations. There is probably some overlap with other +relocation types already defined. +@end deffn +@deffn {} BFD_RELOC_SPARC_BASE13 +@deffnx {} BFD_RELOC_SPARC_BASE22 +I think these are specific to SPARC a.out (e.g., Sun 4). +@end deffn +@deffn {} BFD_RELOC_SPARC_64 +@deffnx {} BFD_RELOC_SPARC_10 +@deffnx {} BFD_RELOC_SPARC_11 +@deffnx {} BFD_RELOC_SPARC_OLO10 +@deffnx {} BFD_RELOC_SPARC_HH22 +@deffnx {} BFD_RELOC_SPARC_HM10 +@deffnx {} BFD_RELOC_SPARC_LM22 +@deffnx {} BFD_RELOC_SPARC_PC_HH22 +@deffnx {} BFD_RELOC_SPARC_PC_HM10 +@deffnx {} BFD_RELOC_SPARC_PC_LM22 +@deffnx {} BFD_RELOC_SPARC_WDISP16 +@deffnx {} BFD_RELOC_SPARC_WDISP19 +@deffnx {} BFD_RELOC_SPARC_GLOB_JMP +@deffnx {} BFD_RELOC_SPARC_7 +@deffnx {} BFD_RELOC_SPARC_6 +@deffnx {} BFD_RELOC_SPARC_5 +Some relocations we're using for SPARC V9 -- subject to change. +@end deffn +@deffn {} BFD_RELOC_ALPHA_GPDISP_HI16 +Alpha ECOFF and ELF relocations. Some of these treat the symbol or +"addend" in some special way. +For GPDISP_HI16 ("gpdisp") relocations, the symbol is ignored when +writing; when reading, it will be the absolute section symbol. The +addend is the displacement in bytes of the "lda" instruction from +the "ldah" instruction (which is at the address of this reloc). +@end deffn +@deffn {} BFD_RELOC_ALPHA_GPDISP_LO16 +For GPDISP_LO16 ("ignore") relocations, the symbol is handled as +with GPDISP_HI16 relocs. The addend is ignored when writing the +relocations out, and is filled in with the file's GP value on +reading, for convenience. +@end deffn +@deffn {} BFD_RELOC_ALPHA_GPDISP +The ELF GPDISP relocation is exactly the same as the GPDISP_HI16 +relocation except that there is no accompanying GPDISP_LO16 +relocation. +@end deffn +@deffn {} BFD_RELOC_ALPHA_LITERAL +@deffnx {} BFD_RELOC_ALPHA_ELF_LITERAL +@deffnx {} BFD_RELOC_ALPHA_LITUSE +The Alpha LITERAL/LITUSE relocs are produced by a symbol reference; +the assembler turns it into a LDQ instruction to load the address of +the symbol, and then fills in a register in the real instruction. + +The LITERAL reloc, at the LDQ instruction, refers to the .lita +section symbol. The addend is ignored when writing, but is filled +in with the file's GP value on reading, for convenience, as with the +GPDISP_LO16 reloc. + +The ELF_LITERAL reloc is somewhere between 16_GOTOFF and GPDISP_LO16. +It should refer to the symbol to be referenced, as with 16_GOTOFF, +but it generates output not based on the position within the .got +section, but relative to the GP value chosen for the file during the +final link stage. + +The LITUSE reloc, on the instruction using the loaded address, gives +information to the linker that it might be able to use to optimize +away some literal section references. The symbol is ignored (read +as the absolute section symbol), and the "addend" indicates the type +of instruction using the register: +1 - "memory" fmt insn +2 - byte-manipulation (byte offset reg) +3 - jsr (target of branch) + +The GNU linker currently doesn't do any of this optimizing. +@end deffn +@deffn {} BFD_RELOC_ALPHA_HINT +The HINT relocation indicates a value that should be filled into the +"hint" field of a jmp/jsr/ret instruction, for possible branch- +prediction logic which may be provided on some processors. +@end deffn +@deffn {} BFD_RELOC_ALPHA_LINKAGE +The LINKAGE relocation outputs a linkage pair in the object file, +which is filled by the linker. +@end deffn +@deffn {} BFD_RELOC_ALPHA_CODEADDR +The CODEADDR relocation outputs a STO_CA in the object file, +which is filled by the linker. +@end deffn +@deffn {} BFD_RELOC_MIPS_JMP +Bits 27..2 of the relocation address shifted right 2 bits; +simple reloc otherwise. +@end deffn +@deffn {} BFD_RELOC_MIPS16_JMP +The MIPS16 jump instruction. +@end deffn +@deffn {} BFD_RELOC_MIPS16_GPREL +MIPS16 GP relative reloc. +@end deffn +@deffn {} BFD_RELOC_HI16 +High 16 bits of 32-bit value; simple reloc. +@end deffn +@deffn {} BFD_RELOC_HI16_S +High 16 bits of 32-bit value but the low 16 bits will be sign +extended and added to form the final result. If the low 16 +bits form a negative number, we need to add one to the high value +to compensate for the borrow when the low bits are added. +@end deffn +@deffn {} BFD_RELOC_LO16 +Low 16 bits. +@end deffn +@deffn {} BFD_RELOC_PCREL_HI16_S +Like BFD_RELOC_HI16_S, but PC relative. +@end deffn +@deffn {} BFD_RELOC_PCREL_LO16 +Like BFD_RELOC_LO16, but PC relative. +@end deffn +@deffn {} BFD_RELOC_MIPS_GPREL +Relocation relative to the global pointer. +@end deffn +@deffn {} BFD_RELOC_MIPS_LITERAL +Relocation against a MIPS literal section. +@end deffn +@deffn {} BFD_RELOC_MIPS_GOT16 +@deffnx {} BFD_RELOC_MIPS_CALL16 +@deffnx {} BFD_RELOC_MIPS_GPREL32 +@deffnx {} BFD_RELOC_MIPS_GOT_HI16 +@deffnx {} BFD_RELOC_MIPS_GOT_LO16 +@deffnx {} BFD_RELOC_MIPS_CALL_HI16 +@deffnx {} BFD_RELOC_MIPS_CALL_LO16 +MIPS ELF relocations. +@end deffn +@deffn {} BFD_RELOC_386_GOT32 +@deffnx {} BFD_RELOC_386_PLT32 +@deffnx {} BFD_RELOC_386_COPY +@deffnx {} BFD_RELOC_386_GLOB_DAT +@deffnx {} BFD_RELOC_386_JUMP_SLOT +@deffnx {} BFD_RELOC_386_RELATIVE +@deffnx {} BFD_RELOC_386_GOTOFF +@deffnx {} BFD_RELOC_386_GOTPC +i386/elf relocations +@end deffn +@deffn {} BFD_RELOC_NS32K_IMM_8 +@deffnx {} BFD_RELOC_NS32K_IMM_16 +@deffnx {} BFD_RELOC_NS32K_IMM_32 +@deffnx {} BFD_RELOC_NS32K_IMM_8_PCREL +@deffnx {} BFD_RELOC_NS32K_IMM_16_PCREL +@deffnx {} BFD_RELOC_NS32K_IMM_32_PCREL +@deffnx {} BFD_RELOC_NS32K_DISP_8 +@deffnx {} BFD_RELOC_NS32K_DISP_16 +@deffnx {} BFD_RELOC_NS32K_DISP_32 +@deffnx {} BFD_RELOC_NS32K_DISP_8_PCREL +@deffnx {} BFD_RELOC_NS32K_DISP_16_PCREL +@deffnx {} BFD_RELOC_NS32K_DISP_32_PCREL +ns32k relocations +@end deffn +@deffn {} BFD_RELOC_PPC_B26 +@deffnx {} BFD_RELOC_PPC_BA26 +@deffnx {} BFD_RELOC_PPC_TOC16 +@deffnx {} BFD_RELOC_PPC_B16 +@deffnx {} BFD_RELOC_PPC_B16_BRTAKEN +@deffnx {} BFD_RELOC_PPC_B16_BRNTAKEN +@deffnx {} BFD_RELOC_PPC_BA16 +@deffnx {} BFD_RELOC_PPC_BA16_BRTAKEN +@deffnx {} BFD_RELOC_PPC_BA16_BRNTAKEN +@deffnx {} BFD_RELOC_PPC_COPY +@deffnx {} BFD_RELOC_PPC_GLOB_DAT +@deffnx {} BFD_RELOC_PPC_JMP_SLOT +@deffnx {} BFD_RELOC_PPC_RELATIVE +@deffnx {} BFD_RELOC_PPC_LOCAL24PC +@deffnx {} BFD_RELOC_PPC_EMB_NADDR32 +@deffnx {} BFD_RELOC_PPC_EMB_NADDR16 +@deffnx {} BFD_RELOC_PPC_EMB_NADDR16_LO +@deffnx {} BFD_RELOC_PPC_EMB_NADDR16_HI +@deffnx {} BFD_RELOC_PPC_EMB_NADDR16_HA +@deffnx {} BFD_RELOC_PPC_EMB_SDAI16 +@deffnx {} BFD_RELOC_PPC_EMB_SDA2I16 +@deffnx {} BFD_RELOC_PPC_EMB_SDA2REL +@deffnx {} BFD_RELOC_PPC_EMB_SDA21 +@deffnx {} BFD_RELOC_PPC_EMB_MRKREF +@deffnx {} BFD_RELOC_PPC_EMB_RELSEC16 +@deffnx {} BFD_RELOC_PPC_EMB_RELST_LO +@deffnx {} BFD_RELOC_PPC_EMB_RELST_HI +@deffnx {} BFD_RELOC_PPC_EMB_RELST_HA +@deffnx {} BFD_RELOC_PPC_EMB_BIT_FLD +@deffnx {} BFD_RELOC_PPC_EMB_RELSDA +Power(rs6000) and PowerPC relocations. +@end deffn +@deffn {} BFD_RELOC_CTOR +The type of reloc used to build a contructor table - at the moment +probably a 32 bit wide absolute relocation, but the target can choose. +It generally does map to one of the other relocation types. +@end deffn +@deffn {} BFD_RELOC_ARM_PCREL_BRANCH +ARM 26 bit pc-relative branch. The lowest two bits must be zero and are +not stored in the instruction. +@end deffn +@deffn {} BFD_RELOC_ARM_IMMEDIATE +@deffnx {} BFD_RELOC_ARM_OFFSET_IMM +@deffnx {} BFD_RELOC_ARM_SHIFT_IMM +@deffnx {} BFD_RELOC_ARM_SWI +@deffnx {} BFD_RELOC_ARM_MULTI +@deffnx {} BFD_RELOC_ARM_CP_OFF_IMM +@deffnx {} BFD_RELOC_ARM_ADR_IMM +@deffnx {} BFD_RELOC_ARM_LDR_IMM +@deffnx {} BFD_RELOC_ARM_LITERAL +@deffnx {} BFD_RELOC_ARM_IN_POOL +@deffnx {} BFD_RELOC_ARM_OFFSET_IMM8 +@deffnx {} BFD_RELOC_ARM_HWLITERAL +@deffnx {} BFD_RELOC_ARM_THUMB_ADD +@deffnx {} BFD_RELOC_ARM_THUMB_IMM +@deffnx {} BFD_RELOC_ARM_THUMB_SHIFT +@deffnx {} BFD_RELOC_ARM_THUMB_OFFSET +These relocs are only used within the ARM assembler. They are not +(at present) written to any object files. +@end deffn +@deffn {} BFD_RELOC_SH_PCDISP8BY2 +@deffnx {} BFD_RELOC_SH_PCDISP12BY2 +@deffnx {} BFD_RELOC_SH_IMM4 +@deffnx {} BFD_RELOC_SH_IMM4BY2 +@deffnx {} BFD_RELOC_SH_IMM4BY4 +@deffnx {} BFD_RELOC_SH_IMM8 +@deffnx {} BFD_RELOC_SH_IMM8BY2 +@deffnx {} BFD_RELOC_SH_IMM8BY4 +@deffnx {} BFD_RELOC_SH_PCRELIMM8BY2 +@deffnx {} BFD_RELOC_SH_PCRELIMM8BY4 +@deffnx {} BFD_RELOC_SH_SWITCH16 +@deffnx {} BFD_RELOC_SH_SWITCH32 +@deffnx {} BFD_RELOC_SH_USES +@deffnx {} BFD_RELOC_SH_COUNT +@deffnx {} BFD_RELOC_SH_ALIGN +@deffnx {} BFD_RELOC_SH_CODE +@deffnx {} BFD_RELOC_SH_DATA +@deffnx {} BFD_RELOC_SH_LABEL +Hitachi SH relocs. Not all of these appear in object files. +@end deffn +@deffn {} BFD_RELOC_D10V_10_PCREL_R +Mitsubishi D10V relocs. +This is a 10-bit reloc with the right 2 bits +assumed to be 0. +@end deffn +@deffn {} BFD_RELOC_D10V_10_PCREL_L +Mitsubishi D10V relocs. +This is a 10-bit reloc with the right 2 bits +assumed to be 0. This is the same as the previous reloc +except it is in the left container, i.e., +shifted left 15 bits. +@end deffn +@deffn {} BFD_RELOC_D10V_18 +This is an 18-bit reloc with the right 2 bits +assumed to be 0. +@end deffn +@deffn {} BFD_RELOC_D10V_18_PCREL +This is an 18-bit reloc with the right 2 bits +assumed to be 0. +@end deffn +@deffn {} BFD_RELOC_M32R_24 +Mitsubishi M32R relocs. +This is a 24 bit absolute address. +@end deffn +@deffn {} BFD_RELOC_M32R_10_PCREL +This is a 10-bit pc-relative reloc with the right 2 bits assumed to be 0. +@end deffn +@deffn {} BFD_RELOC_M32R_18_PCREL +This is an 18-bit reloc with the right 2 bits assumed to be 0. +@end deffn +@deffn {} BFD_RELOC_M32R_26_PCREL +This is a 26-bit reloc with the right 2 bits assumed to be 0. +@end deffn +@deffn {} BFD_RELOC_M32R_HI16_ULO +This is a 16-bit reloc containing the high 16 bits of an address +used when the lower 16 bits are treated as unsigned. +@end deffn +@deffn {} BFD_RELOC_M32R_HI16_SLO +This is a 16-bit reloc containing the high 16 bits of an address +used when the lower 16 bits are treated as signed. +@end deffn +@deffn {} BFD_RELOC_M32R_LO16 +This is a 16-bit reloc containing the lower 16 bits of an address. +@end deffn +@deffn {} BFD_RELOC_M32R_SDA16 +This is a 16-bit reloc containing the small data area offset for use in +add3, load, and store instructions. +@end deffn +@deffn {} BFD_RELOC_MN10300_32_PCREL +This is a 32bit pcrel reloc for the mn10300, offset by two bytes in the +instruction. +@end deffn +@deffn {} BFD_RELOC_MN10300_16_PCREL +This is a 16bit pcrel reloc for the mn10300, offset by two bytes in the +instruction. +@end deffn +. +@example +typedef enum bfd_reloc_code_real bfd_reloc_code_real_type; +@end example +@findex bfd_reloc_type_lookup +@subsubsection @code{bfd_reloc_type_lookup} +@strong{Synopsis} +@example +reloc_howto_type * +bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code); +@end example +@strong{Description}@* +Return a pointer to a howto structure which, when +invoked, will perform the relocation @var{code} on data from the +architecture noted. +@* +@findex bfd_default_reloc_type_lookup +@subsubsection @code{bfd_default_reloc_type_lookup} +@strong{Synopsis} +@example +reloc_howto_type *bfd_default_reloc_type_lookup + (bfd *abfd, bfd_reloc_code_real_type code); +@end example +@strong{Description}@* +Provides a default relocation lookup routine for any architecture. +@* +@findex bfd_get_reloc_code_name +@subsubsection @code{bfd_get_reloc_code_name} +@strong{Synopsis} +@example +const char *bfd_get_reloc_code_name (bfd_reloc_code_real_type code); +@end example +@strong{Description}@* +Provides a printable name for the supplied relocation code. +Useful mainly for printing error messages. +@* +@findex bfd_generic_relax_section +@subsubsection @code{bfd_generic_relax_section} +@strong{Synopsis} +@example +boolean bfd_generic_relax_section + (bfd *abfd, + asection *section, + struct bfd_link_info *, + boolean *); +@end example +@strong{Description}@* +Provides default handling for relaxing for back ends which +don't do relaxing -- i.e., does nothing. +@* +@findex bfd_generic_get_relocated_section_contents +@subsubsection @code{bfd_generic_get_relocated_section_contents} +@strong{Synopsis} +@example +bfd_byte * +bfd_generic_get_relocated_section_contents (bfd *abfd, + struct bfd_link_info *link_info, + struct bfd_link_order *link_order, + bfd_byte *data, + boolean relocateable, + asymbol **symbols); +@end example +@strong{Description}@* +Provides default handling of relocation effort for back ends +which can't be bothered to do it efficiently. +@* diff --git a/gnu/usr.bin/binutils/bfd/doc/section.texi b/gnu/usr.bin/binutils/bfd/doc/section.texi new file mode 100644 index 00000000000..d5ff109cdcf --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/section.texi @@ -0,0 +1,649 @@ +@section Sections +The raw data contained within a BFD is maintained through the +section abstraction. A single BFD may have any number of +sections. It keeps hold of them by pointing to the first; +each one points to the next in the list. + +Sections are supported in BFD in @code{section.c}. + +@menu +* Section Input:: +* Section Output:: +* typedef asection:: +* section prototypes:: +@end menu +@* +@node Section Input, Section Output, Sections, Sections +@subsection Section input +When a BFD is opened for reading, the section structures are +created and attached to the BFD. + +Each section has a name which describes the section in the +outside world---for example, @code{a.out} would contain at least +three sections, called @code{.text}, @code{.data} and @code{.bss}. + +Names need not be unique; for example a COFF file may have several +sections named @code{.data}. + +Sometimes a BFD will contain more than the ``natural'' number of +sections. A back end may attach other sections containing +constructor data, or an application may add a section (using +@code{bfd_make_section}) to the sections attached to an already open +BFD. For example, the linker creates an extra section +@code{COMMON} for each input file's BFD to hold information about +common storage. + +The raw data is not necessarily read in when +the section descriptor is created. Some targets may leave the +data in place until a @code{bfd_get_section_contents} call is +made. Other back ends may read in all the data at once. For +example, an S-record file has to be read once to determine the +size of the data. An IEEE-695 file doesn't contain raw data in +sections, but data and relocation expressions intermixed, so +the data area has to be parsed to get out the data and +relocations. +@* +@node Section Output, typedef asection, Section Input, Sections +@subsection Section output +To write a new object style BFD, the various sections to be +written have to be created. They are attached to the BFD in +the same way as input sections; data is written to the +sections using @code{bfd_set_section_contents}. + +Any program that creates or combines sections (e.g., the assembler +and linker) must use the @code{asection} fields @code{output_section} and +@code{output_offset} to indicate the file sections to which each +section must be written. (If the section is being created from +scratch, @code{output_section} should probably point to the section +itself and @code{output_offset} should probably be zero.) + +The data to be written comes from input sections attached +(via @code{output_section} pointers) to +the output sections. The output section structure can be +considered a filter for the input section: the output section +determines the vma of the output data and the name, but the +input section determines the offset into the output section of +the data to be written. + +E.g., to create a section "O", starting at 0x100, 0x123 long, +containing two subsections, "A" at offset 0x0 (i.e., at vma +0x100) and "B" at offset 0x20 (i.e., at vma 0x120) the @code{asection} +structures would look like: + +@example + section name "A" + output_offset 0x00 + size 0x20 + output_section -----------> section name "O" + | vma 0x100 + section name "B" | size 0x123 + output_offset 0x20 | + size 0x103 | + output_section --------| +@end example +@* +@subsection Link orders +The data within a section is stored in a @dfn{link_order}. +These are much like the fixups in @code{gas}. The link_order +abstraction allows a section to grow and shrink within itself. + +A link_order knows how big it is, and which is the next +link_order and where the raw data for it is; it also points to +a list of relocations which apply to it. + +The link_order is used by the linker to perform relaxing on +final code. The compiler creates code which is as big as +necessary to make it work without relaxing, and the user can +select whether to relax. Sometimes relaxing takes a lot of +time. The linker runs around the relocations to see if any +are attached to data which can be shrunk, if so it does it on +a link_order by link_order basis. +@* + +@node typedef asection, section prototypes, Section Output, Sections +@subsection typedef asection +Here is the section structure: +@* +. +@example +typedef struct sec +@{ + /* The name of the section; the name isn't a copy, the pointer is + the same as that passed to bfd_make_section. */ + + CONST char *name; + + /* Which section is it; 0..nth. */ + + int index; + + /* The next section in the list belonging to the BFD, or NULL. */ + + struct sec *next; + + /* The field flags contains attributes of the section. Some + flags are read in from the object file, and some are + synthesized from other information. */ + + flagword flags; + +#define SEC_NO_FLAGS 0x000 + + /* Tells the OS to allocate space for this section when loading. + This is clear for a section containing debug information + only. */ +#define SEC_ALLOC 0x001 + + /* Tells the OS to load the section from the file when loading. + This is clear for a .bss section. */ +#define SEC_LOAD 0x002 + + /* The section contains data still to be relocated, so there is + some relocation information too. */ +#define SEC_RELOC 0x004 + +#if 0 /* Obsolete ? */ +#define SEC_BALIGN 0x008 +#endif + + /* A signal to the OS that the section contains read only + data. */ +#define SEC_READONLY 0x010 + + /* The section contains code only. */ +#define SEC_CODE 0x020 + + /* The section contains data only. */ +#define SEC_DATA 0x040 + + /* The section will reside in ROM. */ +#define SEC_ROM 0x080 + + /* The section contains constructor information. This section + type is used by the linker to create lists of constructors and + destructors used by @code{g++}. When a back end sees a symbol + which should be used in a constructor list, it creates a new + section for the type of name (e.g., @code{__CTOR_LIST__}), attaches + the symbol to it, and builds a relocation. To build the lists + of constructors, all the linker has to do is catenate all the + sections called @code{__CTOR_LIST__} and relocate the data + contained within - exactly the operations it would peform on + standard data. */ +#define SEC_CONSTRUCTOR 0x100 + + /* The section is a constuctor, and should be placed at the + end of the text, data, or bss section(?). */ +#define SEC_CONSTRUCTOR_TEXT 0x1100 +#define SEC_CONSTRUCTOR_DATA 0x2100 +#define SEC_CONSTRUCTOR_BSS 0x3100 + + /* The section has contents - a data section could be + @code{SEC_ALLOC} | @code{SEC_HAS_CONTENTS}; a debug section could be + @code{SEC_HAS_CONTENTS} */ +#define SEC_HAS_CONTENTS 0x200 + + /* An instruction to the linker to not output the section + even if it has information which would normally be written. */ +#define SEC_NEVER_LOAD 0x400 + + /* The section is a COFF shared library section. This flag is + only for the linker. If this type of section appears in + the input file, the linker must copy it to the output file + without changing the vma or size. FIXME: Although this + was originally intended to be general, it really is COFF + specific (and the flag was renamed to indicate this). It + might be cleaner to have some more general mechanism to + allow the back end to control what the linker does with + sections. */ +#define SEC_COFF_SHARED_LIBRARY 0x800 + + /* The section contains common symbols (symbols may be defined + multiple times, the value of a symbol is the amount of + space it requires, and the largest symbol value is the one + used). Most targets have exactly one of these (which we + translate to bfd_com_section_ptr), but ECOFF has two. */ +#define SEC_IS_COMMON 0x8000 + + /* The section contains only debugging information. For + example, this is set for ELF .debug and .stab sections. + strip tests this flag to see if a section can be + discarded. */ +#define SEC_DEBUGGING 0x10000 + + /* The contents of this section are held in memory pointed to + by the contents field. This is checked by + bfd_get_section_contents, and the data is retrieved from + memory if appropriate. */ +#define SEC_IN_MEMORY 0x20000 + + /* The contents of this section are to be excluded by the + linker for executable and shared objects unless those + objects are to be further relocated. */ +#define SEC_EXCLUDE 0x40000 + + /* The contents of this section are to be sorted by the + based on the address specified in the associated symbol + table. */ +#define SEC_SORT_ENTRIES 0x80000 + + /* When linking, duplicate sections of the same name should be + discarded, rather than being combined into a single section as + is usually done. This is similar to how common symbols are + handled. See SEC_LINK_DUPLICATES below. */ +#define SEC_LINK_ONCE 0x100000 + + /* If SEC_LINK_ONCE is set, this bitfield describes how the linker + should handle duplicate sections. */ +#define SEC_LINK_DUPLICATES 0x600000 + + /* This value for SEC_LINK_DUPLICATES means that duplicate + sections with the same name should simply be discarded. */ +#define SEC_LINK_DUPLICATES_DISCARD 0x0 + + /* This value for SEC_LINK_DUPLICATES means that the linker + should warn if there are any duplicate sections, although + it should still only link one copy. */ +#define SEC_LINK_DUPLICATES_ONE_ONLY 0x200000 + + /* This value for SEC_LINK_DUPLICATES means that the linker + should warn if any duplicate sections are a different size. */ +#define SEC_LINK_DUPLICATES_SAME_SIZE 0x400000 + + /* This value for SEC_LINK_DUPLICATES means that the linker + should warn if any duplicate sections contain different + contents. */ +#define SEC_LINK_DUPLICATES_SAME_CONTENTS 0x600000 + + /* This section was created by the linker as part of dynamic + relocation or other arcane processing. It is skipped when + going through the first-pass output, trusting that someone + else up the line will take care of it later. */ +#define SEC_LINKER_CREATED 0x800000 + + /* End of section flags. */ + + /* Some internal packed boolean fields. */ + + /* See the vma field. */ + unsigned int user_set_vma : 1; + + /* Whether relocations have been processed. */ + unsigned int reloc_done : 1; + + /* A mark flag used by some of the linker backends. */ + unsigned int linker_mark : 1; + + /* End of internal packed boolean fields. */ + + /* The virtual memory address of the section - where it will be + at run time. The symbols are relocated against this. The + user_set_vma flag is maintained by bfd; if it's not set, the + backend can assign addresses (for example, in @code{a.out}, where + the default address for @code{.data} is dependent on the specific + target and various flags). */ + + bfd_vma vma; + + /* The load address of the section - where it would be in a + rom image; really only used for writing section header + information. */ + + bfd_vma lma; + + /* The size of the section in bytes, as it will be output. + contains a value even if the section has no contents (e.g., the + size of @code{.bss}). This will be filled in after relocation */ + + bfd_size_type _cooked_size; + + /* The original size on disk of the section, in bytes. Normally this + value is the same as the size, but if some relaxing has + been done, then this value will be bigger. */ + + bfd_size_type _raw_size; + + /* If this section is going to be output, then this value is the + offset into the output section of the first byte in the input + section. E.g., if this was going to start at the 100th byte in + the output section, this value would be 100. */ + + bfd_vma output_offset; + + /* The output section through which to map on output. */ + + struct sec *output_section; + + /* The alignment requirement of the section, as an exponent of 2 - + e.g., 3 aligns to 2^3 (or 8). */ + + unsigned int alignment_power; + + /* If an input section, a pointer to a vector of relocation + records for the data in this section. */ + + struct reloc_cache_entry *relocation; + + /* If an output section, a pointer to a vector of pointers to + relocation records for the data in this section. */ + + struct reloc_cache_entry **orelocation; + + /* The number of relocation records in one of the above */ + + unsigned reloc_count; + + /* Information below is back end specific - and not always used + or updated. */ + + /* File position of section data */ + + file_ptr filepos; + + /* File position of relocation info */ + + file_ptr rel_filepos; + + /* File position of line data */ + + file_ptr line_filepos; + + /* Pointer to data for applications */ + + PTR userdata; + + /* If the SEC_IN_MEMORY flag is set, this points to the actual + contents. */ + unsigned char *contents; + + /* Attached line number information */ + + alent *lineno; + + /* Number of line number records */ + + unsigned int lineno_count; + + /* When a section is being output, this value changes as more + linenumbers are written out */ + + file_ptr moving_line_filepos; + + /* What the section number is in the target world */ + + int target_index; + + PTR used_by_bfd; + + /* If this is a constructor section then here is a list of the + relocations created to relocate items within it. */ + + struct relent_chain *constructor_chain; + + /* The BFD which owns the section. */ + + bfd *owner; + + /* A symbol which points at this section only */ + struct symbol_cache_entry *symbol; + struct symbol_cache_entry **symbol_ptr_ptr; + + struct bfd_link_order *link_order_head; + struct bfd_link_order *link_order_tail; +@} asection ; + + /* These sections are global, and are managed by BFD. The application + and target back end are not permitted to change the values in + these sections. New code should use the section_ptr macros rather + than referring directly to the const sections. The const sections + may eventually vanish. */ +#define BFD_ABS_SECTION_NAME "*ABS*" +#define BFD_UND_SECTION_NAME "*UND*" +#define BFD_COM_SECTION_NAME "*COM*" +#define BFD_IND_SECTION_NAME "*IND*" + + /* the absolute section */ +extern const asection bfd_abs_section; +#define bfd_abs_section_ptr ((asection *) &bfd_abs_section) +#define bfd_is_abs_section(sec) ((sec) == bfd_abs_section_ptr) + /* Pointer to the undefined section */ +extern const asection bfd_und_section; +#define bfd_und_section_ptr ((asection *) &bfd_und_section) +#define bfd_is_und_section(sec) ((sec) == bfd_und_section_ptr) + /* Pointer to the common section */ +extern const asection bfd_com_section; +#define bfd_com_section_ptr ((asection *) &bfd_com_section) + /* Pointer to the indirect section */ +extern const asection bfd_ind_section; +#define bfd_ind_section_ptr ((asection *) &bfd_ind_section) +#define bfd_is_ind_section(sec) ((sec) == bfd_ind_section_ptr) + +extern const struct symbol_cache_entry * const bfd_abs_symbol; +extern const struct symbol_cache_entry * const bfd_com_symbol; +extern const struct symbol_cache_entry * const bfd_und_symbol; +extern const struct symbol_cache_entry * const bfd_ind_symbol; +#define bfd_get_section_size_before_reloc(section) \ + (section->reloc_done ? (abort(),1): (section)->_raw_size) +#define bfd_get_section_size_after_reloc(section) \ + ((section->reloc_done) ? (section)->_cooked_size: (abort(),1)) +@end example + +@node section prototypes, , typedef asection, Sections +@subsection Section prototypes +These are the functions exported by the section handling part of BFD. +@* +@findex bfd_get_section_by_name +@subsubsection @code{bfd_get_section_by_name} +@strong{Synopsis} +@example +asection *bfd_get_section_by_name(bfd *abfd, CONST char *name); +@end example +@strong{Description}@* +Run through @var{abfd} and return the one of the +@code{asection}s whose name matches @var{name}, otherwise @code{NULL}. +@xref{Sections}, for more information. + +This should only be used in special cases; the normal way to process +all sections of a given name is to use @code{bfd_map_over_sections} and +@code{strcmp} on the name (or better yet, base it on the section flags +or something else) for each section. +@* +@findex bfd_make_section_old_way +@subsubsection @code{bfd_make_section_old_way} +@strong{Synopsis} +@example +asection *bfd_make_section_old_way(bfd *abfd, CONST char *name); +@end example +@strong{Description}@* +Create a new empty section called @var{name} +and attach it to the end of the chain of sections for the +BFD @var{abfd}. An attempt to create a section with a name which +is already in use returns its pointer without changing the +section chain. + +It has the funny name since this is the way it used to be +before it was rewritten.... + +Possible errors are: +@itemize @bullet + +@item +@code{bfd_error_invalid_operation} - +If output has already started for this BFD. +@item +@code{bfd_error_no_memory} - +If memory allocation fails. +@end itemize +@* +@findex bfd_make_section_anyway +@subsubsection @code{bfd_make_section_anyway} +@strong{Synopsis} +@example +asection *bfd_make_section_anyway(bfd *abfd, CONST char *name); +@end example +@strong{Description}@* +Create a new empty section called @var{name} and attach it to the end of +the chain of sections for @var{abfd}. Create a new section even if there +is already a section with that name. + +Return @code{NULL} and set @code{bfd_error} on error; possible errors are: +@itemize @bullet + +@item +@code{bfd_error_invalid_operation} - If output has already started for @var{abfd}. +@item +@code{bfd_error_no_memory} - If memory allocation fails. +@end itemize +@* +@findex bfd_make_section +@subsubsection @code{bfd_make_section} +@strong{Synopsis} +@example +asection *bfd_make_section(bfd *, CONST char *name); +@end example +@strong{Description}@* +Like @code{bfd_make_section_anyway}, but return @code{NULL} (without calling +bfd_set_error ()) without changing the section chain if there is already a +section named @var{name}. If there is an error, return @code{NULL} and set +@code{bfd_error}. +@* +@findex bfd_set_section_flags +@subsubsection @code{bfd_set_section_flags} +@strong{Synopsis} +@example +boolean bfd_set_section_flags(bfd *abfd, asection *sec, flagword flags); +@end example +@strong{Description}@* +Set the attributes of the section @var{sec} in the BFD +@var{abfd} to the value @var{flags}. Return @code{true} on success, +@code{false} on error. Possible error returns are: + +@itemize @bullet + +@item +@code{bfd_error_invalid_operation} - +The section cannot have one or more of the attributes +requested. For example, a .bss section in @code{a.out} may not +have the @code{SEC_HAS_CONTENTS} field set. +@end itemize +@* +@findex bfd_map_over_sections +@subsubsection @code{bfd_map_over_sections} +@strong{Synopsis} +@example +void bfd_map_over_sections(bfd *abfd, + void (*func)(bfd *abfd, + asection *sect, + PTR obj), + PTR obj); +@end example +@strong{Description}@* +Call the provided function @var{func} for each section +attached to the BFD @var{abfd}, passing @var{obj} as an +argument. The function will be called as if by + +@example + func(abfd, the_section, obj); +@end example + +This is the prefered method for iterating over sections; an +alternative would be to use a loop: + +@example + section *p; + for (p = abfd->sections; p != NULL; p = p->next) + func(abfd, p, ...) +@end example +@* +@findex bfd_set_section_size +@subsubsection @code{bfd_set_section_size} +@strong{Synopsis} +@example +boolean bfd_set_section_size(bfd *abfd, asection *sec, bfd_size_type val); +@end example +@strong{Description}@* +Set @var{sec} to the size @var{val}. If the operation is +ok, then @code{true} is returned, else @code{false}. + +Possible error returns: +@itemize @bullet + +@item +@code{bfd_error_invalid_operation} - +Writing has started to the BFD, so setting the size is invalid. +@end itemize +@* +@findex bfd_set_section_contents +@subsubsection @code{bfd_set_section_contents} +@strong{Synopsis} +@example +boolean bfd_set_section_contents + (bfd *abfd, + asection *section, + PTR data, + file_ptr offset, + bfd_size_type count); +@end example +@strong{Description}@* +Sets the contents of the section @var{section} in BFD +@var{abfd} to the data starting in memory at @var{data}. The +data is written to the output section starting at offset +@var{offset} for @var{count} bytes. + +Normally @code{true} is returned, else @code{false}. Possible error +returns are: +@itemize @bullet + +@item +@code{bfd_error_no_contents} - +The output section does not have the @code{SEC_HAS_CONTENTS} +attribute, so nothing can be written to it. +@item +and some more too +@end itemize +This routine is front end to the back end function +@code{_bfd_set_section_contents}. +@* +@findex bfd_get_section_contents +@subsubsection @code{bfd_get_section_contents} +@strong{Synopsis} +@example +boolean bfd_get_section_contents + (bfd *abfd, asection *section, PTR location, + file_ptr offset, bfd_size_type count); +@end example +@strong{Description}@* +Read data from @var{section} in BFD @var{abfd} +into memory starting at @var{location}. The data is read at an +offset of @var{offset} from the start of the input section, +and is read for @var{count} bytes. + +If the contents of a constructor with the @code{SEC_CONSTRUCTOR} +flag set are requested or if the section does not have the +@code{SEC_HAS_CONTENTS} flag set, then the @var{location} is filled +with zeroes. If no errors occur, @code{true} is returned, else +@code{false}. +@* +@findex bfd_copy_private_section_data +@subsubsection @code{bfd_copy_private_section_data} +@strong{Synopsis} +@example +boolean bfd_copy_private_section_data(bfd *ibfd, asection *isec, bfd *obfd, asection *osec); +@end example +@strong{Description}@* +Copy private section information from @var{isec} in the BFD +@var{ibfd} to the section @var{osec} in the BFD @var{obfd}. +Return @code{true} on success, @code{false} on error. Possible error +returns are: + +@itemize @bullet + +@item +@code{bfd_error_no_memory} - +Not enough memory exists to create private data for @var{osec}. +@end itemize +@example +#define bfd_copy_private_section_data(ibfd, isection, obfd, osection) \ + BFD_SEND (obfd, _bfd_copy_private_section_data, \ + (ibfd, isection, obfd, osection)) +@end example +@* diff --git a/gnu/usr.bin/binutils/bfd/doc/syms.texi b/gnu/usr.bin/binutils/bfd/doc/syms.texi new file mode 100644 index 00000000000..034f086ec8f --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/syms.texi @@ -0,0 +1,407 @@ +@section Symbols +BFD tries to maintain as much symbol information as it can when +it moves information from file to file. BFD passes information +to applications though the @code{asymbol} structure. When the +application requests the symbol table, BFD reads the table in +the native form and translates parts of it into the internal +format. To maintain more than the information passed to +applications, some targets keep some information ``behind the +scenes'' in a structure only the particular back end knows +about. For example, the coff back end keeps the original +symbol table structure as well as the canonical structure when +a BFD is read in. On output, the coff back end can reconstruct +the output symbol table so that no information is lost, even +information unique to coff which BFD doesn't know or +understand. If a coff symbol table were read, but were written +through an a.out back end, all the coff specific information +would be lost. The symbol table of a BFD +is not necessarily read in until a canonicalize request is +made. Then the BFD back end fills in a table provided by the +application with pointers to the canonical information. To +output symbols, the application provides BFD with a table of +pointers to pointers to @code{asymbol}s. This allows applications +like the linker to output a symbol as it was read, since the ``behind +the scenes'' information will be still available. +@menu +* Reading Symbols:: +* Writing Symbols:: +* Mini Symbols:: +* typedef asymbol:: +* symbol handling functions:: +@end menu +@* +@node Reading Symbols, Writing Symbols, Symbols, Symbols +@subsection Reading symbols +There are two stages to reading a symbol table from a BFD: +allocating storage, and the actual reading process. This is an +excerpt from an application which reads the symbol table: + +@example + long storage_needed; + asymbol **symbol_table; + long number_of_symbols; + long i; + + storage_needed = bfd_get_symtab_upper_bound (abfd); + + if (storage_needed < 0) + FAIL + + if (storage_needed == 0) @{ + return ; + @} + symbol_table = (asymbol **) xmalloc (storage_needed); + ... + number_of_symbols = + bfd_canonicalize_symtab (abfd, symbol_table); + + if (number_of_symbols < 0) + FAIL + + for (i = 0; i < number_of_symbols; i++) @{ + process_symbol (symbol_table[i]); + @} +@end example + +All storage for the symbols themselves is in an objalloc +connected to the BFD; it is freed when the BFD is closed. +@* +@node Writing Symbols, Mini Symbols, Reading Symbols, Symbols +@subsection Writing symbols +Writing of a symbol table is automatic when a BFD open for +writing is closed. The application attaches a vector of +pointers to pointers to symbols to the BFD being written, and +fills in the symbol count. The close and cleanup code reads +through the table provided and performs all the necessary +operations. The BFD output code must always be provided with an +``owned'' symbol: one which has come from another BFD, or one +which has been created using @code{bfd_make_empty_symbol}. Here is an +example showing the creation of a symbol table with only one element: + +@example + #include "bfd.h" + main() + @{ + bfd *abfd; + asymbol *ptrs[2]; + asymbol *new; + + abfd = bfd_openw("foo","a.out-sunos-big"); + bfd_set_format(abfd, bfd_object); + new = bfd_make_empty_symbol(abfd); + new->name = "dummy_symbol"; + new->section = bfd_make_section_old_way(abfd, ".text"); + new->flags = BSF_GLOBAL; + new->value = 0x12345; + + ptrs[0] = new; + ptrs[1] = (asymbol *)0; + + bfd_set_symtab(abfd, ptrs, 1); + bfd_close(abfd); + @} + + ./makesym + nm foo + 00012345 A dummy_symbol +@end example + +Many formats cannot represent arbitary symbol information; for +instance, the @code{a.out} object format does not allow an +arbitary number of sections. A symbol pointing to a section +which is not one of @code{.text}, @code{.data} or @code{.bss} cannot +be described. +@* +@node Mini Symbols, typedef asymbol, Writing Symbols, Symbols +@subsection Mini Symbols +Mini symbols provide read-only access to the symbol table. +They use less memory space, but require more time to access. +They can be useful for tools like nm or objdump, which may +have to handle symbol tables of extremely large executables. + +The @code{bfd_read_minisymbols} function will read the symbols +into memory in an internal form. It will return a @code{void *} +pointer to a block of memory, a symbol count, and the size of +each symbol. The pointer is allocated using @code{malloc}, and +should be freed by the caller when it is no longer needed. + +The function @code{bfd_minisymbol_to_symbol} will take a pointer +to a minisymbol, and a pointer to a structure returned by +@code{bfd_make_empty_symbol}, and return a @code{asymbol} structure. +The return value may or may not be the same as the value from +@code{bfd_make_empty_symbol} which was passed in. +@* + +@node typedef asymbol, symbol handling functions, Mini Symbols, Symbols +@subsection typedef asymbol +An @code{asymbol} has the form: +@* +. +@example +typedef struct symbol_cache_entry +@{ + /* A pointer to the BFD which owns the symbol. This information + is necessary so that a back end can work out what additional + information (invisible to the application writer) is carried + with the symbol. + + This field is *almost* redundant, since you can use section->owner + instead, except that some symbols point to the global sections + bfd_@{abs,com,und@}_section. This could be fixed by making + these globals be per-bfd (or per-target-flavor). FIXME. */ + + struct _bfd *the_bfd; /* Use bfd_asymbol_bfd(sym) to access this field. */ + + /* The text of the symbol. The name is left alone, and not copied; the + application may not alter it. */ + CONST char *name; + + /* The value of the symbol. This really should be a union of a + numeric value with a pointer, since some flags indicate that + a pointer to another symbol is stored here. */ + symvalue value; + + /* Attributes of a symbol: */ + +#define BSF_NO_FLAGS 0x00 + + /* The symbol has local scope; @code{static} in @code{C}. The value + is the offset into the section of the data. */ +#define BSF_LOCAL 0x01 + + /* The symbol has global scope; initialized data in @code{C}. The + value is the offset into the section of the data. */ +#define BSF_GLOBAL 0x02 + + /* The symbol has global scope and is exported. The value is + the offset into the section of the data. */ +#define BSF_EXPORT BSF_GLOBAL /* no real difference */ + + /* A normal C symbol would be one of: + @code{BSF_LOCAL}, @code{BSF_FORT_COMM}, @code{BSF_UNDEFINED} or + @code{BSF_GLOBAL} */ + + /* The symbol is a debugging record. The value has an arbitary + meaning. */ +#define BSF_DEBUGGING 0x08 + + /* The symbol denotes a function entry point. Used in ELF, + perhaps others someday. */ +#define BSF_FUNCTION 0x10 + + /* Used by the linker. */ +#define BSF_KEEP 0x20 +#define BSF_KEEP_G 0x40 + + /* A weak global symbol, overridable without warnings by + a regular global symbol of the same name. */ +#define BSF_WEAK 0x80 + + /* This symbol was created to point to a section, e.g. ELF's + STT_SECTION symbols. */ +#define BSF_SECTION_SYM 0x100 + + /* The symbol used to be a common symbol, but now it is + allocated. */ +#define BSF_OLD_COMMON 0x200 + + /* The default value for common data. */ +#define BFD_FORT_COMM_DEFAULT_VALUE 0 + + /* In some files the type of a symbol sometimes alters its + location in an output file - ie in coff a @code{ISFCN} symbol + which is also @code{C_EXT} symbol appears where it was + declared and not at the end of a section. This bit is set + by the target BFD part to convey this information. */ + +#define BSF_NOT_AT_END 0x400 + + /* Signal that the symbol is the label of constructor section. */ +#define BSF_CONSTRUCTOR 0x800 + + /* Signal that the symbol is a warning symbol. The name is a + warning. The name of the next symbol is the one to warn about; + if a reference is made to a symbol with the same name as the next + symbol, a warning is issued by the linker. */ +#define BSF_WARNING 0x1000 + + /* Signal that the symbol is indirect. This symbol is an indirect + pointer to the symbol with the same name as the next symbol. */ +#define BSF_INDIRECT 0x2000 + + /* BSF_FILE marks symbols that contain a file name. This is used + for ELF STT_FILE symbols. */ +#define BSF_FILE 0x4000 + + /* Symbol is from dynamic linking information. */ +#define BSF_DYNAMIC 0x8000 + + /* The symbol denotes a data object. Used in ELF, and perhaps + others someday. */ +#define BSF_OBJECT 0x10000 + + flagword flags; + + /* A pointer to the section to which this symbol is + relative. This will always be non NULL, there are special + sections for undefined and absolute symbols. */ + struct sec *section; + + /* Back end special data. */ + union + @{ + PTR p; + bfd_vma i; + @} udata; + +@} asymbol; +@end example + +@node symbol handling functions, , typedef asymbol, Symbols +@subsection Symbol handling functions + +@* +@findex bfd_get_symtab_upper_bound +@subsubsection @code{bfd_get_symtab_upper_bound} +@strong{Description}@* +Return the number of bytes required to store a vector of pointers +to @code{asymbols} for all the symbols in the BFD @var{abfd}, +including a terminal NULL pointer. If there are no symbols in +the BFD, then return 0. If an error occurs, return -1. +@example +#define bfd_get_symtab_upper_bound(abfd) \ + BFD_SEND (abfd, _bfd_get_symtab_upper_bound, (abfd)) +@end example +@* +@findex bfd_is_local_label +@subsubsection @code{bfd_is_local_label} +@strong{Synopsis} +@example +boolean bfd_is_local_label(bfd *abfd, asymbol *sym); +@end example +@strong{Description}@* +Return true if the given symbol @var{sym} in the BFD @var{abfd} is +a compiler generated local label, else return false. +@* +@findex bfd_is_local_label_name +@subsubsection @code{bfd_is_local_label_name} +@strong{Synopsis} +@example +boolean bfd_is_local_label_name(bfd *abfd, const char *name); +@end example +@strong{Description}@* +Return true if a symbol with the name @var{name} in the BFD +@var{abfd} is a compiler generated local label, else return +false. This just checks whether the name has the form of a +local label. +@example +#define bfd_is_local_label_name(abfd, name) \ + BFD_SEND (abfd, _bfd_is_local_label_name, (abfd, name)) +@end example +@* +@findex bfd_canonicalize_symtab +@subsubsection @code{bfd_canonicalize_symtab} +@strong{Description}@* +Read the symbols from the BFD @var{abfd}, and fills in +the vector @var{location} with pointers to the symbols and +a trailing NULL. +Return the actual number of symbol pointers, not +including the NULL. +@example +#define bfd_canonicalize_symtab(abfd, location) \ + BFD_SEND (abfd, _bfd_canonicalize_symtab,\ + (abfd, location)) +@end example +@* +@findex bfd_set_symtab +@subsubsection @code{bfd_set_symtab} +@strong{Synopsis} +@example +boolean bfd_set_symtab (bfd *abfd, asymbol **location, unsigned int count); +@end example +@strong{Description}@* +Arrange that when the output BFD @var{abfd} is closed, +the table @var{location} of @var{count} pointers to symbols +will be written. +@* +@findex bfd_print_symbol_vandf +@subsubsection @code{bfd_print_symbol_vandf} +@strong{Synopsis} +@example +void bfd_print_symbol_vandf(PTR file, asymbol *symbol); +@end example +@strong{Description}@* +Print the value and flags of the @var{symbol} supplied to the +stream @var{file}. +@* +@findex bfd_make_empty_symbol +@subsubsection @code{bfd_make_empty_symbol} +@strong{Description}@* +Create a new @code{asymbol} structure for the BFD @var{abfd} +and return a pointer to it. + +This routine is necessary because each back end has private +information surrounding the @code{asymbol}. Building your own +@code{asymbol} and pointing to it will not create the private +information, and will cause problems later on. +@example +#define bfd_make_empty_symbol(abfd) \ + BFD_SEND (abfd, _bfd_make_empty_symbol, (abfd)) +@end example +@* +@findex bfd_make_debug_symbol +@subsubsection @code{bfd_make_debug_symbol} +@strong{Description}@* +Create a new @code{asymbol} structure for the BFD @var{abfd}, +to be used as a debugging symbol. Further details of its use have +yet to be worked out. +@example +#define bfd_make_debug_symbol(abfd,ptr,size) \ + BFD_SEND (abfd, _bfd_make_debug_symbol, (abfd, ptr, size)) +@end example +@* +@findex bfd_decode_symclass +@subsubsection @code{bfd_decode_symclass} +@strong{Description}@* +Return a character corresponding to the symbol +class of @var{symbol}, or '?' for an unknown class. +@* +@strong{Synopsis} +@example +int bfd_decode_symclass(asymbol *symbol); +@end example +@findex bfd_symbol_info +@subsubsection @code{bfd_symbol_info} +@strong{Description}@* +Fill in the basic info about symbol that nm needs. +Additional info may be added by the back-ends after +calling this function. +@* +@strong{Synopsis} +@example +void bfd_symbol_info(asymbol *symbol, symbol_info *ret); +@end example +@findex bfd_copy_private_symbol_data +@subsubsection @code{bfd_copy_private_symbol_data} +@strong{Synopsis} +@example +boolean bfd_copy_private_symbol_data(bfd *ibfd, asymbol *isym, bfd *obfd, asymbol *osym); +@end example +@strong{Description}@* +Copy private symbol information from @var{isym} in the BFD +@var{ibfd} to the symbol @var{osym} in the BFD @var{obfd}. +Return @code{true} on success, @code{false} on error. Possible error +returns are: + +@itemize @bullet + +@item +@code{bfd_error_no_memory} - +Not enough memory exists to create private data for @var{osec}. +@end itemize +@example +#define bfd_copy_private_symbol_data(ibfd, isymbol, obfd, osymbol) \ + BFD_SEND (obfd, _bfd_copy_private_symbol_data, \ + (ibfd, isymbol, obfd, osymbol)) +@end example +@* diff --git a/gnu/usr.bin/binutils/bfd/doc/targets.texi b/gnu/usr.bin/binutils/bfd/doc/targets.texi new file mode 100644 index 00000000000..05dce15a2f8 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/targets.texi @@ -0,0 +1,478 @@ +@section Targets + +@* +@strong{Description}@* +Each port of BFD to a different machine requries the creation +of a target back end. All the back end provides to the root +part of BFD is a structure containing pointers to functions +which perform certain low level operations on files. BFD +translates the applications's requests through a pointer into +calls to the back end routines. + +When a file is opened with @code{bfd_openr}, its format and +target are unknown. BFD uses various mechanisms to determine +how to interpret the file. The operations performed are: + +@itemize @bullet + +@item +Create a BFD by calling the internal routine +@code{_bfd_new_bfd}, then call @code{bfd_find_target} with the +target string supplied to @code{bfd_openr} and the new BFD pointer. + +@item +If a null target string was provided to @code{bfd_find_target}, +look up the environment variable @code{GNUTARGET} and use +that as the target string. + +@item +If the target string is still @code{NULL}, or the target string is +@code{default}, then use the first item in the target vector +as the target type, and set @code{target_defaulted} in the BFD to +cause @code{bfd_check_format} to loop through all the targets. +@xref{bfd_target}. @xref{Formats}. + +@item +Otherwise, inspect the elements in the target vector +one by one, until a match on target name is found. When found, +use it. + +@item +Otherwise return the error @code{bfd_error_invalid_target} to +@code{bfd_openr}. + +@item +@code{bfd_openr} attempts to open the file using +@code{bfd_open_file}, and returns the BFD. +@end itemize +Once the BFD has been opened and the target selected, the file +format may be determined. This is done by calling +@code{bfd_check_format} on the BFD with a suggested format. +If @code{target_defaulted} has been set, each possible target +type is tried to see if it recognizes the specified format. +@code{bfd_check_format} returns @code{true} when the caller guesses right. +@menu +* bfd_target:: +@end menu +@* +@node bfd_target, , Targets, Targets + +@subsection bfd_target + +@* +@strong{Description}@* +This structure contains everything that BFD knows about a +target. It includes things like its byte order, name, and which +routines to call to do various operations. + +Every BFD points to a target structure with its @code{xvec} +member. + +The macros below are used to dispatch to functions through the +@code{bfd_target} vector. They are used in a number of macros further +down in @file{bfd.h}, and are also used when calling various +routines by hand inside the BFD implementation. The @var{arglist} +argument must be parenthesized; it contains all the arguments +to the called function. + +They make the documentation (more) unpleasant to read, so if +someone wants to fix this and not break the above, please do. +@example +#define BFD_SEND(bfd, message, arglist) \ + ((*((bfd)->xvec->message)) arglist) + +#ifdef DEBUG_BFD_SEND +#undef BFD_SEND +#define BFD_SEND(bfd, message, arglist) \ + (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \ + ((*((bfd)->xvec->message)) arglist) : \ + (bfd_assert (__FILE__,__LINE__), NULL)) +#endif +@end example +For operations which index on the BFD format: +@example +#define BFD_SEND_FMT(bfd, message, arglist) \ + (((bfd)->xvec->message[(int)((bfd)->format)]) arglist) + +#ifdef DEBUG_BFD_SEND +#undef BFD_SEND_FMT +#define BFD_SEND_FMT(bfd, message, arglist) \ + (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \ + (((bfd)->xvec->message[(int)((bfd)->format)]) arglist) : \ + (bfd_assert (__FILE__,__LINE__), NULL)) +#endif +@end example +This is the structure which defines the type of BFD this is. The +@code{xvec} member of the struct @code{bfd} itself points here. Each +module that implements access to a different target under BFD, +defines one of these. + +FIXME, these names should be rationalised with the names of +the entry points which call them. Too bad we can't have one +macro to define them both! +@example +enum bfd_flavour @{ + bfd_target_unknown_flavour, + bfd_target_aout_flavour, + bfd_target_coff_flavour, + bfd_target_ecoff_flavour, + bfd_target_elf_flavour, + bfd_target_ieee_flavour, + bfd_target_nlm_flavour, + bfd_target_oasys_flavour, + bfd_target_tekhex_flavour, + bfd_target_srec_flavour, + bfd_target_ihex_flavour, + bfd_target_som_flavour, + bfd_target_os9k_flavour, + bfd_target_versados_flavour, + bfd_target_msdos_flavour, + bfd_target_evax_flavour +@}; + +enum bfd_endian @{ BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN @}; + + /* Forward declaration. */ +typedef struct bfd_link_info _bfd_link_info; + +typedef struct bfd_target +@{ +@end example +Identifies the kind of target, e.g., SunOS4, Ultrix, etc. +@example + char *name; +@end example +The "flavour" of a back end is a general indication about the contents +of a file. +@example + enum bfd_flavour flavour; +@end example +The order of bytes within the data area of a file. +@example + enum bfd_endian byteorder; +@end example +The order of bytes within the header parts of a file. +@example + enum bfd_endian header_byteorder; +@end example +A mask of all the flags which an executable may have set - +from the set @code{BFD_NO_FLAGS}, @code{HAS_RELOC}, ...@code{D_PAGED}. +@example + flagword object_flags; +@end example +A mask of all the flags which a section may have set - from +the set @code{SEC_NO_FLAGS}, @code{SEC_ALLOC}, ...@code{SET_NEVER_LOAD}. +@example + flagword section_flags; +@end example +The character normally found at the front of a symbol +(if any), perhaps `_'. +@example + char symbol_leading_char; +@end example +The pad character for file names within an archive header. +@example + char ar_pad_char; +@end example +The maximum number of characters in an archive header. +@example + unsigned short ar_max_namelen; +@end example +Entries for byte swapping for data. These are different from the other +entry points, since they don't take a BFD asthe first argument. +Certain other handlers could do the same. +@example + bfd_vma (*bfd_getx64) PARAMS ((const bfd_byte *)); + bfd_signed_vma (*bfd_getx_signed_64) PARAMS ((const bfd_byte *)); + void (*bfd_putx64) PARAMS ((bfd_vma, bfd_byte *)); + bfd_vma (*bfd_getx32) PARAMS ((const bfd_byte *)); + bfd_signed_vma (*bfd_getx_signed_32) PARAMS ((const bfd_byte *)); + void (*bfd_putx32) PARAMS ((bfd_vma, bfd_byte *)); + bfd_vma (*bfd_getx16) PARAMS ((const bfd_byte *)); + bfd_signed_vma (*bfd_getx_signed_16) PARAMS ((const bfd_byte *)); + void (*bfd_putx16) PARAMS ((bfd_vma, bfd_byte *)); +@end example +Byte swapping for the headers +@example + bfd_vma (*bfd_h_getx64) PARAMS ((const bfd_byte *)); + bfd_signed_vma (*bfd_h_getx_signed_64) PARAMS ((const bfd_byte *)); + void (*bfd_h_putx64) PARAMS ((bfd_vma, bfd_byte *)); + bfd_vma (*bfd_h_getx32) PARAMS ((const bfd_byte *)); + bfd_signed_vma (*bfd_h_getx_signed_32) PARAMS ((const bfd_byte *)); + void (*bfd_h_putx32) PARAMS ((bfd_vma, bfd_byte *)); + bfd_vma (*bfd_h_getx16) PARAMS ((const bfd_byte *)); + bfd_signed_vma (*bfd_h_getx_signed_16) PARAMS ((const bfd_byte *)); + void (*bfd_h_putx16) PARAMS ((bfd_vma, bfd_byte *)); +@end example +Format dependent routines: these are vectors of entry points +within the target vector structure, one for each format to check. + +Check the format of a file being read. Return a @code{bfd_target *} or zero. +@example + const struct bfd_target *(*_bfd_check_format[bfd_type_end]) PARAMS ((bfd *)); +@end example +Set the format of a file being written. +@example + boolean (*_bfd_set_format[bfd_type_end]) PARAMS ((bfd *)); +@end example +Write cached information into a file being written, at @code{bfd_close}. +@example + boolean (*_bfd_write_contents[bfd_type_end]) PARAMS ((bfd *)); +@end example +The general target vector. +@example + + /* Generic entry points. */ +#define BFD_JUMP_TABLE_GENERIC(NAME)\ +CAT(NAME,_close_and_cleanup),\ +CAT(NAME,_bfd_free_cached_info),\ +CAT(NAME,_new_section_hook),\ +CAT(NAME,_get_section_contents),\ +CAT(NAME,_get_section_contents_in_window) + + /* Called when the BFD is being closed to do any necessary cleanup. */ + boolean (*_close_and_cleanup) PARAMS ((bfd *)); + /* Ask the BFD to free all cached information. */ + boolean (*_bfd_free_cached_info) PARAMS ((bfd *)); + /* Called when a new section is created. */ + boolean (*_new_section_hook) PARAMS ((bfd *, sec_ptr)); + /* Read the contents of a section. */ + boolean (*_bfd_get_section_contents) PARAMS ((bfd *, sec_ptr, PTR, + file_ptr, bfd_size_type)); + boolean (*_bfd_get_section_contents_in_window) + PARAMS ((bfd *, sec_ptr, bfd_window *, + file_ptr, bfd_size_type)); + + /* Entry points to copy private data. */ +#define BFD_JUMP_TABLE_COPY(NAME)\ +CAT(NAME,_bfd_copy_private_bfd_data),\ +CAT(NAME,_bfd_merge_private_bfd_data),\ +CAT(NAME,_bfd_copy_private_section_data),\ +CAT(NAME,_bfd_copy_private_symbol_data),\ +CAT(NAME,_bfd_set_private_flags),\ +CAT(NAME,_bfd_print_private_bfd_data)\ + /* Called to copy BFD general private data from one object file + to another. */ + boolean (*_bfd_copy_private_bfd_data) PARAMS ((bfd *, bfd *)); + /* Called to merge BFD general private data from one object file + to a common output file when linking. */ + boolean (*_bfd_merge_private_bfd_data) PARAMS ((bfd *, bfd *)); + /* Called to copy BFD private section data from one object file + to another. */ + boolean (*_bfd_copy_private_section_data) PARAMS ((bfd *, sec_ptr, + bfd *, sec_ptr)); + /* Called to copy BFD private symbol data from one symbol + to another. */ + boolean (*_bfd_copy_private_symbol_data) PARAMS ((bfd *, asymbol *, + bfd *, asymbol *)); + /* Called to set private backend flags */ + boolean (*_bfd_set_private_flags) PARAMS ((bfd *, flagword)); + + /* Called to print private BFD data */ + boolean (*_bfd_print_private_bfd_data) PARAMS ((bfd *, PTR)); + + /* Core file entry points. */ +#define BFD_JUMP_TABLE_CORE(NAME)\ +CAT(NAME,_core_file_failing_command),\ +CAT(NAME,_core_file_failing_signal),\ +CAT(NAME,_core_file_matches_executable_p) + char * (*_core_file_failing_command) PARAMS ((bfd *)); + int (*_core_file_failing_signal) PARAMS ((bfd *)); + boolean (*_core_file_matches_executable_p) PARAMS ((bfd *, bfd *)); + + /* Archive entry points. */ +#define BFD_JUMP_TABLE_ARCHIVE(NAME)\ +CAT(NAME,_slurp_armap),\ +CAT(NAME,_slurp_extended_name_table),\ +CAT(NAME,_construct_extended_name_table),\ +CAT(NAME,_truncate_arname),\ +CAT(NAME,_write_armap),\ +CAT(NAME,_read_ar_hdr),\ +CAT(NAME,_openr_next_archived_file),\ +CAT(NAME,_get_elt_at_index),\ +CAT(NAME,_generic_stat_arch_elt),\ +CAT(NAME,_update_armap_timestamp) + boolean (*_bfd_slurp_armap) PARAMS ((bfd *)); + boolean (*_bfd_slurp_extended_name_table) PARAMS ((bfd *)); + boolean (*_bfd_construct_extended_name_table) + PARAMS ((bfd *, char **, bfd_size_type *, const char **)); + void (*_bfd_truncate_arname) PARAMS ((bfd *, CONST char *, char *)); + boolean (*write_armap) PARAMS ((bfd *arch, + unsigned int elength, + struct orl *map, + unsigned int orl_count, + int stridx)); + PTR (*_bfd_read_ar_hdr_fn) PARAMS ((bfd *)); + bfd * (*openr_next_archived_file) PARAMS ((bfd *arch, bfd *prev)); +#define bfd_get_elt_at_index(b,i) BFD_SEND(b, _bfd_get_elt_at_index, (b,i)) + bfd * (*_bfd_get_elt_at_index) PARAMS ((bfd *, symindex)); + int (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *)); + boolean (*_bfd_update_armap_timestamp) PARAMS ((bfd *)); + + /* Entry points used for symbols. */ +#define BFD_JUMP_TABLE_SYMBOLS(NAME)\ +CAT(NAME,_get_symtab_upper_bound),\ +CAT(NAME,_get_symtab),\ +CAT(NAME,_make_empty_symbol),\ +CAT(NAME,_print_symbol),\ +CAT(NAME,_get_symbol_info),\ +CAT(NAME,_bfd_is_local_label_name),\ +CAT(NAME,_get_lineno),\ +CAT(NAME,_find_nearest_line),\ +CAT(NAME,_bfd_make_debug_symbol),\ +CAT(NAME,_read_minisymbols),\ +CAT(NAME,_minisymbol_to_symbol) + long (*_bfd_get_symtab_upper_bound) PARAMS ((bfd *)); + long (*_bfd_canonicalize_symtab) PARAMS ((bfd *, + struct symbol_cache_entry **)); + struct symbol_cache_entry * + (*_bfd_make_empty_symbol) PARAMS ((bfd *)); + void (*_bfd_print_symbol) PARAMS ((bfd *, PTR, + struct symbol_cache_entry *, + bfd_print_symbol_type)); +#define bfd_print_symbol(b,p,s,e) BFD_SEND(b, _bfd_print_symbol, (b,p,s,e)) + void (*_bfd_get_symbol_info) PARAMS ((bfd *, + struct symbol_cache_entry *, + symbol_info *)); +#define bfd_get_symbol_info(b,p,e) BFD_SEND(b, _bfd_get_symbol_info, (b,p,e)) + boolean (*_bfd_is_local_label_name) PARAMS ((bfd *, const char *)); + + alent * (*_get_lineno) PARAMS ((bfd *, struct symbol_cache_entry *)); + boolean (*_bfd_find_nearest_line) PARAMS ((bfd *abfd, + struct sec *section, struct symbol_cache_entry **symbols, + bfd_vma offset, CONST char **file, CONST char **func, + unsigned int *line)); + /* Back-door to allow format-aware applications to create debug symbols + while using BFD for everything else. Currently used by the assembler + when creating COFF files. */ + asymbol * (*_bfd_make_debug_symbol) PARAMS (( + bfd *abfd, + void *ptr, + unsigned long size)); +#define bfd_read_minisymbols(b, d, m, s) \ + BFD_SEND (b, _read_minisymbols, (b, d, m, s)) + long (*_read_minisymbols) PARAMS ((bfd *, boolean, PTR *, + unsigned int *)); +#define bfd_minisymbol_to_symbol(b, d, m, f) \ + BFD_SEND (b, _minisymbol_to_symbol, (b, d, m, f)) + asymbol *(*_minisymbol_to_symbol) PARAMS ((bfd *, boolean, const PTR, + asymbol *)); + + /* Routines for relocs. */ +#define BFD_JUMP_TABLE_RELOCS(NAME)\ +CAT(NAME,_get_reloc_upper_bound),\ +CAT(NAME,_canonicalize_reloc),\ +CAT(NAME,_bfd_reloc_type_lookup) + long (*_get_reloc_upper_bound) PARAMS ((bfd *, sec_ptr)); + long (*_bfd_canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **, + struct symbol_cache_entry **)); + /* See documentation on reloc types. */ + reloc_howto_type * + (*reloc_type_lookup) PARAMS ((bfd *abfd, + bfd_reloc_code_real_type code)); + + /* Routines used when writing an object file. */ +#define BFD_JUMP_TABLE_WRITE(NAME)\ +CAT(NAME,_set_arch_mach),\ +CAT(NAME,_set_section_contents) + boolean (*_bfd_set_arch_mach) PARAMS ((bfd *, enum bfd_architecture, + unsigned long)); + boolean (*_bfd_set_section_contents) PARAMS ((bfd *, sec_ptr, PTR, + file_ptr, bfd_size_type)); + + /* Routines used by the linker. */ +#define BFD_JUMP_TABLE_LINK(NAME)\ +CAT(NAME,_sizeof_headers),\ +CAT(NAME,_bfd_get_relocated_section_contents),\ +CAT(NAME,_bfd_relax_section),\ +CAT(NAME,_bfd_link_hash_table_create),\ +CAT(NAME,_bfd_link_add_symbols),\ +CAT(NAME,_bfd_final_link),\ +CAT(NAME,_bfd_link_split_section) + int (*_bfd_sizeof_headers) PARAMS ((bfd *, boolean)); + bfd_byte * (*_bfd_get_relocated_section_contents) PARAMS ((bfd *, + struct bfd_link_info *, struct bfd_link_order *, + bfd_byte *data, boolean relocateable, + struct symbol_cache_entry **)); + + boolean (*_bfd_relax_section) PARAMS ((bfd *, struct sec *, + struct bfd_link_info *, boolean *again)); + + /* Create a hash table for the linker. Different backends store + different information in this table. */ + struct bfd_link_hash_table *(*_bfd_link_hash_table_create) PARAMS ((bfd *)); + + /* Add symbols from this object file into the hash table. */ + boolean (*_bfd_link_add_symbols) PARAMS ((bfd *, struct bfd_link_info *)); + + /* Do a link based on the link_order structures attached to each + section of the BFD. */ + boolean (*_bfd_final_link) PARAMS ((bfd *, struct bfd_link_info *)); + + /* Should this section be split up into smaller pieces during linking. */ + boolean (*_bfd_link_split_section) PARAMS ((bfd *, struct sec *)); + + /* Routines to handle dynamic symbols and relocs. */ +#define BFD_JUMP_TABLE_DYNAMIC(NAME)\ +CAT(NAME,_get_dynamic_symtab_upper_bound),\ +CAT(NAME,_canonicalize_dynamic_symtab),\ +CAT(NAME,_get_dynamic_reloc_upper_bound),\ +CAT(NAME,_canonicalize_dynamic_reloc) + /* Get the amount of memory required to hold the dynamic symbols. */ + long (*_bfd_get_dynamic_symtab_upper_bound) PARAMS ((bfd *)); + /* Read in the dynamic symbols. */ + long (*_bfd_canonicalize_dynamic_symtab) + PARAMS ((bfd *, struct symbol_cache_entry **)); + /* Get the amount of memory required to hold the dynamic relocs. */ + long (*_bfd_get_dynamic_reloc_upper_bound) PARAMS ((bfd *)); + /* Read in the dynamic relocs. */ + long (*_bfd_canonicalize_dynamic_reloc) + PARAMS ((bfd *, arelent **, struct symbol_cache_entry **)); + +@end example +Data for use by back-end routines, which isn't generic enough to belong +in this structure. +@example + PTR backend_data; +@} bfd_target; +@end example +@* +@findex bfd_set_default_target +@subsubsection @code{bfd_set_default_target} +@strong{Synopsis} +@example +boolean bfd_set_default_target (const char *name); +@end example +@strong{Description}@* +Set the default target vector to use when recognizing a BFD. +This takes the name of the target, which may be a BFD target +name or a configuration triplet. +@* +@findex bfd_find_target +@subsubsection @code{bfd_find_target} +@strong{Synopsis} +@example +const bfd_target *bfd_find_target(CONST char *target_name, bfd *abfd); +@end example +@strong{Description}@* +Return a pointer to the transfer vector for the object target +named @var{target_name}. If @var{target_name} is @code{NULL}, choose the +one in the environment variable @code{GNUTARGET}; if that is null or not +defined, then choose the first entry in the target list. +Passing in the string "default" or setting the environment +variable to "default" will cause the first entry in the target +list to be returned, and "target_defaulted" will be set in the +BFD. This causes @code{bfd_check_format} to loop over all the +targets to find the one that matches the file being read. +@* +@findex bfd_target_list +@subsubsection @code{bfd_target_list} +@strong{Synopsis} +@example +const char **bfd_target_list(void); +@end example +@strong{Description}@* +Return a freshly malloced NULL-terminated +vector of the names of all the valid BFD targets. Do not +modify the names. +@* diff --git a/gnu/usr.bin/binutils/bfd/makefile.vms b/gnu/usr.bin/binutils/bfd/makefile.vms index 1d131d63379..bc70bcd2f85 100644 --- a/gnu/usr.bin/binutils/bfd/makefile.vms +++ b/gnu/usr.bin/binutils/bfd/makefile.vms @@ -1,12 +1,11 @@ # -# Makefile for bfd library under openVMS/AXP +# Makefile for bfd library under openVMS/Alpha # # For use with gnu-make for vms # -# Created by Klaus Kaempf, kkaempf@progis.de +# Created by Klaus K"ampf, kkaempf@progis.de # # -CC=gcc OBJS=archive.obj,archures.obj,bfd.obj,cache.obj,coffgen.obj,corefile.obj,format.obj,\ init.obj,libbfd.obj,opncls.obj,reloc.obj,section.obj,syms.obj,targets.obj,\ @@ -15,7 +14,8 @@ OBJS=archive.obj,archures.obj,bfd.obj,cache.obj,coffgen.obj,corefile.obj,format. cpu-alpha.obj ifeq ($(CC),gcc) -DEFS=/define=(SELECT_VECS="&evax_alpha_vec",SELECT_ARCHITECTURES="&bfd_alpha_arch","unlink=remove") +DEFS=/define=(SELECT_VECS="&evax_alpha_vec",SELECT_ARCHITECTURES="&bfd_alpha_arch",\ +"HAVE_evax_alpha_vec=1") CFLAGS=/include=([],[-.include])$(DEFS) else DEFS=/define=(DEFAULT_VECTOR="evax_alpha_vec",SELECT_VECS="&evax_alpha_vec",\ @@ -33,14 +33,25 @@ libbfd.olb: sysdep.h bfd.h $(OBJS) sysdep.h: [.hosts]alphavms.h config.h $(CP) $< $@ -bfd.h: bfd.h-vms - $(CP) $< $@ +bfd.h: bfd-in2.h + $$ @configure -config.h: config.h-vms - $(CP) $< $@ +targmatch.h: bfd.h +config.h: bfd.h evax-alpha.c: evax.h evax-emh.c: evax.h evax-egsd.c: evax.h evax-etir.c: evax.h evax-misc.c: evax.h +targets.c: targmatch.h + + +clean: + $$ purge + $(RM) libbfd.olb; + $(RM) sysdep.h; + $(RM) bfd.h; + $(RM) targmatch.h; + $(RM) config.h; + $(RM) *.obj; diff --git a/gnu/usr.bin/binutils/bfd/sparclinux.c b/gnu/usr.bin/binutils/bfd/sparclinux.c new file mode 100644 index 00000000000..3e051a2daf8 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/sparclinux.c @@ -0,0 +1,770 @@ +/* BFD back-end for linux flavored sparc a.out binaries. + Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc. + +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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, +USA. */ + +#define TARGET_PAGE_SIZE 4096 +#define ZMAGIC_DISK_BLOCK_SIZE 1024 +#define SEGMENT_SIZE TARGET_PAGE_SIZE +#define TEXT_START_ADDR 0x0 +#define N_SHARED_LIB(x) 0 +#define BYTES_IN_WORD 4 + +#define MACHTYPE_OK(mtype) ((mtype) == M_SPARC || (mtype) == M_UNKNOWN) + +#include "bfd.h" +#include "sysdep.h" +#include "libbfd.h" +#include "aout/aout64.h" +#include "aout/stab_gnu.h" +#include "aout/ar.h" +#include "libaout.h" /* BFD a.out internal data structures */ + +#define DEFAULT_ARCH bfd_arch_sparc +#define MY(OP) CAT(sparclinux_,OP) +#define TARGETNAME "a.out-sparc-linux" + +extern const bfd_target MY(vec); + +/* We always generate QMAGIC files in preference to ZMAGIC files. It + would be possible to make this a linker option, if that ever + becomes important. */ + +static void MY_final_link_callback + PARAMS ((bfd *, file_ptr *, file_ptr *, file_ptr *)); + +static boolean sparclinux_bfd_final_link + PARAMS ((bfd *abfd, struct bfd_link_info *info)); + +static boolean +sparclinux_bfd_final_link (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + obj_aout_subformat (abfd) = q_magic_format; + return NAME(aout,final_link) (abfd, info, MY_final_link_callback); +} + +#define MY_bfd_final_link sparclinux_bfd_final_link + +/* Set the machine type correctly. */ + +static boolean sparclinux_write_object_contents PARAMS ((bfd *abfd)); + +static boolean +sparclinux_write_object_contents (abfd) + bfd *abfd; +{ + struct external_exec exec_bytes; + struct internal_exec *execp = exec_hdr (abfd); + + N_SET_MACHTYPE (*execp, M_SPARC); + + obj_reloc_entry_size (abfd) = RELOC_STD_SIZE; + + WRITE_HEADERS(abfd, execp); + + return true; +} + +#define MY_write_object_contents sparclinux_write_object_contents +/* Code to link against Linux a.out shared libraries. */ + +/* See if a symbol name is a reference to the global offset table. */ + +#ifndef GOT_REF_PREFIX +#define GOT_REF_PREFIX "__GOT_" +#endif + +#define IS_GOT_SYM(name) \ + (strncmp (name, GOT_REF_PREFIX, sizeof GOT_REF_PREFIX - 1) == 0) + +/* See if a symbol name is a reference to the procedure linkage table. */ + +#ifndef PLT_REF_PREFIX +#define PLT_REF_PREFIX "__PLT_" +#endif + +#define IS_PLT_SYM(name) \ + (strncmp (name, PLT_REF_PREFIX, sizeof PLT_REF_PREFIX - 1) == 0) + +/* This string is used to generate specialized error messages. */ + +#ifndef NEEDS_SHRLIB +#define NEEDS_SHRLIB "__NEEDS_SHRLIB_" +#endif + +/* This special symbol is a set vector that contains a list of + pointers to fixup tables. It will be present in any dynamicly + linked file. The linker generated fixup table should also be added + to the list, and it should always appear in the second slot (the + first one is a dummy with a magic number that is defined in + crt0.o). */ + +#ifndef SHARABLE_CONFLICTS +#define SHARABLE_CONFLICTS "__SHARABLE_CONFLICTS__" +#endif + +/* We keep a list of fixups. The terminology is a bit strange, but + each fixup contains two 32 bit numbers. A regular fixup contains + an address and a pointer, and at runtime we should store the + address at the location pointed to by the pointer. A builtin fixup + contains two pointers, and we should read the address using one + pointer and store it at the location pointed to by the other + pointer. Builtin fixups come into play when we have duplicate + __GOT__ symbols for the same variable. The builtin fixup will copy + the GOT pointer from one over into the other. */ + +struct fixup +{ + struct fixup *next; + struct linux_link_hash_entry *h; + bfd_vma value; + + /* Nonzero if this is a jump instruction that needs to be fixed, + zero if this is just a pointer */ + char jump; + + char builtin; +}; + +/* We don't need a special hash table entry structure, but we do need + to keep some information between linker passes, so we use a special + hash table. */ + +struct linux_link_hash_entry +{ + struct aout_link_hash_entry root; +}; + +struct linux_link_hash_table +{ + struct aout_link_hash_table root; + + /* First dynamic object found in link. */ + bfd *dynobj; + + /* Number of fixups. */ + size_t fixup_count; + + /* Number of builtin fixups. */ + size_t local_builtins; + + /* List of fixups. */ + struct fixup *fixup_list; +}; + +static struct bfd_hash_entry *linux_link_hash_newfunc + PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); +static struct bfd_link_hash_table *linux_link_hash_table_create + PARAMS ((bfd *)); +static struct fixup *new_fixup + PARAMS ((struct bfd_link_info *, struct linux_link_hash_entry *, + bfd_vma, int)); +static boolean linux_link_create_dynamic_sections + PARAMS ((bfd *, struct bfd_link_info *)); +static boolean linux_add_one_symbol + PARAMS ((struct bfd_link_info *, bfd *, const char *, flagword, asection *, + bfd_vma, const char *, boolean, boolean, + struct bfd_link_hash_entry **)); +static boolean linux_tally_symbols + PARAMS ((struct linux_link_hash_entry *, PTR)); +static boolean linux_finish_dynamic_link + PARAMS ((bfd *, struct bfd_link_info *)); + +/* Routine to create an entry in an Linux link hash table. */ + +static struct bfd_hash_entry * +linux_link_hash_newfunc (entry, table, string) + struct bfd_hash_entry *entry; + struct bfd_hash_table *table; + const char *string; +{ + struct linux_link_hash_entry *ret = (struct linux_link_hash_entry *) entry; + + /* Allocate the structure if it has not already been allocated by a + subclass. */ + if (ret == (struct linux_link_hash_entry *) NULL) + ret = ((struct linux_link_hash_entry *) + bfd_hash_allocate (table, sizeof (struct linux_link_hash_entry))); + if (ret == NULL) + return (struct bfd_hash_entry *) ret; + + /* Call the allocation method of the superclass. */ + ret = ((struct linux_link_hash_entry *) + NAME(aout,link_hash_newfunc) ((struct bfd_hash_entry *) ret, + table, string)); + if (ret != NULL) + { + /* Set local fields; there aren't any. */ + } + + return (struct bfd_hash_entry *) ret; +} + +/* Create a Linux link hash table. */ + +static struct bfd_link_hash_table * +linux_link_hash_table_create (abfd) + bfd *abfd; +{ + struct linux_link_hash_table *ret; + + ret = ((struct linux_link_hash_table *) + bfd_alloc (abfd, sizeof (struct linux_link_hash_table))); + if (ret == (struct linux_link_hash_table *) NULL) + return (struct bfd_link_hash_table *) NULL; + if (! NAME(aout,link_hash_table_init) (&ret->root, abfd, + linux_link_hash_newfunc)) + { + free (ret); + return (struct bfd_link_hash_table *) NULL; + } + + ret->dynobj = NULL; + ret->fixup_count = 0; + ret->local_builtins = 0; + ret->fixup_list = NULL; + + return &ret->root.root; +} + +/* Look up an entry in a Linux link hash table. */ + +#define linux_link_hash_lookup(table, string, create, copy, follow) \ + ((struct linux_link_hash_entry *) \ + aout_link_hash_lookup (&(table)->root, (string), (create), (copy),\ + (follow))) + +/* Traverse a Linux link hash table. */ + +#define linux_link_hash_traverse(table, func, info) \ + (aout_link_hash_traverse \ + (&(table)->root, \ + (boolean (*) PARAMS ((struct aout_link_hash_entry *, PTR))) (func), \ + (info))) + +/* Get the Linux link hash table from the info structure. This is + just a cast. */ + +#define linux_hash_table(p) ((struct linux_link_hash_table *) ((p)->hash)) + +/* Store the information for a new fixup. */ + +static struct fixup * +new_fixup (info, h, value, builtin) + struct bfd_link_info *info; + struct linux_link_hash_entry *h; + bfd_vma value; + int builtin; +{ + struct fixup *f; + + f = (struct fixup *) bfd_hash_allocate (&info->hash->table, + sizeof (struct fixup)); + if (f == NULL) + return f; + f->next = linux_hash_table (info)->fixup_list; + linux_hash_table (info)->fixup_list = f; + f->h = h; + f->value = value; + f->builtin = builtin; + f->jump = 0; + ++linux_hash_table (info)->fixup_count; + return f; +} + +/* We come here once we realize that we are going to link to a shared + library. We need to create a special section that contains the + fixup table, and we ultimately need to add a pointer to this into + the set vector for SHARABLE_CONFLICTS. At this point we do not + know the size of the section, but that's OK - we just need to + create it for now. */ + +static boolean +linux_link_create_dynamic_sections (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + flagword flags; + register asection *s; + + /* Note that we set the SEC_IN_MEMORY flag. */ + flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY; + + /* We choose to use the name ".linux-dynamic" for the fixup table. + Why not? */ + s = bfd_make_section (abfd, ".linux-dynamic"); + if (s == NULL + || ! bfd_set_section_flags (abfd, s, flags) + || ! bfd_set_section_alignment (abfd, s, 2)) + return false; + s->_raw_size = 0; + s->contents = 0; + + return true; +} + +/* Function to add a single symbol to the linker hash table. This is + a wrapper around _bfd_generic_link_add_one_symbol which handles the + tweaking needed for dynamic linking support. */ + +static boolean +linux_add_one_symbol (info, abfd, name, flags, section, value, string, + copy, collect, hashp) + struct bfd_link_info *info; + bfd *abfd; + const char *name; + flagword flags; + asection *section; + bfd_vma value; + const char *string; + boolean copy; + boolean collect; + struct bfd_link_hash_entry **hashp; +{ + struct linux_link_hash_entry *h; + boolean insert; + + /* Look up and see if we already have this symbol in the hash table. + If we do, and the defining entry is from a shared library, we + need to create the dynamic sections. + + FIXME: What if abfd->xvec != info->hash->creator? We may want to + be able to link Linux a.out and ELF objects together, but serious + confusion is possible. */ + + insert = false; + + if (! info->relocateable + && linux_hash_table (info)->dynobj == NULL + && strcmp (name, SHARABLE_CONFLICTS) == 0 + && (flags & BSF_CONSTRUCTOR) != 0 + && abfd->xvec == info->hash->creator) + { + if (! linux_link_create_dynamic_sections (abfd, info)) + return false; + linux_hash_table (info)->dynobj = abfd; + insert = true; + } + + if (bfd_is_abs_section (section) + && abfd->xvec == info->hash->creator) + { + h = linux_link_hash_lookup (linux_hash_table (info), name, false, + false, false); + if (h != NULL + && (h->root.root.type == bfd_link_hash_defined + || h->root.root.type == bfd_link_hash_defweak)) + { + struct fixup *f; + + if (hashp != NULL) + *hashp = (struct bfd_link_hash_entry *) h; + + f = new_fixup (info, h, value, ! IS_PLT_SYM (name)); + if (f == NULL) + return false; + f->jump = IS_PLT_SYM (name); + + return true; + } + } + + /* Do the usual procedure for adding a symbol. */ + if (! _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, + value, string, copy, collect, + hashp)) + return false; + + /* Insert a pointer to our table in the set vector. The dynamic + linker requires this information */ + if (insert) + { + asection *s; + + /* Here we do our special thing to add the pointer to the + dynamic section in the SHARABLE_CONFLICTS set vector. */ + s = bfd_get_section_by_name (linux_hash_table (info)->dynobj, + ".linux-dynamic"); + BFD_ASSERT (s != NULL); + + if (! (_bfd_generic_link_add_one_symbol + (info, linux_hash_table (info)->dynobj, SHARABLE_CONFLICTS, + BSF_GLOBAL | BSF_CONSTRUCTOR, s, 0, NULL, false, false, NULL))) + return false; + } + + return true; +} + +/* We will crawl the hash table and come here for every global symbol. + We will examine each entry and see if there are indications that we + need to add a fixup. There are two possible cases - one is where + you have duplicate definitions of PLT or GOT symbols - these will + have already been caught and added as "builtin" fixups. If we find + that the corresponding non PLT/GOT symbol is also present, we + convert it to a regular fixup instead. + + This function is called via linux_link_hash_traverse. */ + +static boolean +linux_tally_symbols (h, data) + struct linux_link_hash_entry *h; + PTR data; +{ + struct bfd_link_info *info = (struct bfd_link_info *) data; + struct fixup *f, *f1; + int is_plt; + struct linux_link_hash_entry *h1, *h2; + boolean exists; + + if (h->root.root.type == bfd_link_hash_undefined + && strncmp (h->root.root.root.string, NEEDS_SHRLIB, + sizeof NEEDS_SHRLIB - 1) == 0) + { + const char *name; + char *p; + char *alloc = NULL; + + name = h->root.root.root.string + sizeof NEEDS_SHRLIB - 1; + p = strrchr (name, '_'); + if (p != NULL) + alloc = (char *) bfd_malloc (strlen (name) + 1); + + if (p == NULL || alloc == NULL) + (*_bfd_error_handler) ("Output file requires shared library `%s'\n", + name); + else + { + strcpy (alloc, name); + p = strrchr (alloc, '_'); + *p++ = '\0'; + (*_bfd_error_handler) + ("Output file requires shared library `%s.so.%s'\n", + alloc, p); + free (alloc); + } + + abort (); + } + + /* If this symbol is not a PLT/GOT, we do not even need to look at + it. */ + is_plt = IS_PLT_SYM (h->root.root.root.string); + + if (is_plt || IS_GOT_SYM (h->root.root.root.string)) + { + /* Look up this symbol twice. Once just as a regular lookup, + and then again following all of the indirect links until we + reach a real symbol. */ + h1 = linux_link_hash_lookup (linux_hash_table (info), + (h->root.root.root.string + + sizeof PLT_REF_PREFIX - 1), + false, false, true); + /* h2 does not follow indirect symbols. */ + h2 = linux_link_hash_lookup (linux_hash_table (info), + (h->root.root.root.string + + sizeof PLT_REF_PREFIX - 1), + false, false, false); + + /* The real symbol must exist but if it is also an ABS symbol, + there is no need to have a fixup. This is because they both + came from the same library. If on the other hand, we had to + use an indirect symbol to get to the real symbol, we add the + fixup anyway, since there are cases where these symbols come + from different shared libraries */ + if (h1 != NULL + && (((h1->root.root.type == bfd_link_hash_defined + || h1->root.root.type == bfd_link_hash_defweak) + && ! bfd_is_abs_section (h1->root.root.u.def.section)) + || h2->root.root.type == bfd_link_hash_indirect)) + { + /* See if there is a "builtin" fixup already present + involving this symbol. If so, convert it to a regular + fixup. In the end, this relaxes some of the requirements + about the order of performing fixups. */ + exists = false; + for (f1 = linux_hash_table (info)->fixup_list; + f1 != NULL; + f1 = f1->next) + { + if ((f1->h != h && f1->h != h1) + || (! f1->builtin && ! f1->jump)) + continue; + if (f1->h == h1) + exists = true; + if (! exists + && bfd_is_abs_section (h->root.root.u.def.section)) + { + f = new_fixup (info, h1, f1->h->root.root.u.def.value, 0); + f->jump = is_plt; + } + f1->h = h1; + f1->jump = is_plt; + f1->builtin = 0; + exists = true; + } + if (! exists + && bfd_is_abs_section (h->root.root.u.def.section)) + { + f = new_fixup (info, h1, h->root.root.u.def.value, 0); + if (f == NULL) + { + /* FIXME: No way to return error. */ + abort (); + } + f->jump = is_plt; + } + } + + /* Quick and dirty way of stripping these symbols from the + symtab. */ + if (bfd_is_abs_section (h->root.root.u.def.section)) + h->root.written = true; + } + + return true; +} + +/* This is called to set the size of the .linux-dynamic section is. + It is called by the Linux linker emulation before_allocation + routine. We have finished reading all of the input files, and now + we just scan the hash tables to find out how many additional fixups + are required. */ + +boolean +bfd_sparclinux_size_dynamic_sections (output_bfd, info) + bfd *output_bfd; + struct bfd_link_info *info; +{ + struct fixup *f; + asection *s; + + if (output_bfd->xvec != &MY(vec)) + return true; + + /* First find the fixups... */ + linux_link_hash_traverse (linux_hash_table (info), + linux_tally_symbols, + (PTR) info); + + /* If there are builtin fixups, leave room for a marker. This is + used by the dynamic linker so that it knows that all that follow + are builtin fixups instead of regular fixups. */ + for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next) + { + if (f->builtin) + { + ++linux_hash_table (info)->fixup_count; + ++linux_hash_table (info)->local_builtins; + break; + } + } + + if (linux_hash_table (info)->dynobj == NULL) + { + if (linux_hash_table (info)->fixup_count > 0) + abort (); + return true; + } + + /* Allocate memory for our fixup table. We will fill it in later. */ + s = bfd_get_section_by_name (linux_hash_table (info)->dynobj, + ".linux-dynamic"); + if (s != NULL) + { + s->_raw_size = 8 + linux_hash_table (info)->fixup_count * 8; + s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size); + if (s->contents == NULL) + return false; + memset (s->contents, 0, (size_t) s->_raw_size); + } + + return true; +} + +/* We come here once we are ready to actually write the fixup table to + the output file. Scan the fixup tables and so forth and generate + the stuff we need. */ + +static boolean +linux_finish_dynamic_link (output_bfd, info) + bfd *output_bfd; + struct bfd_link_info *info; +{ + asection *s, *os, *is; + bfd_byte *fixup_table; + struct linux_link_hash_entry *h; + struct fixup *f; + unsigned int new_addr; + int section_offset; + unsigned int fixups_written; + + if (linux_hash_table (info)->dynobj == NULL) + return true; + + s = bfd_get_section_by_name (linux_hash_table (info)->dynobj, + ".linux-dynamic"); + BFD_ASSERT (s != NULL); + os = s->output_section; + fixups_written = 0; + +#ifdef LINUX_LINK_DEBUG + printf ("Fixup table file offset: %x VMA: %x\n", + os->filepos + s->output_offset, + os->vma + s->output_offset); +#endif + + fixup_table = s->contents; + bfd_put_32 (output_bfd, linux_hash_table (info)->fixup_count, fixup_table); + fixup_table += 4; + + /* Fill in fixup table. */ + for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next) + { + if (f->builtin) + continue; + + if (f->h->root.root.type != bfd_link_hash_defined + && f->h->root.root.type != bfd_link_hash_defweak) + { + (*_bfd_error_handler) + ("Symbol %s not defined for fixups\n", + f->h->root.root.root.string); + continue; + } + + is = f->h->root.root.u.def.section; + section_offset = is->output_section->vma + is->output_offset; + new_addr = f->h->root.root.u.def.value + section_offset; + +#ifdef LINUX_LINK_DEBUG + printf ("Fixup(%d) %s: %x %x\n",f->jump, f->h->root.root.string, + new_addr, f->value); +#endif + + if (f->jump) + { + /* Relative address */ + new_addr = new_addr - (f->value + 5); + bfd_put_32 (output_bfd, new_addr, fixup_table); + fixup_table += 4; + bfd_put_32 (output_bfd, f->value + 1, fixup_table); + fixup_table += 4; + } + else + { + bfd_put_32 (output_bfd, new_addr, fixup_table); + fixup_table += 4; + bfd_put_32 (output_bfd, f->value, fixup_table); + fixup_table += 4; + } + ++fixups_written; + } + + if (linux_hash_table (info)->local_builtins != 0) + { + /* Special marker so we know to switch to the other type of fixup */ + bfd_put_32 (output_bfd, 0, fixup_table); + fixup_table += 4; + bfd_put_32 (output_bfd, 0, fixup_table); + fixup_table += 4; + ++fixups_written; + for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next) + { + if (! f->builtin) + continue; + + if (f->h->root.root.type != bfd_link_hash_defined + && f->h->root.root.type != bfd_link_hash_defweak) + { + (*_bfd_error_handler) + ("Symbol %s not defined for fixups\n", + f->h->root.root.root.string); + continue; + } + + is = f->h->root.root.u.def.section; + section_offset = is->output_section->vma + is->output_offset; + new_addr = f->h->root.root.u.def.value + section_offset; + +#ifdef LINUX_LINK_DEBUG + printf ("Fixup(B) %s: %x %x\n", f->h->root.root.string, + new_addr, f->value); +#endif + + bfd_put_32 (output_bfd, new_addr, fixup_table); + fixup_table += 4; + bfd_put_32 (output_bfd, f->value, fixup_table); + fixup_table += 4; + ++fixups_written; + } + } + + if (linux_hash_table (info)->fixup_count != fixups_written) + { + (*_bfd_error_handler) ("Warning: fixup count mismatch\n"); + while (linux_hash_table (info)->fixup_count > fixups_written) + { + bfd_put_32 (output_bfd, 0, fixup_table); + fixup_table += 4; + bfd_put_32 (output_bfd, 0, fixup_table); + fixup_table += 4; + ++fixups_written; + } + } + + h = linux_link_hash_lookup (linux_hash_table (info), + "__BUILTIN_FIXUPS__", + false, false, false); + + if (h != NULL + && (h->root.root.type == bfd_link_hash_defined + || h->root.root.type == bfd_link_hash_defweak)) + { + is = h->root.root.u.def.section; + section_offset = is->output_section->vma + is->output_offset; + new_addr = h->root.root.u.def.value + section_offset; + +#ifdef LINUX_LINK_DEBUG + printf ("Builtin fixup table at %x\n", new_addr); +#endif + + bfd_put_32 (output_bfd, new_addr, fixup_table); + } + else + bfd_put_32 (output_bfd, 0, fixup_table); + + if (bfd_seek (output_bfd, os->filepos + s->output_offset, SEEK_SET) != 0) + return false; + + if (bfd_write ((PTR) s->contents, 1, s->_raw_size, output_bfd) + != s->_raw_size) + return false; + + return true; +} + +#define MY_bfd_link_hash_table_create linux_link_hash_table_create +#define MY_add_one_symbol linux_add_one_symbol +#define MY_finish_dynamic_link linux_finish_dynamic_link + +#define MY_zmagic_contiguous 1 + +#include "aout-target.h" diff --git a/gnu/usr.bin/binutils/etc/standards.info-3 b/gnu/usr.bin/binutils/etc/standards.info-3 new file mode 100644 index 00000000000..056b25bba2b --- /dev/null +++ b/gnu/usr.bin/binutils/etc/standards.info-3 @@ -0,0 +1,679 @@ +This is Info file standards.info, produced by Makeinfo-1.64 from the +input file ./standards.texi. + +START-INFO-DIR-ENTRY +* Standards: (standards). GNU coding standards. +END-INFO-DIR-ENTRY + + GNU Coding Standards Copyright (C) 1992, 1993, 1994, 1995, 1996 Free +Software Foundation, Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + + Permission is granted to copy and distribute modified versions of +this manual under the conditions for verbatim copying, provided that +the entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + + Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be stated in a +translation approved by the Free Software Foundation. + + +File: standards.info, Node: Directory Variables, Next: Standard Targets, Prev: Command Variables, Up: Makefile Conventions + +Variables for Installation Directories +-------------------------------------- + + Installation directories should always be named by variables, so it +is easy to install in a nonstandard place. The standard names for these +variables are described below. They are based on a standard filesystem +layout; variants of it are used in SVR4, 4.4BSD, Linux, Ultrix v4, and +other modern operating systems. + + These two variables set the root for the installation. All the other +installation directories should be subdirectories of one of these two, +and nothing should be directly installed into these two directories. + +`prefix' + A prefix used in constructing the default values of the variables + listed below. The default value of `prefix' should be + `/usr/local'. When building the complete GNU system, the prefix + will be empty and `/usr' will be a symbolic link to `/'. (If you + are using Autoconf, write it as `@prefix@'.) + +`exec_prefix' + A prefix used in constructing the default values of some of the + variables listed below. The default value of `exec_prefix' should + be `$(prefix)'. (If you are using Autoconf, write it as + `@exec_prefix@'.) + + Generally, `$(exec_prefix)' is used for directories that contain + machine-specific files (such as executables and subroutine + libraries), while `$(prefix)' is used directly for other + directories. + + Executable programs are installed in one of the following +directories. + +`bindir' + The directory for installing executable programs that users can + run. This should normally be `/usr/local/bin', but write it as + `$(exec_prefix)/bin'. (If you are using Autoconf, write it as + `@bindir@'.) + +`sbindir' + The directory for installing executable programs that can be run + from the shell, but are only generally useful to system + administrators. This should normally be `/usr/local/sbin', but + write it as `$(exec_prefix)/sbin'. (If you are using Autoconf, + write it as `@sbindir@'.) + +`libexecdir' + The directory for installing executable programs to be run by other + programs rather than by users. This directory should normally be + `/usr/local/libexec', but write it as `$(exec_prefix)/libexec'. + (If you are using Autoconf, write it as `@libexecdir@'.) + + Data files used by the program during its execution are divided into +categories in two ways. + + * Some files are normally modified by programs; others are never + normally modified (though users may edit some of these). + + * Some files are architecture-independent and can be shared by all + machines at a site; some are architecture-dependent and can be + shared only by machines of the same kind and operating system; + others may never be shared between two machines. + + This makes for six different possibilities. However, we want to +discourage the use of architecture-dependent files, aside from object +files and libraries. It is much cleaner to make other data files +architecture-independent, and it is generally not hard. + + Therefore, here are the variables Makefiles should use to specify +directories: + +`datadir' + The directory for installing read-only architecture independent + data files. This should normally be `/usr/local/share', but write + it as `$(prefix)/share'. (If you are using Autoconf, write it as + `@datadir@'.) As a special exception, see `$(infodir)' and + `$(includedir)' below. + +`sysconfdir' + The directory for installing read-only data files that pertain to a + single machine-that is to say, files for configuring a host. + Mailer and network configuration files, `/etc/passwd', and so + forth belong here. All the files in this directory should be + ordinary ASCII text files. This directory should normally be + `/usr/local/etc', but write it as `$(prefix)/etc'. (If you are + using Autoconf, write it as `@sysconfdir@'.) + + Do not install executables in this directory (they probably belong + in `$(libexecdir)' or `$(sbindir)'). Also do not install files + that are modified in the normal course of their use (programs + whose purpose is to change the configuration of the system + excluded). Those probably belong in `$(localstatedir)'. + +`sharedstatedir' + The directory for installing architecture-independent data files + which the programs modify while they run. This should normally be + `/usr/local/com', but write it as `$(prefix)/com'. (If you are + using Autoconf, write it as `@sharedstatedir@'.) + +`localstatedir' + The directory for installing data files which the programs modify + while they run, and that pertain to one specific machine. Users + should never need to modify files in this directory to configure + the package's operation; put such configuration information in + separate files that go in `$(datadir)' or `$(sysconfdir)'. + `$(localstatedir)' should normally be `/usr/local/var', but write + it as `$(prefix)/var'. (If you are using Autoconf, write it as + `@localstatedir@'.) + +`libdir' + The directory for object files and libraries of object code. Do + not install executables here, they probably ought to go in + `$(libexecdir)' instead. The value of `libdir' should normally be + `/usr/local/lib', but write it as `$(exec_prefix)/lib'. (If you + are using Autoconf, write it as `@libdir@'.) + +`infodir' + The directory for installing the Info files for this package. By + default, it should be `/usr/local/info', but it should be written + as `$(prefix)/info'. (If you are using Autoconf, write it as + `@infodir@'.) + +`lispdir' + The directory for installing any Emacs Lisp files in this package. + By default, it should be `/usr/local/share/emacs/site-lisp', but + it should be written as `$(prefix)/share/emacs/site-lisp'. + + If you are using Autoconf, write the default as `@lispdir@'. In + order to make `@lispdir@' work, you need the following lines in + your `configure.in' file: + + lispdir='${datadir}/emacs/site-lisp' + AC_SUBST(lispdir) + +`includedir' + The directory for installing header files to be included by user + programs with the C `#include' preprocessor directive. This + should normally be `/usr/local/include', but write it as + `$(prefix)/include'. (If you are using Autoconf, write it as + `@includedir@'.) + + Most compilers other than GCC do not look for header files in + `/usr/local/include'. So installing the header files this way is + only useful with GCC. Sometimes this is not a problem because some + libraries are only really intended to work with GCC. But some + libraries are intended to work with other compilers. They should + install their header files in two places, one specified by + `includedir' and one specified by `oldincludedir'. + +`oldincludedir' + The directory for installing `#include' header files for use with + compilers other than GCC. This should normally be `/usr/include'. + (If you are using Autoconf, you can write it as `@oldincludedir@'.) + + The Makefile commands should check whether the value of + `oldincludedir' is empty. If it is, they should not try to use + it; they should cancel the second installation of the header files. + + A package should not replace an existing header in this directory + unless the header came from the same package. Thus, if your Foo + package provides a header file `foo.h', then it should install the + header file in the `oldincludedir' directory if either (1) there + is no `foo.h' there or (2) the `foo.h' that exists came from the + Foo package. + + To tell whether `foo.h' came from the Foo package, put a magic + string in the file--part of a comment--and `grep' for that string. + + Unix-style man pages are installed in one of the following: + +`mandir' + The top-level directory for installing the man pages (if any) for + this package. It will normally be `/usr/local/man', but you should + write it as `$(prefix)/man'. (If you are using Autoconf, write it + as `@mandir@'.) + +`man1dir' + The directory for installing section 1 man pages. Write it as + `$(mandir)/man1'. + +`man2dir' + The directory for installing section 2 man pages. Write it as + `$(mandir)/man2' + +`...' + *Don't make the primary documentation for any GNU software be a + man page. Write a manual in Texinfo instead. Man pages are just + for the sake of people running GNU software on Unix, which is a + secondary application only.* + +`manext' + The file name extension for the installed man page. This should + contain a period followed by the appropriate digit; it should + normally be `.1'. + +`man1ext' + The file name extension for installed section 1 man pages. + +`man2ext' + The file name extension for installed section 2 man pages. + +`...' + Use these names instead of `manext' if the package needs to + install man pages in more than one section of the manual. + + And finally, you should set the following variable: + +`srcdir' + The directory for the sources being compiled. The value of this + variable is normally inserted by the `configure' shell script. + (If you are using Autconf, use `srcdir = @srcdir@'.) + + For example: + + # Common prefix for installation directories. + # NOTE: This directory must exist when you start the install. + prefix = /usr/local + exec_prefix = $(prefix) + # Where to put the executable for the command `gcc'. + bindir = $(exec_prefix)/bin + # Where to put the directories used by the compiler. + libexecdir = $(exec_prefix)/libexec + # Where to put the Info files. + infodir = $(prefix)/info + + If your program installs a large number of files into one of the +standard user-specified directories, it might be useful to group them +into a subdirectory particular to that program. If you do this, you +should write the `install' rule to create these subdirectories. + + Do not expect the user to include the subdirectory name in the value +of any of the variables listed above. The idea of having a uniform set +of variable names for installation directories is to enable the user to +specify the exact same values for several different GNU packages. In +order for this to be useful, all the packages must be designed so that +they will work sensibly when the user does so. + + +File: standards.info, Node: Standard Targets, Next: Install Command Categories, Prev: Directory Variables, Up: Makefile Conventions + +Standard Targets for Users +-------------------------- + + All GNU programs should have the following targets in their +Makefiles: + +`all' + Compile the entire program. This should be the default target. + This target need not rebuild any documentation files; Info files + should normally be included in the distribution, and DVI files + should be made only when explicitly asked for. + + By default, the Make rules should compile and link with `-g', so + that executable programs have debugging symbols. Users who don't + mind being helpless can strip the executables later if they wish. + +`install' + Compile the program and copy the executables, libraries, and so on + to the file names where they should reside for actual use. If + there is a simple test to verify that a program is properly + installed, this target should run that test. + + Do not strip executables when installing them. Devil-may-care + users can use the `install-strip' target to do that. + + If possible, write the `install' target rule so that it does not + modify anything in the directory where the program was built, + provided `make all' has just been done. This is convenient for + building the program under one user name and installing it under + another. + + The commands should create all the directories in which files are + to be installed, if they don't already exist. This includes the + directories specified as the values of the variables `prefix' and + `exec_prefix', as well as all subdirectories that are needed. One + way to do this is by means of an `installdirs' target as described + below. + + Use `-' before any command for installing a man page, so that + `make' will ignore any errors. This is in case there are systems + that don't have the Unix man page documentation system installed. + + The way to install Info files is to copy them into `$(infodir)' + with `$(INSTALL_DATA)' (*note Command Variables::.), and then run + the `install-info' program if it is present. `install-info' is a + program that edits the Info `dir' file to add or update the menu + entry for the given Info file; it is part of the Texinfo package. + Here is a sample rule to install an Info file: + + $(infodir)/foo.info: foo.info + $(POST_INSTALL) + # There may be a newer info file in . than in srcdir. + -if test -f foo.info; then d=.; \ + else d=$(srcdir); fi; \ + $(INSTALL_DATA) $$d/foo.info $@; \ + # Run install-info only if it exists. + # Use `if' instead of just prepending `-' to the + # line so we notice real errors from install-info. + # We use `$(SHELL) -c' because some shells do not + # fail gracefully when there is an unknown command. + if $(SHELL) -c 'install-info --version' \ + >/dev/null 2>&1; then \ + install-info --dir-file=$(infodir)/dir \ + $(infodir)/foo.info; \ + else true; fi + + When writing the `install' target, you must classify all the + commands into three categories: normal ones, "pre-installation" + commands and "post-installation" commands. *Note Install Command + Categories::. + +`uninstall' + Delete all the installed files--the copies that the `install' + target creates. + + This rule should not modify the directories where compilation is + done, only the directories where files are installed. + + The uninstallation commands are divided into three categories, + just like the installation commands. *Note Install Command + Categories::. + +`install-strip' + Like `install', but strip the executable files while installing + them. In many cases, the definition of this target can be very + simple: + + install-strip: + $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' \ + install + + Normally we do not recommend stripping an executable unless you + are sure the program has no bugs. However, it can be reasonable + to install a stripped executable for actual execution while saving + the unstripped executable elsewhere in case there is a bug. + +`clean' + Delete all files from the current directory that are normally + created by building the program. Don't delete the files that + record the configuration. Also preserve files that could be made + by building, but normally aren't because the distribution comes + with them. + + Delete `.dvi' files here if they are not part of the distribution. + +`distclean' + Delete all files from the current directory that are created by + configuring or building the program. If you have unpacked the + source and built the program without creating any other files, + `make distclean' should leave only the files that were in the + distribution. + +`mostlyclean' + Like `clean', but may refrain from deleting a few files that people + normally don't want to recompile. For example, the `mostlyclean' + target for GCC does not delete `libgcc.a', because recompiling it + is rarely necessary and takes a lot of time. + +`maintainer-clean' + Delete almost everything from the current directory that can be + reconstructed with this Makefile. This typically includes + everything deleted by `distclean', plus more: C source files + produced by Bison, tags tables, Info files, and so on. + + The reason we say "almost everything" is that running the command + `make maintainer-clean' should not delete `configure' even if + `configure' can be remade using a rule in the Makefile. More + generally, `make maintainer-clean' should not delete anything that + needs to exist in order to run `configure' and then begin to build + the program. This is the only exception; `maintainer-clean' should + delete everything else that can be rebuilt. + + The `maintainer-clean' target is intended to be used by a + maintainer of the package, not by ordinary users. You may need + special tools to reconstruct some of the files that `make + maintainer-clean' deletes. Since these files are normally + included in the distribution, we don't take care to make them easy + to reconstruct. If you find you need to unpack the full + distribution again, don't blame us. + + To help make users aware of this, the commands for the special + `maintainer-clean' target should start with these two: + + @echo 'This command is intended for maintainers to use; it' + @echo 'deletes files that may need special tools to rebuild.' + +`TAGS' + Update a tags table for this program. + +`info' + Generate any Info files needed. The best way to write the rules + is as follows: + + info: foo.info + + foo.info: foo.texi chap1.texi chap2.texi + $(MAKEINFO) $(srcdir)/foo.texi + + You must define the variable `MAKEINFO' in the Makefile. It should + run the `makeinfo' program, which is part of the Texinfo + distribution. + + Normally a GNU distribution comes with Info files, and that means + the Info files are present in the source directory. Therefore, + the Make rule for an info file should update it in the source + directory. When users build the package, ordinarily Make will not + update the Info files because they will already be up to date. + +`dvi' + Generate DVI files for all Texinfo documentation. For example: + + dvi: foo.dvi + + foo.dvi: foo.texi chap1.texi chap2.texi + $(TEXI2DVI) $(srcdir)/foo.texi + + You must define the variable `TEXI2DVI' in the Makefile. It should + run the program `texi2dvi', which is part of the Texinfo + distribution.(1) Alternatively, write just the dependencies, and + allow GNU `make' to provide the command. + +`dist' + Create a distribution tar file for this program. The tar file + should be set up so that the file names in the tar file start with + a subdirectory name which is the name of the package it is a + distribution for. This name can include the version number. + + For example, the distribution tar file of GCC version 1.40 unpacks + into a subdirectory named `gcc-1.40'. + + The easiest way to do this is to create a subdirectory + appropriately named, use `ln' or `cp' to install the proper files + in it, and then `tar' that subdirectory. + + Compress the tar file file with `gzip'. For example, the actual + distribution file for GCC version 1.40 is called `gcc-1.40.tar.gz'. + + The `dist' target should explicitly depend on all non-source files + that are in the distribution, to make sure they are up to date in + the distribution. *Note Making Releases: Releases. + +`check' + Perform self-tests (if any). The user must build the program + before running the tests, but need not install the program; you + should write the self-tests so that they work when the program is + built but not installed. + + The following targets are suggested as conventional names, for +programs in which they are useful. + +`installcheck' + Perform installation tests (if any). The user must build and + install the program before running the tests. You should not + assume that `$(bindir)' is in the search path. + +`installdirs' + It's useful to add a target named `installdirs' to create the + directories where files are installed, and their parent + directories. There is a script called `mkinstalldirs' which is + convenient for this; you can find it in the Texinfo package. You + can use a rule like this: + + # Make sure all installation directories (e.g. $(bindir)) + # actually exist by making them if necessary. + installdirs: mkinstalldirs + $(srcdir)/mkinstalldirs $(bindir) $(datadir) \ + $(libdir) $(infodir) \ + $(mandir) + + This rule should not modify the directories where compilation is + done. It should do nothing but create installation directories. + + ---------- Footnotes ---------- + + (1) `texi2dvi' uses TeX to do the real work of formatting. TeX is +not distributed with Texinfo. + + +File: standards.info, Node: Install Command Categories, Prev: Standard Targets, Up: Makefile Conventions + +Install Command Categories +-------------------------- + + When writing the `install' target, you must classify all the +commands into three categories: normal ones, "pre-installation" +commands and "post-installation" commands. + + Normal commands move files into their proper places, and set their +modes. They may not alter any files except the ones that come entirely +from the package they belong to. + + Pre-installation and post-installation commands may alter other +files; in particular, they can edit global configuration files or data +bases. + + Pre-installation commands are typically executed before the normal +commands, and post-installation commands are typically run after the +normal commands. + + The most common use for a post-installation command is to run +`install-info'. This cannot be done with a normal command, since it +alters a file (the Info directory) which does not come entirely and +solely from the package being installed. It is a post-installation +command because it needs to be done after the normal command which +installs the package's Info files. + + Most programs don't need any pre-installation commands, but we have +the feature just in case it is needed. + + To classify the commands in the `install' rule into these three +categories, insert "category lines" among them. A category line +specifies the category for the commands that follow. + + A category line consists of a tab and a reference to a special Make +variable, plus an optional comment at the end. There are three +variables you can use, one for each category; the variable name +specifies the category. Category lines are no-ops in ordinary execution +because these three Make variables are normally undefined (and you +*should not* define them in the makefile). + + Here are the three possible category lines, each with a comment that +explains what it means: + + $(PRE_INSTALL) # Pre-install commands follow. + $(POST_INSTALL) # Post-install commands follow. + $(NORMAL_INSTALL) # Normal commands follow. + + If you don't use a category line at the beginning of the `install' +rule, all the commands are classified as normal until the first category +line. If you don't use any category lines, all the commands are +classified as normal. + + These are the category lines for `uninstall': + + $(PRE_UNINSTALL) # Pre-uninstall commands follow. + $(POST_UNINSTALL) # Post-uninstall commands follow. + $(NORMAL_UNINSTALL) # Normal commands follow. + + Typically, a pre-uninstall command would be used for deleting entries +from the Info directory. + + If the `install' or `uninstall' target has any dependencies which +act as subroutines of installation, then you should start *each* +dependency's commands with a category line, and start the main target's +commands with a category line also. This way, you can ensure that each +command is placed in the right category regardless of which of the +dependencies actually run. + + Pre-installation and post-installation commands should not run any +programs except for these: + + [ basename bash cat chgrp chmod chown cmp cp dd diff echo + egrep expand expr false fgrep find getopt grep gunzip gzip + hostname install install-info kill ldconfig ln ls md5sum + mkdir mkfifo mknod mv printenv pwd rm rmdir sed sort tee + test touch true uname xargs yes + + The reason for distinguishing the commands in this way is for the +sake of making binary packages. Typically a binary package contains +all the executables and other files that need to be installed, and has +its own method of installing them--so it does not need to run the normal +installation commands. But installing the binary package does need to +execute the pre-installation and post-installation commands. + + Programs to build binary packages work by extracting the +pre-installation and post-installation commands. Here is one way of +extracting the pre-installation commands: + + make -n install -o all \ + PRE_INSTALL=pre-install \ + POST_INSTALL=post-install \ + NORMAL_INSTALL=normal-install \ + | gawk -f pre-install.awk + +where the file `pre-install.awk' could contain this: + + $0 ~ /^\t[ \t]*(normal_install|post_install)[ \t]*$/ {on = 0} + on {print $0} + $0 ~ /^\t[ \t]*pre_install[ \t]*$/ {on = 1} + + The resulting file of pre-installation commands is executed as a +shell script as part of installing the binary package. + + +File: standards.info, Node: Releases, Prev: Makefile Conventions, Up: Managing Releases + +Making Releases +=============== + + Package the distribution of Foo version 69.96 in a gzipped tar file +named `foo-69.96.tar.gz'. It should unpack into a subdirectory named +`foo-69.96'. + + Building and installing the program should never modify any of the +files contained in the distribution. This means that all the files +that form part of the program in any way must be classified into "source +files" and "non-source files". Source files are written by humans and +never changed automatically; non-source files are produced from source +files by programs under the control of the Makefile. + + Naturally, all the source files must be in the distribution. It is +okay to include non-source files in the distribution, provided they are +up-to-date and machine-independent, so that building the distribution +normally will never modify them. We commonly include non-source files +produced by Bison, `lex', TeX, and `makeinfo'; this helps avoid +unnecessary dependencies between our distributions, so that users can +install whichever packages they want to install. + + Non-source files that might actually be modified by building and +installing the program should *never* be included in the distribution. +So if you do distribute non-source files, always make sure they are up +to date when you make a new distribution. + + Make sure that the directory into which the distribution unpacks (as +well as any subdirectories) are all world-writable (octal mode 777). +This is so that old versions of `tar' which preserve the ownership and +permissions of the files from the tar archive will be able to extract +all the files even if the user is unprivileged. + + Make sure that all the files in the distribution are world-readable. + + Make sure that no file name in the distribution is more than 14 +characters long. Likewise, no file created by building the program +should have a name longer than 14 characters. The reason for this is +that some systems adhere to a foolish interpretation of the POSIX +standard, and refuse to open a longer name, rather than truncating as +they did in the past. + + Don't include any symbolic links in the distribution itself. If the +tar file contains symbolic links, then people cannot even unpack it on +systems that don't support symbolic links. Also, don't use multiple +names for one file in different directories, because certain file +systems cannot handle this and that prevents unpacking the distribution. + + Try to make sure that all the file names will be unique on MS-DOS. A +name on MS-DOS consists of up to 8 characters, optionally followed by a +period and up to three characters. MS-DOS will truncate extra +characters both before and after the period. Thus, `foobarhacker.c' +and `foobarhacker.o' are not ambiguous; they are truncated to +`foobarha.c' and `foobarha.o', which are distinct. + + Include in your distribution a copy of the `texinfo.tex' you used to +test print any `*.texinfo' or `*.texi' files. + + Likewise, if your program uses small GNU software packages like +regex, getopt, obstack, or termcap, include them in the distribution +file. Leaving them out would make the distribution file a little +smaller at the expense of possible inconvenience to a user who doesn't +know what other files to get. + + diff --git a/gnu/usr.bin/binutils/gas/cgen.c b/gnu/usr.bin/binutils/gas/cgen.c new file mode 100644 index 00000000000..e9024e42e78 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/cgen.c @@ -0,0 +1,527 @@ +/* GAS interface for targets using CGEN: Cpu tools GENerator. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + +This file is part of GAS, the GNU Assembler. + +GAS 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 2, or (at your option) +any later version. + +GAS 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 GAS; see the file COPYING. If not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "ansidecl.h" +#include "bfd.h" +#include "cgen-opc.h" +#include "as.h" +#include "subsegs.h" + +/* Callback to insert a register into the symbol table. + A target may choose to let GAS parse the registers. + ??? Not currently used. */ + +void +cgen_asm_record_register (name, number) + char *name; + int number; +{ + /* Use symbol_create here instead of symbol_new so we don't try to + output registers into the object file's symbol table. */ + symbol_table_insert (symbol_create (name, reg_section, + number, &zero_address_frag)); +} + +/* We need to keep a list of fixups. We can't simply generate them as + we go, because that would require us to first create the frag, and + that would screw up references to ``.''. + + This is used by cpu's with simple operands. It keeps knowledge of what + an `expressionS' is and what a `fixup' is out of CGEN which for the time + being is preferable. + + OPINDEX is the index in the operand table. + OPINFO is something the caller chooses to help in reloc determination. */ + +struct fixup +{ + int opindex; + int opinfo; + expressionS exp; +}; + +#define MAX_FIXUPS 5 + +static struct fixup fixups[MAX_FIXUPS]; +static int num_fixups; + +/* Prepare to parse an instruction. + ??? May wish to make this static and delete calls in md_assemble. */ + +void +cgen_asm_init_parse () +{ + num_fixups = 0; +} + +/* Queue a fixup. */ + +void +cgen_queue_fixup (opindex, opinfo, expP) + int opindex; + expressionS *expP; +{ + /* We need to generate a fixup for this expression. */ + if (num_fixups >= MAX_FIXUPS) + as_fatal ("too many fixups"); + fixups[num_fixups].exp = *expP; + fixups[num_fixups].opindex = opindex; + fixups[num_fixups].opinfo = opinfo; + ++num_fixups; +} + +/* Default routine to record a fixup. + This is a cover function to fix_new. + It exists because we record INSN with the fixup. + + FRAG and WHERE are their respective arguments to fix_new_exp. + LENGTH is in bits. + OPINFO is something the caller chooses to help in reloc determination. + + At this point we do not use a bfd_reloc_code_real_type for + operands residing in the insn, but instead just use the + operand index. This lets us easily handle fixups for any + operand type. We pick a BFD reloc type in md_apply_fix. */ + +fixS * +cgen_record_fixup (frag, where, insn, length, operand, opinfo, symbol, offset) + fragS *frag; + int where; + const struct cgen_insn *insn; + int length; + const struct cgen_operand *operand; + int opinfo; + symbolS *symbol; + offsetT offset; +{ + fixS *fixP; + + /* It may seem strange to use operand->attrs and not insn->attrs here, + but it is the operand that has a pc relative relocation. */ + + fixP = fix_new (frag, where, length / 8, symbol, offset, + CGEN_OPERAND_ATTR (operand, CGEN_OPERAND_PCREL_ADDR) != 0, + (bfd_reloc_code_real_type) ((int) BFD_RELOC_UNUSED + CGEN_OPERAND_INDEX (operand))); + fixP->tc_fix_data.insn = (PTR) insn; + fixP->tc_fix_data.opinfo = opinfo; + + return fixP; +} + +/* Default routine to record a fixup given an expression. + This is a cover function to fix_new_exp. + It exists because we record INSN with the fixup. + + FRAG and WHERE are their respective arguments to fix_new_exp. + LENGTH is in bits. + OPINFO is something the caller chooses to help in reloc determination. + + At this point we do not use a bfd_reloc_code_real_type for + operands residing in the insn, but instead just use the + operand index. This lets us easily handle fixups for any + operand type. We pick a BFD reloc type in md_apply_fix. */ + +fixS * +cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp) + fragS *frag; + int where; + const struct cgen_insn *insn; + int length; + const struct cgen_operand *operand; + int opinfo; + expressionS *exp; +{ + fixS *fixP; + + /* It may seem strange to use operand->attrs and not insn->attrs here, + but it is the operand that has a pc relative relocation. */ + + fixP = fix_new_exp (frag, where, length / 8, exp, + CGEN_OPERAND_ATTR (operand, CGEN_OPERAND_PCREL_ADDR) != 0, + (bfd_reloc_code_real_type) ((int) BFD_RELOC_UNUSED + CGEN_OPERAND_INDEX (operand))); + fixP->tc_fix_data.insn = (PTR) insn; + fixP->tc_fix_data.opinfo = opinfo; + + return fixP; +} + +/* Callback for cgen interface. Parse the expression at *STRP. + The result is an error message or NULL for success (in which case + *STRP is advanced past the parsed text). + WANT is an indication of what the caller is looking for. + If WANT == CGEN_ASM_PARSE_INIT the caller is beginning to try to match + a table entry with the insn, reset the queued fixups counter. + An enum cgen_parse_operand_result is stored in RESULTP. + OPINDEX is the operand's table entry index. + OPINFO is something the caller chooses to help in reloc determination. + The resulting value is stored in VALUEP. */ + +const char * +cgen_parse_operand (want, strP, opindex, opinfo, resultP, valueP) + enum cgen_parse_operand_type want; + const char **strP; + int opindex; + int opinfo; + enum cgen_parse_operand_result *resultP; + bfd_vma *valueP; +{ + char *hold; + const char *errmsg = NULL; + expressionS exp; + + if (want == CGEN_PARSE_OPERAND_INIT) + { + cgen_asm_init_parse (); + return NULL; + } + + hold = input_line_pointer; + input_line_pointer = (char *) *strP; + expression (&exp); + *strP = input_line_pointer; + input_line_pointer = hold; + + /* FIXME: Need to check `want'. */ + + switch (exp.X_op) + { + case O_illegal : + errmsg = "illegal operand"; + *resultP = CGEN_PARSE_OPERAND_RESULT_ERROR; + break; + case O_absent : + errmsg = "missing operand"; + *resultP = CGEN_PARSE_OPERAND_RESULT_ERROR; + break; + case O_constant : + *valueP = exp.X_add_number; + *resultP = CGEN_PARSE_OPERAND_RESULT_NUMBER; + break; + case O_register : + *valueP = exp.X_add_number; + *resultP = CGEN_PARSE_OPERAND_RESULT_REGISTER; + break; + default : + cgen_queue_fixup (opindex, opinfo, &exp); + *valueP = 0; + *resultP = CGEN_PARSE_OPERAND_RESULT_QUEUED; + break; + } + + return errmsg; +} + +/* Finish assembling instruction INSN. + BUF contains what we've built up so far. + LENGTH is the size of the insn in bits. */ + +void +cgen_asm_finish_insn (insn, buf, length) + const struct cgen_insn *insn; + cgen_insn_t *buf; + unsigned int length; +{ + int i, relax_operand; + char *f; + unsigned int byte_len = length / 8; + + /* ??? Target foo issues various warnings here, so one might want to provide + a hook here. However, our caller is defined in tc-foo.c so there + shouldn't be a need for a hook. */ + + /* Write out the instruction. + It is important to fetch enough space in one call to `frag_more'. + We use (f - frag_now->fr_literal) to compute where we are and we + don't want frag_now to change between calls. + + Relaxable instructions: We need to ensure we allocate enough + space for the largest insn. */ + + if (CGEN_INSN_ATTR (insn, CGEN_INSN_RELAX) != 0) + abort (); /* These currently shouldn't get here. */ + + /* Is there a relaxable insn with the relaxable operand needing a fixup? */ + + relax_operand = -1; + if (CGEN_INSN_ATTR (insn, CGEN_INSN_RELAXABLE) != 0) + { + /* Scan the fixups for the operand affected by relaxing + (i.e. the branch address). */ + + for (i = 0; i < num_fixups; ++i) + { + if (CGEN_OPERAND_ATTR (& CGEN_SYM (operand_table) [fixups[i].opindex], + CGEN_OPERAND_RELAX) != 0) + { + relax_operand = i; + break; + } + } + } + + if (relax_operand != -1) + { + int max_len; + fragS *old_frag; + +#ifdef TC_CGEN_MAX_RELAX + max_len = TC_CGEN_MAX_RELAX (insn, byte_len); +#else + max_len = CGEN_MAX_INSN_SIZE; +#endif + /* Ensure variable part and fixed part are in same fragment. */ + /* FIXME: Having to do this seems like a hack. */ + frag_grow (max_len); + /* Allocate space for the fixed part. */ + f = frag_more (byte_len); + /* Create a relaxable fragment for this instruction. */ + old_frag = frag_now; + frag_var (rs_machine_dependent, + max_len - byte_len /* max chars */, + 0 /* variable part already allocated */, + /* FIXME: When we machine generate the relax table, + machine generate a macro to compute subtype. */ + 1 /* subtype */, + fixups[relax_operand].exp.X_add_symbol, + fixups[relax_operand].exp.X_add_number, + f); + /* Record the operand number with the fragment so md_convert_frag + can use cgen_md_record_fixup to record the appropriate reloc. */ + /* FIXME: fr_targ.cgen is used pending deciding whether to + allow a target to add members to fragS. For more info + see the comment above fr_targ in as.h. */ + old_frag->fr_targ.cgen.insn = insn; + old_frag->fr_targ.cgen.opindex = fixups[relax_operand].opindex; + old_frag->fr_targ.cgen.opinfo = fixups[relax_operand].opinfo; + } + else + f = frag_more (byte_len); + + /* If we're recording insns as numbers (rather than a string of bytes), + target byte order handling is deferred until now. */ +#if 0 /*def CGEN_INT_INSN*/ + switch (length) + { + case 16: + if (cgen_big_endian_p) + bfd_putb16 ((bfd_vma) *buf, f); + else + bfd_putl16 ((bfd_vma) *buf, f); + break; + case 32: + if (cgen_big_endian_p) + bfd_putb32 ((bfd_vma) *buf, f); + else + bfd_putl32 ((bfd_vma) *buf, f); + break; + default: + abort (); + } +#else + memcpy (f, buf, byte_len); +#endif + + /* Create any fixups. */ + for (i = 0; i < num_fixups; ++i) + { + /* Don't create fixups for these. That's done during relaxation. + We don't need to test for CGEN_INSN_RELAX as they can't get here + (see above). */ + if (CGEN_INSN_ATTR (insn, CGEN_INSN_RELAXABLE) != 0 + && CGEN_OPERAND_ATTR (& CGEN_SYM (operand_table) [fixups[i].opindex], + CGEN_OPERAND_RELAX) != 0) + continue; + +#ifndef md_cgen_record_fixup_exp +#define md_cgen_record_fixup_exp cgen_record_fixup_exp +#endif + + md_cgen_record_fixup_exp (frag_now, f - frag_now->fr_literal, + insn, length, + & CGEN_SYM (operand_table) [fixups[i].opindex], + fixups[i].opinfo, + &fixups[i].exp); + } +} + +/* Apply a fixup to the object code. This is called for all the + fixups we generated by the call to fix_new_exp, above. In the call + above we used a reloc code which was the largest legal reloc code + plus the operand index. Here we undo that to recover the operand + index. At this point all symbol values should be fully resolved, + and we attempt to completely resolve the reloc. If we can not do + that, we determine the correct reloc code and put it back in the fixup. */ + +/* FIXME: This function handles some of the fixups and bfd_install_relocation + handles the rest. bfd_install_relocation (or some other bfd function) + should handle them all. */ + +int +cgen_md_apply_fix3 (fixP, valueP, seg) + fixS *fixP; + valueT *valueP; + segT seg; +{ + char *where = fixP->fx_frag->fr_literal + fixP->fx_where; + valueT value; + + /* FIXME FIXME FIXME: The value we are passed in *valuep includes + the symbol values. Since we are using BFD_ASSEMBLER, if we are + doing this relocation the code in write.c is going to call + bfd_install_relocation, which is also going to use the symbol + value. That means that if the reloc is fully resolved we want to + use *valuep since bfd_install_relocation is not being used. + However, if the reloc is not fully resolved we do not want to use + *valuep, and must use fx_offset instead. However, if the reloc + is PC relative, we do want to use *valuep since it includes the + result of md_pcrel_from. This is confusing. */ + + if (fixP->fx_addsy == (symbolS *) NULL) + { + value = *valueP; + fixP->fx_done = 1; + } + else if (fixP->fx_pcrel) + value = *valueP; + else + { + value = fixP->fx_offset; + if (fixP->fx_subsy != (symbolS *) NULL) + { + if (S_GET_SEGMENT (fixP->fx_subsy) == absolute_section) + value -= S_GET_VALUE (fixP->fx_subsy); + else + { + /* We don't actually support subtracting a symbol. */ + as_bad_where (fixP->fx_file, fixP->fx_line, + "expression too complex"); + } + } + } + + if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED) + { + int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED; + const struct cgen_operand *operand = & CGEN_SYM (operand_table) [opindex]; + const char *errmsg; + bfd_reloc_code_real_type reloc_type; + struct cgen_fields fields; + const struct cgen_insn *insn = (struct cgen_insn *) fixP->tc_fix_data.insn; + + /* If the reloc has been fully resolved finish the operand here. */ + /* FIXME: This duplicates the capabilities of code in BFD. */ + if (fixP->fx_done + /* FIXME: If partial_inplace isn't set bfd_install_relocation won't + finish the job. Testing for pcrel is a temporary hack. */ + || fixP->fx_pcrel) + { + /* This may seem like overkill, and using bfd_install_relocation or + some such may be preferable, but this is simple. */ + CGEN_FIELDS_BITSIZE (&fields) = CGEN_INSN_BITSIZE (insn); + CGEN_SYM (set_operand) (opindex, &value, &fields); + errmsg = CGEN_SYM (validate_operand) (opindex, &fields); + if (errmsg) + as_warn_where (fixP->fx_file, fixP->fx_line, "%s\n", errmsg); + CGEN_SYM (insert_operand) (opindex, &fields, where); + } + + if (fixP->fx_done) + return 1; + + /* The operand isn't fully resolved. Determine a BFD reloc value + based on the operand information and leave it to + bfd_install_relocation. Note that this doesn't work when + partial_inplace == false. */ + + reloc_type = CGEN_SYM (lookup_reloc) (insn, operand, fixP); + if (reloc_type != BFD_RELOC_NONE) + { + fixP->fx_r_type = reloc_type; + } + else + { + as_bad_where (fixP->fx_file, fixP->fx_line, + "unresolved expression that must be resolved"); + fixP->fx_done = 1; + return 1; + } + } + else if (fixP->fx_done) + { + /* We're finished with this fixup. Install it because + bfd_install_relocation won't be called to do it. */ + switch (fixP->fx_r_type) + { + case BFD_RELOC_8: + md_number_to_chars (where, value, 1); + break; + case BFD_RELOC_16: + md_number_to_chars (where, value, 2); + break; + case BFD_RELOC_32: + md_number_to_chars (where, value, 4); + break; + /* FIXME: later add support for 64 bits. */ + default: + abort (); + } + } + else + { + /* bfd_install_relocation will be called to finish things up. */ + } + + /* Tuck `value' away for use by tc_gen_reloc. + See the comment describing fx_addnumber in write.h. + This field is misnamed (or misused :-). */ + fixP->fx_addnumber = value; + + return 1; +} + +/* Translate internal representation of relocation info to BFD target format. + + FIXME: To what extent can we get all relevant targets to use this? */ + +arelent * +cgen_tc_gen_reloc (section, fixP) + asection *section; + fixS *fixP; +{ + arelent *reloc; + + reloc = (arelent *) bfd_alloc (stdoutput, sizeof (arelent)); + + reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type); + if (reloc->howto == (reloc_howto_type *) NULL) + { + as_bad_where (fixP->fx_file, fixP->fx_line, + "internal error: can't export reloc type %d (`%s')", + fixP->fx_r_type, bfd_get_reloc_code_name (fixP->fx_r_type)); + return NULL; + } + + assert (!fixP->fx_pcrel == !reloc->howto->pc_relative); + + reloc->sym_ptr_ptr = &fixP->fx_addsy->bsym; + reloc->address = fixP->fx_frag->fr_address + fixP->fx_where; + reloc->addend = fixP->fx_addnumber; + + return reloc; +} diff --git a/gnu/usr.bin/binutils/gas/config/e-i386coff.c b/gnu/usr.bin/binutils/gas/config/e-i386coff.c new file mode 100644 index 00000000000..afed72886ac --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/e-i386coff.c @@ -0,0 +1,17 @@ +#include "as.h" +#include "emul.h" + +static const char * +i386coff_bfd_name () +{ + abort (); + return NULL; +} + +#define emul_bfd_name i386coff_bfd_name +#define emul_format &coff_format_ops + +#define emul_name "i386coff" +#define emul_struct_name i386coff +#define emul_default_endian 0 +#include "emul-target.h" diff --git a/gnu/usr.bin/binutils/gas/config/e-i386elf.c b/gnu/usr.bin/binutils/gas/config/e-i386elf.c new file mode 100644 index 00000000000..a16701e811e --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/e-i386elf.c @@ -0,0 +1,17 @@ +#include "as.h" +#include "emul.h" + +static const char * +i386elf_bfd_name () +{ + abort (); + return NULL; +} + +#define emul_bfd_name i386elf_bfd_name +#define emul_format &elf_format_ops + +#define emul_name "i386elf" +#define emul_struct_name i386elf +#define emul_default_endian 0 +#include "emul-target.h" diff --git a/gnu/usr.bin/binutils/gas/config/itbl-mips.h b/gnu/usr.bin/binutils/gas/config/itbl-mips.h new file mode 100644 index 00000000000..f6482bd1f75 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/itbl-mips.h @@ -0,0 +1,47 @@ + +/* itbl-mips.h + + Copyright (C) 1997 Free Software Foundation, Inc. + + This file is part of GAS, the GNU Assembler. + + GAS 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 2, or (at your option) + any later version. + + GAS 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 GAS; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* Defines for Mips itbl cop support */ + +#include "opcode/mips.h" + +/* Values for processors will be from 0 to NUMBER_OF_PROCESSORS-1 */ +#define NUMBER_OF_PROCESSORS 4 +#define MAX_BITPOS 31 + +/* Mips specifics */ +#define MIPS_OPCODE_COP0 (0x21) /* COPz+CO, bits 31-25: 0100zz1 */ +#define MIPS_ENCODE_COP_NUM(z) ((MIPS_OPCODE_COP0|z<<1)<<25) +#define MIPS_IS_COP_INSN(insn) ((MIPS_OPCODE_COP0&(insn>>25)) \ + == MIPS_OPCODE_COP0) +#define MIPS_DECODE_COP_NUM(insn) ((~MIPS_OPCODE_COP0&(insn>>25))>>1) +#define MIPS_DECODE_COP_COFUN(insn) ((~MIPS_ENCODE_COP_NUM(3))&(insn)) + +/* definitions required by generic code */ +#define ITBL_IS_INSN(insn) MIPS_IS_COP_INSN(insn) +#define ITBL_DECODE_PNUM(insn) MIPS_DECODE_COP_NUM(insn) +#define ITBL_ENCODE_PNUM(pnum) MIPS_ENCODE_COP_NUM(pnum) + +#define ITBL_OPCODE_STRUCT mips_opcode +#define ITBL_OPCODES mips_opcodes +#define ITBL_NUM_OPCODES NUMOPCODES +#define ITBL_NUM_MACROS M_NUM_MACROS diff --git a/gnu/usr.bin/binutils/gas/config/tc-d10v.c b/gnu/usr.bin/binutils/gas/config/tc-d10v.c new file mode 100644 index 00000000000..28519c7edd4 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/tc-d10v.c @@ -0,0 +1,1430 @@ +/* tc-d10v.c -- Assembler code for the Mitsubishi D10V + + Copyright (C) 1996, 1997 Free Software Foundation. + + This file is part of GAS, the GNU Assembler. + + GAS 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 2, or (at your option) + any later version. + + GAS 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 GAS; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <stdio.h> +#include <ctype.h> +#include "as.h" +#include "subsegs.h" +#include "opcode/d10v.h" +#include "elf/ppc.h" + +const char comment_chars[] = ";"; +const char line_comment_chars[] = "#"; +const char line_separator_chars[] = ""; +const char *md_shortopts = "O"; +const char EXP_CHARS[] = "eE"; +const char FLT_CHARS[] = "dD"; + +int Optimizing = 0; + +#define AT_WORD (-1) + +/* fixups */ +#define MAX_INSN_FIXUPS (5) +struct d10v_fixup +{ + expressionS exp; + int operand; + int pcrel; + int size; + bfd_reloc_code_real_type reloc; +}; + +typedef struct _fixups +{ + int fc; + struct d10v_fixup fix[MAX_INSN_FIXUPS]; + struct _fixups *next; +} Fixups; + +static Fixups FixUps[2]; +static Fixups *fixups; + +/* local functions */ +static int reg_name_search PARAMS ((char *name)); +static int register_name PARAMS ((expressionS *expressionP)); +static int check_range PARAMS ((unsigned long num, int bits, int flags)); +static int postfix PARAMS ((char *p)); +static bfd_reloc_code_real_type get_reloc PARAMS ((struct d10v_operand *op)); +static int get_operands PARAMS ((expressionS exp[])); +static struct d10v_opcode *find_opcode PARAMS ((struct d10v_opcode *opcode, expressionS ops[])); +static unsigned long build_insn PARAMS ((struct d10v_opcode *opcode, expressionS *opers, unsigned long insn)); +static void write_long PARAMS ((struct d10v_opcode *opcode, unsigned long insn, Fixups *fx)); +static void write_1_short PARAMS ((struct d10v_opcode *opcode, unsigned long insn, Fixups *fx)); +static int write_2_short PARAMS ((struct d10v_opcode *opcode1, unsigned long insn1, + struct d10v_opcode *opcode2, unsigned long insn2, int exec_type, Fixups *fx)); +static unsigned long do_assemble PARAMS ((char *str, struct d10v_opcode **opcode)); +static unsigned long d10v_insert_operand PARAMS (( unsigned long insn, int op_type, + offsetT value, int left, fixS *fix)); +static int parallel_ok PARAMS ((struct d10v_opcode *opcode1, unsigned long insn1, + struct d10v_opcode *opcode2, unsigned long insn2, + int exec_type)); + +struct option md_longopts[] = { + {NULL, no_argument, NULL, 0} +}; +size_t md_longopts_size = sizeof(md_longopts); + +static void d10v_dot_word PARAMS ((int)); + +/* The target specific pseudo-ops which we support. */ +const pseudo_typeS md_pseudo_table[] = +{ + { "word", d10v_dot_word, 2 }, + { NULL, NULL, 0 } +}; + +/* Opcode hash table. */ +static struct hash_control *d10v_hash; + +/* reg_name_search does a binary search of the d10v_predefined_registers + array to see if "name" is a valid regiter name. Returns the register + number from the array on success, or -1 on failure. */ + +static int +reg_name_search (name) + char *name; +{ + int middle, low, high; + int cmp; + + low = 0; + high = d10v_reg_name_cnt() - 1; + + do + { + middle = (low + high) / 2; + cmp = strcasecmp (name, d10v_predefined_registers[middle].name); + if (cmp < 0) + high = middle - 1; + else if (cmp > 0) + low = middle + 1; + else + return d10v_predefined_registers[middle].value; + } + while (low <= high); + return -1; +} + +/* register_name() checks the string at input_line_pointer + to see if it is a valid register name */ + +static int +register_name (expressionP) + expressionS *expressionP; +{ + int reg_number; + char c, *p = input_line_pointer; + + while (*p && *p!='\n' && *p!='\r' && *p !=',' && *p!=' ' && *p!=')') + p++; + + c = *p; + if (c) + *p++ = 0; + + /* look to see if it's in the register table */ + reg_number = reg_name_search (input_line_pointer); + if (reg_number >= 0) + { + expressionP->X_op = O_register; + /* temporarily store a pointer to the string here */ + expressionP->X_op_symbol = (struct symbol *)input_line_pointer; + expressionP->X_add_number = reg_number; + input_line_pointer = p; + return 1; + } + if (c) + *(p-1) = c; + return 0; +} + + +static int +check_range (num, bits, flags) + unsigned long num; + int bits; + int flags; +{ + long min, max, bit1; + int retval=0; + + /* don't bother checking 16-bit values */ + if (bits == 16) + return 0; + + if (flags & OPERAND_SHIFT) + { + /* all special shift operands are unsigned */ + /* and <= 16. We allow 0 for now. */ + if (num>16) + return 1; + else + return 0; + } + + if (flags & OPERAND_SIGNED) + { + max = (1 << (bits - 1))-1; + min = - (1 << (bits - 1)); + if (((long)num > max) || ((long)num < min)) + retval = 1; + } + else + { + max = (1 << bits) - 1; + min = 0; + if ((num > max) || (num < min)) + retval = 1; + } + return retval; +} + + +void +md_show_usage (stream) + FILE *stream; +{ + fprintf(stream, "D10V options:\n\ +-O optimize. Will do some operations in parallel.\n"); +} + +int +md_parse_option (c, arg) + int c; + char *arg; +{ + switch (c) + { + case 'O': + /* Optimize. Will attempt to parallelize operations */ + Optimizing = 1; + break; + default: + return 0; + } + return 1; +} + +symbolS * +md_undefined_symbol (name) + char *name; +{ + return 0; +} + +/* Turn a string in input_line_pointer into a floating point constant of type + type, and store the appropriate bytes in *litP. The number of LITTLENUMS + emitted is stored in *sizeP . An error message is returned, or NULL on OK. + */ +char * +md_atof (type, litP, sizeP) + int type; + char *litP; + int *sizeP; +{ + int prec; + LITTLENUM_TYPE words[4]; + char *t; + int i; + + switch (type) + { + case 'f': + prec = 2; + break; + case 'd': + prec = 4; + break; + default: + *sizeP = 0; + return "bad call to md_atof"; + } + + t = atof_ieee (input_line_pointer, type, words); + if (t) + input_line_pointer = t; + + *sizeP = prec * 2; + + for (i = 0; i < prec; i++) + { + md_number_to_chars (litP, (valueT) words[i], 2); + litP += 2; + } + return NULL; +} + +void +md_convert_frag (abfd, sec, fragP) + bfd *abfd; + asection *sec; + fragS *fragP; +{ + abort (); +} + +valueT +md_section_align (seg, addr) + asection *seg; + valueT addr; +{ + int align = bfd_get_section_alignment (stdoutput, seg); + return ((addr + (1 << align) - 1) & (-1 << align)); +} + + +void +md_begin () +{ + char *prev_name = ""; + struct d10v_opcode *opcode; + d10v_hash = hash_new(); + + /* Insert unique names into hash table. The D10v instruction set + has many identical opcode names that have different opcodes based + on the operands. This hash table then provides a quick index to + the first opcode with a particular name in the opcode table. */ + + for (opcode = (struct d10v_opcode *)d10v_opcodes; opcode->name; opcode++) + { + if (strcmp (prev_name, opcode->name)) + { + prev_name = (char *)opcode->name; + hash_insert (d10v_hash, opcode->name, (char *) opcode); + } + } + + fixups = &FixUps[0]; + FixUps[0].next = &FixUps[1]; + FixUps[1].next = &FixUps[0]; +} + + +/* this function removes the postincrement or postdecrement + operator ( '+' or '-' ) from an expression */ + +static int postfix (p) + char *p; +{ + while (*p != '-' && *p != '+') + { + if (*p==0 || *p=='\n' || *p=='\r') + break; + p++; + } + + if (*p == '-') + { + *p = ' '; + return (-1); + } + if (*p == '+') + { + *p = ' '; + return (1); + } + + return (0); +} + + +static bfd_reloc_code_real_type +get_reloc (op) + struct d10v_operand *op; +{ + int bits = op->bits; + + if (bits <= 4) + return (0); + + if (op->flags & OPERAND_ADDR) + { + if (bits == 8) + return (BFD_RELOC_D10V_10_PCREL_R); + else + return (BFD_RELOC_D10V_18_PCREL); + } + + return (BFD_RELOC_16); +} + + +/* get_operands parses a string of operands and returns + an array of expressions */ + +static int +get_operands (exp) + expressionS exp[]; +{ + char *p = input_line_pointer; + int numops = 0; + int post = 0; + + while (*p) + { + while (*p == ' ' || *p == '\t' || *p == ',') + p++; + if (*p==0 || *p=='\n' || *p=='\r') + break; + + if (*p == '@') + { + p++; + exp[numops].X_op = O_absent; + if (*p == '(') + { + p++; + exp[numops].X_add_number = OPERAND_ATPAR; + } + else if (*p == '-') + { + p++; + exp[numops].X_add_number = OPERAND_ATMINUS; + } + else + { + exp[numops].X_add_number = OPERAND_ATSIGN; + post = postfix (p); + } + numops++; + continue; + } + + if (*p == ')') + { + /* just skip the trailing paren */ + p++; + continue; + } + + input_line_pointer = p; + + /* check to see if it might be a register name */ + if (!register_name (&exp[numops])) + { + /* parse as an expression */ + expression (&exp[numops]); + } + + if (!strncasecmp (input_line_pointer, "@word", 5)) + { + if (exp[numops].X_op == O_register) + { + /* if it looked like a register name but was followed by "@word" */ + /* then it was really a symbol, so change it to one */ + exp[numops].X_op = O_symbol; + exp[numops].X_add_symbol = symbol_find_or_make ((char *)exp[numops].X_op_symbol); + exp[numops].X_op_symbol = NULL; + } + exp[numops].X_add_number = AT_WORD; + input_line_pointer += 5; + } + + if (exp[numops].X_op == O_illegal) + as_bad ("illegal operand"); + else if (exp[numops].X_op == O_absent) + as_bad ("missing operand"); + + numops++; + p = input_line_pointer; + } + + switch (post) + { + case -1: /* postdecrement mode */ + exp[numops].X_op = O_absent; + exp[numops++].X_add_number = OPERAND_MINUS; + break; + case 1: /* postincrement mode */ + exp[numops].X_op = O_absent; + exp[numops++].X_add_number = OPERAND_PLUS; + break; + } + + exp[numops].X_op = 0; + return (numops); +} + +static unsigned long +d10v_insert_operand (insn, op_type, value, left, fix) + unsigned long insn; + int op_type; + offsetT value; + int left; + fixS *fix; +{ + int shift, bits; + + shift = d10v_operands[op_type].shift; + if (left) + shift += 15; + + bits = d10v_operands[op_type].bits; + + /* truncate to the proper number of bits */ + if (check_range (value, bits, d10v_operands[op_type].flags)) + as_bad_where (fix->fx_file, fix->fx_line, "operand out of range: %d", value); + + value &= 0x7FFFFFFF >> (31 - bits); + insn |= (value << shift); + + return insn; +} + + +/* build_insn takes a pointer to the opcode entry in the opcode table + and the array of operand expressions and returns the instruction */ + +static unsigned long +build_insn (opcode, opers, insn) + struct d10v_opcode *opcode; + expressionS *opers; + unsigned long insn; +{ + int i, bits, shift, flags, format; + unsigned int number; + + /* the insn argument is only used for the DIVS kludge */ + if (insn) + format = LONG_R; + else + { + insn = opcode->opcode; + format = opcode->format; + } + + for (i=0;opcode->operands[i];i++) + { + flags = d10v_operands[opcode->operands[i]].flags; + bits = d10v_operands[opcode->operands[i]].bits; + shift = d10v_operands[opcode->operands[i]].shift; + number = opers[i].X_add_number; + + if (flags & OPERAND_REG) + { + number &= REGISTER_MASK; + if (format == LONG_L) + shift += 15; + } + + if (opers[i].X_op != O_register && opers[i].X_op != O_constant) + { + /* now create a fixup */ + + if (fixups->fc >= MAX_INSN_FIXUPS) + as_fatal ("too many fixups"); + + if (opers[i].X_op == O_symbol && number == AT_WORD) + { + number = opers[i].X_add_number = 0; + fixups->fix[fixups->fc].reloc = BFD_RELOC_D10V_18; + } else + fixups->fix[fixups->fc].reloc = + get_reloc((struct d10v_operand *)&d10v_operands[opcode->operands[i]]); + + if (fixups->fix[fixups->fc].reloc == BFD_RELOC_16 || + fixups->fix[fixups->fc].reloc == BFD_RELOC_D10V_18) + fixups->fix[fixups->fc].size = 2; + else + fixups->fix[fixups->fc].size = 4; + + fixups->fix[fixups->fc].exp = opers[i]; + fixups->fix[fixups->fc].operand = opcode->operands[i]; + fixups->fix[fixups->fc].pcrel = (flags & OPERAND_ADDR) ? true : false; + (fixups->fc)++; + } + + /* truncate to the proper number of bits */ + if ((opers[i].X_op == O_constant) && check_range (number, bits, flags)) + as_bad("operand out of range: %d",number); + number &= 0x7FFFFFFF >> (31 - bits); + insn = insn | (number << shift); + } + + /* kludge: for DIVS, we need to put the operands in twice */ + /* on the second pass, format is changed to LONG_R to force */ + /* the second set of operands to not be shifted over 15 */ + if ((opcode->opcode == OPCODE_DIVS) && (format==LONG_L)) + insn = build_insn (opcode, opers, insn); + + return insn; +} + +/* write out a long form instruction */ +static void +write_long (opcode, insn, fx) + struct d10v_opcode *opcode; + unsigned long insn; + Fixups *fx; +{ + int i, where; + char *f = frag_more(4); + + insn |= FM11; + number_to_chars_bigendian (f, insn, 4); + + for (i=0; i < fx->fc; i++) + { + if (fx->fix[i].reloc) + { + where = f - frag_now->fr_literal; + if (fx->fix[i].size == 2) + where += 2; + + if (fx->fix[i].reloc == BFD_RELOC_D10V_18) + fx->fix[i].operand |= 4096; + + fix_new_exp (frag_now, + where, + fx->fix[i].size, + &(fx->fix[i].exp), + fx->fix[i].pcrel, + fx->fix[i].operand|2048); + } + } + fx->fc = 0; +} + + +/* write out a short form instruction by itself */ +static void +write_1_short (opcode, insn, fx) + struct d10v_opcode *opcode; + unsigned long insn; + Fixups *fx; +{ + char *f = frag_more(4); + int i, where; + + if (opcode->exec_type & PARONLY) + as_fatal ("Instruction must be executed in parallel with another instruction."); + + /* the other container needs to be NOP */ + /* according to 4.3.1: for FM=00, sub-instructions performed only + by IU cannot be encoded in L-container. */ + if (opcode->unit == IU) + insn |= FM00 | (NOP << 15); /* right container */ + else + insn = FM00 | (insn << 15) | NOP; /* left container */ + + number_to_chars_bigendian (f, insn, 4); + for (i=0; i < fx->fc; i++) + { + if (fx->fix[i].reloc) + { + where = f - frag_now->fr_literal; + if (fx->fix[i].size == 2) + where += 2; + + if (fx->fix[i].reloc == BFD_RELOC_D10V_18) + fx->fix[i].operand |= 4096; + + /* if it's an R reloc, we may have to switch it to L */ + if ( (fx->fix[i].reloc == BFD_RELOC_D10V_10_PCREL_R) && (opcode->unit != IU) ) + fx->fix[i].operand |= 1024; + + fix_new_exp (frag_now, + where, + fx->fix[i].size, + &(fx->fix[i].exp), + fx->fix[i].pcrel, + fx->fix[i].operand|2048); + } + } + fx->fc = 0; +} + +/* write out a short form instruction if possible */ +/* return number of instructions not written out */ +static int +write_2_short (opcode1, insn1, opcode2, insn2, exec_type, fx) + struct d10v_opcode *opcode1, *opcode2; + unsigned long insn1, insn2; + int exec_type; + Fixups *fx; +{ + unsigned long insn; + char *f; + int i,j, where; + + if ( (exec_type != 1) && ((opcode1->exec_type & PARONLY) + || (opcode2->exec_type & PARONLY))) + as_fatal("Instruction must be executed in parallel"); + + if ( (opcode1->format & LONG_OPCODE) || (opcode2->format & LONG_OPCODE)) + as_fatal ("Long instructions may not be combined."); + + if(opcode1->exec_type & BRANCH_LINK && opcode2->exec_type != PARONLY) + { + /* subroutines must be called from 32-bit boundaries */ + /* so the return address will be correct */ + write_1_short (opcode1, insn1, fx->next); + return (1); + } + + switch (exec_type) + { + case 0: /* order not specified */ + if ( Optimizing && parallel_ok (opcode1, insn1, opcode2, insn2, exec_type)) + { + /* parallel */ + if (opcode1->unit == IU) + insn = FM00 | (insn2 << 15) | insn1; + else if (opcode2->unit == MU) + insn = FM00 | (insn2 << 15) | insn1; + else + { + insn = FM00 | (insn1 << 15) | insn2; + fx = fx->next; + } + } + else if (opcode1->unit == IU) + { + /* reverse sequential */ + insn = FM10 | (insn2 << 15) | insn1; + } + else + { + /* sequential */ + insn = FM01 | (insn1 << 15) | insn2; + fx = fx->next; + } + break; + case 1: /* parallel */ + if (opcode1->exec_type & SEQ || opcode2->exec_type & SEQ) + as_fatal ("One of these instructions may not be executed in parallel."); + + if (opcode1->unit == IU) + { + if (opcode2->unit == IU) + as_fatal ("Two IU instructions may not be executed in parallel"); + as_warn ("Swapping instruction order"); + insn = FM00 | (insn2 << 15) | insn1; + } + else if (opcode2->unit == MU) + { + if (opcode1->unit == MU) + as_fatal ("Two MU instructions may not be executed in parallel"); + as_warn ("Swapping instruction order"); + insn = FM00 | (insn2 << 15) | insn1; + } + else + { + insn = FM00 | (insn1 << 15) | insn2; + fx = fx->next; + } + break; + case 2: /* sequential */ + if (opcode1->unit == IU) + as_fatal ("IU instruction may not be in the left container"); + insn = FM01 | (insn1 << 15) | insn2; + fx = fx->next; + break; + case 3: /* reverse sequential */ + if (opcode2->unit == MU) + as_fatal ("MU instruction may not be in the right container"); + insn = FM10 | (insn1 << 15) | insn2; + fx = fx->next; + break; + default: + as_fatal("unknown execution type passed to write_2_short()"); + } + + f = frag_more(4); + number_to_chars_bigendian (f, insn, 4); + + for (j=0; j<2; j++) + { + for (i=0; i < fx->fc; i++) + { + if (fx->fix[i].reloc) + { + where = f - frag_now->fr_literal; + if (fx->fix[i].size == 2) + where += 2; + + if ( (fx->fix[i].reloc == BFD_RELOC_D10V_10_PCREL_R) && (j == 0) ) + fx->fix[i].operand |= 1024; + + if (fx->fix[i].reloc == BFD_RELOC_D10V_18) + fx->fix[i].operand |= 4096; + + fix_new_exp (frag_now, + where, + fx->fix[i].size, + &(fx->fix[i].exp), + fx->fix[i].pcrel, + fx->fix[i].operand|2048); + } + } + fx->fc = 0; + fx = fx->next; + } + return (0); +} + + +/* Check 2 instructions and determine if they can be safely */ +/* executed in parallel. Returns 1 if they can be. */ +static int +parallel_ok (op1, insn1, op2, insn2, exec_type) + struct d10v_opcode *op1, *op2; + unsigned long insn1, insn2; + int exec_type; +{ + int i, j, flags, mask, shift, regno; + unsigned long ins, mod[2], used[2]; + struct d10v_opcode *op; + + if ((op1->exec_type & SEQ) != 0 || (op2->exec_type & SEQ) != 0 + || (op1->exec_type & PAR) == 0 || (op2->exec_type & PAR) == 0 + || (op1->unit == BOTH) || (op2->unit == BOTH) + || (op1->unit == IU && op2->unit == IU) + || (op1->unit == MU && op2->unit == MU)) + return 0; + + /* If the first instruction is a branch and this is auto parallazation, + don't combine with any second instruction. */ + if (exec_type == 0 && (op1->exec_type & BRANCH) != 0) + return 0; + + /* The idea here is to create two sets of bitmasks (mod and used) */ + /* which indicate which registers are modified or used by each instruction. */ + /* The operation can only be done in parallel if instruction 1 and instruction 2 */ + /* modify different registers, and neither instruction modifies any registers */ + /* the other is using. Accesses to control registers, PSW, and memory are treated */ + /* as accesses to a single register. So if both instructions write memory or one */ + /* instruction writes memory and the other reads, then they cannot be done in parallel. */ + /* Likewise, if one instruction mucks with the psw and the other reads the PSW */ + /* (which includes C, F0, and F1), then they cannot operate safely in parallel. */ + + /* the bitmasks (mod and used) look like this (bit 31 = MSB) */ + /* r0-r15 0-15 */ + /* a0-a1 16-17 */ + /* cr (not psw) 18 */ + /* psw 19 */ + /* mem 20 */ + + for (j=0;j<2;j++) + { + if (j == 0) + { + op = op1; + ins = insn1; + } + else + { + op = op2; + ins = insn2; + } + mod[j] = used[j] = 0; + if (op->exec_type & BRANCH_LINK) + mod[j] |= 1 << 13; + + for (i = 0; op->operands[i]; i++) + { + flags = d10v_operands[op->operands[i]].flags; + shift = d10v_operands[op->operands[i]].shift; + mask = 0x7FFFFFFF >> (31 - d10v_operands[op->operands[i]].bits); + if (flags & OPERAND_REG) + { + regno = (ins >> shift) & mask; + if (flags & OPERAND_ACC) + regno += 16; + else if (flags & OPERAND_CONTROL) /* mvtc or mvfc */ + { + if (regno == 0) + regno = 19; + else + regno = 18; + } + else if (flags & OPERAND_FLAG) + regno = 19; + + if ( flags & OPERAND_DEST ) + { + mod[j] |= 1 << regno; + if (flags & OPERAND_EVEN) + mod[j] |= 1 << (regno + 1); + } + else + { + used[j] |= 1 << regno ; + if (flags & OPERAND_EVEN) + used[j] |= 1 << (regno + 1); + } + } + } + if (op->exec_type & RMEM) + used[j] |= 1 << 20; + else if (op->exec_type & WMEM) + mod[j] |= 1 << 20; + else if (op->exec_type & RF0) + used[j] |= 1 << 19; + else if (op->exec_type & WF0) + mod[j] |= 1 << 19; + else if (op->exec_type & WCAR) + mod[j] |= 1 << 19; + } + if ((mod[0] & mod[1]) == 0 && (mod[0] & used[1]) == 0 && (mod[1] & used[0]) == 0) + return 1; + return 0; +} + + +/* This is the main entry point for the machine-dependent assembler. str points to a + machine-dependent instruction. This function is supposed to emit the frags/bytes + it assembles to. For the D10V, it mostly handles the special VLIW parsing and packing + and leaves the difficult stuff to do_assemble(). + */ + +static unsigned long prev_insn; +static struct d10v_opcode *prev_opcode = 0; +static subsegT prev_subseg; +static segT prev_seg = 0;; + +void +md_assemble (str) + char *str; +{ + struct d10v_opcode *opcode; + unsigned long insn; + int extype=0; /* execution type; parallel, etc */ + static int etype=0; /* saved extype. used for multiline instructions */ + char *str2; + + if (etype == 0) + { + /* look for the special multiple instruction separators */ + str2 = strstr (str, "||"); + if (str2) + extype = 1; + else + { + str2 = strstr (str, "->"); + if (str2) + extype = 2; + else + { + str2 = strstr (str, "<-"); + if (str2) + extype = 3; + } + } + /* str2 points to the separator, if one */ + if (str2) + { + *str2 = 0; + + /* if two instructions are present and we already have one saved + then first write it out */ + d10v_cleanup(); + + /* assemble first instruction and save it */ + prev_insn = do_assemble (str, &prev_opcode); + if (prev_insn == -1) + as_fatal ("can't find opcode "); + fixups = fixups->next; + str = str2 + 2; + } + } + + insn = do_assemble (str, &opcode); + if (insn == -1) + { + if (extype) + { + etype = extype; + return; + } + as_fatal ("can't find opcode "); + } + + if (etype) + { + extype = etype; + etype = 0; + } + + /* if this is a long instruction, write it and any previous short instruction */ + if (opcode->format & LONG_OPCODE) + { + if (extype) + as_fatal("Unable to mix instructions as specified"); + d10v_cleanup(); + write_long (opcode, insn, fixups); + prev_opcode = NULL; + return; + } + + if (prev_opcode && prev_seg && ((prev_seg != now_seg) || (prev_subseg != now_subseg))) + d10v_cleanup(); + + if (prev_opcode && (write_2_short (prev_opcode, prev_insn, opcode, insn, extype, fixups) == 0)) + { + /* no instructions saved */ + prev_opcode = NULL; + } + else + { + if (extype) + as_fatal("Unable to mix instructions as specified"); + /* save off last instruction so it may be packed on next pass */ + prev_opcode = opcode; + prev_insn = insn; + prev_seg = now_seg; + prev_subseg = now_subseg; + fixups = fixups->next; + } +} + + +/* do_assemble assembles a single instruction and returns an opcode */ +/* it returns -1 (an invalid opcode) on error */ + +static unsigned long +do_assemble (str, opcode) + char *str; + struct d10v_opcode **opcode; +{ + unsigned char *op_start, *save; + unsigned char *op_end; + char name[20]; + int nlen = 0; + expressionS myops[6]; + unsigned long insn; + + /* Drop leading whitespace */ + while (*str == ' ') + str++; + + /* find the opcode end */ + for (op_start = op_end = (unsigned char *) (str); + *op_end + && nlen < 20 + && !is_end_of_line[*op_end] && *op_end != ' '; + op_end++) + { + name[nlen] = tolower(op_start[nlen]); + nlen++; + } + name[nlen] = 0; + + if (nlen == 0) + return (-1); + + /* find the first opcode with the proper name */ + *opcode = (struct d10v_opcode *)hash_find (d10v_hash, name); + if (*opcode == NULL) + as_fatal ("unknown opcode: %s",name); + + save = input_line_pointer; + input_line_pointer = op_end; + *opcode = find_opcode (*opcode, myops); + if (*opcode == 0) + return -1; + input_line_pointer = save; + + insn = build_insn ((*opcode), myops, 0); + return (insn); +} + +/* find_opcode() gets a pointer to an entry in the opcode table. */ +/* It must look at all opcodes with the same name and use the operands */ +/* to choose the correct opcode. */ + +static struct d10v_opcode * +find_opcode (opcode, myops) + struct d10v_opcode *opcode; + expressionS myops[]; +{ + int i, match, done; + struct d10v_opcode *next_opcode; + + /* get all the operands and save them as expressions */ + get_operands (myops); + + /* now see if the operand is a fake. If so, find the correct size */ + /* instruction, if possible */ + if (opcode->format == OPCODE_FAKE) + { + int opnum = opcode->operands[0]; + + if (myops[opnum].X_op == O_register) + { + myops[opnum].X_op = O_symbol; + myops[opnum].X_add_symbol = symbol_find_or_make ((char *)myops[opnum].X_op_symbol); + myops[opnum].X_add_number = 0; + myops[opnum].X_op_symbol = NULL; + } + + if (myops[opnum].X_op == O_constant || (myops[opnum].X_op == O_symbol && + S_IS_DEFINED(myops[opnum].X_add_symbol) && + (S_GET_SEGMENT(myops[opnum].X_add_symbol) == now_seg))) + { + next_opcode=opcode+1; + for (i=0; opcode->operands[i+1]; i++) + { + int bits = d10v_operands[next_opcode->operands[opnum]].bits; + int flags = d10v_operands[next_opcode->operands[opnum]].flags; + if (flags & OPERAND_ADDR) + bits += 2; + if (myops[opnum].X_op == O_constant) + { + if (!check_range (myops[opnum].X_add_number, bits, flags)) + return next_opcode; + } + else + { + fragS *f; + long value; + /* calculate the current address by running through the previous frags */ + /* and adding our current offset */ + for (value = 0, f = frchain_now->frch_root; f; f = f->fr_next) + value += f->fr_fix + f->fr_offset; + + if (flags & OPERAND_ADDR) + value = S_GET_VALUE(myops[opnum].X_add_symbol) - value - + (obstack_next_free(&frchain_now->frch_obstack) - frag_now->fr_literal); + else + value = S_GET_VALUE(myops[opnum].X_add_symbol); + + if (myops[opnum].X_add_number == AT_WORD) + { + if (bits > 4) + { + bits += 2; + if (!check_range (value, bits, flags)) + return next_opcode; + } + } + else if (!check_range (value, bits, flags)) + return next_opcode; + } + next_opcode++; + } + as_fatal ("value out of range"); + } + else + { + /* not a constant, so use a long instruction */ + return opcode+2; + } + } + else + { + match = 0; + /* now search the opcode table table for one with operands */ + /* that matches what we've got */ + while (!match) + { + match = 1; + for (i = 0; opcode->operands[i]; i++) + { + int flags = d10v_operands[opcode->operands[i]].flags; + int X_op = myops[i].X_op; + int num = myops[i].X_add_number; + + if (X_op==0) + { + match=0; + break; + } + + if (flags & OPERAND_REG) + { + if ((X_op != O_register) || + ((flags & OPERAND_ACC) != (num & OPERAND_ACC)) || + ((flags & OPERAND_FLAG) != (num & OPERAND_FLAG)) || + ((flags & OPERAND_CONTROL) != (num & OPERAND_CONTROL))) + { + match=0; + break; + } + } + + if (((flags & OPERAND_MINUS) && ((X_op != O_absent) || (num != OPERAND_MINUS))) || + ((flags & OPERAND_PLUS) && ((X_op != O_absent) || (num != OPERAND_PLUS))) || + ((flags & OPERAND_ATMINUS) && ((X_op != O_absent) || (num != OPERAND_ATMINUS))) || + ((flags & OPERAND_ATPAR) && ((X_op != O_absent) || (num != OPERAND_ATPAR))) || + ((flags & OPERAND_ATSIGN) && ((X_op != O_absent) || (num != OPERAND_ATSIGN)))) + { + match=0; + break; + } + } + /* we're only done if the operands matched so far AND there + are no more to check */ + if (match && myops[i].X_op==0) + break; + else + match = 0; + + next_opcode = opcode+1; + if (next_opcode->opcode == 0) + break; + if (strcmp(next_opcode->name, opcode->name)) + break; + opcode = next_opcode; + } + } + + if (!match) + { + as_bad ("bad opcode or operands"); + return (0); + } + + /* Check that all registers that are required to be even are. */ + /* Also, if any operands were marked as registers, but were really symbols */ + /* fix that here. */ + for (i=0; opcode->operands[i]; i++) + { + if ((d10v_operands[opcode->operands[i]].flags & OPERAND_EVEN) && + (myops[i].X_add_number & 1)) + as_fatal("Register number must be EVEN"); + if (myops[i].X_op == O_register) + { + if (!(d10v_operands[opcode->operands[i]].flags & OPERAND_REG)) + { + myops[i].X_op = O_symbol; + myops[i].X_add_symbol = symbol_find_or_make ((char *)myops[i].X_op_symbol); + myops[i].X_add_number = 0; + myops[i].X_op_symbol = NULL; + } + } + } + return opcode; +} + +/* if while processing a fixup, a reloc really needs to be created */ +/* then it is done here */ + +arelent * +tc_gen_reloc (seg, fixp) + asection *seg; + fixS *fixp; +{ + arelent *reloc; + reloc = (arelent *) xmalloc (sizeof (arelent)); + reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym; + reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; + reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); + if (reloc->howto == (reloc_howto_type *) NULL) + { + as_bad_where (fixp->fx_file, fixp->fx_line, + "reloc %d not supported by object file format", (int)fixp->fx_r_type); + return NULL; + } + reloc->addend = fixp->fx_addnumber; + return reloc; +} + +int +md_estimate_size_before_relax (fragp, seg) + fragS *fragp; + asection *seg; +{ + abort (); + return 0; +} + +long +md_pcrel_from_section (fixp, sec) + fixS *fixp; + segT sec; +{ + if (fixp->fx_addsy != (symbolS *)NULL && (!S_IS_DEFINED (fixp->fx_addsy) || + (S_GET_SEGMENT (fixp->fx_addsy) != sec))) + return 0; + return fixp->fx_frag->fr_address + fixp->fx_where; +} + +int +md_apply_fix3 (fixp, valuep, seg) + fixS *fixp; + valueT *valuep; + segT seg; +{ + char *where; + unsigned long insn; + long value; + int op_type; + int left=0; + + if (fixp->fx_addsy == (symbolS *) NULL) + { + value = *valuep; + fixp->fx_done = 1; + } + else if (fixp->fx_pcrel) + value = *valuep; + else + { + value = fixp->fx_offset; + if (fixp->fx_subsy != (symbolS *) NULL) + { + if (S_GET_SEGMENT (fixp->fx_subsy) == absolute_section) + value -= S_GET_VALUE (fixp->fx_subsy); + else + { + /* We don't actually support subtracting a symbol. */ + as_bad_where (fixp->fx_file, fixp->fx_line, + "expression too complex"); + } + } + } + + op_type = fixp->fx_r_type; + if (op_type & 2048) + { + op_type -= 2048; + if (op_type & 1024) + { + op_type -= 1024; + fixp->fx_r_type = BFD_RELOC_D10V_10_PCREL_L; + left = 1; + } + else if (op_type & 4096) + { + op_type -= 4096; + fixp->fx_r_type = BFD_RELOC_D10V_18; + } + else + fixp->fx_r_type = get_reloc((struct d10v_operand *)&d10v_operands[op_type]); + } + + /* Fetch the instruction, insert the fully resolved operand + value, and stuff the instruction back again. */ + where = fixp->fx_frag->fr_literal + fixp->fx_where; + insn = bfd_getb32 ((unsigned char *) where); + + switch (fixp->fx_r_type) + { + case BFD_RELOC_D10V_10_PCREL_L: + case BFD_RELOC_D10V_10_PCREL_R: + case BFD_RELOC_D10V_18_PCREL: + case BFD_RELOC_D10V_18: + /* instruction addresses are always right-shifted by 2 */ + value >>= 2; + if (fixp->fx_size == 2) + bfd_putb16 ((bfd_vma) value, (unsigned char *) where); + else + { + insn = d10v_insert_operand (insn, op_type, (offsetT)value, left, fixp); + bfd_putb32 ((bfd_vma) insn, (unsigned char *) where); + } + break; + case BFD_RELOC_32: + bfd_putb32 ((bfd_vma) value, (unsigned char *) where); + break; + case BFD_RELOC_16: + bfd_putb16 ((bfd_vma) value, (unsigned char *) where); + break; + default: + as_fatal ("line %d: unknown relocation type: 0x%x",fixp->fx_line,fixp->fx_r_type); + } + return 0; +} + +/* d10v_cleanup() is called after the assembler has finished parsing the input + file or after a label is defined. Because the D10V assembler sometimes saves short + instructions to see if it can package them with the next instruction, there may + be a short instruction that still needs written. */ +int +d10v_cleanup () +{ + segT seg; + subsegT subseg; + + if (prev_opcode) + { + seg = now_seg; + subseg = now_subseg; + subseg_set (prev_seg, prev_subseg); + write_1_short (prev_opcode, prev_insn, fixups->next); + subseg_set (seg, subseg); + prev_opcode = NULL; + } + return 1; +} + +/* Like normal .word, except support @word */ +/* clobbers input_line_pointer, checks end-of-line. */ +static void +d10v_dot_word (nbytes) + register int nbytes; /* 1=.byte, 2=.word, 4=.long */ +{ + expressionS exp; + bfd_reloc_code_real_type reloc; + char *p; + int offset; + + if (is_it_end_of_statement ()) + { + demand_empty_rest_of_line (); + return; + } + + do + { + expression (&exp); + if (!strncasecmp (input_line_pointer, "@word", 5)) + { + exp.X_add_number = 0; + input_line_pointer += 5; + + p = frag_more (2); + fix_new_exp (frag_now, p - frag_now->fr_literal, 2, + &exp, 0, BFD_RELOC_D10V_18); + } + else + emit_expr (&exp, 2); + } + while (*input_line_pointer++ == ','); + + input_line_pointer--; /* Put terminator back into stream. */ + demand_empty_rest_of_line (); +} + + +/* Mitsubishi asked that we support some old syntax that apparently */ +/* had immediate operands starting with '#'. This is in some of their */ +/* sample code but is not documented (although it appears in some */ +/* examples in their assembler manual). For now, we'll solve this */ +/* compatibility problem by simply ignoring any '#' at the beginning */ +/* of an operand. */ + +/* operands that begin with '#' should fall through to here */ +/* from expr.c */ + +void +md_operand (expressionP) + expressionS *expressionP; +{ + if (*input_line_pointer == '#') + { + input_line_pointer++; + expression (expressionP); + } +} + diff --git a/gnu/usr.bin/binutils/gas/config/tc-d10v.h b/gnu/usr.bin/binutils/gas/config/tc-d10v.h new file mode 100644 index 00000000000..21aef2a0b46 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/tc-d10v.h @@ -0,0 +1,56 @@ +/* tc-d10v.h -- Header file for tc-d10v.c. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Written by Martin Hunt, Cygnus Support. + + This file is part of GAS, the GNU Assembler. + + GAS 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 2, or (at your option) + any later version. + + GAS 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 GAS; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#define TC_D10V + +#define TARGET_BYTES_BIG_ENDIAN 0 + +#ifndef BFD_ASSEMBLER + #error D10V support requires BFD_ASSEMBLER +#endif + +/* The target BFD architecture. */ +#define TARGET_ARCH bfd_arch_d10v + +#define TARGET_FORMAT "elf32-d10v" + +#define MD_APPLY_FIX3 + +/* call md_pcrel_from_section, not md_pcrel_from */ +#define MD_PCREL_FROM_SECTION(FIXP, SEC) md_pcrel_from_section(FIXP, SEC) + +/* Permit temporary numeric labels. */ +#define LOCAL_LABELS_FB 1 + +#define DIFF_EXPR_OK /* .-foo gets turned into PC relative relocs */ + +/* We don't need to handle .word strangely. */ +#define WORKING_DOT_WORD + +#define md_number_to_chars number_to_chars_bigendian + +int d10v_cleanup PARAMS ((void)); +#define md_after_pass_hook() d10v_cleanup() +#define md_cleanup() d10v_cleanup() +#define md_do_align(a,b,c,d,e) d10v_cleanup() +#define TC_START_LABEL(ch, ptr) (ch == ':' && d10v_cleanup()) + + diff --git a/gnu/usr.bin/binutils/gas/config/tc-m32r.c b/gnu/usr.bin/binutils/gas/config/tc-m32r.c new file mode 100644 index 00000000000..185c8aad0e6 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/tc-m32r.c @@ -0,0 +1,1011 @@ +/* tc-m32r.c -- Assembler for the Mitsubishi M32R. + Copyright (C) 1996, 1997 Free Software Foundation. + + This file is part of GAS, the GNU Assembler. + + GAS 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 2, or (at your option) + any later version. + + GAS 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 GAS; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <stdio.h> +#include <ctype.h> +#include "as.h" +#include "subsegs.h" +#include "cgen-opc.h" + +/* Non-null if last insn was a 16 bit insn on a 32 bit boundary + (i.e. was the first of two 16 bit insns). */ +static const struct cgen_insn *prev_insn = NULL; + +/* Non-zero if we've seen a relaxable insn since the last 32 bit + alignment request. */ +static int seen_relaxable_p = 0; + +/* Non-zero if -relax specified, in which case sufficient relocs are output + for the linker to do relaxing. + We do simple forms of relaxing internally, but they are always done. + This flag does not apply to them. */ +static int m32r_relax; + +/* If non-NULL, pointer to cpu description file to read. + This allows runtime additions to the assembler. */ +static char *m32r_cpu_desc; + +/* stuff for .scomm symbols. */ +static segT sbss_section; +static asection scom_section; +static asymbol scom_symbol; + +const char comment_chars[] = ";"; +const char line_comment_chars[] = "#"; +const char line_separator_chars[] = ""; +const char EXP_CHARS[] = "eE"; +const char FLT_CHARS[] = "dD"; + +/* Relocations against symbols are done in two + parts, with a HI relocation and a LO relocation. Each relocation + has only 16 bits of space to store an addend. This means that in + order for the linker to handle carries correctly, it must be able + to locate both the HI and the LO relocation. This means that the + relocations must appear in order in the relocation table. + + In order to implement this, we keep track of each unmatched HI + relocation. We then sort them so that they immediately precede the + corresponding LO relocation. */ + +struct m32r_hi_fixup +{ + /* Next HI fixup. */ + struct m32r_hi_fixup *next; + /* This fixup. */ + fixS *fixp; + /* The section this fixup is in. */ + segT seg; +}; + +/* The list of unmatched HI relocs. */ + +static struct m32r_hi_fixup *m32r_hi_fixup_list; + +static void m32r_record_hi16 PARAMS ((int, fixS *, segT seg)); + +const char *md_shortopts = ""; + +struct option md_longopts[] = { +#if 0 /* not supported yet */ +#define OPTION_RELAX (OPTION_MD_BASE) + {"relax", no_argument, NULL, OPTION_RELAX}, +#define OPTION_CPU_DESC (OPTION_MD_BASE + 1) + {"cpu-desc", required_argument, NULL, OPTION_CPU_DESC}, +#endif + {NULL, no_argument, NULL, 0} +}; +size_t md_longopts_size = sizeof(md_longopts); + +int +md_parse_option (c, arg) + int c; + char *arg; +{ + switch (c) + { +#if 0 /* not supported yet */ + case OPTION_RELAX: + m32r_relax = 1; + break; + case OPTION_CPU_DESC: + m32r_cpu_desc = arg; + break; +#endif + default: + return 0; + } + return 1; +} + +void +md_show_usage (stream) + FILE *stream; +{ + fprintf (stream, "M32R options:\n"); +#if 0 + fprintf (stream, "\ +--relax create linker relaxable code\n"); + fprintf (stream, "\ +--cpu-desc provide runtime cpu description file\n"); +#else + fprintf (stream, "[none]\n"); +#endif +} + +static void fill_insn PARAMS ((int)); +static void m32r_scomm PARAMS ((int)); + +/* Set by md_assemble for use by m32r_fill_insn. */ +static subsegT prev_subseg; +static segT prev_seg; + +/* The target specific pseudo-ops which we support. */ +const pseudo_typeS md_pseudo_table[] = +{ + { "word", cons, 4 }, + { "fillinsn", fill_insn, 0 }, + { "scomm", m32r_scomm, 0 }, + { NULL, NULL, 0 } +}; + +/* FIXME: Should be machine generated. */ +#define NOP_INSN 0x7000 +#define PAR_NOP_INSN 0xf000 /* can only be used in 2nd slot */ + +/* When we align the .text section, insert the correct NOP pattern. + N is the power of 2 alignment. LEN is the length of pattern FILL. + MAX is the maximum number of characters to skip when doing the alignment, + or 0 if there is no maximum. */ + +int +m32r_do_align (n, fill, len, max) + int n; + const char *fill; + int len; + int max; +{ + if ((fill == NULL || (*fill == 0 && len == 1)) + && (now_seg->flags & SEC_CODE) != 0 + /* Only do this special handling if aligning to at least a + 4 byte boundary. */ + && n > 1 + /* Only do this special handling if we're allowed to emit at + least two bytes. */ + && (max == 0 || max > 1)) + { + static const unsigned char nop_pattern[] = { 0xf0, 0x00 }; + +#if 0 + /* First align to a 2 byte boundary, in case there is an odd .byte. */ + /* FIXME: How much memory will cause gas to use when assembling a big + program? Perhaps we can avoid the frag_align call? */ + frag_align (1, 0, 0); +#endif + /* Next align to a 4 byte boundary (we know n >= 2) using a parallel + nop. */ + frag_align_pattern (2, nop_pattern, sizeof nop_pattern, 0); + /* If doing larger alignments use a repeating sequence of appropriate + nops. */ + if (n > 2) + { + static const unsigned char multi_nop_pattern[] = { 0x70, 0x00, 0xf0, 0x00 }; + frag_align_pattern (n, multi_nop_pattern, sizeof multi_nop_pattern, + max ? max - 2 : 0); + } + return 1; + } + + return 0; +} + +static void +assemble_nop (opcode) + int opcode; +{ + char *f = frag_more (2); + md_number_to_chars (f, opcode, 2); +} + +/* If the last instruction was the first of 2 16 bit insns, + output a nop to move the PC to a 32 bit boundary. + + This is done via an alignment specification since branch relaxing + may make it unnecessary. + + Internally, we need to output one of these each time a 32 bit insn is + seen after an insn that is relaxable. */ + +static void +fill_insn (ignore) + int ignore; +{ + (void) m32r_do_align (2, NULL, 0, 0); + prev_insn = NULL; + seen_relaxable_p = 0; +} + +/* Cover function to fill_insn called after a label and at end of assembly. + + The result is always 1: we're called in a conditional to see if the + current line is a label. */ + +int +m32r_fill_insn (done) + int done; +{ + segT seg; + subsegT subseg; + + if (prev_seg != NULL) + { + seg = now_seg; + subseg = now_subseg; + subseg_set (prev_seg, prev_subseg); + fill_insn (0); + subseg_set (seg, subseg); + } + return 1; +} + +void +md_begin () +{ + flagword applicable; + segT seg; + subsegT subseg; + + /* Initialize the `cgen' interface. */ + + /* This is a callback from cgen to gas to parse operands. */ + cgen_parse_operand_fn = cgen_parse_operand; + /* Set the machine number and endian. */ + CGEN_SYM (init_asm) (0 /* mach number */, + target_big_endian ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE); + +#if 0 /* not supported yet */ + /* If a runtime cpu description file was provided, parse it. */ + if (m32r_cpu_desc != NULL) + { + const char *errmsg; + + errmsg = cgen_read_cpu_file (m32r_cpu_desc); + if (errmsg != NULL) + as_bad ("%s: %s", m32r_cpu_desc, errmsg); + } +#endif + + /* Save the current subseg so we can restore it [it's the default one and + we don't want the initial section to be .sbss. */ + seg = now_seg; + subseg = now_subseg; + + /* The sbss section is for local .scomm symbols. */ + sbss_section = subseg_new (".sbss", 0); + /* This is copied from perform_an_assembly_pass. */ + applicable = bfd_applicable_section_flags (stdoutput); + bfd_set_section_flags (stdoutput, sbss_section, applicable & SEC_ALLOC); +#if 0 /* What does this do? [see perform_an_assembly_pass] */ + seg_info (bss_section)->bss = 1; +#endif + + subseg_set (seg, subseg); + + /* We must construct a fake section similar to bfd_com_section + but with the name .scommon. */ + scom_section = bfd_com_section; + scom_section.name = ".scommon"; + scom_section.output_section = &scom_section; + scom_section.symbol = &scom_symbol; + scom_section.symbol_ptr_ptr = &scom_section.symbol; + scom_symbol = *bfd_com_section.symbol; + scom_symbol.name = ".scommon"; + scom_symbol.section = &scom_section; +} + +void +md_assemble (str) + char *str; +{ +#ifdef CGEN_INT_INSN + cgen_insn_t buffer[CGEN_MAX_INSN_SIZE / sizeof (cgen_insn_t)]; +#else + char buffer[CGEN_MAX_INSN_SIZE]; +#endif + struct cgen_fields fields; + const struct cgen_insn *insn; + char *errmsg; + + /* Initialize GAS's cgen interface for a new instruction. */ + cgen_asm_init_parse (); + + insn = CGEN_SYM (assemble_insn) (str, &fields, buffer, &errmsg); + if (!insn) + { + as_bad (errmsg); + return; + } + + if (CGEN_INSN_BITSIZE (insn) == 32) + { + /* 32 bit insns must live on 32 bit boundaries. */ + /* FIXME: If calling fill_insn too many times turns us into a memory + pig, can we call assemble_nop instead of !seen_relaxable_p? */ + if (prev_insn || seen_relaxable_p) + fill_insn (0); + cgen_asm_finish_insn (insn, buffer, CGEN_FIELDS_BITSIZE (&fields)); + } + else + { + /* Keep track of whether we've seen a pair of 16 bit insns. + PREV_INSN is NULL when we're on a 32 bit boundary. */ + if (prev_insn) + prev_insn = NULL; + else + prev_insn = insn; + cgen_asm_finish_insn (insn, buffer, CGEN_FIELDS_BITSIZE (&fields)); + + /* If the insn needs the following one to be on a 32 bit boundary + (e.g. subroutine calls), fill this insn's slot. */ + if (prev_insn + && CGEN_INSN_ATTR (insn, CGEN_INSN_FILL_SLOT) != 0) + fill_insn (0); + } + + /* If this is a relaxable insn (can be replaced with a larger version) + mark the fact so that we can emit an alignment directive for a following + 32 bit insn if we see one. */ + if (CGEN_INSN_ATTR (insn, CGEN_INSN_RELAXABLE) != 0) + seen_relaxable_p = 1; + + /* Set these so m32r_fill_insn can use them. */ + prev_seg = now_seg; + prev_subseg = now_subseg; +} + +/* The syntax in the manual says constants begin with '#'. + We just ignore it. */ + +void +md_operand (expressionP) + expressionS *expressionP; +{ + if (*input_line_pointer == '#') + { + input_line_pointer++; + expression (expressionP); + } +} + +valueT +md_section_align (segment, size) + segT segment; + valueT size; +{ + int align = bfd_get_section_alignment (stdoutput, segment); + return ((size + (1 << align) - 1) & (-1 << align)); +} + +symbolS * +md_undefined_symbol (name) + char *name; +{ + return 0; +} + +/* .scomm pseudo-op handler. + + This is a new pseudo-op to handle putting objects in .scommon. + By doing this the linker won't need to do any work and more importantly + it removes the implicit -G arg necessary to correctly link the object file. +*/ + +static void +m32r_scomm (ignore) + int ignore; +{ + register char *name; + register char c; + register char *p; + offsetT size; + register symbolS *symbolP; + offsetT align; + int align2; + + name = input_line_pointer; + c = get_symbol_end (); + + /* just after name is now '\0' */ + p = input_line_pointer; + *p = c; + SKIP_WHITESPACE (); + if (*input_line_pointer != ',') + { + as_bad ("Expected comma after symbol-name: rest of line ignored."); + ignore_rest_of_line (); + return; + } + + input_line_pointer++; /* skip ',' */ + if ((size = get_absolute_expression ()) < 0) + { + as_warn (".SCOMMon length (%ld.) <0! Ignored.", (long) size); + ignore_rest_of_line (); + return; + } + + /* The third argument to .scomm is the alignment. */ + if (*input_line_pointer != ',') + align = 8; + else + { + ++input_line_pointer; + align = get_absolute_expression (); + if (align <= 0) + { + as_warn ("ignoring bad alignment"); + align = 8; + } + } + /* Convert to a power of 2 alignment. */ + if (align) + { + for (align2 = 0; (align & 1) == 0; align >>= 1, ++align2) + continue; + if (align != 1) + { + as_bad ("Common alignment not a power of 2"); + ignore_rest_of_line (); + return; + } + } + else + align2 = 0; + + *p = 0; + symbolP = symbol_find_or_make (name); + *p = c; + + if (S_IS_DEFINED (symbolP)) + { + as_bad ("Ignoring attempt to re-define symbol `%s'.", + S_GET_NAME (symbolP)); + ignore_rest_of_line (); + return; + } + + if (S_GET_VALUE (symbolP) && S_GET_VALUE (symbolP) != (valueT) size) + { + as_bad ("Length of .scomm \"%s\" is already %ld. Not changed to %ld.", + S_GET_NAME (symbolP), + (long) S_GET_VALUE (symbolP), + (long) size); + + ignore_rest_of_line (); + return; + } + + if (symbolP->local) + { + segT old_sec = now_seg; + int old_subsec = now_subseg; + char *pfrag; + + record_alignment (sbss_section, align2); + subseg_set (sbss_section, 0); + if (align2) + frag_align (align2, 0, 0); + if (S_GET_SEGMENT (symbolP) == sbss_section) + symbolP->sy_frag->fr_symbol = 0; + symbolP->sy_frag = frag_now; + pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, size, + (char *) 0); + *pfrag = 0; + S_SET_SIZE (symbolP, size); + S_SET_SEGMENT (symbolP, sbss_section); + S_CLEAR_EXTERNAL (symbolP); + subseg_set (old_sec, old_subsec); + } + else + { + S_SET_VALUE (symbolP, (valueT) size); + S_SET_ALIGN (symbolP, align2); + S_SET_EXTERNAL (symbolP); + S_SET_SEGMENT (symbolP, &scom_section); + } + + demand_empty_rest_of_line (); +} + +/* Interface to relax_segment. */ + +/* FIXME: Build table by hand, get it working, then machine generate. */ + +const relax_typeS md_relax_table[] = +{ +/* The fields are: + 1) most positive reach of this state, + 2) most negative reach of this state, + 3) how many bytes this mode will add to the size of the current frag + 4) which index into the table to try if we can't fit into this one. */ + + /* The first entry must be unused because an `rlx_more' value of zero ends + each list. */ + {1, 1, 0, 0}, + + /* The displacement used by GAS is from the end of the 2 byte insn, + so we subtract 2 from the following. */ + /* 16 bit insn, 8 bit disp -> 10 bit range. + This doesn't handle a branch in the right slot at the border: + the "& -4" isn't taken into account. It's not important enough to + complicate things over it, so we subtract an extra 2 (or + 2 in -ve + case). */ + {511 - 2 - 2, -512 - 2 + 2, 0, 2 }, + /* 32 bit insn, 24 bit disp -> 26 bit range. */ + {0x2000000 - 1 - 2, -0x2000000 - 2, 2, 0 }, + /* Same thing, but with leading nop for alignment. */ + {0x2000000 - 1 - 2, -0x2000000 - 2, 4, 0 } +}; + +long +m32r_relax_frag (fragP, stretch) + fragS *fragP; + long stretch; +{ + /* Address of branch insn. */ + long address = fragP->fr_address + fragP->fr_fix - 2; + long growth = 0; + + /* Keep 32 bit insns aligned on 32 bit boundaries. */ + if (fragP->fr_subtype == 2) + { + if ((address & 3) != 0) + { + fragP->fr_subtype = 3; + growth = 2; + } + } + else if (fragP->fr_subtype == 3) + { + if ((address & 3) == 0) + { + fragP->fr_subtype = 2; + growth = -2; + } + } + else + { + growth = relax_frag (fragP, stretch); + + /* Long jump on odd halfword boundary? */ + if (fragP->fr_subtype == 2 && (address & 3) != 0) + { + fragP->fr_subtype = 3; + growth += 2; + } + } + + return growth; +} + +/* Return an initial guess of the length by which a fragment must grow to + hold a branch to reach its destination. + Also updates fr_type/fr_subtype as necessary. + + Called just before doing relaxation. + Any symbol that is now undefined will not become defined. + The guess for fr_var is ACTUALLY the growth beyond fr_fix. + Whatever we do to grow fr_fix or fr_var contributes to our returned value. + Although it may not be explicit in the frag, pretend fr_var starts with a + 0 value. */ + +int +md_estimate_size_before_relax (fragP, segment) + fragS *fragP; + segT segment; +{ + int old_fr_fix = fragP->fr_fix; + char *opcode = fragP->fr_opcode; + + /* The only thing we have to handle here are symbols outside of the + current segment. They may be undefined or in a different segment in + which case linker scripts may place them anywhere. + However, we can't finish the fragment here and emit the reloc as insn + alignment requirements may move the insn about. */ + + if (S_GET_SEGMENT (fragP->fr_symbol) != segment) + { + /* The symbol is undefined in this segment. + Change the relaxation subtype to the max allowable and leave + all further handling to md_convert_frag. */ + fragP->fr_subtype = 2; + +#if 0 /* Can't use this, but leave in for illustration. */ + /* Change 16 bit insn to 32 bit insn. */ + opcode[0] |= 0x80; + + /* Increase known (fixed) size of fragment. */ + fragP->fr_fix += 2; + + /* Create a relocation for it. */ + fix_new (fragP, old_fr_fix, 4, + fragP->fr_symbol, + fragP->fr_offset, 1 /* pcrel */, + /* FIXME: Can't use a real BFD reloc here. + cgen_md_apply_fix3 can't handle it. */ + BFD_RELOC_M32R_26_PCREL); + + /* Mark this fragment as finished. */ + frag_wane (fragP); +#else + return 2; +#endif + } + + return (fragP->fr_var + fragP->fr_fix - old_fr_fix); +} + +/* *fragP has been relaxed to its final size, and now needs to have + the bytes inside it modified to conform to the new size. + + Called after relaxation is finished. + fragP->fr_type == rs_machine_dependent. + fragP->fr_subtype is the subtype of what the address relaxed to. */ + +void +md_convert_frag (abfd, sec, fragP) + bfd *abfd; + segT sec; + fragS *fragP; +{ + char *opcode, *displacement; + int target_address, opcode_address, extension, addend; + + opcode = fragP->fr_opcode; + + /* Address opcode resides at in file space. */ + opcode_address = fragP->fr_address + fragP->fr_fix - 2; + + switch (fragP->fr_subtype) + { + case 1 : + extension = 0; + displacement = &opcode[1]; + break; + case 2 : + opcode[0] |= 0x80; + extension = 2; + displacement = &opcode[1]; + break; + case 3 : + opcode[2] = opcode[0] | 0x80; + md_number_to_chars (opcode, PAR_NOP_INSN, 2); + opcode_address += 2; + extension = 4; + displacement = &opcode[3]; + break; + default : + abort (); + } + + if (S_GET_SEGMENT (fragP->fr_symbol) != sec) + { + /* symbol must be resolved by linker */ + if (fragP->fr_offset & 3) + as_warn ("Addend to unresolved symbol not on word boundary."); + addend = fragP->fr_offset >> 2; + } + else + { + /* Address we want to reach in file space. */ + target_address = S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset; + target_address += fragP->fr_symbol->sy_frag->fr_address; + addend = (target_address - (opcode_address & -4)) >> 2; + } + + /* Create a relocation for symbols that must be resolved by the linker. + Otherwise output the completed insn. */ + + if (S_GET_SEGMENT (fragP->fr_symbol) != sec) + { + assert (fragP->fr_subtype != 1); + assert (fragP->fr_targ.cgen.insn != 0); + cgen_record_fixup (fragP, + /* Offset of branch insn in frag. */ + fragP->fr_fix + extension - 4, + fragP->fr_targ.cgen.insn, + 4 /*length*/, + /* FIXME: quick hack */ +#if 0 + CGEN_OPERAND_ENTRY (fragP->fr_targ.cgen.opindex), +#else + CGEN_OPERAND_ENTRY (M32R_OPERAND_DISP24), +#endif + fragP->fr_targ.cgen.opinfo, + fragP->fr_symbol, fragP->fr_offset); + } + +#define SIZE_FROM_RELAX_STATE(n) ((n) == 1 ? 1 : 3) + + md_number_to_chars (displacement, (valueT) addend, + SIZE_FROM_RELAX_STATE (fragP->fr_subtype)); + + fragP->fr_fix += extension; +} + +/* Functions concerning relocs. */ + +/* The location from which a PC relative jump should be calculated, + given a PC relative reloc. */ + +long +md_pcrel_from_section (fixP, sec) + fixS *fixP; + segT sec; +{ + if (fixP->fx_addsy != (symbolS *) NULL + && (! S_IS_DEFINED (fixP->fx_addsy) + || S_GET_SEGMENT (fixP->fx_addsy) != sec)) + { + /* The symbol is undefined (or is defined but not in this section). + Let the linker figure it out. */ + return 0; + } + + return (fixP->fx_frag->fr_address + fixP->fx_where) & -4L; +} + +/* Return the bfd reloc type for OPERAND of INSN at fixup FIXP. + Returns BFD_RELOC_NONE if no reloc type can be found. + *FIXP may be modified if desired. */ + +bfd_reloc_code_real_type +CGEN_SYM (lookup_reloc) (insn, operand, fixP) + const struct cgen_insn *insn; + const struct cgen_operand *operand; + fixS *fixP; +{ + switch (CGEN_OPERAND_TYPE (operand)) + { + case M32R_OPERAND_DISP8 : return BFD_RELOC_M32R_10_PCREL; + case M32R_OPERAND_DISP16 : return BFD_RELOC_M32R_18_PCREL; + case M32R_OPERAND_DISP24 : return BFD_RELOC_M32R_26_PCREL; + case M32R_OPERAND_UIMM24 : return BFD_RELOC_M32R_24; + case M32R_OPERAND_HI16 : + case M32R_OPERAND_SLO16 : + case M32R_OPERAND_ULO16 : + /* If low/high/shigh/sda was used, it is recorded in `opinfo'. */ + if (fixP->tc_fix_data.opinfo != 0) + return fixP->tc_fix_data.opinfo; + break; + } + return BFD_RELOC_NONE; +} + +/* Called while parsing an instruction to create a fixup. + We need to check for HI16 relocs and queue them up for later sorting. */ + +fixS * +m32r_cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp) + fragS *frag; + int where; + const struct cgen_insn *insn; + int length; + const struct cgen_operand *operand; + int opinfo; + expressionS *exp; +{ + fixS *fixP = cgen_record_fixup_exp (frag, where, insn, length, + operand, opinfo, exp); + + switch (CGEN_OPERAND_TYPE (operand)) + { + case M32R_OPERAND_HI16 : + /* If low/high/shigh/sda was used, it is recorded in `opinfo'. */ + if (fixP->tc_fix_data.opinfo == BFD_RELOC_M32R_HI16_SLO + || fixP->tc_fix_data.opinfo == BFD_RELOC_M32R_HI16_ULO) + m32r_record_hi16 (fixP->tc_fix_data.opinfo, fixP, now_seg); + break; + } + + return fixP; +} + +/* Record a HI16 reloc for later matching with its LO16 cousin. */ + +static void +m32r_record_hi16 (reloc_type, fixP, seg) + int reloc_type; + fixS *fixP; + segT seg; +{ + struct m32r_hi_fixup *hi_fixup; + + assert (reloc_type == BFD_RELOC_M32R_HI16_SLO + || reloc_type == BFD_RELOC_M32R_HI16_ULO); + + hi_fixup = ((struct m32r_hi_fixup *) + xmalloc (sizeof (struct m32r_hi_fixup))); + hi_fixup->fixp = fixP; + hi_fixup->seg = now_seg; + hi_fixup->next = m32r_hi_fixup_list; + m32r_hi_fixup_list = hi_fixup; +} + +/* Return BFD reloc type from opinfo field in a fixS. + It's tricky using fx_r_type in m32r_frob_file because the values + are BFD_RELOC_UNUSED + operand number. */ +#define FX_OPINFO_R_TYPE(f) ((f)->tc_fix_data.opinfo) + +/* Sort any unmatched HI16 relocs so that they immediately precede + the corresponding LO16 reloc. This is called before md_apply_fix and + tc_gen_reloc. */ + +void +m32r_frob_file () +{ + struct m32r_hi_fixup *l; + + for (l = m32r_hi_fixup_list; l != NULL; l = l->next) + { + segment_info_type *seginfo; + int pass; + + assert (FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_M32R_HI16_SLO + || FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_M32R_HI16_ULO); + + /* Check quickly whether the next fixup happens to be a matching low. */ + if (l->fixp->fx_next != NULL + && FX_OPINFO_R_TYPE (l->fixp->fx_next) == BFD_RELOC_M32R_LO16 + && l->fixp->fx_addsy == l->fixp->fx_next->fx_addsy + && l->fixp->fx_offset == l->fixp->fx_next->fx_offset) + continue; + + /* Look through the fixups for this segment for a matching `low'. + When we find one, move the high/shigh just in front of it. We do + this in two passes. In the first pass, we try to find a + unique `low'. In the second pass, we permit multiple high's + relocs for a single `low'. */ + seginfo = seg_info (l->seg); + for (pass = 0; pass < 2; pass++) + { + fixS *f, *prev; + + prev = NULL; + for (f = seginfo->fix_root; f != NULL; f = f->fx_next) + { + /* Check whether this is a `low' fixup which matches l->fixp. */ + if (FX_OPINFO_R_TYPE (f) == BFD_RELOC_M32R_LO16 + && f->fx_addsy == l->fixp->fx_addsy + && f->fx_offset == l->fixp->fx_offset + && (pass == 1 + || prev == NULL + || (FX_OPINFO_R_TYPE (prev) != BFD_RELOC_M32R_HI16_SLO + && FX_OPINFO_R_TYPE (prev) != BFD_RELOC_M32R_HI16_ULO) + || prev->fx_addsy != f->fx_addsy + || prev->fx_offset != f->fx_offset)) + { + fixS **pf; + + /* Move l->fixp before f. */ + for (pf = &seginfo->fix_root; + *pf != l->fixp; + pf = &(*pf)->fx_next) + assert (*pf != NULL); + + *pf = l->fixp->fx_next; + + l->fixp->fx_next = f; + if (prev == NULL) + seginfo->fix_root = l->fixp; + else + prev->fx_next = l->fixp; + + break; + } + + prev = f; + } + + if (f != NULL) + break; + + if (pass == 1) + as_warn_where (l->fixp->fx_file, l->fixp->fx_line, + "Unmatched high/shigh reloc"); + } + } +} + +/* See whether we need to force a relocation into the output file. + This is used to force out switch and PC relative relocations when + relaxing. */ + +int +m32r_force_relocation (fix) + fixS *fix; +{ + if (! m32r_relax) + return 0; + + return (fix->fx_pcrel + || 0 /* ??? */); +} + +/* Write a value out to the object file, using the appropriate endianness. */ + +void +md_number_to_chars (buf, val, n) + char *buf; + valueT val; + int n; +{ + if (target_big_endian) + number_to_chars_bigendian (buf, val, n); + else + number_to_chars_littleendian (buf, val, n); +} + +/* Turn a string in input_line_pointer into a floating point constant of type + type, and store the appropriate bytes in *litP. The number of LITTLENUMS + emitted is stored in *sizeP . An error message is returned, or NULL on OK. +*/ + +/* Equal to MAX_PRECISION in atof-ieee.c */ +#define MAX_LITTLENUMS 6 + +char * +md_atof (type, litP, sizeP) + char type; + char *litP; + int *sizeP; +{ + int i,prec; + LITTLENUM_TYPE words[MAX_LITTLENUMS]; + LITTLENUM_TYPE *wordP; + char *t; + char *atof_ieee (); + + switch (type) + { + case 'f': + case 'F': + case 's': + case 'S': + prec = 2; + break; + + case 'd': + case 'D': + case 'r': + case 'R': + prec = 4; + break; + + /* FIXME: Some targets allow other format chars for bigger sizes here. */ + + default: + *sizeP = 0; + return "Bad call to md_atof()"; + } + + t = atof_ieee (input_line_pointer, type, words); + if (t) + input_line_pointer = t; + *sizeP = prec * sizeof (LITTLENUM_TYPE); + + if (target_big_endian) + { + for (i = 0; i < prec; i++) + { + md_number_to_chars (litP, (valueT) words[i], sizeof (LITTLENUM_TYPE)); + litP += sizeof (LITTLENUM_TYPE); + } + } + else + { + for (i = prec - 1; i >= 0; i--) + { + md_number_to_chars (litP, (valueT) words[i], sizeof (LITTLENUM_TYPE)); + litP += sizeof (LITTLENUM_TYPE); + } + } + + return 0; +} diff --git a/gnu/usr.bin/binutils/gas/config/tc-m32r.h b/gnu/usr.bin/binutils/gas/config/tc-m32r.h new file mode 100644 index 00000000000..dab2a182b5c --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/tc-m32r.h @@ -0,0 +1,112 @@ +/* tc-m32r.h -- Header file for tc-m32r.c. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + + This file is part of GAS, the GNU Assembler. + + GAS 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 2, or (at your option) + any later version. + + GAS 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 GAS; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#define TC_M32R + +#ifndef BFD_ASSEMBLER +/* leading space so will compile with cc */ + #error M32R support requires BFD_ASSEMBLER +#endif + +#define LISTING_HEADER "M32R GAS " + +/* The target BFD architecture. */ +#define TARGET_ARCH bfd_arch_m32r + +#define TARGET_FORMAT "elf32-m32r" + +#define TARGET_BYTES_BIG_ENDIAN 1 + +/* call md_pcrel_from_section, not md_pcrel_from */ +#define MD_PCREL_FROM_SECTION(FIXP, SEC) md_pcrel_from_section(FIXP, SEC) + +/* Permit temporary numeric labels. */ +#define LOCAL_LABELS_FB 1 + +#define DIFF_EXPR_OK /* .-foo gets turned into PC relative relocs */ + +/* We don't need to handle .word strangely. */ +#define WORKING_DOT_WORD + +/* For 8 vs 16 vs 32 bit branch selection. */ +extern const struct relax_type md_relax_table[]; +#define TC_GENERIC_RELAX_TABLE md_relax_table +#if 0 +extern void m32r_prepare_relax_scan (); +#define md_prepare_relax_scan(fragP, address, aim, this_state, this_type) \ +m32r_prepare_relax_scan (fragP, address, aim, this_state, this_type) +#else +#define md_relax_frag(fragP, stretch) \ +m32r_relax_frag (fragP, stretch) +#endif +/* Account for nop if 32 bit insn falls on odd halfword boundary. */ +#define TC_CGEN_MAX_RELAX(insn, len) (6) + +/* Alignments are used to ensure 32 bit insns live on 32 bit boundaries, so + we use a special alignment function to insert the correct nop pattern. */ +extern int m32r_do_align PARAMS ((int, const char *, int, int)); +#define md_do_align(n, fill, len, max, l) \ +if (m32r_do_align (n, fill, len, max)) goto l + +/* FIXME: Obviously the cgen_xxx decls here should be in a header. Later. */ + +#define MD_APPLY_FIX3 +extern int cgen_md_apply_fix3 (); +#define md_apply_fix3 cgen_md_apply_fix3 + +#define md_init_frag(fragP) \ +do { \ + (fragP)->fr_targ.cgen.insn = 0; \ + (fragP)->fr_targ.cgen.opindex = 0; \ + (fragP)->fr_targ.cgen.opinfo = 0; \ +} while (0); + +/* After creating a fixup for an instruction operand, we need to check for + HI16 relocs and queue them up for later sorting. */ +#define md_cgen_record_fixup_exp m32r_cgen_record_fixup_exp +extern struct fix *m32r_cgen_record_fixup_exp (); +extern struct fix *cgen_record_fixup_exp (); + +#define TC_HANDLES_FX_DONE + +/* Record a pointer to the insn table entry for each fixup. */ +#define TC_FIX_TYPE struct { PTR insn; int opinfo; } +#define TC_INIT_FIX_DATA(FIXP) \ + ((FIXP)->tc_fix_data.insn = NULL, (FIXP)->tc_fix_data.opinfo = 0) + +extern arelent *cgen_tc_gen_reloc (); +#define tc_gen_reloc cgen_tc_gen_reloc + +#define tc_frob_file() m32r_frob_file () +extern void m32r_frob_file PARAMS ((void)); + +/* When relaxing, we need to emit various relocs we otherwise wouldn't. */ +#define TC_FORCE_RELOCATION(fix) m32r_force_relocation (fix) +extern int m32r_force_relocation (); + +/* Ensure insns at labels are aligned to 32 bit boundaries. */ +int m32r_fill_insn PARAMS ((int)); +#define md_after_pass_hook() m32r_fill_insn (1) +#define TC_START_LABEL(ch, ptr) (ch == ':' && m32r_fill_insn (0)) + +/* Add extra M32R sections. */ +#define ELF_TC_SPECIAL_SECTIONS \ + { ".sdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, \ + { ".sbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE }, diff --git a/gnu/usr.bin/binutils/gas/config/te-dynix.h b/gnu/usr.bin/binutils/gas/config/te-dynix.h new file mode 100644 index 00000000000..9e7b30f9784 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/te-dynix.h @@ -0,0 +1,7 @@ +/* This is for i386-sequent-bsd. The assembler probably does not + actually work, as the support in BFD is not complete as of this + writing. See bfd/i386-dynix.c. */ + +#define TE_DYNIX 1 + +#include "obj-format.h" diff --git a/gnu/usr.bin/binutils/gas/config/te-lnews.h b/gnu/usr.bin/binutils/gas/config/te-lnews.h new file mode 100644 index 00000000000..acbcc5a6416 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/te-lnews.h @@ -0,0 +1,5 @@ +/* te-lnews.h -- little-endian NEWS emulation. */ + +#define ECOFF_LITTLE_FORMAT "ecoff-biglittlemips" + +#include "obj-format.h" diff --git a/gnu/usr.bin/binutils/gas/config/te-svr4.h b/gnu/usr.bin/binutils/gas/config/te-svr4.h new file mode 100644 index 00000000000..7217ee119e6 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/te-svr4.h @@ -0,0 +1,4 @@ +#define TE_SVR4 +#define LOCAL_LABELS_FB 1 + +#include "obj-format.h" diff --git a/gnu/usr.bin/binutils/gas/dep-in.sed b/gnu/usr.bin/binutils/gas/dep-in.sed new file mode 100644 index 00000000000..e4ac32b9932 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/dep-in.sed @@ -0,0 +1,44 @@ +:loop +/\\$/N +/\\$/b loop + +s! ../config.h!!g +s! ../../bfd/bfd.h!!g +s! ../itbl-parse.h!!g +s!@INCDIR@!$(INCDIR)!g +s!@BFDDIR@!$(BFDDIR)!g +s!@SRCDIR@/config!$(srcdir)/config!g +s!@SRCDIR@/../opcodes!$(srcdir)/../opcodes!g +s!@SRCDIR@/!!g +s! config.h!!g +s! as.h!!g +s! targ-env.h!!g +s! obj-format.h!!g +s! targ-cpu.h!!g +s! flonum.h!!g +s! expr.h!!g +s! struc-symbol.h!!g +s! write.h!!g +s! frags.h!!g +s! hash.h!!g +s! read.h!!g +s! symbols.h!!g +s! tc.h!!g +s! obj.h!!g +s! listing.h!!g +s! bignum.h!!g +s! bit_fix.h!!g +s! itbl-cpu.h!!g +s! \$(srcdir)/config/te-generic.h!!g +s! \$(INCDIR)/libiberty.h!!g +s! \$(INCDIR)/ansidecl.h!!g +s! \$(INCDIR)/fopen-same.h!!g + +s/\\\n */ /g + +s/ *$// +s/ */ /g +/:$/d + +s/\(.\{50\}[^ ]*\) /\1 \\\ + /g diff --git a/gnu/usr.bin/binutils/gas/doc/as.info-7 b/gnu/usr.bin/binutils/gas/doc/as.info-7 new file mode 100644 index 00000000000..016c19f6d5d --- /dev/null +++ b/gnu/usr.bin/binutils/gas/doc/as.info-7 @@ -0,0 +1,843 @@ +This is Info file as.info, produced by Makeinfo-1.64 from the input +file ./as.texinfo. + +START-INFO-DIR-ENTRY +* As: (as). The GNU assembler. +END-INFO-DIR-ENTRY + + This file documents the GNU Assembler "as". + + Copyright (C) 1991, 92, 93, 94, 95, 96, 1997 Free Software +Foundation, Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + + Permission is granted to copy and distribute modified versions of +this manual under the conditions for verbatim copying, provided that +the entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + + Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions. + + +File: as.info, Node: Index, Prev: Acknowledgements, Up: Top + +Index +***** + +* Menu: + +* #: Comments. +* #APP: Preprocessing. +* #NO_APP: Preprocessing. +* -: Command Line. +* -enforce-aligned-data: Sparc-Aligned-Data. +* -statistics: statistics. +* -a: a. +* -ac: a. +* -ad: a. +* -ah: a. +* -al: a. +* -an: a. +* -as: a. +* -Asparclet: Sparc-Opts. +* -Asparclite: Sparc-Opts. +* -Av6: Sparc-Opts. +* -Av8: Sparc-Opts. +* -Av9: Sparc-Opts. +* -Av9a: Sparc-Opts. +* -D: D. +* -f: f. +* -I PATH: I. +* -K: K. +* -L: L. +* -M: M. +* -o: o. +* -R: R. +* -v: v. +* -version: v. +* -W: W. +* .o: Object. +* 16-bit code, i386: i386-16bit. +* 29K support: AMD29K-Dependent. +* @word modifier, D10V: D10V-Word. +* $ in symbol names <1>: H8/500-Chars. +* $ in symbol names <2>: D10V-Chars. +* $ in symbol names: SH-Chars. +* -+ option, VAX/VMS: VAX-Opts. +* -A options, i960: Options-i960. +* -b option, i960: Options-i960. +* -D, ignored on VAX: VAX-Opts. +* -d, VAX option: VAX-Opts. +* -EB option (MIPS): MIPS Opts. +* -EL option (MIPS): MIPS Opts. +* -G option (MIPS): MIPS Opts. +* -h option, VAX/VMS: VAX-Opts. +* -J, ignored on VAX: VAX-Opts. +* -no-relax option, i960: Options-i960. +* -nocpp ignored (MIPS): MIPS Opts. +* -S, ignored on VAX: VAX-Opts. +* -t, ignored on VAX: VAX-Opts. +* -V, redundant on VAX: VAX-Opts. +* .insn: MIPS insn. +* .param on HPPA: HPPA Directives. +* .set mipsN: MIPS ISA. +* .set pop: MIPS option stack. +* .set push: MIPS option stack. +* . (symbol): Dot. +* : (label): Statements. +* \" (doublequote character): Strings. +* \DDD (octal character code): Strings. +* \XD... (hex character code): Strings. +* \\ (\ character): Strings. +* \b (backspace character): Strings. +* \f (formfeed character): Strings. +* \n (newline character): Strings. +* \r (carriage return character): Strings. +* \t (tab): Strings. +* a.out symbol attributes: a.out Symbols. +* ABORT directive: ABORT. +* abort directive: Abort. +* align directive: Align. +* align directive, SPARC: Sparc-Directives. +* app-file directive: App-File. +* ascii directive: Ascii. +* asciz directive: Asciz. +* balignl directive: Balign. +* balignw directive: Balign. +* balign directive: Balign. +* block directive, AMD 29K: AMD29K Directives. +* bss directive, i960: Directives-i960. +* byte directive: Byte. +* callj, i960 pseudo-opcode: callj-i960. +* code16 directive, i386: i386-16bit. +* code32 directive, i386: i386-16bit. +* common directive, SPARC: Sparc-Directives. +* comm directive: Comm. +* cputype directive, AMD 29K: AMD29K Directives. +* data1 directive, M680x0: M68K-Directives. +* data2 directive, M680x0: M68K-Directives. +* data directive: Data. +* def directive: Def. +* desc directive: Desc. +* dfloat directive, VAX: VAX-directives. +* dim directive: Dim. +* double directive: Double. +* double directive, i386: i386-Float. +* double directive, M680x0: M68K-Float. +* double directive, VAX: VAX-float. +* eject directive: Eject. +* else directive: Else. +* endef directive: Endef. +* endif directive: Endif. +* endm directive: Macro. +* equiv directive: Equiv. +* equ directive: Equ. +* err directive: Err. +* even directive, M680x0: M68K-Directives. +* exitm directive: Macro. +* extended directive, i960: Directives-i960. +* extend directive M680x0: M68K-Float. +* extern directive: Extern. +* ffloat directive, VAX: VAX-directives. +* file directive: File. +* file directive, AMD 29K: AMD29K Directives. +* fill directive: Fill. +* float directive: Float. +* float directive, i386: i386-Float. +* float directive, M680x0: M68K-Float. +* float directive, VAX: VAX-float. +* fwait instruction, i386: i386-Float. +* gbr960, i960 postprocessor: Options-i960. +* gfloat directive, VAX: VAX-directives. +* global directive: Global. +* gp register, MIPS: MIPS Object. +* half directive, SPARC: Sparc-Directives. +* hfloat directive, VAX: VAX-directives. +* hword directive: hword. +* ident directive: Ident. +* ifdef directive: If. +* ifndef directive: If. +* ifnotdef directive: If. +* if directive: If. +* imul instruction, i386: i386-Notes. +* include directive: Include. +* include directive search path: I. +* int directive: Int. +* int directive, H8/300: H8/300 Directives. +* int directive, H8/500: H8/500 Directives. +* int directive, i386: i386-Float. +* int directive, SH: SH Directives. +* irpc directive: Irpc. +* irp directive: Irp. +* lcomm directive: Lcomm. +* ldouble directive M680x0: M68K-Float. +* leafproc directive, i960: Directives-i960. +* lflags directive (ignored): Lflags. +* line directive: Line. +* line directive, AMD 29K: AMD29K Directives. +* linkonce directive: Linkonce. +* list directive: List. +* ln directive: Ln. +* long directive: Long. +* long directive, i386: i386-Float. +* macro directive: Macro. +* mri directive: MRI. +* mul instruction, i386: i386-Notes. +* nolist directive: Nolist. +* octa directive: Octa. +* org directive: Org. +* p2alignl directive: P2align. +* p2alignw directive: P2align. +* p2align directive: P2align. +* proc directive, SPARC: Sparc-Directives. +* psize directive: Psize. +* quad directive: Quad. +* quad directive, i386: i386-Float. +* rept directive: Rept. +* reserve directive, SPARC: Sparc-Directives. +* sbttl directive: Sbttl. +* scl directive: Scl. +* section directive: Section. +* sect directive, AMD 29K: AMD29K Directives. +* seg directive, SPARC: Sparc-Directives. +* set directive: Set. +* short directive: Short. +* single directive: Single. +* single directive, i386: i386-Float. +* size directive: Size. +* skip directive: Skip. +* skip directive, M680x0: M68K-Directives. +* skip directive, SPARC: Sparc-Directives. +* space directive: Space. +* stabX directives: Stab. +* stabd directive: Stab. +* stabn directive: Stab. +* stabs directive: Stab. +* string directive: String. +* string directive on HPPA: HPPA Directives. +* symver directive: Symver. +* sysproc directive, i960: Directives-i960. +* tag directive: Tag. +* text directive: Text. +* tfloat directive, i386: i386-Float. +* title directive: Title. +* type directive: Type. +* use directive, AMD 29K: AMD29K Directives. +* val directive: Val. +* word directive: Word. +* word directive, H8/300: H8/300 Directives. +* word directive, H8/500: H8/500 Directives. +* word directive, i386: i386-Float. +* word directive, SH: SH Directives. +* word directive, SPARC: Sparc-Directives. +* xword directive, SPARC: Sparc-Directives. +* -base-size-default-16: M68K-Opts. +* -base-size-default-32: M68K-Opts. +* -bitwise-or option, M680x0: M68K-Opts. +* -disp-size-default-16: M68K-Opts. +* -disp-size-default-32: M68K-Opts. +* -register-prefix-optional option, M680x0: M68K-Opts. +* -l option, M680x0: M68K-Opts. +* -m68000 and related options: M68K-Opts. +* MIT: M68K-Syntax. +* a.out: Object. +* absolute section: Ld Sections. +* addition, permitted arguments: Infix Ops. +* addresses: Expressions. +* addresses, format of: Secs Background. +* addressing modes, D10V: D10V-Addressing. +* addressing modes, H8/300: H8/300-Addressing. +* addressing modes, H8/500: H8/500-Addressing. +* addressing modes, M680x0: M68K-Syntax. +* addressing modes, SH: SH-Addressing. +* addressing modes, Z8000: Z8000-Addressing. +* advancing location counter: Org. +* altered difference tables: Word. +* alternate syntax for the 680x0: M68K-Moto-Syntax. +* AMD 29K floating point (IEEE): AMD29K Floating Point. +* AMD 29K identifiers: AMD29K-Chars. +* AMD 29K line comment character: AMD29K-Chars. +* AMD 29K machine directives: AMD29K Directives. +* AMD 29K macros: AMD29K-Macros. +* AMD 29K opcodes: AMD29K Opcodes. +* AMD 29K options (none): AMD29K Options. +* AMD 29K protected registers: AMD29K-Regs. +* AMD 29K register names: AMD29K-Regs. +* AMD 29K special purpose registers: AMD29K-Regs. +* AMD 29K support: AMD29K-Dependent. +* architecture options, i960: Options-i960. +* architecture options, M680x0: M68K-Opts. +* architectures, SPARC: Sparc-Opts. +* arguments for addition: Infix Ops. +* arguments for subtraction: Infix Ops. +* arguments in expressions: Arguments. +* arithmetic functions: Operators. +* arithmetic operands: Arguments. +* assembler bugs, reporting: Bug Reporting. +* assembler crash: Bug Criteria. +* assembler internal logic error: As Sections. +* assembler version: v. +* assembler, and linker: Secs Background. +* assembly listings, enabling: a. +* assigning values to symbols <1>: Setting Symbols. +* assigning values to symbols: Equ. +* attributes, symbol: Symbol Attributes. +* auxiliary attributes, COFF symbols: COFF Symbols. +* auxiliary symbol information, COFF: Dim. +* Av7: Sparc-Opts. +* backslash (\\): Strings. +* backspace (\b): Strings. +* big endian output, MIPS: Overview. +* big-endian output, MIPS: MIPS Opts. +* bignums: Bignums. +* binary integers: Integers. +* bitfields, not supported on VAX: VAX-no. +* block: Z8000 Directives. +* branch improvement, M680x0: M68K-Branch. +* branch improvement, VAX: VAX-branch. +* branch recording, i960: Options-i960. +* branch statistics table, i960: Options-i960. +* bss section <1>: bss. +* bss section: Ld Sections. +* bug criteria: Bug Criteria. +* bug reports: Bug Reporting. +* bugs in assembler: Reporting Bugs. +* bus lock prefixes, i386: i386-prefixes. +* bval: Z8000 Directives. +* call instructions, i386: i386-Opcodes. +* carriage return (\r): Strings. +* character constants: Characters. +* character escape codes: Strings. +* character, single: Chars. +* characters used in symbols: Symbol Intro. +* COFF auxiliary symbol information: Dim. +* COFF structure debugging: Tag. +* COFF symbol attributes: COFF Symbols. +* COFF symbol descriptor: Desc. +* COFF symbol storage class: Scl. +* COFF symbol type: Type. +* COFF symbols, debugging: Def. +* COFF value attribute: Val. +* COMDAT: Linkonce. +* command line conventions: Command Line. +* command-line options ignored, VAX: VAX-Opts. +* comments: Comments. +* comments, M680x0: M68K-Chars. +* comments, removed by preprocessor: Preprocessing. +* common sections: Linkonce. +* common variable storage: bss. +* compare and jump expansions, i960: Compare-and-branch-i960. +* compare/branch instructions, i960: Compare-and-branch-i960. +* conditional assembly: If. +* constant, single character: Chars. +* constants: Constants. +* constants, bignum: Bignums. +* constants, character: Characters. +* constants, converted by preprocessor: Preprocessing. +* constants, floating point: Flonums. +* constants, integer: Integers. +* constants, number: Numbers. +* constants, string: Strings. +* continuing statements: Statements. +* conversion instructions, i386: i386-Opcodes. +* coprocessor wait, i386: i386-prefixes. +* crash of assembler: Bug Criteria. +* current address: Dot. +* current address, advancing: Org. +* D10V @word modifier: D10V-Word. +* D10V addressing modes: D10V-Addressing. +* D10V floating point: D10V-Float. +* D10V line comment character: D10V-Chars. +* D10V opcode summary: D10V-Opcodes. +* D10V optimization: Overview. +* D10V options: D10V-Opts. +* D10V registers: D10V-Regs. +* D10V size modifiers: D10V-Size. +* D10V sub-instruction ordering: D10V-Chars. +* D10V sub-instructions: D10V-Subs. +* D10V support: D10V-Dependent. +* D10V syntax: D10V-Syntax. +* data alignment on SPARC: Sparc-Aligned-Data. +* data and text sections, joining: R. +* data section: Ld Sections. +* debuggers, and symbol order: Symbols. +* debugging COFF symbols: Def. +* decimal integers: Integers. +* deprecated directives: Deprecated. +* descriptor, of a.out symbol: Symbol Desc. +* difference tables altered: Word. +* difference tables, warning: K. +* directives and instructions: Statements. +* directives, M680x0: M68K-Directives. +* directives, machine independent: Pseudo Ops. +* directives, Z8000: Z8000 Directives. +* displacement sizing character, VAX: VAX-operands. +* dot (symbol): Dot. +* doublequote (\"): Strings. +* ECOFF sections: MIPS Object. +* eight-byte integer: Quad. +* empty expressions: Empty Exprs. +* emulation: Overview. +* endianness, MIPS: Overview. +* EOF, newline must precede: Statements. +* error messsages: Errors. +* error on valid input: Bug Criteria. +* errors, continuing after: Z. +* escape codes, character: Strings. +* even: Z8000 Directives. +* expr (internal section): As Sections. +* expression arguments: Arguments. +* expressions: Expressions. +* expressions, empty: Empty Exprs. +* expressions, integer: Integer Exprs. +* faster processing (-f): f. +* fatal signal: Bug Criteria. +* file name, logical <1>: App-File. +* file name, logical: File. +* files, including: Include. +* files, input: Input Files. +* filling memory <1>: Skip. +* filling memory: Space. +* floating point numbers: Flonums. +* floating point numbers (double): Double. +* floating point numbers (single) <1>: Single. +* floating point numbers (single): Float. +* floating point, AMD 29K (IEEE): AMD29K Floating Point. +* floating point, D10V: D10V-Float. +* floating point, H8/300 (IEEE): H8/300 Floating Point. +* floating point, H8/500 (IEEE): H8/500 Floating Point. +* floating point, HPPA (IEEE): HPPA Floating Point. +* floating point, i386: i386-Float. +* floating point, i960 (IEEE): Floating Point-i960. +* floating point, M680x0: M68K-Float. +* floating point, SH (IEEE): SH Floating Point. +* floating point, SPARC (IEEE): Sparc-Float. +* floating point, VAX: VAX-float. +* flonums: Flonums. +* format of error messages: Errors. +* format of warning messages: Errors. +* formfeed (\f): Strings. +* functions, in expressions: Operators. +* global: Z8000 Directives. +* grouping data: Sub-Sections. +* H8/300 addressing modes: H8/300-Addressing. +* H8/300 floating point (IEEE): H8/300 Floating Point. +* H8/300 line comment character: H8/300-Chars. +* H8/300 line separator: H8/300-Chars. +* H8/300 machine directives (none): H8/300 Directives. +* H8/300 opcode summary: H8/300 Opcodes. +* H8/300 options (none): H8/300 Options. +* H8/300 registers: H8/300-Regs. +* H8/300 size suffixes: H8/300 Opcodes. +* H8/300 support: H8/300-Dependent. +* H8/300H, assembling for: H8/300 Directives. +* H8/500 addressing modes: H8/500-Addressing. +* H8/500 floating point (IEEE): H8/500 Floating Point. +* H8/500 line comment character: H8/500-Chars. +* H8/500 line separator: H8/500-Chars. +* H8/500 machine directives (none): H8/500 Directives. +* H8/500 opcode summary: H8/500 Opcodes. +* H8/500 options (none): H8/500 Options. +* H8/500 registers: H8/500-Regs. +* H8/500 support: H8/500-Dependent. +* hex character code (\XD...): Strings. +* hexadecimal integers: Integers. +* HPPA directives not supported: HPPA Directives. +* HPPA floating point (IEEE): HPPA Floating Point. +* HPPA Syntax: HPPA Options. +* HPPA-only directives: HPPA Directives. +* i386 16-bit code: i386-16bit. +* i386 fwait instruction: i386-Float. +* i386 mul, imul instructions: i386-Notes. +* i386 conversion instructions: i386-Opcodes. +* i386 floating point: i386-Float. +* i386 immediate operands: i386-Syntax. +* i386 jump optimization: i386-jumps. +* i386 jump, call, return: i386-Syntax. +* i386 jump/call operands: i386-Syntax. +* i386 memory references: i386-Memory. +* i386 opcode naming: i386-Opcodes. +* i386 opcode prefixes: i386-prefixes. +* i386 options (none): i386-Options. +* i386 register operands: i386-Syntax. +* i386 registers: i386-Regs. +* i386 sections: i386-Syntax. +* i386 size suffixes: i386-Syntax. +* i386 source, destination operands: i386-Syntax. +* i386 support: i386-Dependent. +* i386 syntax compatibility: i386-Syntax. +* i80306 support: i386-Dependent. +* i960 callj pseudo-opcode: callj-i960. +* i960 architecture options: Options-i960. +* i960 branch recording: Options-i960. +* i960 compare and jump expansions: Compare-and-branch-i960. +* i960 compare/branch instructions: Compare-and-branch-i960. +* i960 floating point (IEEE): Floating Point-i960. +* i960 machine directives: Directives-i960. +* i960 opcodes: Opcodes for i960. +* i960 options: Options-i960. +* i960 support: i960-Dependent. +* identifiers, AMD 29K: AMD29K-Chars. +* immediate character, M680x0: M68K-Chars. +* immediate character, VAX: VAX-operands. +* immediate operands, i386: i386-Syntax. +* indirect character, VAX: VAX-operands. +* infix operators: Infix Ops. +* inhibiting interrupts, i386: i386-prefixes. +* input: Input Files. +* input file linenumbers: Input Files. +* instruction set, M680x0: M68K-opcodes. +* instruction summary, D10V: D10V-Opcodes. +* instruction summary, H8/300: H8/300 Opcodes. +* instruction summary, H8/500: H8/500 Opcodes. +* instruction summary, SH: SH Opcodes. +* instruction summary, Z8000: Z8000 Opcodes. +* instructions and directives: Statements. +* integer expressions: Integer Exprs. +* integer, 16-byte: Octa. +* integer, 8-byte: Quad. +* integers: Integers. +* integers, 16-bit: hword. +* integers, 32-bit: Int. +* integers, binary: Integers. +* integers, decimal: Integers. +* integers, hexadecimal: Integers. +* integers, octal: Integers. +* integers, one byte: Byte. +* internal assembler sections: As Sections. +* invalid input: Bug Criteria. +* invocation summary: Overview. +* joining text and data sections: R. +* jump instructions, i386: i386-Opcodes. +* jump optimization, i386: i386-jumps. +* jump/call operands, i386: i386-Syntax. +* label (:): Statements. +* labels: Labels. +* ld: Object. +* length of symbols: Symbol Intro. +* line comment character: Comments. +* line comment character, AMD 29K: AMD29K-Chars. +* line comment character, D10V: D10V-Chars. +* line comment character, H8/300: H8/300-Chars. +* line comment character, H8/500: H8/500-Chars. +* line comment character, M680x0: M68K-Chars. +* line comment character, SH: SH-Chars. +* line comment character, Z8000: Z8000-Chars. +* line numbers, in input files: Input Files. +* line numbers, in warnings/errors: Errors. +* line separator character: Statements. +* line separator, H8/300: H8/300-Chars. +* line separator, H8/500: H8/500-Chars. +* line separator, SH: SH-Chars. +* line separator, Z8000: Z8000-Chars. +* lines starting with #: Comments. +* linker: Object. +* linker, and assembler: Secs Background. +* listing control, turning off: Nolist. +* listing control, turning on: List. +* listing control: new page: Eject. +* listing control: paper size: Psize. +* listing control: subtitle: Sbttl. +* listing control: title line: Title. +* listings, enabling: a. +* little endian output, MIPS: Overview. +* little-endian output, MIPS: MIPS Opts. +* local common symbols: Lcomm. +* local labels, retaining in output: L. +* local symbol names: Symbol Names. +* location counter: Dot. +* location counter, advancing: Org. +* logical file name <1>: File. +* logical file name: App-File. +* logical line number: Line. +* logical line numbers: Comments. +* lval: Z8000 Directives. +* M680x0 addressing modes: M68K-Syntax. +* M680x0 architecture options: M68K-Opts. +* M680x0 branch improvement: M68K-Branch. +* M680x0 directives: M68K-Directives. +* M680x0 floating point: M68K-Float. +* M680x0 immediate character: M68K-Chars. +* M680x0 line comment character: M68K-Chars. +* M680x0 opcodes: M68K-opcodes. +* M680x0 options: M68K-Opts. +* M680x0 pseudo-opcodes: M68K-Branch. +* M680x0 size modifiers: M68K-Syntax. +* M680x0 support: M68K-Dependent. +* M680x0 syntax: M68K-Syntax. +* machine dependencies: Machine Dependencies. +* machine directives, AMD 29K: AMD29K Directives. +* machine directives, H8/300 (none): H8/300 Directives. +* machine directives, H8/500 (none): H8/500 Directives. +* machine directives, i960: Directives-i960. +* machine directives, SH (none): SH Directives. +* machine directives, SPARC: Sparc-Directives. +* machine directives, VAX: VAX-directives. +* machine independent directives: Pseudo Ops. +* machine instructions (not covered): Manual. +* machine-independent syntax: Syntax. +* macros: Macro. +* Macros, AMD 29K: AMD29K-Macros. +* macros, count executed: Macro. +* manual, structure and purpose: Manual. +* memory references, i386: i386-Memory. +* merging text and data sections: R. +* messages from assembler: Errors. +* minus, permitted arguments: Infix Ops. +* MIPS architecture options: MIPS Opts. +* MIPS big-endian output: MIPS Opts. +* MIPS debugging directives: MIPS Stabs. +* MIPS ECOFF sections: MIPS Object. +* MIPS endianness: Overview. +* MIPS ISA: Overview. +* MIPS ISA override: MIPS ISA. +* MIPS little-endian output: MIPS Opts. +* MIPS option stack: MIPS option stack. +* MIPS processor: MIPS-Dependent. +* mnemonics for opcodes, VAX: VAX-opcodes. +* mnemonics, D10V: D10V-Opcodes. +* mnemonics, H8/300: H8/300 Opcodes. +* mnemonics, H8/500: H8/500 Opcodes. +* mnemonics, SH: SH Opcodes. +* mnemonics, Z8000: Z8000 Opcodes. +* Motorola syntax for the 680x0: M68K-Moto-Syntax. +* MRI compatibility mode: M. +* MRI mode, temporarily: MRI. +* multi-line statements: Statements. +* name: Z8000 Directives. +* named section: Section. +* named sections: Ld Sections. +* names, symbol: Symbol Names. +* naming object file: o. +* new page, in listings: Eject. +* newline (\n): Strings. +* newline, required at file end: Statements. +* null-terminated strings: Asciz. +* number constants: Numbers. +* number of macros executed: Macro. +* numbered subsections: Sub-Sections. +* numbers, 16-bit: hword. +* numeric values: Expressions. +* object file: Object. +* object file format: Object Formats. +* object file name: o. +* object file, after errors: Z. +* obsolescent directives: Deprecated. +* octal character code (\DDD): Strings. +* octal integers: Integers. +* opcode mnemonics, VAX: VAX-opcodes. +* opcode naming, i386: i386-Opcodes. +* opcode prefixes, i386: i386-prefixes. +* opcode suffixes, i386: i386-Syntax. +* opcode summary, D10V: D10V-Opcodes. +* opcode summary, H8/300: H8/300 Opcodes. +* opcode summary, H8/500: H8/500 Opcodes. +* opcode summary, SH: SH Opcodes. +* opcode summary, Z8000: Z8000 Opcodes. +* opcodes for AMD 29K: AMD29K Opcodes. +* opcodes, i960: Opcodes for i960. +* opcodes, M680x0: M68K-opcodes. +* operand delimiters, i386: i386-Syntax. +* operand notation, VAX: VAX-operands. +* operands in expressions: Arguments. +* operator precedence: Infix Ops. +* operators, in expressions: Operators. +* operators, permitted arguments: Infix Ops. +* optimization, D10V: Overview. +* option summary: Overview. +* options for AMD29K (none): AMD29K Options. +* options for i386 (none): i386-Options. +* options for SPARC: Sparc-Opts. +* options for VAX/VMS: VAX-Opts. +* options, all versions of assembler: Invoking. +* options, command line: Command Line. +* options, D10V: D10V-Opts. +* options, H8/300 (none): H8/300 Options. +* options, H8/500 (none): H8/500 Options. +* options, i960: Options-i960. +* options, M680x0: M68K-Opts. +* options, SH (none): SH Options. +* options, Z8000: Z8000 Options. +* other attribute, of a.out symbol: Symbol Other. +* output file: Object. +* padding the location counter: Align. +* padding the location counter given a power of two: P2align. +* padding the location counter given number of bytes: Balign. +* page, in listings: Eject. +* paper size, for listings: Psize. +* paths for .include: I. +* patterns, writing in memory: Fill. +* plus, permitted arguments: Infix Ops. +* precedence of operators: Infix Ops. +* precision, floating point: Flonums. +* prefix operators: Prefix Ops. +* prefixes, i386: i386-prefixes. +* preprocessing: Preprocessing. +* preprocessing, turning on and off: Preprocessing. +* primary attributes, COFF symbols: COFF Symbols. +* protected registers, AMD 29K: AMD29K-Regs. +* pseudo-opcodes, M680x0: M68K-Branch. +* pseudo-ops for branch, VAX: VAX-branch. +* pseudo-ops, machine independent: Pseudo Ops. +* purpose of GNU assembler: GNU Assembler. +* real-mode code, i386: i386-16bit. +* register names, AMD 29K: AMD29K-Regs. +* register names, H8/300: H8/300-Regs. +* register names, VAX: VAX-operands. +* register operands, i386: i386-Syntax. +* registers, D10V: D10V-Regs. +* registers, H8/500: H8/500-Regs. +* registers, i386: i386-Regs. +* registers, SH: SH-Regs. +* registers, Z8000: Z8000-Regs. +* relocation: Sections. +* relocation example: Ld Sections. +* repeat prefixes, i386: i386-prefixes. +* reporting bugs in assembler: Reporting Bugs. +* return instructions, i386: i386-Syntax. +* rsect: Z8000 Directives. +* search path for .include: I. +* section override prefixes, i386: i386-prefixes. +* section-relative addressing: Secs Background. +* sections: Sections. +* sections in messages, internal: As Sections. +* sections, i386: i386-Syntax. +* sections, named: Ld Sections. +* segm: Z8000 Directives. +* SH addressing modes: SH-Addressing. +* SH floating point (IEEE): SH Floating Point. +* SH line comment character: SH-Chars. +* SH line separator: SH-Chars. +* SH machine directives (none): SH Directives. +* SH opcode summary: SH Opcodes. +* SH options (none): SH Options. +* SH registers: SH-Regs. +* SH support: SH-Dependent. +* single character constant: Chars. +* sixteen bit integers: hword. +* sixteen byte integer: Octa. +* size modifiers, D10V: D10V-Size. +* size modifiers, M680x0: M68K-Syntax. +* size prefixes, i386: i386-prefixes. +* size suffixes, H8/300: H8/300 Opcodes. +* sizes operands, i386: i386-Syntax. +* small objects, MIPS ECOFF: MIPS Object. +* SOM symbol attributes: SOM Symbols. +* source program: Input Files. +* source, destination operands; i386: i386-Syntax. +* space used, maximum for assembly: statistics. +* SPARC architectures: Sparc-Opts. +* SPARC data alignment: Sparc-Aligned-Data. +* SPARC floating point (IEEE): Sparc-Float. +* SPARC machine directives: Sparc-Directives. +* SPARC options: Sparc-Opts. +* SPARC support: Sparc-Dependent. +* special characters, M680x0: M68K-Chars. +* special purpose registers, AMD 29K: AMD29K-Regs. +* standard assembler sections: Secs Background. +* standard input, as input file: Command Line. +* statement on multiple lines: Statements. +* statement separator character: Statements. +* statement separator, H8/300: H8/300-Chars. +* statement separator, H8/500: H8/500-Chars. +* statement separator, SH: SH-Chars. +* statement separator, Z8000: Z8000-Chars. +* statements, structure of: Statements. +* statistics, about assembly: statistics. +* stopping the assembly: Abort. +* string constants: Strings. +* string literals: Ascii. +* string, copying to object file: String. +* structure debugging, COFF: Tag. +* sub-instruction ordering, D10V: D10V-Chars. +* sub-instructions, D10V: D10V-Subs. +* subexpressions: Arguments. +* subtitles for listings: Sbttl. +* subtraction, permitted arguments: Infix Ops. +* summary of options: Overview. +* support: HPPA-Dependent. +* supporting files, including: Include. +* suppressing warnings: W. +* sval: Z8000 Directives. +* symbol attributes: Symbol Attributes. +* symbol attributes, a.out: a.out Symbols. +* symbol attributes, COFF: COFF Symbols. +* symbol attributes, SOM: SOM Symbols. +* symbol descriptor, COFF: Desc. +* symbol names: Symbol Names. +* symbol names, $ in <1>: SH-Chars. +* symbol names, $ in <2>: D10V-Chars. +* symbol names, $ in: H8/500-Chars. +* symbol names, local: Symbol Names. +* symbol names, temporary: Symbol Names. +* symbol storage class (COFF): Scl. +* symbol type: Symbol Type. +* symbol type, COFF: Type. +* symbol value: Symbol Value. +* symbol value, setting: Set. +* symbol values, assigning: Setting Symbols. +* symbol versioning: Symver. +* symbol, common: Comm. +* symbol, making visible to linker: Global. +* symbolic debuggers, information for: Stab. +* symbols: Symbols. +* symbols with lowercase, VAX/VMS: VAX-Opts. +* symbols, assigning values to: Equ. +* symbols, local common: Lcomm. +* syntax compatibility, i386: i386-Syntax. +* syntax, D10V: D10V-Syntax. +* syntax, M680x0: M68K-Syntax. +* syntax, machine-independent: Syntax. +* tab (\t): Strings. +* temporary symbol names: Symbol Names. +* text and data sections, joining: R. +* text section: Ld Sections. +* time, total for assembly: statistics. +* trusted compiler: f. +* turning preprocessing on and off: Preprocessing. +* type of a symbol: Symbol Type. +* undefined section: Ld Sections. +* unsegm: Z8000 Directives. +* value attribute, COFF: Val. +* value of a symbol: Symbol Value. +* VAX bitfields not supported: VAX-no. +* VAX branch improvement: VAX-branch. +* VAX command-line options ignored: VAX-Opts. +* VAX displacement sizing character: VAX-operands. +* VAX floating point: VAX-float. +* VAX immediate character: VAX-operands. +* VAX indirect character: VAX-operands. +* VAX machine directives: VAX-directives. +* VAX opcode mnemonics: VAX-opcodes. +* VAX operand notation: VAX-operands. +* VAX register names: VAX-operands. +* VAX support: Vax-Dependent. +* Vax-11 C compatibility: VAX-Opts. +* VAX/VMS options: VAX-Opts. +* version of assembler: v. +* versions of symbols: Symver. +* VMS (VAX) options: VAX-Opts. +* warning for altered difference tables: K. +* warning messages: Errors. +* warnings, suppressing: W. +* whitespace: Whitespace. +* whitespace, removed by preprocessor: Preprocessing. +* wide floating point directives, VAX: VAX-directives. +* writing patterns in memory: Fill. +* wval: Z8000 Directives. +* Z800 addressing modes: Z8000-Addressing. +* Z8000 directives: Z8000 Directives. +* Z8000 line comment character: Z8000-Chars. +* Z8000 line separator: Z8000-Chars. +* Z8000 opcode summary: Z8000 Opcodes. +* Z8000 options: Z8000 Options. +* Z8000 registers: Z8000-Regs. +* Z8000 support: Z8000-Dependent. +* zero-terminated strings: Asciz. + + diff --git a/gnu/usr.bin/binutils/gas/doc/c-d10v.texi b/gnu/usr.bin/binutils/gas/doc/c-d10v.texi new file mode 100644 index 00000000000..b2593473196 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/doc/c-d10v.texi @@ -0,0 +1,246 @@ +@c Copyright (C) 1996 Free Software Foundation, Inc. +@c This is part of the GAS manual. +@c For copying conditions, see the file as.texinfo. +@ifset GENERIC +@page +@node D10V-Dependent +@chapter D10V Dependent Features +@end ifset +@ifclear GENERIC +@node Machine Dependencies +@chapter D10V Dependent Features +@end ifclear + +@cindex D10V support +@menu +* D10V-Opts:: D10V Options +* D10V-Syntax:: Syntax +* D10V-Float:: Floating Point +* D10V-Opcodes:: Opcodes +@end menu + +@node D10V-Opts +@section D10V Options +@cindex options, D10V +@cindex D10V options +The Mitsubishi D10V version of @code{@value{AS}} has a few machine +dependent options. + +@table @samp +@item -O +The D10V can often execute two sub-instructions in parallel. When this option +is used, @code{@value{AS}} will attempt to optimize its output by detecting when +instructions can be executed in parallel. +@end table + +@node D10V-Syntax +@section Syntax +@cindex D10V syntax +@cindex syntax, D10V + +The D10V syntax is based on the syntax in Mitsubishi's D10V architecture manual. +The differences are detailed below. + +@menu +* D10V-Size:: Size Modifiers +* D10V-Subs:: Sub-Instructions +* D10V-Chars:: Special Characters +* D10V-Regs:: Register Names +* D10V-Addressing:: Addressing Modes +* D10V-Word:: @@WORD Modifier +@end menu + + +@node D10V-Size +@subsection Size Modifiers +@cindex D10V size modifiers +@cindex size modifiers, D10V +The D10V version of @code{@value{AS}} uses the instruction names in the D10V +Architecture Manual. However, the names in the manual are sometimes ambiguous. +There are instruction names that can assemble to a short or long form opcode. +How does the assembler pick the correct form? @code{@value{AS}} will always pick the +smallest form if it can. When dealing with a symbol that is not defined yet when a +line is being assembled, it will always use the long form. If you need to force the +assembler to use either the short or long form of the instruction, you can append +either @samp{.s} (short) or @samp{.l} (long) to it. For example, if you are writing +an assembly program and you want to do a branch to a symbol that is defined later +in your program, you can write @samp{bra.s foo}. +Objdump and GDB will always append @samp{.s} or @samp{.l} to instructions which +have both short and long forms. + +@node D10V-Subs +@subsection Sub-Instructions +@cindex D10V sub-instructions +@cindex sub-instructions, D10V +The D10V assembler takes as input a series of instructions, either one-per-line, +or in the special two-per-line format described in the next section. Some of these +instructions will be short-form or sub-instructions. These sub-instructions can be packed +into a single instruction. The assembler will do this automatically. It will also detect +when it should not pack instructions. For example, when a label is defined, the next +instruction will never be packaged with the previous one. Whenever a branch and link +instruction is called, it will not be packaged with the next instruction so the return +address will be valid. Nops are automatically inserted when necessary. + +If you do not want the assembler automatically making these decisions, you can control +the packaging and execution type (parallel or sequential) with the special execution +symbols described in the next section. + +@node D10V-Chars +@subsection Special Characters +@cindex line comment character, D10V +@cindex D10V line comment character +@samp{;} and @samp{#} are the line comment characters. +@cindex sub-instruction ordering, D10V +@cindex D10V sub-instruction ordering +Sub-instructions may be executed in order, in reverse-order, or in parallel. +Instructions listed in the standard one-per-line format will be executed sequentially. +To specify the executing order, use the following symbols: +@table @samp +@item -> +Sequential with instruction on the left first. +@item <- +Sequential with instruction on the right first. +@item || +Parallel +@end table +The D10V syntax allows either one instruction per line, one instruction per line with +the execution symbol, or two instructions per line. For example +@table @code +@item abs a1 -> abs r0 +Execute these sequentially. The instruction on the right is in the right +container and is executed second. +@item abs r0 <- abs a1 +Execute these reverse-sequentially. The instruction on the right is in the right +container, and is executed first. +@item ld2w r2,@@r8+ || mac a0,r0,r7 +Execute these in parallel. +@item ld2w r2,@@r8+ || +@itemx mac a0,r0,r7 +Two-line format. Execute these in parallel. +@item ld2w r2,@@r8+ +@itemx mac a0,r0,r7 +Two-line format. Execute these sequentially. Assembler will +put them in the proper containers. +@item ld2w r2,@@r8+ -> +@itemx mac a0,r0,r7 +Two-line format. Execute these sequentially. Same as above but +second instruction will always go into right container. +@end table +@cindex symbol names, @samp{$} in +@cindex @code{$} in symbol names +Since @samp{$} has no special meaning, you may use it in symbol names. + +@node D10V-Regs +@subsection Register Names +@cindex D10V registers +@cindex registers, D10V +You can use the predefined symbols @samp{r0} through @samp{r15} to refer to the D10V +registers. You can also use @samp{sp} as an alias for @samp{r15}. The accumulators +are @samp{a0} and @samp{a1}. There are special register-pair names that may +optionally be used in opcodes that require even-numbered registers. Register names are +not case sensitive. + +Register Pairs +@table @code +@item r0-r1 +@item r2-r3 +@item r4-r5 +@item r6-r7 +@item r8-r9 +@item r10-r11 +@item r12-r13 +@item r14-r15 +@end table + +The D10V also has predefined symbols for these control registers and status bits: +@table @code +@item psw +Processor Status Word +@item bpsw +Backup Processor Status Word +@item pc +Program Counter +@item bpc +Backup Program Counter +@item rpt_c +Repeat Count +@item rpt_s +Repeat Start address +@item rpt_e +Repeat End address +@item mod_s +Modulo Start address +@item mod_e +Modulo End address +@item iba +Instruction Break Address +@item f0 +Flag 0 +@item f1 +Flag 1 +@item c +Carry flag +@end table + +@node D10V-Addressing +@subsection Addressing Modes +@cindex addressing modes, D10V +@cindex D10V addressing modes +@code{@value{AS}} understands the following addressing modes for the D10V. +@code{R@var{n}} in the following refers to any of the numbered +registers, but @emph{not} the control registers. +@table @code +@item R@var{n} +Register direct +@item @@R@var{n} +Register indirect +@item @@R@var{n}+ +Register indirect with post-increment +@item @@R@var{n}- +Register indirect with post-decrement +@item @@-SP +Register indirect with pre-decrement +@item @@(@var{disp}, R@var{n}) +Register indirect with displacement +@item @var{addr} +PC relative address (for branch or rep). +@item #@var{imm} +Immediate data (the @samp{#} is optional and ignored) +@end table + +@node D10V-Word +@subsection @@WORD Modifier +@cindex D10V @@word modifier +@cindex @@word modifier, D10V +Any symbol followed by @code{@@word} will be replaced by the symbol's value +shifted right by 2. This is used in situations such as loading a register +with the address of a function (or any other code fragment). For example, if +you want to load a register with the location of the function @code{main} then +jump to that function, you could do it as follws: +@smallexample +@group +ldi r2, main@@word +jmp r2 +@end group +@end smallexample + +@node D10V-Float +@section Floating Point +@cindex floating point, D10V +@cindex D10V floating point +The D10V has no hardware floating point, but the @code{.float} and @code{.double} +directives generates @sc{ieee} floating-point numbers for compatibility +with other development tools. + +@node D10V-Opcodes +@section Opcodes +@cindex D10V opcode summary +@cindex opcode summary, D10V +@cindex mnemonics, D10V +@cindex instruction summary, D10V +For detailed information on the D10V machine instruction set, see +@cite{D10V Architecture: A VLIW Microprocessor for Multimedia Applications} +(Mitsubishi Electric Corp.). +@code{@value{AS}} implements all the standard D10V opcodes. The only changes are those +described in the section on size modifiers + diff --git a/gnu/usr.bin/binutils/gas/itbl-lex.c b/gnu/usr.bin/binutils/gas/itbl-lex.c new file mode 100644 index 00000000000..5d27c83f8eb --- /dev/null +++ b/gnu/usr.bin/binutils/gas/itbl-lex.c @@ -0,0 +1,1660 @@ +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header: /cvs/OpenBSD/src/gnu/usr.bin/binutils/gas/itbl-lex.c,v 1.1 1997/05/29 09:21:57 niklas Exp $ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include <stdio.h> + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include <stdlib.h> +#include <unistd.h> + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include <io.h> +#include <stdlib.h> +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 15 +#define YY_END_OF_BUFFER 16 +static yyconst short int yy_accept[60] = + { 0, + 0, 0, 16, 14, 13, 12, 11, 8, 8, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 8, 0, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 7, 9, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 5, 1, 2, 3, 10, 6, 10, 4, 0 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 4, 1, 1, 5, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 6, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 1, 8, 1, + 1, 1, 1, 1, 9, 10, 11, 12, 13, 10, + 14, 15, 16, 15, 15, 15, 17, 18, 15, 15, + 15, 19, 20, 15, 15, 15, 15, 15, 15, 15, + 1, 1, 1, 1, 15, 1, 21, 10, 22, 23, + + 24, 10, 25, 15, 26, 15, 15, 15, 27, 28, + 15, 29, 15, 30, 31, 15, 15, 15, 15, 32, + 15, 15, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[33] = + { 0, + 1, 1, 1, 1, 1, 2, 2, 1, 2, 2, + 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, + 3, 3 + } ; + +static yyconst short int yy_base[62] = + { 0, + 0, 0, 83, 84, 84, 84, 84, 27, 29, 70, + 0, 62, 61, 60, 20, 55, 47, 46, 45, 12, + 35, 37, 0, 0, 62, 60, 59, 58, 53, 49, + 45, 43, 42, 41, 37, 32, 0, 0, 43, 44, + 43, 42, 42, 36, 23, 27, 26, 25, 25, 20, + 0, 0, 0, 0, 35, 0, 23, 0, 84, 58, + 43 + } ; + +static yyconst short int yy_def[62] = + { 0, + 59, 1, 59, 59, 59, 59, 59, 59, 59, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 59, 61, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 61, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 0, 59, + 59 + } ; + +static yyconst short int yy_nxt[117] = + { 0, + 4, 5, 6, 5, 7, 8, 9, 7, 10, 11, + 12, 13, 11, 14, 11, 15, 11, 11, 11, 11, + 16, 17, 18, 11, 19, 20, 11, 11, 21, 11, + 11, 11, 22, 22, 22, 22, 29, 30, 35, 36, + 37, 37, 22, 22, 38, 58, 58, 56, 57, 54, + 53, 52, 51, 56, 55, 54, 53, 52, 23, 24, + 24, 51, 50, 49, 48, 47, 46, 45, 44, 43, + 42, 41, 40, 39, 34, 33, 32, 31, 28, 27, + 26, 25, 59, 3, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59 + } ; + +static yyconst short int yy_chk[117] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 8, 8, 9, 9, 15, 15, 20, 20, + 21, 21, 22, 22, 61, 57, 55, 50, 49, 48, + 47, 46, 45, 44, 43, 42, 41, 40, 8, 60, + 60, 39, 36, 35, 34, 33, 32, 31, 30, 29, + 28, 27, 26, 25, 19, 18, 17, 16, 14, 13, + 12, 10, 3, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +char *yytext; +#line 1 "./itbl-lex.l" +#define INITIAL 0 +/* itbl-lex.l + Copyright (C) 1997 Free Software Foundation, Inc. + + This file is part of GAS, the GNU Assembler. + + GAS 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 2, or (at your option) + any later version. + + GAS 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 GAS; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ +#line 22 "./itbl-lex.l" +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <ctype.h> +#include "itbl-parse.h" + +#ifdef DEBUG +#define DBG(x) printf x +#define MDBG(x) printf x +#else +#define DBG(x) +#define MDBG(x) +#endif + +int insntbl_line = 1; +#line 440 "lex.yy.c" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include <stdlib.h> +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 44 "./itbl-lex.l" + + +#line 590 "lex.yy.c" + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 60 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 84 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 46 "./itbl-lex.l" +{ + return CREG; + } + YY_BREAK +case 2: +YY_RULE_SETUP +#line 49 "./itbl-lex.l" +{ + return DREG; + } + YY_BREAK +case 3: +YY_RULE_SETUP +#line 52 "./itbl-lex.l" +{ + return GREG; + } + YY_BREAK +case 4: +YY_RULE_SETUP +#line 55 "./itbl-lex.l" +{ + return IMMED; + } + YY_BREAK +case 5: +YY_RULE_SETUP +#line 58 "./itbl-lex.l" +{ + return ADDR; + } + YY_BREAK +case 6: +YY_RULE_SETUP +#line 61 "./itbl-lex.l" +{ + return INSN; + } + YY_BREAK +case 7: +YY_RULE_SETUP +#line 64 "./itbl-lex.l" +{ + yytext[yyleng] = 0; + yylval.processor = strtoul (yytext+1, 0, 0); + return PNUM; + } + YY_BREAK +case 8: +YY_RULE_SETUP +#line 69 "./itbl-lex.l" +{ + yytext[yyleng] = 0; + yylval.num = strtoul (yytext, 0, 0); + return NUM; + } + YY_BREAK +case 9: +YY_RULE_SETUP +#line 74 "./itbl-lex.l" +{ + yytext[yyleng] = 0; + yylval.num = strtoul (yytext, 0, 0); + return NUM; + } + YY_BREAK +case 10: +YY_RULE_SETUP +#line 79 "./itbl-lex.l" +{ + yytext[yyleng] = 0; + yylval.str = strdup (yytext); + return ID; + } + YY_BREAK +case 11: +YY_RULE_SETUP +#line 84 "./itbl-lex.l" +{ + int c; + while ((c = input ()) != EOF) + { + if (c == '\n') + { + unput (c); + break; + } + } + } + YY_BREAK +case 12: +YY_RULE_SETUP +#line 95 "./itbl-lex.l" +{ + insntbl_line++; + MDBG (("in lex, NL = %d (x%x)\n", NL, NL)); + return NL; + } + YY_BREAK +case 13: +YY_RULE_SETUP +#line 100 "./itbl-lex.l" +{ + } + YY_BREAK +case 14: +YY_RULE_SETUP +#line 102 "./itbl-lex.l" +{ + MDBG (("char = %x, %d\n", yytext[0], yytext[0])); + return yytext[0]; + } + YY_BREAK +case 15: +YY_RULE_SETUP +#line 106 "./itbl-lex.l" +ECHO; + YY_BREAK +#line 794 "lex.yy.c" +case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a singled characater, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 60 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 60 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 59); + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + yytext_ptr = yy_c_buf_p; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + { + yy_c_buf_p = + yytext_ptr + YY_MORE_ADJ; + return EOF; + } + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + break; + + case EOB_ACT_LAST_MATCH: +#ifdef __cplusplus + YY_FATAL_ERROR( + "unexpected last match in yyinput()" ); +#else + YY_FATAL_ERROR( + "unexpected last match in input()" ); +#endif + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + + return c; + } + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +extern int isatty YY_PROTO(( int )); +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *str ) +#else +YY_BUFFER_STATE yy_scan_string( str ) +yyconst char *str; +#endif + { + int len; + for ( len = 0; str[len]; ++len ) + ; + + return yy_scan_bytes( str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n - YY_MORE_ADJ; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 106 "./itbl-lex.l" + + +int +yywrap () + { + return 1; + } diff --git a/gnu/usr.bin/binutils/gas/itbl-lex.l b/gnu/usr.bin/binutils/gas/itbl-lex.l new file mode 100644 index 00000000000..1703eda0ba7 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/itbl-lex.l @@ -0,0 +1,112 @@ +/* itbl-lex.l + Copyright (C) 1997 Free Software Foundation, Inc. + + This file is part of GAS, the GNU Assembler. + + GAS 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 2, or (at your option) + any later version. + + GAS 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 GAS; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +%{ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <ctype.h> +#include "itbl-parse.h" + +#ifdef DEBUG +#define DBG(x) printf x +#define MDBG(x) printf x +#else +#define DBG(x) +#define MDBG(x) +#endif + +int insntbl_line = 1; +%} + +ALNUM [A-Za-z0-9_] +DIGIT [0-9] +ALPHA [A-Za-z_] +HEX [0-9A-Fa-f] + +%% + +"creg"|"CREG" { + return CREG; + } +"dreg"|"DREG" { + return DREG; + } +"greg"|"GREG" { + return GREG; + } +"immed"|"IMMED" { + return IMMED; + } +"addr"|"ADDR" { + return ADDR; + } +"insn"|"INSN" { + return INSN; + } +"p"{DIGIT} { + yytext[yyleng] = 0; + yylval.processor = strtoul (yytext+1, 0, 0); + return PNUM; + } +{DIGIT}+ { + yytext[yyleng] = 0; + yylval.num = strtoul (yytext, 0, 0); + return NUM; + } +"0x"{HEX}+ { + yytext[yyleng] = 0; + yylval.num = strtoul (yytext, 0, 0); + return NUM; + } +{ALPHA}{ALNUM}* { + yytext[yyleng] = 0; + yylval.str = strdup (yytext); + return ID; + } +";"|"#" { + int c; + while ((c = input ()) != EOF) + { + if (c == '\n') + { + unput (c); + break; + } + } + } +"\n" { + insntbl_line++; + MDBG (("in lex, NL = %d (x%x)\n", NL, NL)); + return NL; + } +" "|"\t" { + } +. { + MDBG (("char = %x, %d\n", yytext[0], yytext[0])); + return yytext[0]; + } +%% + +int +yywrap () + { + return 1; + } diff --git a/gnu/usr.bin/binutils/gas/itbl-ops.c b/gnu/usr.bin/binutils/gas/itbl-ops.c new file mode 100644 index 00000000000..58fc3ebbc56 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/itbl-ops.c @@ -0,0 +1,921 @@ +/* itbl-ops.c + Copyright (C) 1997 Free Software Foundation, Inc. + + This file is part of GAS, the GNU Assembler. + + GAS 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 2, or (at your option) + any later version. + + GAS 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 GAS; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/*======================================================================*/ +/* + * Herein lies the support for dynamic specification of processor + * instructions and registers. Mnemonics, values, and formats for each + * instruction and register are specified in an ascii file consisting of + * table entries. The grammar for the table is defined in the document + * "Processor instruction table specification". + * + * Instructions use the gnu assembler syntax, with the addition of + * allowing mnemonics for register. + * Eg. "func $2,reg3,0x100,symbol ; comment" + * func - opcode name + * $n - register n + * reg3 - mnemonic for processor's register defined in table + * 0xddd..d - immediate value + * symbol - address of label or external symbol + * + * First, itbl_parse reads in the table of register and instruction + * names and formats, and builds a list of entries for each + * processor/type combination. lex and yacc are used to parse + * the entries in the table and call functions defined here to + * add each entry to our list. + * + * Then, when assembling or disassembling, these functions are called to + * 1) get information on a processor's registers and + * 2) assemble/disassemble an instruction. + * To assemble(disassemble) an instruction, the function + * itbl_assemble(itbl_disassemble) is called to search the list of + * instruction entries, and if a match is found, uses the format + * described in the instruction entry structure to complete the action. + * + * Eg. Suppose we have a Mips coprocessor "cop3" with data register "d2" + * and we want to define function "pig" which takes two operands. + * + * Given the table entries: + * "p3 insn pig 0x1:24-21 dreg:20-16 immed:15-0" + * "p3 dreg d2 0x2" + * and that the instruction encoding for coprocessor pz has encoding: + * #define MIPS_ENCODE_COP_NUM(z) ((0x21|(z<<1))<<25) + * #define ITBL_ENCODE_PNUM(pnum) MIPS_ENCODE_COP_NUM(pnum) + * + * a structure to describe the instruction might look something like: + * struct itbl_entry = { + * e_processor processor = e_p3 + * e_type type = e_insn + * char *name = "pig" + * uint value = 0x1 + * uint flags = 0 + * struct itbl_range range = 24-21 + * struct itbl_field *field = { + * e_type type = e_dreg + * struct itbl_range range = 20-16 + * struct itbl_field *next = { + * e_type type = e_immed + * struct itbl_range range = 15-0 + * struct itbl_field *next = 0 + * }; + * }; + * struct itbl_entry *next = 0 + * }; + * + * And the assembler instructions: + * "pig d2,0x100" + * "pig $2,0x100" + * + * would both assemble to the hex value: + * "0x4e220100" + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "itbl-ops.h" +#include "itbl-parse.h" + +/* #define DEBUG */ + +#ifdef DEBUG +#include <assert.h> +#define ASSERT(x) assert(x) +#define DBG(x) printf x +#else +#define ASSERT(x) +#define DBG(x) +#endif + +#ifndef min +#define min(a,b) (a<b?a:b) +#endif + +int itbl_have_entries = 0; + +/*======================================================================*/ +/* structures for keeping itbl format entries */ + +struct itbl_range + { + int sbit; /* mask starting bit position */ + int ebit; /* mask ending bit position */ + }; + +struct itbl_field + { + e_type type; /* dreg/creg/greg/immed/symb */ + struct itbl_range range; /* field's bitfield range within instruction */ + unsigned long flags; /* field flags */ + struct itbl_field *next; /* next field in list */ + }; + + +/* These structures define the instructions and registers for a processor. + * If the type is an instruction, the structure defines the format of an + * instruction where the fields are the list of operands. + * The flags field below uses the same values as those defined in the + * gnu assembler and are machine specific. */ +struct itbl_entry + { + e_processor processor; /* processor number */ + e_type type; /* dreg/creg/greg/insn */ + char *name; /* mnemionic name for insn/register */ + unsigned long value; /* opcode/instruction mask/register number */ + unsigned long flags; /* effects of the instruction */ + struct itbl_range range; /* bit range within instruction for value */ + struct itbl_field *fields; /* list of operand definitions (if any) */ + struct itbl_entry *next; /* next entry */ + }; + + +/* local data and structures */ + +static int itbl_num_opcodes = 0; +/* Array of entries for each processor and entry type */ +static struct itbl_entry *entries[e_nprocs][e_ntypes] = +{ + {0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0} +}; + +/* local prototypes */ +static unsigned long build_opcode PARAMS ((struct itbl_entry *e)); +static e_type get_type PARAMS ((int yytype)); +static e_processor get_processor PARAMS ((int yyproc)); +static struct itbl_entry **get_entries PARAMS ((e_processor processor, + e_type type)); +static struct itbl_entry *find_entry_byname PARAMS ((e_processor processor, + e_type type, char *name)); +static struct itbl_entry *find_entry_byval PARAMS ((e_processor processor, + e_type type, unsigned long val, struct itbl_range *r)); +static struct itbl_entry *alloc_entry PARAMS ((e_processor processor, + e_type type, char *name, unsigned long value)); +static unsigned long apply_range PARAMS ((unsigned long value, + struct itbl_range r)); +static unsigned long extract_range PARAMS ((unsigned long value, + struct itbl_range r)); +static struct itbl_field *alloc_field PARAMS ((e_type type, int sbit, + int ebit, unsigned long flags)); + + +/*======================================================================*/ +/* Interfaces to the parser */ + + +/* Open the table and use lex and yacc to parse the entries. + * Return 1 for failure; 0 for success. */ + +int +itbl_parse (char *insntbl) +{ + extern FILE *yyin; + extern int yyparse (void); + yyin = fopen (insntbl, "r"); + if (yyin == 0) + { + printf ("Can't open processor instruction specification file \"%s\"\n", + insntbl); + return 1; + } + else + { + while (yyparse ()); + } + fclose (yyin); + itbl_have_entries = 1; + return 0; +} + +/* Add a register entry */ + +struct itbl_entry * +itbl_add_reg (int yyprocessor, int yytype, char *regname, + int regnum) +{ +#if 0 +#include "as.h" +#include "symbols.h" + /* Since register names don't have a prefix, we put them in the symbol table so + they can't be used as symbols. This also simplifies argument parsing as + we can let gas parse registers for us. The recorded register number is + regnum. */ + /* Use symbol_create here instead of symbol_new so we don't try to + output registers into the object file's symbol table. */ + symbol_table_insert (symbol_create (regname, reg_section, + regnum, &zero_address_frag)); +#endif + return alloc_entry (get_processor (yyprocessor), get_type (yytype), regname, + (unsigned long) regnum); +} + +/* Add an instruction entry */ + +struct itbl_entry * +itbl_add_insn (int yyprocessor, char *name, unsigned long value, + int sbit, int ebit, unsigned long flags) +{ + struct itbl_entry *e; + e = alloc_entry (get_processor (yyprocessor), e_insn, name, value); + if (e) + { + e->range.sbit = sbit; + e->range.ebit = ebit; + e->flags = flags; + itbl_num_opcodes++; + } + return e; +} + +/* Add an operand to an instruction entry */ + +struct itbl_field * +itbl_add_operand (struct itbl_entry *e, int yytype, int sbit, + int ebit, unsigned long flags) +{ + struct itbl_field *f, **last_f; + if (!e) + return 0; + /* Add to end of fields' list. */ + f = alloc_field (get_type (yytype), sbit, ebit, flags); + if (f) + { + last_f = &e->fields; + while (*last_f) + last_f = &(*last_f)->next; + *last_f = f; + f->next = 0; + } + return f; +} + + +/*======================================================================*/ +/* Interfaces for assembler and disassembler */ + +#ifndef STAND_ALONE +#include "as.h" +#include "symbols.h" +static void append_insns_as_macros (void); + +/* initialize for gas */ +void +itbl_init (void) +{ + struct itbl_entry *e, **es; + e_processor procn; + e_type type; + + if (!itbl_have_entries) + return; + + /* Since register names don't have a prefix, put them in the symbol table so + they can't be used as symbols. This simplifies argument parsing as + we can let gas parse registers for us. */ + /* Use symbol_create instead of symbol_new so we don't try to + output registers into the object file's symbol table. */ + + for (type = e_regtype0; type < e_nregtypes; type++) + for (procn = e_p0; procn < e_nprocs; procn++) + { + es = get_entries (procn, type); + for (e = *es; e; e = e->next) + { + symbol_table_insert (symbol_create (e->name, reg_section, + e->value, &zero_address_frag)); + } + } + append_insns_as_macros (); +} + + +/* Append insns to opcodes table and increase number of opcodes + * Structure of opcodes table: + * struct itbl_opcode + * { + * const char *name; + * const char *args; - string describing the arguments. + * unsigned long match; - opcode, or ISA level if pinfo=INSN_MACRO + * unsigned long mask; - opcode mask, or macro id if pinfo=INSN_MACRO + * unsigned long pinfo; - insn flags, or INSN_MACRO + * }; + * examples: + * {"li", "t,i", 0x34000000, 0xffe00000, WR_t }, + * {"li", "t,I", 0, (int) M_LI, INSN_MACRO }, + */ + +static char *form_args (struct itbl_entry *e); +static void +append_insns_as_macros (void) +{ + struct ITBL_OPCODE_STRUCT *new_opcodes, *o; + struct itbl_entry *e, **es; + int n, id, size, new_size, new_num_opcodes; + + if (!itbl_have_entries) + return; + + if (!itbl_num_opcodes) /* no new instructions to add! */ + { + return; + } + DBG (("previous num_opcodes=%d\n", ITBL_NUM_OPCODES)); + + new_num_opcodes = ITBL_NUM_OPCODES + itbl_num_opcodes; + ASSERT (new_num_opcodes >= itbl_num_opcodes); + + size = sizeof (struct ITBL_OPCODE_STRUCT) * ITBL_NUM_OPCODES; + ASSERT (size >= 0); + DBG (("I get=%d\n", size / sizeof (ITBL_OPCODES[0]))); + + new_size = sizeof (struct ITBL_OPCODE_STRUCT) * new_num_opcodes; + ASSERT (new_size > size); + + /* FIXME since ITBL_OPCODES culd be a static table, + we can't realloc or delete the old memory. */ + new_opcodes = (struct ITBL_OPCODE_STRUCT *) malloc (new_size); + if (!new_opcodes) + { + printf ("Unable to allocate memory for new instructions\n"); + return; + } + if (size) /* copy prexisting opcodes table */ + memcpy (new_opcodes, ITBL_OPCODES, size); + + /* FIXME! some NUMOPCODES are calculated expressions. + These need to be changed before itbls can be supported. */ + + id = ITBL_NUM_MACROS; /* begin the next macro id after the last */ + o = &new_opcodes[ITBL_NUM_OPCODES]; /* append macro to opcodes list */ + for (n = e_p0; n < e_nprocs; n++) + { + es = get_entries (n, e_insn); + for (e = *es; e; e = e->next) + { + /* name, args, mask, match, pinfo + * {"li", "t,i", 0x34000000, 0xffe00000, WR_t }, + * {"li", "t,I", 0, (int) M_LI, INSN_MACRO }, + * Construct args from itbl_fields. + */ + o->name = e->name; + o->args = strdup (form_args (e)); + o->mask = apply_range (e->value, e->range); + /* FIXME how to catch durring assembly? */ + /* mask to identify this insn */ + o->match = apply_range (e->value, e->range); + o->pinfo = 0; + +#ifdef USE_MACROS + o->mask = id++; /* FIXME how to catch durring assembly? */ + o->match = 0; /* for macros, the insn_isa number */ + o->pinfo = INSN_MACRO; +#endif + + /* Don't add instructions which caused an error */ + if (o->args) + o++; + else + new_num_opcodes--; + } + } + ITBL_OPCODES = new_opcodes; + ITBL_NUM_OPCODES = new_num_opcodes; + + /* FIXME + At this point, we can free the entries, as they should have + been added to the assembler's tables. + Don't free name though, since name is being used by the new + opcodes table. + + Eventually, we should also free the new opcodes table itself + on exit. + */ +} + +static char * +form_args (struct itbl_entry *e) +{ + static char s[31]; + char c = 0, *p = s; + struct itbl_field *f; + + ASSERT (e); + for (f = e->fields; f; f = f->next) + { + switch (f->type) + { + case e_dreg: + c = 'd'; + break; + case e_creg: + c = 't'; + break; + case e_greg: + c = 's'; + break; + case e_immed: + c = 'i'; + break; + case e_addr: + c = 'a'; + break; + default: + c = 0; /* ignore; unknown field type */ + } + if (c) + { + if (p != s) + *p++ = ','; + *p++ = c; + } + } + *p = 0; + return s; +} +#endif /* !STAND_ALONE */ + + +/* Get processor's register name from val */ + +unsigned long +itbl_get_reg_val (char *name) +{ + e_type t; + e_processor p; + int r = 0; + for (p = e_p0; p < e_nprocs; p++) + for (t = e_regtype0; t < e_nregtypes; t++) + { + if (r = itbl_get_val (p, t, name), r) + return r; + } + return 0; +} + +char * +itbl_get_name (e_processor processor, e_type type, unsigned long val) +{ + struct itbl_entry *r; + /* type depends on instruction passed */ + r = find_entry_byval (processor, type, val, 0); + if (r) + return r->name; + else + return 0; /* error; invalid operand */ +} + +/* Get processor's register value from name */ + +unsigned long +itbl_get_val (e_processor processor, e_type type, char *name) +{ + struct itbl_entry *r; + /* type depends on instruction passed */ + r = find_entry_byname (processor, type, name); + if (r) + return r->value; + else + return 0; /* error; invalid operand */ +} + + +/* Assemble instruction "name" with operands "s". + * name - name of instruction + * s - operands + * returns - long word for assembled instruction */ + +unsigned long +itbl_assemble (char *name, char *s) +{ + unsigned long opcode; + struct itbl_entry *e; + struct itbl_field *f; + char *n; + int processor; + + if (!name || !*name) + return 0; /* error! must have a opcode name/expr */ + + /* find entry in list of instructions for all processors */ + for (processor = 0; processor < e_nprocs; processor++) + { + e = find_entry_byname (processor, e_insn, name); + if (e) + break; + } + if (!e) + return 0; /* opcode not in table; invalid instrustion */ + opcode = build_opcode (e); + + /* parse opcode's args (if any) */ + for (f = e->fields; f; f = f->next) /* for each arg, ... */ + { + struct itbl_entry *r; + unsigned long value; + if (!s || !*s) + return 0; /* error - not enough operands */ + n = itbl_get_field (&s); + /* n should be in form $n or 0xhhh (are symbol names valid?? */ + switch (f->type) + { + case e_dreg: + case e_creg: + case e_greg: + /* Accept either a string name + * or '$' followed by the register number */ + if (*n == '$') + { + n++; + value = strtol (n, 0, 10); + /* FIXME! could have "0l"... then what?? */ + if (value == 0 && *n != '0') + return 0; /* error; invalid operand */ + } + else + { + r = find_entry_byname (e->processor, f->type, n); + if (r) + value = r->value; + else + return 0; /* error; invalid operand */ + } + break; + case e_addr: + /* use assembler's symbol table to find symbol */ + /* FIXME!! Do we need this? + if so, what about relocs?? + my_getExpression (&imm_expr, s); + return 0; /-* error; invalid operand *-/ + break; + */ + /* If not a symbol, fall thru to IMMED */ + case e_immed: + if (*n == '0' && *(n + 1) == 'x') /* hex begins 0x... */ + { + n += 2; + value = strtol (n, 0, 16); + /* FIXME! could have "0xl"... then what?? */ + } + else + { + value = strtol (n, 0, 10); + /* FIXME! could have "0l"... then what?? */ + if (value == 0 && *n != '0') + return 0; /* error; invalid operand */ + } + break; + default: + return 0; /* error; invalid field spec */ + } + opcode |= apply_range (value, f->range); + } + if (s && *s) + return 0; /* error - too many operands */ + return opcode; /* done! */ +} + +/* Disassemble instruction "insn". + * insn - instruction + * s - buffer to hold disassembled instruction + * returns - 1 if succeeded; 0 if failed + */ + +int +itbl_disassemble (char *s, unsigned long insn) +{ + e_processor processor; + struct itbl_entry *e; + struct itbl_field *f; + + if (!ITBL_IS_INSN (insn)) + return 0; /* error*/ + processor = get_processor (ITBL_DECODE_PNUM (insn)); + + /* find entry in list */ + e = find_entry_byval (processor, e_insn, insn, 0); + if (!e) + return 0; /* opcode not in table; invalid instrustion */ + strcpy (s, e->name); + + /* parse insn's args (if any) */ + for (f = e->fields; f; f = f->next) /* for each arg, ... */ + { + struct itbl_entry *r; + unsigned long value; + + if (f == e->fields) /* first operand is preceeded by tab */ + strcat (s, "\t"); + else /* ','s separate following operands */ + strcat (s, ","); + value = extract_range (insn, f->range); + /* n should be in form $n or 0xhhh (are symbol names valid?? */ + switch (f->type) + { + case e_dreg: + case e_creg: + case e_greg: + /* Accept either a string name + * or '$' followed by the register number */ + r = find_entry_byval (e->processor, f->type, value, &f->range); + if (r) + strcat (s, r->name); + else + sprintf (s, "%s$%d", s, value); + break; + case e_addr: + /* use assembler's symbol table to find symbol */ + /* FIXME!! Do we need this? + * if so, what about relocs?? + */ + /* If not a symbol, fall thru to IMMED */ + case e_immed: + sprintf (s, "%s0x%x", s, value); + break; + default: + return 0; /* error; invalid field spec */ + } + } + return 1; /* done! */ +} + +/*======================================================================*/ +/* + * Local functions for manipulating private structures containing + * the names and format for the new instructions and registers + * for each processor. + */ + +/* Calculate instruction's opcode and function values from entry */ + +static unsigned long +build_opcode (struct itbl_entry *e) +{ + unsigned long opcode; + + opcode = apply_range (e->value, e->range); + opcode |= ITBL_ENCODE_PNUM (e->processor); + return opcode; +} + +/* Calculate absolute value given the relative value and bit position range + * within the instruction. + * The range is inclusive where 0 is least significant bit. + * A range of { 24, 20 } will have a mask of + * bit 3 2 1 + * pos: 1098 7654 3210 9876 5432 1098 7654 3210 + * bin: 0000 0001 1111 0000 0000 0000 0000 0000 + * hex: 0 1 f 0 0 0 0 0 + * mask: 0x01f00000. + */ + +static unsigned long +apply_range (unsigned long rval, struct itbl_range r) +{ + unsigned long mask; + unsigned long aval; + int len = MAX_BITPOS - r.sbit; + + ASSERT (r.sbit >= r.ebit); + ASSERT (MAX_BITPOS >= r.sbit); + ASSERT (r.ebit >= 0); + + /* create mask by truncating 1s by shifting */ + mask = 0xffffffff << len; + mask = mask >> len; + mask = mask >> r.ebit; + mask = mask << r.ebit; + + aval = (rval << r.ebit) & mask; + return aval; +} + +/* Calculate relative value given the absolute value and bit position range + * within the instruction. */ + +static unsigned long +extract_range (unsigned long aval, struct itbl_range r) +{ + unsigned long mask; + unsigned long rval; + int len = MAX_BITPOS - r.sbit; + + /* create mask by truncating 1s by shifting */ + mask = 0xffffffff << len; + mask = mask >> len; + mask = mask >> r.ebit; + mask = mask << r.ebit; + + rval = (aval & mask) >> r.ebit; + return rval; +} + +/* Extract processor's assembly instruction field name from s; + * forms are "n args" "n,args" or "n" */ +/* Return next argument from string pointer "s" and advance s. + * delimiters are " ,\0" */ + +char * +itbl_get_field (char **S) +{ + static char n[128]; + char *p, *ps, *s; + int len; + + s = *S; + if (!s || !*s) + return 0; + p = s + strlen (s); + if (ps = strchr (s, ','), ps) + p = ps; + if (ps = strchr (s, ' '), ps) + p = min (p, ps); + if (ps = strchr (s, '\0'), ps) + p = min (p, ps); + if (p == 0) + return 0; /* error! */ + len = p - s; + ASSERT (128 > len + 1); + strncpy (n, s, len); + n[len] = 0; + if (s[len] == '\0') + s = 0; /* no more args */ + else + s += len + 1; /* advance to next arg */ + + *S = s; + return n; +} + +/* Search entries for a given processor and type + * to find one matching the name "n". + * Return a pointer to the entry */ + +static struct itbl_entry * +find_entry_byname (e_processor processor, + e_type type, char *n) +{ + struct itbl_entry *e, **es; + + es = get_entries (processor, type); + for (e = *es; e; e = e->next) /* for each entry, ... */ + { + if (!strcmp (e->name, n)) + return e; + } + return 0; +} + +/* Search entries for a given processor and type + * to find one matching the value "val" for the range "r". + * Return a pointer to the entry. + * This function is used for disassembling fields of an instruction. + */ + +static struct itbl_entry * +find_entry_byval (e_processor processor, e_type type, + unsigned long val, struct itbl_range *r) +{ + struct itbl_entry *e, **es; + unsigned long eval; + + es = get_entries (processor, type); + for (e = *es; e; e = e->next) /* for each entry, ... */ + { + if (processor != e->processor) + continue; + /* For insns, we might not know the range of the opcode, + * so a range of 0 will allow this routine to match against + * the range of the entry to be compared with. + * This could cause ambiguities. + * For operands, we get an extracted value and a range. + */ + /* if range is 0, mask val against the range of the compared entry. */ + if (r == 0) /* if no range passed, must be whole 32-bits + * so create 32-bit value from entry's range */ + { + eval = apply_range (e->value, e->range); + val &= apply_range (0xffffffff, e->range); + } + else if (r->sbit == e->range.sbit && r->ebit == e->range.ebit + || e->range.sbit == 0 && e->range.ebit == 0) + { + eval = apply_range (e->value, *r); + val = apply_range (val, *r); + } + else + continue; + if (val == eval) + return e; + } + return 0; +} + +/* Return a pointer to the list of entries for a given processor and type. */ + +static struct itbl_entry ** +get_entries (e_processor processor, e_type type) +{ + return &entries[processor][type]; +} + +/* Return an integral value for the processor passed from yyparse. */ + +static e_processor +get_processor (int yyproc) +{ + /* translate from yacc's processor to enum */ + if (yyproc >= e_p0 && yyproc < e_nprocs) + return (e_processor) yyproc; + return e_invproc; /* error; invalid processor */ +} + +/* Return an integral value for the entry type passed from yyparse. */ + +static e_type +get_type (int yytype) +{ + switch (yytype) + { + /* translate from yacc's type to enum */ + case INSN: + return e_insn; + case DREG: + return e_dreg; + case CREG: + return e_creg; + case GREG: + return e_greg; + case ADDR: + return e_addr; + case IMMED: + return e_immed; + default: + return e_invtype; /* error; invalid type */ + } +} + + +/* Allocate and initialize an entry */ + +static struct itbl_entry * +alloc_entry (e_processor processor, e_type type, + char *name, unsigned long value) +{ + struct itbl_entry *e, **es; + if (!name) + return 0; + e = (struct itbl_entry *) malloc (sizeof (struct itbl_entry)); + if (e) + { + memset (e, 0, sizeof (struct itbl_entry)); + e->name = (char *) malloc (sizeof (strlen (name)) + 1); + if (e->name) + strcpy (e->name, name); + e->processor = processor; + e->type = type; + e->value = value; + es = get_entries (e->processor, e->type); + e->next = *es; + *es = e; + } + return e; +} + +/* Allocate and initialize an entry's field */ + +static struct itbl_field * +alloc_field (e_type type, int sbit, int ebit, + unsigned long flags) +{ + struct itbl_field *f; + f = (struct itbl_field *) malloc (sizeof (struct itbl_field)); + if (f) + { + memset (f, 0, sizeof (struct itbl_field)); + f->type = type; + f->range.sbit = sbit; + f->range.ebit = ebit; + f->flags = flags; + } + return f; +} diff --git a/gnu/usr.bin/binutils/gas/itbl-ops.h b/gnu/usr.bin/binutils/gas/itbl-ops.h new file mode 100644 index 00000000000..2946eff0066 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/itbl-ops.h @@ -0,0 +1,109 @@ +/* itbl-ops.h + Copyright (C) 1997 Free Software Foundation, Inc. + + This file is part of GAS, the GNU Assembler. + + GAS 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 2, or (at your option) + any later version. + + GAS 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 GAS; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* External functions, constants and defines for itbl support */ + +#include "ansidecl.h" + +/* Include file notes: "expr.h" needed before targ-*.h, + * "targ-env.h" includes the chain of target dependant headers, + * "targ-cpu.h" has the HAVE_ITBL_CPU define, and + * as.h includes them all */ +#include "as.h" + +#ifdef HAVE_ITBL_CPU +#include "itbl-cpu.h" +#endif + +/* Defaults for definitions required by generic code */ +#ifndef ITBL_NUMBER_OF_PROCESSORS +#define ITBL_NUMBER_OF_PROCESSORS 1 +#endif + +#ifndef ITBL_MAX_BITPOS +#define ITBL_MAX_BITPOS 31 +#endif + +#ifndef ITBL_TYPE +#define ITBL_TYPE unsigned long +#endif + +#ifndef ITBL_IS_INSN +#define ITBL_IS_INSN(insn) 1 +#endif + +#ifndef ITBL_DECODE_PNUM +#define ITBL_DECODE_PNUM(insn) 0 +#endif + +#ifndef ITBL_ENCODE_PNUM +#define ITBL_ENCODE_PNUM(pnum) 0 +#endif + +typedef ITBL_TYPE t_insn; + +/* types of entries */ +typedef enum + { + e_insn, + e_dreg, + e_regtype0 = e_dreg, + e_creg, + e_greg, + e_addr, + e_nregtypes = e_greg + 1, + e_immed, + e_ntypes, + e_invtype /* invalid type */ + } e_type; + +typedef enum + { + e_p0, + e_nprocs = NUMBER_OF_PROCESSORS, + e_invproc /* invalid processor */ + } e_processor; + +/* 0 means an instruction table was not specified. */ +extern int itbl_have_entries; + +/* These routines are visible to the main part of the assembler */ + +int itbl_parse PARAMS ((char *insntbl)); +void itbl_init PARAMS ((void)); +char *itbl_get_field PARAMS ((char **s)); +unsigned long itbl_assemble PARAMS ((char *name, char *operands)); +int itbl_disassemble PARAMS ((char *str, unsigned long insn)); +int itbl_parse PARAMS ((char *tbl)); /* parses insn tbl */ +unsigned long itbl_get_reg_val PARAMS ((char *name)); +unsigned long itbl_get_val PARAMS ((e_processor processor, e_type type, + char *name)); +char *itbl_get_name PARAMS ((e_processor processor, e_type type, + unsigned long val)); + +/* These routines are called by the table parser used to build the + dynamic list of new processor instructions and registers. */ + +struct itbl_entry *itbl_add_reg PARAMS ((int yyproc, int yytype, + char *regname, int regnum)); +struct itbl_entry *itbl_add_insn PARAMS ((int yyproc, char *name, + unsigned long value, int sbit, int ebit, unsigned long flags)); +struct itbl_field *itbl_add_operand PARAMS ((struct itbl_entry * e, int yytype, + int sbit, int ebit, unsigned long flags)); diff --git a/gnu/usr.bin/binutils/gas/itbl-parse.c b/gnu/usr.bin/binutils/gas/itbl-parse.c new file mode 100644 index 00000000000..530375f7f5d --- /dev/null +++ b/gnu/usr.bin/binutils/gas/itbl-parse.c @@ -0,0 +1,1284 @@ + +/* A Bison parser, made from ./itbl-parse.y with Bison version GNU Bison version 1.24 + */ + +#define YYBISON 1 /* Identify Bison output. */ + +#define DREG 258 +#define CREG 259 +#define GREG 260 +#define IMMED 261 +#define ADDR 262 +#define INSN 263 +#define NUM 264 +#define ID 265 +#define NL 266 +#define PNUM 267 + +#line 21 "./itbl-parse.y" + + +/* + +Yacc grammar for instruction table entries. + +======================================================================= +Original Instruction table specification document: + + MIPS Coprocessor Table Specification + ==================================== + +This document describes the format of the MIPS coprocessor table. The +table specifies a list of valid functions, data registers and control +registers that can be used in coprocessor instructions. This list, +together with the coprocessor instruction classes listed below, +specifies the complete list of coprocessor instructions that will +be recognized and assembled by the GNU assembler. In effect, +this makes the GNU assembler table-driven, where the table is +specified by the programmer. + +The table is an ordinary text file that the GNU assembler reads when +it starts. Using the information in the table, the assembler +generates an internal list of valid coprocessor registers and +functions. The assembler uses this internal list in addition to the +standard MIPS registers and instructions which are built-in to the +assembler during code generation. + +To specify the coprocessor table when invoking the GNU assembler, use +the command line option "--itbl file", where file is the +complete name of the table, including path and extension. + +Examples: + + gas -t cop.tbl test.s -o test.o + gas -t /usr/local/lib/cop.tbl test.s -o test.o + gas --itbl d:\gnu\data\cop.tbl test.s -o test.o + +Only one table may be supplied during a single invocation of +the assembler. + + +Instruction classes +=================== + +Below is a list of the valid coprocessor instruction classes for +any given coprocessor "z". These instructions are already recognized +by the assembler, and are listed here only for reference. + +Class format instructions +------------------------------------------------- +Class1: + op base rt offset + LWCz rt,offset (base) + SWCz rt,offset (base) +Class2: + COPz sub rt rd 0 + MTCz rt,rd + MFCz rt,rd + CTCz rt,rd + CFCz rt,rd +Class3: + COPz CO cofun + COPz cofun +Class4: + COPz BC br offset + BCzT offset + BCzF offset +Class5: + COPz sub rt rd 0 + DMFCz rt,rd + DMTCz rt,rd +Class6: + op base rt offset + LDCz rt,offset (base) + SDCz rt,offset (base) +Class7: + COPz BC br offset + BCzTL offset + BCzFL offset + +The coprocessor table defines coprocessor-specific registers that can +be used with all of the above classes of instructions, where +appropriate. It also defines additional coprocessor-specific +functions for Class3 (COPz cofun) instructions, Thus, the table allows +the programmer to use convenient mnemonics and operands for these +functions, instead of the COPz mmenmonic and cofun operand. + +The names of the MIPS general registers and their aliases are defined +by the assembler and will be recognized as valid register names by the +assembler when used (where allowed) in coprocessor instructions. +However, the names and values of all coprocessor data and control +register mnemonics must be specified in the coprocessor table. + + +Table Grammar +============= + +Here is the grammar for the coprocessor table: + + table -> entry* + + entry -> [z entrydef] [comment] '\n' + + entrydef -> type name val + entrydef -> 'insn' name val funcdef ; type of entry (instruction) + + z -> 'p'['0'..'3'] ; processor number + type -> ['dreg' | 'creg' | 'greg' ] ; type of entry (register) + ; 'dreg', 'creg' or 'greg' specifies a data, control, or general + ; register mnemonic, respectively + name -> [ltr|dec]* ; mnemonic of register/function + val -> [dec|hex] ; register/function number (integer constant) + + funcdef -> frange flags fields + ; bitfield range for opcode + ; list of fields' formats + fields -> field* + field -> [','] ftype frange flags + flags -> ['*' flagexpr] + flagexpr -> '[' flagexpr ']' + flagexpr -> val '|' flagexpr + ftype -> [ type | 'immed' | 'addr' ] + ; 'immed' specifies an immediate value; see grammar for "val" above + ; 'addr' specifies a C identifier; name of symbol to be resolved at + ; link time + frange -> ':' val '-' val ; starting to ending bit positions, where + ; where 0 is least significant bit + frange -> (null) ; default range of 31-0 will be assumed + + comment -> [';'|'#'] [char]* + char -> any printable character + ltr -> ['a'..'z'|'A'..'Z'] + dec -> ['0'..'9']* ; value in decimal + hex -> '0x'['0'..'9' | 'a'..'f' | 'A'..'F']* ; value in hexidecimal + + +Examples +======== + +Example 1: + +The table: + + p1 dreg d1 1 ; data register "d1" for COP1 has value 1 + p1 creg c3 3 ; ctrl register "c3" for COP1 has value 3 + p3 func fill 0x1f:24-20 ; function "fill" for COP3 has value 31 and + ; no fields + +will allow the assembler to accept the following coprocessor instructions: + + LWC1 d1,0x100 ($2) + fill + +Here, the general purpose register "$2", and instruction "LWC1", are standard +mnemonics built-in to the MIPS assembler. + + +Example 2: + +The table: + + p3 dreg d3 3 ; data register "d3" for COP3 has value 3 + p3 creg c2 22 ; control register "c2" for COP3 has value 22 + p3 func fee 0x1f:24-20 dreg:17-13 creg:12-8 immed:7-0 + ; function "fee" for COP3 has value 31, and 3 fields + ; consisting of a data register, a control register, + ; and an immediate value. + +will allow the assembler to accept the following coprocessor instruction: + + fee d3,c2,0x1 + +and will emit the object code: + + 31-26 25 24-20 19-18 17-13 12-8 7-0 + COPz CO fun dreg creg immed + 010011 1 11111 00 00011 10110 00000001 + + 0x4ff07601 + + +Example 3: + +The table: + + p3 dreg d3 3 ; data register "d3" for COP3 has value 3 + p3 creg c2 22 ; control register "c2" for COP3 has value 22 + p3 func fuu 0x01f00001 dreg:17-13 creg:12-8 + +will allow the assembler to accept the following coprocessor +instruction: + + fuu d3,c2 + +and will emit the object code: + + 31-26 25 24-20 19-18 17-13 12-8 7-0 + COPz CO fun dreg creg + 010011 1 11111 00 00011 10110 00000001 + + 0x4ff07601 + +In this way, the programmer can force arbitrary bits of an instruction +to have predefined values. + +======================================================================= +Additional notes: + +Encoding of ranges: +To handle more than one bit position range within an instruction, +use 0s to mask out the ranges which don't apply. +May decide to modify the syntax to allow commas separate multiple +ranges within an instruction (range','range). + +Changes in grammar: + The number of parms argument to the function entry +was deleted from the original format such that we now count the fields. + +---- +FIXME! should really change lexical analyzer +to recognize 'dreg' etc. in context sensative way. +Currently function names or mnemonics may be incorrectly parsed as keywords + +FIXME! hex is ambiguous with any digit + +*/ + +#include <stdio.h> +#include "itbl-ops.h" + +/* #define DEBUG */ + +#ifdef DEBUG +#ifndef DBG_LVL +#define DBG_LVL 1 +#endif +#else +#define DBG_LVL 0 +#endif + +#if DBG_LVL >= 1 +#define DBG(x) printf x +#else +#define DBG(x) +#endif + +#if DBG_LVL >= 2 +#define DBGL2(x) printf x +#else +#define DBGL2(x) +#endif + +static int sbit, ebit; +static struct itbl_entry *insn=0; +extern int insntbl_line; +int yyparse PARAMS ((void)); +int yylex PARAMS ((void)); +static int yyerror PARAMS ((const char *)); + + +#line 283 "./itbl-parse.y" +typedef union + { + char *str; + int num; + int processor; + unsigned long val; + } YYSTYPE; + +#ifndef YYLTYPE +typedef + struct yyltype + { + int timestamp; + int first_line; + int first_column; + int last_line; + int last_column; + char *text; + } + yyltype; + +#define YYLTYPE yyltype +#endif + +#include <stdio.h> + +#ifndef __cplusplus +#ifndef __STDC__ +#define const +#endif +#endif + + + +#define YYFINAL 51 +#define YYFLAG -32768 +#define YYNTBASE 20 + +#define YYTRANSLATE(x) ((unsigned)(x) <= 267 ? yytranslate[x] : 34) + +static const char yytranslate[] = { 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 17, 2, 13, 19, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 18, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 15, 2, 16, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 14, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12 +}; + +#if YYDEBUG != 0 +static const short yyprhs[] = { 0, + 0, 2, 5, 6, 12, 13, 23, 25, 28, 32, + 35, 36, 38, 40, 42, 46, 50, 54, 56, 59, + 60, 65, 66, 68, 70, 72, 74, 76, 78 +}; + +static const short yyrhs[] = { 21, + 0, 22, 21, 0, 0, 30, 31, 32, 33, 11, + 0, 0, 30, 8, 32, 33, 29, 28, 23, 24, + 11, 0, 11, 0, 1, 11, 0, 13, 26, 24, + 0, 26, 24, 0, 0, 31, 0, 7, 0, 6, + 0, 25, 29, 28, 0, 9, 14, 27, 0, 15, + 27, 16, 0, 9, 0, 17, 27, 0, 0, 18, + 9, 19, 9, 0, 0, 12, 0, 3, 0, 4, + 0, 5, 0, 10, 0, 9, 0, 9, 0 +}; + +#endif + +#if YYDEBUG != 0 +static const short yyrline[] = { 0, + 300, 304, 306, 309, 316, 323, 324, 325, 328, 330, + 331, 334, 340, 345, 352, 361, 366, 370, 376, 382, + 388, 395, 402, 410, 416, 421, 428, 436, 444 +}; + +static const char * const yytname[] = { "$","error","$undefined.","DREG","CREG", +"GREG","IMMED","ADDR","INSN","NUM","ID","NL","PNUM","','","'|'","'['","']'", +"'*'","':'","'-'","insntbl","entrys","entry","@1","fieldspecs","ftype","fieldspec", +"flagexpr","flags","range","pnum","regtype","name","value","value" +}; +#endif + +static const short yyr1[] = { 0, + 20, 21, 21, 22, 23, 22, 22, 22, 24, 24, + 24, 25, 25, 25, 26, 27, 27, 27, 28, 28, + 29, 29, 30, 31, 31, 31, 32, -1, 33 +}; + +static const short yyr2[] = { 0, + 1, 2, 0, 5, 0, 9, 1, 2, 3, 2, + 0, 1, 1, 1, 3, 3, 3, 1, 2, 0, + 4, 0, 1, 1, 1, 1, 1, 1, 1 +}; + +static const short yydefact[] = { 0, + 0, 7, 23, 1, 0, 0, 8, 2, 24, 25, + 26, 0, 0, 27, 0, 0, 29, 22, 0, 0, + 20, 4, 0, 0, 5, 0, 18, 0, 19, 11, + 21, 0, 0, 14, 13, 0, 0, 22, 11, 12, + 16, 17, 11, 6, 20, 10, 9, 15, 0, 0, + 0 +}; + +static const short yydefgoto[] = { 49, + 4, 5, 30, 37, 38, 39, 29, 25, 21, 6, + 40, 15, 18 +}; + +static const short yypact[] = { 0, + -9,-32768,-32768,-32768, 0, 12,-32768,-32768,-32768,-32768, +-32768, 3, 3,-32768, 9, 9,-32768, -8, 8, 19, + 15,-32768, 10, -6,-32768, 24, 20, -6,-32768, 1, +-32768, -6, 21,-32768,-32768, 18, 25, -8, 1,-32768, +-32768,-32768, 1,-32768, 15,-32768,-32768,-32768, 35, 38, +-32768 +}; + +static const short yypgoto[] = {-32768, + 34,-32768,-32768, -13,-32768, 4, -1, -4, 5,-32768, + 36, 31, 29 +}; + + +#define YYLAST 45 + + +static const short yytable[] = { -3, + 1, 7, 27, 9, 10, 11, 34, 35, 28, 20, + 2, 3, 14, 36, 9, 10, 11, 17, 22, 12, + 9, 10, 11, 34, 35, 46, 33, 23, 26, 47, + 41, 24, 31, 32, 50, 44, 42, 51, 8, 43, + 48, 13, 45, 16, 19 +}; + +static const short yycheck[] = { 0, + 1, 11, 9, 3, 4, 5, 6, 7, 15, 18, + 11, 12, 10, 13, 3, 4, 5, 9, 11, 8, + 3, 4, 5, 6, 7, 39, 28, 9, 19, 43, + 32, 17, 9, 14, 0, 11, 16, 0, 5, 36, + 45, 6, 38, 13, 16 +}; +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ +#line 3 "/usr/unsupported/share/bison.simple" + +/* Skeleton output parser for bison, + Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. + + 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 2, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +#ifndef alloca +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not GNU C. */ +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) +#include <alloca.h> +#else /* not sparc */ +#if defined (MSDOS) && !defined (__TURBOC__) +#include <malloc.h> +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +#include <malloc.h> + #pragma alloca +#else /* not MSDOS, __TURBOC__, or _AIX */ +#ifdef __hpux +#ifdef __cplusplus +extern "C" { +void *alloca (unsigned int); +}; +#else /* not __cplusplus */ +void *alloca (); +#endif /* not __cplusplus */ +#endif /* __hpux */ +#endif /* not _AIX */ +#endif /* not MSDOS, or __TURBOC__ */ +#endif /* not sparc. */ +#endif /* not GNU C. */ +#endif /* alloca not defined. */ + +/* This is the parser code that is written into each bison parser + when the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +/* Note: there must be only one dollar sign in this file. + It is replaced by the list of actions, each action + as one case of the switch. */ + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYACCEPT return(0) +#define YYABORT return(1) +#define YYERROR goto yyerrlab1 +/* Like YYERROR except do call yyerror. + This remains here temporarily to ease the + transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ +#define YYFAIL goto yyerrlab +#define YYRECOVERING() (!!yyerrstatus) +#define YYBACKUP(token, value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { yychar = (token), yylval = (value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { yyerror ("syntax error: cannot back up"); YYERROR; } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +#ifndef YYPURE +#define YYLEX yylex() +#endif + +#ifdef YYPURE +#ifdef YYLSP_NEEDED +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval, &yylloc) +#endif +#else /* not YYLSP_NEEDED */ +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval) +#endif +#endif /* not YYLSP_NEEDED */ +#endif + +/* If nonreentrant, generate the variables here */ + +#ifndef YYPURE + +int yychar; /* the lookahead symbol */ +YYSTYPE yylval; /* the semantic value of the */ + /* lookahead symbol */ + +#ifdef YYLSP_NEEDED +YYLTYPE yylloc; /* location data for the lookahead */ + /* symbol */ +#endif + +int yynerrs; /* number of parse errors so far */ +#endif /* not YYPURE */ + +#if YYDEBUG != 0 +int yydebug; /* nonzero means print parse trace */ +/* Since this is uninitialized, it does not stop multiple parsers + from coexisting. */ +#endif + +/* YYINITDEPTH indicates the initial size of the parser's stacks */ + +#ifndef YYINITDEPTH +#define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH is the maximum size the stacks can grow to + (effective only if the built-in stack extension method is used). */ + +#if YYMAXDEPTH == 0 +#undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 10000 +#endif + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +int yyparse (void); +#endif + +#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ +#define __yy_memcpy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT) +#else /* not GNU C or C++ */ +#ifndef __cplusplus + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (from, to, count) + char *from; + char *to; + int count; +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#else /* __cplusplus */ + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (char *from, char *to, int count) +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#endif +#endif + +#line 192 "/usr/unsupported/share/bison.simple" + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +#else +#define YYPARSE_PARAM +#define YYPARSE_PARAM_DECL +#endif + +int +yyparse(YYPARSE_PARAM) + YYPARSE_PARAM_DECL +{ + register int yystate; + register int yyn; + register short *yyssp; + register YYSTYPE *yyvsp; + int yyerrstatus; /* number of tokens to shift before error messages enabled */ + int yychar1 = 0; /* lookahead token as an internal (translated) token number */ + + short yyssa[YYINITDEPTH]; /* the state stack */ + YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ + + short *yyss = yyssa; /* refer to the stacks thru separate pointers */ + YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ + +#ifdef YYLSP_NEEDED + YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; + +#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#else +#define YYPOPSTACK (yyvsp--, yyssp--) +#endif + + int yystacksize = YYINITDEPTH; + +#ifdef YYPURE + int yychar; + YYSTYPE yylval; + int yynerrs; +#ifdef YYLSP_NEEDED + YYLTYPE yylloc; +#endif +#endif + + YYSTYPE yyval; /* the variable used to return */ + /* semantic values from the action */ + /* routines */ + + int yylen; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Starting parse\n"); +#endif + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss - 1; + yyvsp = yyvs; +#ifdef YYLSP_NEEDED + yylsp = yyls; +#endif + +/* Push a new state, which is found in yystate . */ +/* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. */ +yynewstate: + + *++yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Give user a chance to reallocate the stack */ + /* Use copies of these so that the &'s don't force the real ones into memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; +#ifdef YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; +#endif + + /* Get the current used size of the three stacks, in elements. */ + int size = yyssp - yyss + 1; + +#ifdef yyoverflow + /* Each stack pointer address is followed by the size of + the data in use in that stack, in bytes. */ +#ifdef YYLSP_NEEDED + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yyls1, size * sizeof (*yylsp), + &yystacksize); +#else + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yystacksize); +#endif + + yyss = yyss1; yyvs = yyvs1; +#ifdef YYLSP_NEEDED + yyls = yyls1; +#endif +#else /* no yyoverflow */ + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + { + yyerror("parser stack overflow"); + return 2; + } + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; + yyss = (short *) alloca (yystacksize * sizeof (*yyssp)); + __yy_memcpy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp)); + yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp)); + __yy_memcpy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp)); +#ifdef YYLSP_NEEDED + yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp)); + __yy_memcpy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp)); +#endif +#endif /* no yyoverflow */ + + yyssp = yyss + size - 1; + yyvsp = yyvs + size - 1; +#ifdef YYLSP_NEEDED + yylsp = yyls + size - 1; +#endif + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Stack size increased to %d\n", yystacksize); +#endif + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Entering state %d\n", yystate); +#endif + + goto yybackup; + yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Reading a token: "); +#endif + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Now at end of input.\n"); +#endif + } + else + { + yychar1 = YYTRANSLATE(yychar); + +#if YYDEBUG != 0 + if (yydebug) + { + fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise meaning + of a token, for further debugging info. */ +#ifdef YYPRINT + YYPRINT (stderr, yychar, yylval); +#endif + fprintf (stderr, ")\n"); + } +#endif + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); +#endif + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + /* count tokens shifted since error; after three, turn off error status. */ + if (yyerrstatus) yyerrstatus--; + + yystate = yyn; + goto yynewstate; + +/* Do the default action for the current state. */ +yydefault: + + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + +/* Do a reduction. yyn is the number of a rule to reduce with. */ +yyreduce: + yylen = yyr2[yyn]; + if (yylen > 0) + yyval = yyvsp[1-yylen]; /* implement default value of the action */ + +#if YYDEBUG != 0 + if (yydebug) + { + int i; + + fprintf (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) + fprintf (stderr, "%s ", yytname[yyrhs[i]]); + fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + + + switch (yyn) { + +case 4: +#line 311 "./itbl-parse.y" +{ + DBG (("line %d: entry pnum=%d type=%d name=%s value=x%x\n", + insntbl_line, yyvsp[-4].num, yyvsp[-3].num, yyvsp[-2].str, yyvsp[-1].val)); + itbl_add_reg (yyvsp[-4].num, yyvsp[-3].num, yyvsp[-2].str, yyvsp[-1].val); + ; + break;} +case 5: +#line 317 "./itbl-parse.y" +{ + DBG (("line %d: entry pnum=%d type=INSN name=%s value=x%x", + insntbl_line, yyvsp[-5].num, yyvsp[-3].str, yyvsp[-2].val)); + DBG ((" sbit=%d ebit=%d flags=0x%x\n", sbit, ebit, yyvsp[0].val)); + insn=itbl_add_insn (yyvsp[-5].num, yyvsp[-3].str, yyvsp[-2].val, sbit, ebit, yyvsp[0].val); + ; + break;} +case 12: +#line 336 "./itbl-parse.y" +{ + DBGL2 (("ftype\n")); + yyval.num = yyvsp[0].num; + ; + break;} +case 13: +#line 341 "./itbl-parse.y" +{ + DBGL2 (("addr\n")); + yyval.num = ADDR; + ; + break;} +case 14: +#line 346 "./itbl-parse.y" +{ + DBGL2 (("immed\n")); + yyval.num = IMMED; + ; + break;} +case 15: +#line 354 "./itbl-parse.y" +{ + DBG (("line %d: field type=%d sbit=%d ebit=%d, flags=0x%x\n", + insntbl_line, yyvsp[-2].num, sbit, ebit, yyvsp[0].val)); + itbl_add_operand (insn, yyvsp[-2].num, sbit, ebit, yyvsp[0].val); + ; + break;} +case 16: +#line 363 "./itbl-parse.y" +{ + yyval.val = yyvsp[-2].num | yyvsp[0].val; + ; + break;} +case 17: +#line 367 "./itbl-parse.y" +{ + yyval.val = yyvsp[-1].val; + ; + break;} +case 18: +#line 371 "./itbl-parse.y" +{ + yyval.val = yyvsp[0].num; + ; + break;} +case 19: +#line 378 "./itbl-parse.y" +{ + DBGL2 (("flags=%d\n", yyvsp[0].val)); + yyval.val = yyvsp[0].val; + ; + break;} +case 20: +#line 383 "./itbl-parse.y" +{ + yyval.val = 0; + ; + break;} +case 21: +#line 390 "./itbl-parse.y" +{ + DBGL2 (("range %d %d\n", yyvsp[-2].num, yyvsp[0].num)); + sbit = yyvsp[-2].num; + ebit = yyvsp[0].num; + ; + break;} +case 22: +#line 396 "./itbl-parse.y" +{ + sbit = 31; + ebit = 0; + ; + break;} +case 23: +#line 404 "./itbl-parse.y" +{ + DBGL2 (("pnum=%d\n",yyvsp[0].num)); + yyval.num = yyvsp[0].num; + ; + break;} +case 24: +#line 412 "./itbl-parse.y" +{ + DBGL2 (("dreg\n")); + yyval.num = DREG; + ; + break;} +case 25: +#line 417 "./itbl-parse.y" +{ + DBGL2 (("creg\n")); + yyval.num = CREG; + ; + break;} +case 26: +#line 422 "./itbl-parse.y" +{ + DBGL2 (("greg\n")); + yyval.num = GREG; + ; + break;} +case 27: +#line 430 "./itbl-parse.y" +{ + DBGL2 (("name=%s\n",yyvsp[0].str)); + yyval.str = yyvsp[0].str; + ; + break;} +case 28: +#line 438 "./itbl-parse.y" +{ + DBGL2 (("num=%d\n",yyvsp[0].num)); + yyval.num = yyvsp[0].num; + ; + break;} +case 29: +#line 446 "./itbl-parse.y" +{ + DBGL2 (("val=x%x\n",yyvsp[0].num)); + yyval.val = yyvsp[0].num; + ; + break;} +} + /* the action file gets copied in in place of this dollarsign */ +#line 487 "/usr/unsupported/share/bison.simple" + + yyvsp -= yylen; + yyssp -= yylen; +#ifdef YYLSP_NEEDED + yylsp -= yylen; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; + +#ifdef YYLSP_NEEDED + yylsp++; + if (yylen == 0) + { + yylsp->first_line = yylloc.first_line; + yylsp->first_column = yylloc.first_column; + yylsp->last_line = (yylsp-1)->last_line; + yylsp->last_column = (yylsp-1)->last_column; + yylsp->text = 0; + } + else + { + yylsp->last_line = (yylsp+yylen-1)->last_line; + yylsp->last_column = (yylsp+yylen-1)->last_column; + } +#endif + + /* Now "shift" the result of the reduction. + Determine what state that goes to, + based on the state we popped back to + and the rule number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + +yyerrlab: /* here on detecting error */ + + if (! yyerrstatus) + /* If not already recovering from an error, report this error. */ + { + ++yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + int size = 0; + char *msg; + int x, count; + + count = 0; + /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + size += strlen(yytname[x]) + 15, count++; + msg = (char *) malloc(size + 15); + if (msg != 0) + { + strcpy(msg, "parse error"); + + if (count < 5) + { + count = 0; + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + { + strcat(msg, count == 0 ? ", expecting `" : " or `"); + strcat(msg, yytname[x]); + strcat(msg, "'"); + count++; + } + } + yyerror(msg); + free(msg); + } + else + yyerror ("parse error; also virtual memory exceeded"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror("parse error"); + } + + goto yyerrlab1; +yyerrlab1: /* here on error raised explicitly by an action */ + + if (yyerrstatus == 3) + { + /* if just tried and failed to reuse lookahead token after an error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); +#endif + + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token + after shifting the error token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + +yyerrdefault: /* current state does not do anything special for the error token. */ + +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ + if (yyn) goto yydefault; +#endif + +yyerrpop: /* pop the current state because it cannot handle the error token */ + + if (yyssp == yyss) YYABORT; + yyvsp--; + yystate = *--yyssp; +#ifdef YYLSP_NEEDED + yylsp--; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "Error: state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + +yyerrhandle: + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting error token, "); +#endif + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + yystate = yyn; + goto yynewstate; +} +#line 451 "./itbl-parse.y" + + +static int +yyerror (msg) + const char *msg; +{ + printf ("line %d: %s\n", insntbl_line, msg); + return 0; +} diff --git a/gnu/usr.bin/binutils/gas/itbl-parse.h b/gnu/usr.bin/binutils/gas/itbl-parse.h new file mode 100644 index 00000000000..4c05839448c --- /dev/null +++ b/gnu/usr.bin/binutils/gas/itbl-parse.h @@ -0,0 +1,20 @@ +typedef union + { + char *str; + int num; + int processor; + unsigned long val; + } YYSTYPE; +#define DREG 258 +#define CREG 259 +#define GREG 260 +#define IMMED 261 +#define ADDR 262 +#define INSN 263 +#define NUM 264 +#define ID 265 +#define NL 266 +#define PNUM 267 + + +extern YYSTYPE yylval; diff --git a/gnu/usr.bin/binutils/gas/itbl-parse.y b/gnu/usr.bin/binutils/gas/itbl-parse.y new file mode 100644 index 00000000000..7966ee8fe1b --- /dev/null +++ b/gnu/usr.bin/binutils/gas/itbl-parse.y @@ -0,0 +1,459 @@ +/* itbl-parse.y + Copyright (C) 1997 Free Software Foundation, Inc. + + This file is part of GAS, the GNU Assembler. + + GAS 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 2, or (at your option) + any later version. + + GAS 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 GAS; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +%{ + +/* + +Yacc grammar for instruction table entries. + +======================================================================= +Original Instruction table specification document: + + MIPS Coprocessor Table Specification + ==================================== + +This document describes the format of the MIPS coprocessor table. The +table specifies a list of valid functions, data registers and control +registers that can be used in coprocessor instructions. This list, +together with the coprocessor instruction classes listed below, +specifies the complete list of coprocessor instructions that will +be recognized and assembled by the GNU assembler. In effect, +this makes the GNU assembler table-driven, where the table is +specified by the programmer. + +The table is an ordinary text file that the GNU assembler reads when +it starts. Using the information in the table, the assembler +generates an internal list of valid coprocessor registers and +functions. The assembler uses this internal list in addition to the +standard MIPS registers and instructions which are built-in to the +assembler during code generation. + +To specify the coprocessor table when invoking the GNU assembler, use +the command line option "--itbl file", where file is the +complete name of the table, including path and extension. + +Examples: + + gas -t cop.tbl test.s -o test.o + gas -t /usr/local/lib/cop.tbl test.s -o test.o + gas --itbl d:\gnu\data\cop.tbl test.s -o test.o + +Only one table may be supplied during a single invocation of +the assembler. + + +Instruction classes +=================== + +Below is a list of the valid coprocessor instruction classes for +any given coprocessor "z". These instructions are already recognized +by the assembler, and are listed here only for reference. + +Class format instructions +------------------------------------------------- +Class1: + op base rt offset + LWCz rt,offset (base) + SWCz rt,offset (base) +Class2: + COPz sub rt rd 0 + MTCz rt,rd + MFCz rt,rd + CTCz rt,rd + CFCz rt,rd +Class3: + COPz CO cofun + COPz cofun +Class4: + COPz BC br offset + BCzT offset + BCzF offset +Class5: + COPz sub rt rd 0 + DMFCz rt,rd + DMTCz rt,rd +Class6: + op base rt offset + LDCz rt,offset (base) + SDCz rt,offset (base) +Class7: + COPz BC br offset + BCzTL offset + BCzFL offset + +The coprocessor table defines coprocessor-specific registers that can +be used with all of the above classes of instructions, where +appropriate. It also defines additional coprocessor-specific +functions for Class3 (COPz cofun) instructions, Thus, the table allows +the programmer to use convenient mnemonics and operands for these +functions, instead of the COPz mmenmonic and cofun operand. + +The names of the MIPS general registers and their aliases are defined +by the assembler and will be recognized as valid register names by the +assembler when used (where allowed) in coprocessor instructions. +However, the names and values of all coprocessor data and control +register mnemonics must be specified in the coprocessor table. + + +Table Grammar +============= + +Here is the grammar for the coprocessor table: + + table -> entry* + + entry -> [z entrydef] [comment] '\n' + + entrydef -> type name val + entrydef -> 'insn' name val funcdef ; type of entry (instruction) + + z -> 'p'['0'..'3'] ; processor number + type -> ['dreg' | 'creg' | 'greg' ] ; type of entry (register) + ; 'dreg', 'creg' or 'greg' specifies a data, control, or general + ; register mnemonic, respectively + name -> [ltr|dec]* ; mnemonic of register/function + val -> [dec|hex] ; register/function number (integer constant) + + funcdef -> frange flags fields + ; bitfield range for opcode + ; list of fields' formats + fields -> field* + field -> [','] ftype frange flags + flags -> ['*' flagexpr] + flagexpr -> '[' flagexpr ']' + flagexpr -> val '|' flagexpr + ftype -> [ type | 'immed' | 'addr' ] + ; 'immed' specifies an immediate value; see grammar for "val" above + ; 'addr' specifies a C identifier; name of symbol to be resolved at + ; link time + frange -> ':' val '-' val ; starting to ending bit positions, where + ; where 0 is least significant bit + frange -> (null) ; default range of 31-0 will be assumed + + comment -> [';'|'#'] [char]* + char -> any printable character + ltr -> ['a'..'z'|'A'..'Z'] + dec -> ['0'..'9']* ; value in decimal + hex -> '0x'['0'..'9' | 'a'..'f' | 'A'..'F']* ; value in hexidecimal + + +Examples +======== + +Example 1: + +The table: + + p1 dreg d1 1 ; data register "d1" for COP1 has value 1 + p1 creg c3 3 ; ctrl register "c3" for COP1 has value 3 + p3 func fill 0x1f:24-20 ; function "fill" for COP3 has value 31 and + ; no fields + +will allow the assembler to accept the following coprocessor instructions: + + LWC1 d1,0x100 ($2) + fill + +Here, the general purpose register "$2", and instruction "LWC1", are standard +mnemonics built-in to the MIPS assembler. + + +Example 2: + +The table: + + p3 dreg d3 3 ; data register "d3" for COP3 has value 3 + p3 creg c2 22 ; control register "c2" for COP3 has value 22 + p3 func fee 0x1f:24-20 dreg:17-13 creg:12-8 immed:7-0 + ; function "fee" for COP3 has value 31, and 3 fields + ; consisting of a data register, a control register, + ; and an immediate value. + +will allow the assembler to accept the following coprocessor instruction: + + fee d3,c2,0x1 + +and will emit the object code: + + 31-26 25 24-20 19-18 17-13 12-8 7-0 + COPz CO fun dreg creg immed + 010011 1 11111 00 00011 10110 00000001 + + 0x4ff07601 + + +Example 3: + +The table: + + p3 dreg d3 3 ; data register "d3" for COP3 has value 3 + p3 creg c2 22 ; control register "c2" for COP3 has value 22 + p3 func fuu 0x01f00001 dreg:17-13 creg:12-8 + +will allow the assembler to accept the following coprocessor +instruction: + + fuu d3,c2 + +and will emit the object code: + + 31-26 25 24-20 19-18 17-13 12-8 7-0 + COPz CO fun dreg creg + 010011 1 11111 00 00011 10110 00000001 + + 0x4ff07601 + +In this way, the programmer can force arbitrary bits of an instruction +to have predefined values. + +======================================================================= +Additional notes: + +Encoding of ranges: +To handle more than one bit position range within an instruction, +use 0s to mask out the ranges which don't apply. +May decide to modify the syntax to allow commas separate multiple +ranges within an instruction (range','range). + +Changes in grammar: + The number of parms argument to the function entry +was deleted from the original format such that we now count the fields. + +---- +FIXME! should really change lexical analyzer +to recognize 'dreg' etc. in context sensative way. +Currently function names or mnemonics may be incorrectly parsed as keywords + +FIXME! hex is ambiguous with any digit + +*/ + +#include <stdio.h> +#include "itbl-ops.h" + +/* #define DEBUG */ + +#ifdef DEBUG +#ifndef DBG_LVL +#define DBG_LVL 1 +#endif +#else +#define DBG_LVL 0 +#endif + +#if DBG_LVL >= 1 +#define DBG(x) printf x +#else +#define DBG(x) +#endif + +#if DBG_LVL >= 2 +#define DBGL2(x) printf x +#else +#define DBGL2(x) +#endif + +static int sbit, ebit; +static struct itbl_entry *insn=0; +extern int insntbl_line; +int yyparse PARAMS ((void)); +int yylex PARAMS ((void)); +static int yyerror PARAMS ((const char *)); + +%} + +%union + { + char *str; + int num; + int processor; + unsigned long val; + } + +%token DREG CREG GREG IMMED ADDR INSN NUM ID NL PNUM +%type <val> value flags flagexpr +%type <num> number NUM ftype regtype pnum PNUM +%type <str> ID name + +%start insntbl + +%% + +insntbl: + entrys + ; + +entrys: + entry entrys + | + ; + +entry: + pnum regtype name value NL + { + DBG (("line %d: entry pnum=%d type=%d name=%s value=x%x\n", + insntbl_line, $1, $2, $3, $4)); + itbl_add_reg ($1, $2, $3, $4); + } + | pnum INSN name value range flags + { + DBG (("line %d: entry pnum=%d type=INSN name=%s value=x%x", + insntbl_line, $1, $3, $4)); + DBG ((" sbit=%d ebit=%d flags=0x%x\n", sbit, ebit, $6)); + insn=itbl_add_insn ($1, $3, $4, sbit, ebit, $6); + } + fieldspecs NL + | NL + | error NL + ; + +fieldspecs: + ',' fieldspec fieldspecs + | fieldspec fieldspecs + | + ; + +ftype: + regtype + { + DBGL2 (("ftype\n")); + $$ = $1; + } + | ADDR + { + DBGL2 (("addr\n")); + $$ = ADDR; + } + | IMMED + { + DBGL2 (("immed\n")); + $$ = IMMED; + } + ; + +fieldspec: + ftype range flags + { + DBG (("line %d: field type=%d sbit=%d ebit=%d, flags=0x%x\n", + insntbl_line, $1, sbit, ebit, $3)); + itbl_add_operand (insn, $1, sbit, ebit, $3); + } + ; + +flagexpr: + NUM '|' flagexpr + { + $$ = $1 | $3; + } + | '[' flagexpr ']' + { + $$ = $2; + } + | NUM + { + $$ = $1; + } + ; + +flags: + '*' flagexpr + { + DBGL2 (("flags=%d\n", $2)); + $$ = $2; + } + | + { + $$ = 0; + } + ; + +range: + ':' NUM '-' NUM + { + DBGL2 (("range %d %d\n", $2, $4)); + sbit = $2; + ebit = $4; + } + | + { + sbit = 31; + ebit = 0; + } + ; + +pnum: + PNUM + { + DBGL2 (("pnum=%d\n",$1)); + $$ = $1; + } + ; + +regtype: + DREG + { + DBGL2 (("dreg\n")); + $$ = DREG; + } + | CREG + { + DBGL2 (("creg\n")); + $$ = CREG; + } + | GREG + { + DBGL2 (("greg\n")); + $$ = GREG; + } + ; + +name: + ID + { + DBGL2 (("name=%s\n",$1)); + $$ = $1; + } + ; + +number: + NUM + { + DBGL2 (("num=%d\n",$1)); + $$ = $1; + } + ; + +value: + NUM + { + DBGL2 (("val=x%x\n",$1)); + $$ = $1; + } + ; +%% + +static int +yyerror (msg) + const char *msg; +{ + printf ("line %d: %s\n", insntbl_line, msg); + return 0; +} diff --git a/gnu/usr.bin/binutils/gas/makefile.vms b/gnu/usr.bin/binutils/gas/makefile.vms index c9d4d7e5227..4996135baf6 100644 --- a/gnu/usr.bin/binutils/gas/makefile.vms +++ b/gnu/usr.bin/binutils/gas/makefile.vms @@ -1,22 +1,20 @@ # # makefile for gas # -# Created by Klaus Kämpf, kkaempf@progis.de +# Created by Klaus K"ampf, kkaempf@progis.de # -CC=gcc - ifeq ($(CC),gcc) DEFS= CFLAGS=/include=([],[-.bfd],[.config],[-.include],[-])$(DEFS) LFLAGS= -LIBS=,GNU_CC:[000000]LIBGCC2/lib,GNU_CC:[000000]LIBGCCLIB/lib,\ - sys$$library:vaxcrtl.olb/lib,GNU_CC:[000000]crt0.obj +LIBS=,GNU:[000000]libgcc/lib,sys$$library:vaxcrtl.olb/lib,GNU:[000000]crt0.obj else DEFS=/define=("table_size_of_flonum_powers_of_ten"="tabsiz_flonum_powers_of_ten",\ "_bfd_generic_get_section_contents_in_window"="_bfd_generic_get_win_section_cont",\ "_elf_section_from_bfd_section"="_bfd_elf_sec_from_bfd_sec","const=") -CFLAGS=/noopt/debug/include=([],[-.bfd],[.config],[-.include],[-])$(DEFS) +CFLAGS=/noopt/debug/include=([],[-.bfd],[.config],[-.include],[-])$(DEFS)\ +/warnings=disable=(missingreturn,implicitfunc,ptrmismatch,undefescap,longextern,duptypespec) LFLAGS= LIBS= endif @@ -27,16 +25,22 @@ OBJS=targ-cpu.obj,obj-format.obj,atof-targ.obj,app.obj,as.obj,atof-generic.obj,\ literal.obj,messages.obj,output-file.obj,read.obj,subsegs.obj,symbols.obj,\ write.obj,listing.obj,ecoff.obj,stabs.obj,sb.obj,macro.obj +GASPOBJS = gasp.obj,macro.obj,sb.obj,hash.obj + LIBIBERTY = [-.libiberty]libiberty.olb LIBBFD = [-.bfd]libbfd.olb LIBOPCODES = [-.opcodes]libopcodes.olb +all: config.status [-.bfd]bfd.h as.exe gasp.exe as.exe: $(OBJS) $(LIBOPCODES) $(LIBBFD) $(LIBIBERTY) link$(LFLAGS)/exe=$@ $(OBJS),$(LIBOPCODES)/lib,$(LIBBFD)/lib,$(LIBIBERTY)/lib$(LIBS) -gasp.exe: gasp.obj $(LIBBFD) $(LIBIBERTY) - link$(LFLAGS)/exe=$@ gasp.obj,$(LIBBFD)/lib,$(LIBIBERTY)/lib$(LIBS) +gasp.exe: $(GASPOBJS) $(LIBBFD) $(LIBIBERTY) + link$(LFLAGS)/exe=$@ $(GASPOBJS),$(LIBBFD)/lib,$(LIBIBERTY)/lib$(LIBS) + +config.status: + $$ @config-gas targ-cpu.c: [.config]tc-alpha.c copy $< $@ @@ -52,3 +56,20 @@ atof-targ.c: [.config]atof-ieee.c copy $< $@ targ-cpu.obj: targ-cpu.c targ-cpu.h [.config]atof-vax.c + +[-.bfd]bfd.h: + $(CD) [-.bfd] + gmake -f makefile.vms + $(CD) [-.gas] + +clean: + $$ purge + $(RM) *.obj; + $(RM) *.exe; + $(RM) atof-targ.c; + $(RM) obj-format.c; + $(RM) obj-format.h; + $(RM) targ-env.h; + $(RM) targ-cpu.h; + $(RM) targ-cpu.c; + $(RM) config.status; diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/all/align.d b/gnu/usr.bin/binutils/gas/testsuite/gas/all/align.d new file mode 100644 index 00000000000..86ede6186a9 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/all/align.d @@ -0,0 +1,12 @@ +#objdump: -s -j .text +#name: align + +# Test the alignment pseudo-op. + +.*: .* + +Contents of section .text: + 0000 ff00ff01 ff020202 ffff0303 04040404 ................ + 0010 ffffffff 05050505 ff090a0a 0a0a0a0a ................ + 0020 ff00ff01 ff020202 ffff0303 04040404 ................ + 0030 ffffffff 05050505 ff090a0a 0a0a0a0a ................ diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/all/align.s b/gnu/usr.bin/binutils/gas/testsuite/gas/all/align.s new file mode 100644 index 00000000000..9ccca130cc0 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/all/align.s @@ -0,0 +1,61 @@ +/* Test the alignment pseudo-ops. */ + .text + + .byte 0xff + .p2align 1,0 + + .byte 0xff + .p2align 1,1 + + .byte 0xff + .p2align 2,2 + + .byte 0xff + .byte 0xff + .p2alignw 2,0x0303 + + .p2align 3,4 + .byte 0xff + .byte 0xff + .byte 0xff + .byte 0xff + .p2alignl 3,0x05050505 + + .p2align 1,6 + .p2align 1,7 + + .byte 0xff + .p2align 3,8,5 + .byte 9 + .p2align 3,0xa + + .byte 0xff + .balign 2,0 + + .byte 0xff + .balign 2,1 + + .byte 0xff + .balign 4,2 + + .byte 0xff + .byte 0xff + .balignw 4,0x0303 + + .balign 8,4 + .byte 0xff + .byte 0xff + .byte 0xff + .byte 0xff + .balignl 8,0x05050505 + + .balign 2,6 + .balign 2,7 + + .byte 0xff + .balign 8,8,5 + .byte 9 + .balign 8,0xa + + .p2align 5 + .balign 32 diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/all/cond.d b/gnu/usr.bin/binutils/gas/testsuite/gas/all/cond.d new file mode 100644 index 00000000000..4ee3942efb8 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/all/cond.d @@ -0,0 +1,20 @@ +# This should match the output of gas -alc cond.s. + +.*cond.s.* + + + 1[ ]+.if 0 + 8[ ]+.else + 9[ ]+.if 1 + 10[ ]+.endc + 11 0000 0[02]00 ?000[02][ ]+.long[ ]+2 + 12[ ]+.if 0 + 14[ ]+.else + 15 0004 0[04]00 ?000[04][ ]+.long[ ]+4 + 16[ ]+.endc + 17[ ]+.endc + 18 0008 0000 ?0000[ ]+.p2align 5,0 + 18[ ]+0000 ?0000 + 18[ ]+0000 ?0000 + 18[ ]+0000 ?0000 + 18[ ]+0000 ?0000 diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/all/cond.s b/gnu/usr.bin/binutils/gas/testsuite/gas/all/cond.s new file mode 100644 index 00000000000..39583211e6f --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/all/cond.s @@ -0,0 +1,18 @@ + .if 0 + .if 1 + .endc + .long 0 + .if 0 + .long 1 + .endc + .else + .if 1 + .endc + .long 2 + .if 0 + .long 3 + .else + .long 4 + .endc + .endc + .p2align 5,0 diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/all/itbl b/gnu/usr.bin/binutils/gas/testsuite/gas/all/itbl new file mode 100644 index 00000000000..ac66dfbfe46 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/all/itbl @@ -0,0 +1,20 @@ + + ; Test case for assembler option "itbl". + ; Run as "as --itbl itbl itbl.s" + ; or with stand-alone test case "itbl-test itbl itbl.s". + ; The "p<n>" represent processors of a multi-processor system. + + p1 dreg d1 1 ; data register "d1" for COP1 has value 1 + p1 creg c3 3 ; ctrl register "c3" for COP1 has value 3 + p3 insn fie 0x1e:24-20 ; function "fill" for COP3 has value 31 + p3 dreg d3 3 ; data register "d3" for COP3 has value 3 + p3 creg c2 22 ; control register "c2" for COP3 has value 22 + p3 insn fee 0x1e:24-20,dreg:17-13,creg:12-8,immed:7-0 + + p3 dreg d3 3 ; data register "d3" for COP3 has value 3 + p3 creg c2 22 ; control register "c2" for COP3 has value 22 + p3 insn fum 0x01e00001 dreg:17-13 creg:12-8 + p3 insn foh 0xf:24-21 dreg:20-16 immed:15-0 + + p3 insn pig 0x1:24-21*[0x100|0x2], dreg:20-16, immed:15-0*0x10000 + diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/all/itbl-test.c b/gnu/usr.bin/binutils/gas/testsuite/gas/all/itbl-test.c new file mode 100644 index 00000000000..023f5d95bee --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/all/itbl-test.c @@ -0,0 +1,129 @@ + + +/* itbl-test.c + + Copyright (C) 1997 Free Software Foundation, Inc. + + This file is part of GAS, the GNU Assembler. + + GAS 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 2, or (at your option) + any later version. + + GAS 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 GAS; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* Stand-alone test for instruction specification table support. + Run using "itbl-test <itbl> <asm.s>" + where <itbl> is the name of the instruction table, + and <asm.s> is the name of the assembler fie. */ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "itbl-ops.h" + +static int test_reg (e_processor processor, e_type type, char *name, + unsigned long val); + +int +main (int argc, char **argv) +{ + unsigned int insn; + FILE *fas; + int aline = 0; + char s[81], *name; + + if (argc < 3) + { + printf ("usage: %s itbl asm.s\n", argv[0]); + exit (0); + } + if (itbl_parse (argv[1]) != 0) + { + printf ("failed to parse itbl\n"); + exit (0); + } + + fas = fopen (argv[2], "r"); + if (fas == 0) + { + printf ("failed to open asm file %s\n", argv[2]); + exit (0); + } + while (fgets (s, 80, fas)) + { + char *p; + aline++; + + if (p = strchr (s, ';'), p) /* strip comments */ + *p = 0; + if (p = strchr (s, '#'), p) /* strip comments */ + *p = 0; + p = s + strlen (s) - 1; + while (p >= s && (*p == ' ' || *p == '\t' || *p == '\n')) /* strip trailing spaces */ + p--; + *(p + 1) = 0; + p = s; + while (*p && (*p == ' ' || *p == '\t' || *p == '\n')) /* strip leading spaces */ + p++; + if (!*p) + continue; + + name = itbl_get_field (&p); + insn = itbl_assemble (name, p); + if (insn == 0) + printf ("line %d: Invalid instruction (%s)\n", aline, s); + else + { + char buf[128]; + printf ("line %d: insn(%s) = 0x%x)\n", aline, s, insn); + if (!itbl_disassemble (buf, insn)) + printf ("line %d: Can't disassemble instruction " + "(0x%x)\n", aline, insn); + else + printf ("line %d: disasm(0x%x) = %s)\n", aline, insn, buf); + } + } + + test_reg (1, e_dreg, "d1", 1); + test_reg (3, e_creg, "c2", 22); + test_reg (3, e_dreg, "d3", 3); + + return 0; +} + +static int +test_reg (e_processor processor, e_type type, char *name, + unsigned long val) +{ + char *n; + unsigned long v; + + n = itbl_get_name (processor, type, val); + if (!n || strcmp (n, name)) + printf ("Error - reg name not found for proessor=%d, type=%d, val=%d\n", + processor, type, val); + else + printf ("name=%s found for processor=%d, type=%d, val=%d\n", + n, processor, type, val); + + /* We require that names be unique amoung processors and types. */ + v = itbl_get_reg_val (name); + if (!v || v != val) + printf ("Error - reg val not found for processor=%d, type=%d, name=%s\n", + processor, type, name); + else + printf ("val=0x%x found for processor=%d, type=%d, name=%s\n", + v, processor, type, name); + return 0; +} diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/all/itbl.s b/gnu/usr.bin/binutils/gas/testsuite/gas/all/itbl.s new file mode 100644 index 00000000000..9351aa4bb3c --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/all/itbl.s @@ -0,0 +1,13 @@ + + ; Test case for assembler option "itbl". + ; Run as "as --itbl itbl itbl.s" + ; or with stand-alone test case "itbl-test itbl itbl.s". + + ; Assemble processor instructions as defined in "itbl". + + fee $d3,$c2,0x1 ; 0x4ff07601 + fie ; 0x4ff00000 + foh $2,0x100 + fum $d3,$c2 ; 0x4ff07601 + pig $2,0x100 + diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/m32r/allinsn.d b/gnu/usr.bin/binutils/gas/testsuite/gas/m32r/allinsn.d new file mode 100644 index 00000000000..158ab9f4aad --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/m32r/allinsn.d @@ -0,0 +1,377 @@ +#as: +#objdump: -dr +#name: allinsn + +.*: +file format .* + +Disassembly of section .text: + +00000000 <add>: + 0: 0d ad f0 00 add fp,fp || nop + +00000004 <add3>: + 4: 8d ad 00 00 add3 fp,fp,0 + +00000008 <and>: + 8: 0d cd f0 00 and fp,fp || nop + +0000000c <and3>: + c: 8d cd 00 00 and3 fp,fp,0x0 + +00000010 <or>: + 10: 0d ed f0 00 or fp,fp || nop + +00000014 <or3>: + 14: 8d ed 00 00 or3 fp,fp,0x0 + +00000018 <xor>: + 18: 0d dd f0 00 xor fp,fp || nop + +0000001c <xor3>: + 1c: 8d dd 00 00 xor3 fp,fp,0x0 + +00000020 <addi>: + 20: 4d 00 f0 00 addi fp,0 || nop + +00000024 <addv>: + 24: 0d 8d f0 00 addv fp,fp || nop + +00000028 <addv3>: + 28: 8d 8d 00 00 addv3 fp,fp,0 + +0000002c <addx>: + 2c: 0d 9d f0 00 addx fp,fp || nop + +00000030 <bc8>: + 30: 7c f4 f0 00 bc 0 <add> || nop + +00000034 <bc8_s>: + 34: 7c f3 f0 00 bc 0 <add> || nop + +00000038 <bc24>: + 38: 7c f2 f0 00 bc 0 <add> || nop + +0000003c <bc24_l>: + 3c: fc ff ff f1 bc 0 <add> + +00000040 <beq>: + 40: bd 0d ff f0 beq fp,fp,0 <add> + +00000044 <beqz>: + 44: b0 8d ff ef beqz fp,0 <add> + +00000048 <bgez>: + 48: b0 bd ff ee bgez fp,0 <add> + +0000004c <bgtz>: + 4c: b0 dd ff ed bgtz fp,0 <add> + +00000050 <blez>: + 50: b0 cd ff ec blez fp,0 <add> + +00000054 <bltz>: + 54: b0 ad ff eb bltz fp,0 <add> + +00000058 <bnez>: + 58: b0 9d ff ea bnez fp,0 <add> + +0000005c <bl8>: + 5c: 7e e9 f0 00 bl 0 <add> || nop + +00000060 <bl8_s>: + 60: 7e e8 f0 00 bl 0 <add> || nop + +00000064 <bl24>: + 64: 7e e7 f0 00 bl 0 <add> || nop + +00000068 <bl24_l>: + 68: fe ff ff e6 bl 0 <add> + +0000006c <bnc8>: + 6c: 7d e5 f0 00 bnc 0 <add> || nop + +00000070 <bnc8_s>: + 70: 7d e4 f0 00 bnc 0 <add> || nop + +00000074 <bnc24>: + 74: 7d e3 f0 00 bnc 0 <add> || nop + +00000078 <bnc24_l>: + 78: fd ff ff e2 bnc 0 <add> + +0000007c <bne>: + 7c: bd 1d ff e1 bne fp,fp,0 <add> + +00000080 <bra8>: + 80: 7f e0 f0 00 bra 0 <add> || nop + +00000084 <bra8_s>: + 84: 7f df f0 00 bra 0 <add> || nop + +00000088 <bra24>: + 88: 7f de f0 00 bra 0 <add> || nop + +0000008c <bra24_l>: + 8c: ff ff ff dd bra 0 <add> + +00000090 <cmp>: + 90: 0d 4d f0 00 cmp fp,fp || nop + +00000094 <cmpi>: + 94: 80 4d 00 00 cmpi fp,0 + +00000098 <cmpu>: + 98: 0d 5d f0 00 cmpu fp,fp || nop + +0000009c <cmpui>: + 9c: 80 5d 00 00 cmpui fp,0 + +000000a0 <div>: + a0: 9d 0d 00 00 div fp,fp + +000000a4 <divu>: + a4: 9d 1d 00 00 divu fp,fp + +000000a8 <rem>: + a8: 9d 2d 00 00 rem fp,fp + +000000ac <remu>: + ac: 9d 3d 00 00 remu fp,fp + +000000b0 <jl>: + b0: 1e cd f0 00 jl fp || nop + +000000b4 <jmp>: + b4: 1f cd f0 00 jmp fp || nop + +000000b8 <ld>: + b8: 2d cd f0 00 ld fp,@fp || nop + +000000bc <ld_2>: + bc: 2d cd f0 00 ld fp,@fp || nop + +000000c0 <ld_d>: + c0: ad cd 00 00 ld fp,@\(0,fp\) + +000000c4 <ld_d2>: + c4: ad cd 00 00 ld fp,@\(0,fp\) + +000000c8 <ldb>: + c8: 2d 8d f0 00 ldb fp,@fp || nop + +000000cc <ldb_2>: + cc: 2d 8d f0 00 ldb fp,@fp || nop + +000000d0 <ldb_d>: + d0: ad 8d 00 00 ldb fp,@\(0,fp\) + +000000d4 <ldb_d2>: + d4: ad 8d 00 00 ldb fp,@\(0,fp\) + +000000d8 <ldh>: + d8: 2d ad f0 00 ldh fp,@fp || nop + +000000dc <ldh_2>: + dc: 2d ad f0 00 ldh fp,@fp || nop + +000000e0 <ldh_d>: + e0: ad ad 00 00 ldh fp,@\(0,fp\) + +000000e4 <ldh_d2>: + e4: ad ad 00 00 ldh fp,@\(0,fp\) + +000000e8 <ldub>: + e8: 2d 9d f0 00 ldub fp,@fp || nop + +000000ec <ldub_2>: + ec: 2d 9d f0 00 ldub fp,@fp || nop + +000000f0 <ldub_d>: + f0: ad 9d 00 00 ldub fp,@\(0,fp\) + +000000f4 <ldub_d2>: + f4: ad 9d 00 00 ldub fp,@\(0,fp\) + +000000f8 <lduh>: + f8: 2d bd f0 00 lduh fp,@fp || nop + +000000fc <lduh_2>: + fc: 2d bd f0 00 lduh fp,@fp || nop + +00000100 <lduh_d>: + 100: ad bd 00 00 lduh fp,@\(0,fp\) + +00000104 <lduh_d2>: + 104: ad bd 00 00 lduh fp,@\(0,fp\) + +00000108 <ld_plus>: + 108: 2d ed f0 00 ld fp,@fp\+ || nop + +0000010c <ld24>: + 10c: ed 00 00 00 ld24 fp,0 <add> + 10c: R_M32R_24 .data + +00000110 <ldi8>: + 110: 6d 00 f0 00 ldi fp,0 || nop + +00000114 <ldi8a>: + 114: 6d 00 f0 00 ldi fp,0 || nop + +00000118 <ldi16>: + 118: 6d 00 f0 00 ldi fp,0 || nop + +0000011c <ldi16a>: + 11c: 9d f0 00 00 ldi fp,0 + +00000120 <lock>: + 120: 2d dd f0 00 lock fp,@fp || nop + +00000124 <machi>: + 124: 3d 4d f0 00 machi fp,fp || nop + +00000128 <maclo>: + 128: 3d 5d f0 00 maclo fp,fp || nop + +0000012c <macwhi>: + 12c: 3d 6d f0 00 macwhi fp,fp || nop + +00000130 <macwlo>: + 130: 3d 7d f0 00 macwlo fp,fp || nop + +00000134 <mul>: + 134: 1d 6d f0 00 mul fp,fp || nop + +00000138 <mulhi>: + 138: 3d 0d f0 00 mulhi fp,fp || nop + +0000013c <mullo>: + 13c: 3d 1d f0 00 mullo fp,fp || nop + +00000140 <mulwhi>: + 140: 3d 2d f0 00 mulwhi fp,fp || nop + +00000144 <mulwlo>: + 144: 3d 3d f0 00 mulwlo fp,fp || nop + +00000148 <mv>: + 148: 1d 8d f0 00 mv fp,fp || nop + +0000014c <mvfachi>: + 14c: 5d f0 f0 00 mvfachi fp || nop + +00000150 <mvfaclo>: + 150: 5d f1 f0 00 mvfaclo fp || nop + +00000154 <mvfacmi>: + 154: 5d f2 f0 00 mvfacmi fp || nop + +00000158 <mvfc>: + 158: 1d 90 f0 00 mvfc fp,psw || nop + +0000015c <mvtachi>: + 15c: 5d 70 f0 00 mvtachi fp || nop + +00000160 <mvtaclo>: + 160: 5d 71 f0 00 mvtaclo fp || nop + +00000164 <mvtc>: + 164: 10 ad f0 00 mvtc fp,psw || nop + +00000168 <neg>: + 168: 0d 3d f0 00 neg fp,fp || nop + +0000016c <nop>: + 16c: 0d bd f0 00 not fp,fp || nop + +00000170 <rac>: + 170: dd c0 00 00 seth fp,0x0 + +00000174 <sll>: + 174: 1d 4d f0 00 sll fp,fp || nop + +00000178 <sll3>: + 178: 9d cd 00 00 sll3 fp,fp,0 + +0000017c <slli>: + 17c: 5d 40 f0 00 slli fp,0x0 || nop + +00000180 <sra>: + 180: 1d 2d f0 00 sra fp,fp || nop + +00000184 <sra3>: + 184: 9d ad 00 00 sra3 fp,fp,0 + +00000188 <srai>: + 188: 5d 20 f0 00 srai fp,0x0 || nop + +0000018c <srl>: + 18c: 1d 0d f0 00 srl fp,fp || nop + +00000190 <srl3>: + 190: 9d 8d 00 00 srl3 fp,fp,0 + +00000194 <srli>: + 194: 5d 00 f0 00 srli fp,0x0 || nop + +00000198 <st>: + 198: 2d 4d f0 00 st fp,@fp || nop + +0000019c <st_2>: + 19c: 2d 4d f0 00 st fp,@fp || nop + +000001a0 <st_d>: + 1a0: ad 4d 00 00 st fp,@\(0,fp\) + +000001a4 <st_d2>: + 1a4: ad 4d 00 00 st fp,@\(0,fp\) + +000001a8 <stb>: + 1a8: 2d 0d f0 00 stb fp,@fp || nop + +000001ac <stb_2>: + 1ac: 2d 0d f0 00 stb fp,@fp || nop + +000001b0 <stb_d>: + 1b0: ad 0d 00 00 stb fp,@\(0,fp\) + +000001b4 <stb_d2>: + 1b4: ad 0d 00 00 stb fp,@\(0,fp\) + +000001b8 <sth>: + 1b8: 2d 2d f0 00 sth fp,@fp || nop + +000001bc <sth_2>: + 1bc: 2d 2d f0 00 sth fp,@fp || nop + +000001c0 <sth_d>: + 1c0: ad 2d 00 00 sth fp,@\(0,fp\) + +000001c4 <sth_d2>: + 1c4: ad 2d 00 00 sth fp,@\(0,fp\) + +000001c8 <st_plus>: + 1c8: 2d 6d f0 00 st fp,@\+fp || nop + +000001cc <st_minus>: + 1cc: 2d 7d f0 00 st fp,@-fp || nop + +000001d0 <sub>: + 1d0: 0d 2d f0 00 sub fp,fp || nop + +000001d4 <subv>: + 1d4: 0d 0d f0 00 subv fp,fp || nop + +000001d8 <subx>: + 1d8: 0d 1d f0 00 subx fp,fp || nop + +000001dc <trap>: + 1dc: 10 f0 f0 00 trap 0x0 || nop + +000001e0 <unlock>: + 1e0: 2d 5d f0 00 unlock fp,@fp || nop + +000001e4 <push>: + 1e4: 2d 7f f0 00 st fp,@-sp || nop + +000001e8 <pop>: + 1e8: 2d ef f0 00 ld fp,@sp\+ || nop diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/m32r/allinsn.exp b/gnu/usr.bin/binutils/gas/testsuite/gas/m32r/allinsn.exp new file mode 100644 index 00000000000..c5ddd0eb3ff --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/m32r/allinsn.exp @@ -0,0 +1,5 @@ +# M32R assembler testsuite. + +if [istarget m32r*-*-*] { + run_dump_test "allinsn" +} diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/m32r/allinsn.s b/gnu/usr.bin/binutils/gas/testsuite/gas/m32r/allinsn.s new file mode 100644 index 00000000000..ce0df3ad08c --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/m32r/allinsn.s @@ -0,0 +1,508 @@ + .data +foodata: .word 42 + .text +footext: + .text + .global add +add: + add fp,fp + .text + .global add3 +add3: + add3 fp,fp,0 + .text + .global and +and: + and fp,fp + .text + .global and3 +and3: + and3 fp,fp,0 + .text + .global or +or: + or fp,fp + .text + .global or3 +or3: + or3 fp,fp,0 + .text + .global xor +xor: + xor fp,fp + .text + .global xor3 +xor3: + xor3 fp,fp,0 + .text + .global addi +addi: + addi fp,0 + .text + .global addv +addv: + addv fp,fp + .text + .global addv3 +addv3: + addv3 fp,fp,0 + .text + .global addx +addx: + addx fp,fp + .text + .global bc8 +bc8: + bc footext + .text + .global bc8_s +bc8_s: + bc.s footext + .text + .global bc24 +bc24: + bc footext + .text + .global bc24_l +bc24_l: + bc.l footext + .text + .global beq +beq: + beq fp,fp,footext + .text + .global beqz +beqz: + beqz fp,footext + .text + .global bgez +bgez: + bgez fp,footext + .text + .global bgtz +bgtz: + bgtz fp,footext + .text + .global blez +blez: + blez fp,footext + .text + .global bltz +bltz: + bltz fp,footext + .text + .global bnez +bnez: + bnez fp,footext + .text + .global bl8 +bl8: + bl footext + .text + .global bl8_s +bl8_s: + bl.s footext + .text + .global bl24 +bl24: + bl footext + .text + .global bl24_l +bl24_l: + bl.l footext + .text + .global bnc8 +bnc8: + bnc footext + .text + .global bnc8_s +bnc8_s: + bnc.s footext + .text + .global bnc24 +bnc24: + bnc footext + .text + .global bnc24_l +bnc24_l: + bnc.l footext + .text + .global bne +bne: + bne fp,fp,footext + .text + .global bra8 +bra8: + bra footext + .text + .global bra8_s +bra8_s: + bra.s footext + .text + .global bra24 +bra24: + bra footext + .text + .global bra24_l +bra24_l: + bra.l footext + .text + .global cmp +cmp: + cmp fp,fp + .text + .global cmpi +cmpi: + cmpi fp,0 + .text + .global cmpu +cmpu: + cmpu fp,fp + .text + .global cmpui +cmpui: + cmpui fp,0 + .text + .global div +div: + div fp,fp + .text + .global divu +divu: + divu fp,fp + .text + .global rem +rem: + rem fp,fp + .text + .global remu +remu: + remu fp,fp + .text + .global jl +jl: + jl fp + .text + .global jmp +jmp: + jmp fp + .text + .global ld +ld: + ld fp,@fp + .text + .global ld_2 +ld_2: + ld fp,@(fp) + .text + .global ld_d +ld_d: + ld fp,@(0,fp) + .text + .global ld_d2 +ld_d2: + ld fp,@(fp,0) + .text + .global ldb +ldb: + ldb fp,@fp + .text + .global ldb_2 +ldb_2: + ldb fp,@(fp) + .text + .global ldb_d +ldb_d: + ldb fp,@(0,fp) + .text + .global ldb_d2 +ldb_d2: + ldb fp,@(fp,0) + .text + .global ldh +ldh: + ldh fp,@fp + .text + .global ldh_2 +ldh_2: + ldh fp,@(fp) + .text + .global ldh_d +ldh_d: + ldh fp,@(0,fp) + .text + .global ldh_d2 +ldh_d2: + ldh fp,@(fp,0) + .text + .global ldub +ldub: + ldub fp,@fp + .text + .global ldub_2 +ldub_2: + ldub fp,@(fp) + .text + .global ldub_d +ldub_d: + ldub fp,@(0,fp) + .text + .global ldub_d2 +ldub_d2: + ldub fp,@(fp,0) + .text + .global lduh +lduh: + lduh fp,@fp + .text + .global lduh_2 +lduh_2: + lduh fp,@(fp) + .text + .global lduh_d +lduh_d: + lduh fp,@(0,fp) + .text + .global lduh_d2 +lduh_d2: + lduh fp,@(fp,0) + .text + .global ld_plus +ld_plus: + ld fp,@fp+ + .text + .global ld24 +ld24: + ld24 fp,foodata + .text + .global ldi8 +ldi8: + ldi fp,0 + .text + .global ldi8a +ldi8a: + ldi8 fp,0 + .text + .global ldi16 +ldi16: + ldi fp,0 + .text + .global ldi16a +ldi16a: + ldi16 fp,0 + .text + .global lock +lock: + lock fp,@fp + .text + .global machi +machi: + machi fp,fp + .text + .global maclo +maclo: + maclo fp,fp + .text + .global macwhi +macwhi: + macwhi fp,fp + .text + .global macwlo +macwlo: + macwlo fp,fp + .text + .global mul +mul: + mul fp,fp + .text + .global mulhi +mulhi: + mulhi fp,fp + .text + .global mullo +mullo: + mullo fp,fp + .text + .global mulwhi +mulwhi: + mulwhi fp,fp + .text + .global mulwlo +mulwlo: + mulwlo fp,fp + .text + .global mv +mv: + mv fp,fp + .text + .global mvfachi +mvfachi: + mvfachi fp + .text + .global mvfaclo +mvfaclo: + mvfaclo fp + .text + .global mvfacmi +mvfacmi: + mvfacmi fp + .text + .global mvfc +mvfc: + mvfc fp,psw + .text + .global mvtachi +mvtachi: + mvtachi fp + .text + .global mvtaclo +mvtaclo: + mvtaclo fp + .text + .global mvtc +mvtc: + mvtc fp,psw + .text + .global neg +neg: + neg fp,fp + .text + .global nop +nop: + .text + .global not +not: + not fp,fp + .text + .global rac +rac: + .text + .global rach +rach: + .text + .global rte +rte: + .text + .global seth +seth: + seth fp,0 + .text + .global sll +sll: + sll fp,fp + .text + .global sll3 +sll3: + sll3 fp,fp,0 + .text + .global slli +slli: + slli fp,0 + .text + .global sra +sra: + sra fp,fp + .text + .global sra3 +sra3: + sra3 fp,fp,0 + .text + .global srai +srai: + srai fp,0 + .text + .global srl +srl: + srl fp,fp + .text + .global srl3 +srl3: + srl3 fp,fp,0 + .text + .global srli +srli: + srli fp,0 + .text + .global st +st: + st fp,@fp + .text + .global st_2 +st_2: + st fp,@(fp) + .text + .global st_d +st_d: + st fp,@(0,fp) + .text + .global st_d2 +st_d2: + st fp,@(fp,0) + .text + .global stb +stb: + stb fp,@fp + .text + .global stb_2 +stb_2: + stb fp,@(fp) + .text + .global stb_d +stb_d: + stb fp,@(0,fp) + .text + .global stb_d2 +stb_d2: + stb fp,@(fp,0) + .text + .global sth +sth: + sth fp,@fp + .text + .global sth_2 +sth_2: + sth fp,@(fp) + .text + .global sth_d +sth_d: + sth fp,@(0,fp) + .text + .global sth_d2 +sth_d2: + sth fp,@(fp,0) + .text + .global st_plus +st_plus: + st fp,@+fp + .text + .global st_minus +st_minus: + st fp,@-fp + .text + .global sub +sub: + sub fp,fp + .text + .global subv +subv: + subv fp,fp + .text + .global subx +subx: + subx fp,fp + .text + .global trap +trap: + trap 0 + .text + .global unlock +unlock: + unlock fp,@fp + .text + .global push +push: + push fp + .text + .global pop +pop: + pop fp diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/macros/semi.d b/gnu/usr.bin/binutils/gas/testsuite/gas/macros/semi.d new file mode 100644 index 00000000000..ae89e738592 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/macros/semi.d @@ -0,0 +1,8 @@ +#objdump: -s -j .text +#name: semi + +.*: .* + +Contents of section .text: + 0000 3b203b20 3a203a20 00000000 00000000 ; ; : : ........ + 0010 00000000 00000000 00000000 00000000 ................ diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/macros/semi.s b/gnu/usr.bin/binutils/gas/testsuite/gas/macros/semi.s new file mode 100644 index 00000000000..d6e0963a169 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/macros/semi.s @@ -0,0 +1,14 @@ + .macro semicolon + .ascii "; " + .endm + + .macro colon + .ascii ": " + .endm + + semicolon + .ascii "; " + colon + .ascii ": " + + .p2align 5,0 diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/mips/itbl b/gnu/usr.bin/binutils/gas/testsuite/gas/mips/itbl new file mode 100644 index 00000000000..30f8a79f60c --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/mips/itbl @@ -0,0 +1,19 @@ + + ; Test case for assembler option "itbl". + ; Run as "as --itbl itbl itbl.s" + ; or with stand-alone test case "itbl-test itbl itbl.s". + ; Here, the processors represent mips coprocessors. + + p1 dreg d1 1 ; data register "d1" for COP1 has value 1 + p1 creg c3 3 ; ctrl register "c3" for COP1 has value 3 + p3 insn fie 0x1e:24-20 ; function "fill" for COP3 has value 31 + p3 dreg d3 3 ; data register "d3" for COP3 has value 3 + p3 creg c2 22 ; control register "c2" for COP3 has value 22 + p3 insn fee 0x1e:24-20,dreg:17-13,creg:12-8,immed:7-0 + + p3 dreg d3 3 ; data register "d3" for COP3 has value 3 + p3 creg c2 22 ; control register "c2" for COP3 has value 22 + p3 insn fum 0x01e00001 dreg:17-13 creg:12-8 + p3 insn foh 0xf:24-21 dreg:20-16 immed:15-0 + + p3 insn pig 0x1:24-21*[0x100|0x2], dreg:20-16, immed:15-0*0x10000 diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/mips/itbl.s b/gnu/usr.bin/binutils/gas/testsuite/gas/mips/itbl.s new file mode 100644 index 00000000000..085545be1cb --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/mips/itbl.s @@ -0,0 +1,18 @@ + + ; Test case for assembler option "itbl". + ; Run as "as --itbl itbl itbl.s" + ; or with stand-alone test case "itbl-test itbl itbl.s". + + ; Call mips coprocessor "cofun"s as defined in "itbl". + + fee $d3,$c2,0x1 ; 0x4ff07601 + fie ; 0x4ff00000 + foh $2,0x100 + fum $d3,$c2 ; 0x4ff07601 + pig $2,0x100 + + ; Call a mips coprocessor instruction with register "d1" + ; defined in "itbl". + + LWC1 $d1,0x100($2) + diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/mips/mips16.d b/gnu/usr.bin/binutils/gas/testsuite/gas/mips/mips16.d new file mode 100644 index 00000000000..92a04ebd90c --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/mips/mips16.d @@ -0,0 +1,683 @@ +#objdump: -dr +#as: -mips3 +#name: mips16 + +# Test the mips16 instruction set. + +.*: +file format .*mips.* + +Disassembly of section .text: + +0+000000 <data1>: + 0: 00000000 nop + +0+000004 <insns1>: + 4: 3b40 ld \$v0,0\(\$v1\) + 6: f000 3b41 ld \$v0,1\(\$v1\) + a: f000 3b42 ld \$v0,2\(\$v1\) + e: f000 3b43 ld \$v0,3\(\$v1\) + 12: f000 3b44 ld \$v0,4\(\$v1\) + 16: 3b41 ld \$v0,8\(\$v1\) + 18: 3b42 ld \$v0,16\(\$v1\) + 1a: 3b44 ld \$v0,32\(\$v1\) + 1c: 3b48 ld \$v0,64\(\$v1\) + 1e: 3b50 ld \$v0,128\(\$v1\) + 20: f100 3b40 ld \$v0,256\(\$v1\) + 24: f200 3b40 ld \$v0,512\(\$v1\) + 28: f400 3b40 ld \$v0,1024\(\$v1\) + 2c: f001 3b40 ld \$v0,2048\(\$v1\) + 30: f7ff 3b5f ld \$v0,-1\(\$v1\) + 34: f7ff 3b5e ld \$v0,-2\(\$v1\) + 38: f7ff 3b5d ld \$v0,-3\(\$v1\) + 3c: f7ff 3b5c ld \$v0,-4\(\$v1\) + 40: f7ff 3b58 ld \$v0,-8\(\$v1\) + 44: f7ff 3b50 ld \$v0,-16\(\$v1\) + 48: f7ff 3b40 ld \$v0,-32\(\$v1\) + 4c: f7df 3b40 ld \$v0,-64\(\$v1\) + 50: f79f 3b40 ld \$v0,-128\(\$v1\) + 54: f71f 3b40 ld \$v0,-256\(\$v1\) + 58: f61f 3b40 ld \$v0,-512\(\$v1\) + 5c: f41f 3b40 ld \$v0,-1024\(\$v1\) + 60: f01f 3b40 ld \$v0,-2048\(\$v1\) + 64: f7bf fc40 ld \$v0,0 <data1> + 68: f6a0 fc54 ld \$v0,71c <data2> + 6c: f001 fc40 ld \$v0,868 <bar> + 70: f0c1 fc40 ld \$v0,930 <quux> + 74: f840 ld \$v0,0\(\$sp\) + 76: f000 f841 ld \$v0,1\(\$sp\) + 7a: f000 f842 ld \$v0,2\(\$sp\) + 7e: f000 f843 ld \$v0,3\(\$sp\) + 82: f000 f844 ld \$v0,4\(\$sp\) + 86: f841 ld \$v0,8\(\$sp\) + 88: f842 ld \$v0,16\(\$sp\) + 8a: f844 ld \$v0,32\(\$sp\) + 8c: f848 ld \$v0,64\(\$sp\) + 8e: f850 ld \$v0,128\(\$sp\) + 90: f100 f840 ld \$v0,256\(\$sp\) + 94: f200 f840 ld \$v0,512\(\$sp\) + 98: f400 f840 ld \$v0,1024\(\$sp\) + 9c: f001 f840 ld \$v0,2048\(\$sp\) + a0: f7ff f85f ld \$v0,-1\(\$sp\) + a4: f7ff f85e ld \$v0,-2\(\$sp\) + a8: f7ff f85d ld \$v0,-3\(\$sp\) + ac: f7ff f85c ld \$v0,-4\(\$sp\) + b0: f7ff f858 ld \$v0,-8\(\$sp\) + b4: f7ff f850 ld \$v0,-16\(\$sp\) + b8: f7ff f840 ld \$v0,-32\(\$sp\) + bc: f7df f840 ld \$v0,-64\(\$sp\) + c0: f79f f840 ld \$v0,-128\(\$sp\) + c4: f71f f840 ld \$v0,-256\(\$sp\) + c8: f61f f840 ld \$v0,-512\(\$sp\) + cc: f41f f840 ld \$v0,-1024\(\$sp\) + d0: f01f f840 ld \$v0,-2048\(\$sp\) + d4: bb40 lwu \$v0,0\(\$v1\) + d6: f000 bb41 lwu \$v0,1\(\$v1\) + da: f000 bb42 lwu \$v0,2\(\$v1\) + de: f000 bb43 lwu \$v0,3\(\$v1\) + e2: bb41 lwu \$v0,4\(\$v1\) + e4: bb42 lwu \$v0,8\(\$v1\) + e6: bb44 lwu \$v0,16\(\$v1\) + e8: bb48 lwu \$v0,32\(\$v1\) + ea: bb50 lwu \$v0,64\(\$v1\) + ec: f080 bb40 lwu \$v0,128\(\$v1\) + f0: f100 bb40 lwu \$v0,256\(\$v1\) + f4: f200 bb40 lwu \$v0,512\(\$v1\) + f8: f400 bb40 lwu \$v0,1024\(\$v1\) + fc: f001 bb40 lwu \$v0,2048\(\$v1\) + 100: f7ff bb5f lwu \$v0,-1\(\$v1\) + 104: f7ff bb5e lwu \$v0,-2\(\$v1\) + 108: f7ff bb5d lwu \$v0,-3\(\$v1\) + 10c: f7ff bb5c lwu \$v0,-4\(\$v1\) + 110: f7ff bb58 lwu \$v0,-8\(\$v1\) + 114: f7ff bb50 lwu \$v0,-16\(\$v1\) + 118: f7ff bb40 lwu \$v0,-32\(\$v1\) + 11c: f7df bb40 lwu \$v0,-64\(\$v1\) + 120: f79f bb40 lwu \$v0,-128\(\$v1\) + 124: f71f bb40 lwu \$v0,-256\(\$v1\) + 128: f61f bb40 lwu \$v0,-512\(\$v1\) + 12c: f41f bb40 lwu \$v0,-1024\(\$v1\) + 130: f01f bb40 lwu \$v0,-2048\(\$v1\) + 134: 9b40 lw \$v0,0\(\$v1\) + 136: f000 9b41 lw \$v0,1\(\$v1\) + 13a: f000 9b42 lw \$v0,2\(\$v1\) + 13e: f000 9b43 lw \$v0,3\(\$v1\) + 142: 9b41 lw \$v0,4\(\$v1\) + 144: 9b42 lw \$v0,8\(\$v1\) + 146: 9b44 lw \$v0,16\(\$v1\) + 148: 9b48 lw \$v0,32\(\$v1\) + 14a: 9b50 lw \$v0,64\(\$v1\) + 14c: f080 9b40 lw \$v0,128\(\$v1\) + 150: f100 9b40 lw \$v0,256\(\$v1\) + 154: f200 9b40 lw \$v0,512\(\$v1\) + 158: f400 9b40 lw \$v0,1024\(\$v1\) + 15c: f001 9b40 lw \$v0,2048\(\$v1\) + 160: f7ff 9b5f lw \$v0,-1\(\$v1\) + 164: f7ff 9b5e lw \$v0,-2\(\$v1\) + 168: f7ff 9b5d lw \$v0,-3\(\$v1\) + 16c: f7ff 9b5c lw \$v0,-4\(\$v1\) + 170: f7ff 9b58 lw \$v0,-8\(\$v1\) + 174: f7ff 9b50 lw \$v0,-16\(\$v1\) + 178: f7ff 9b40 lw \$v0,-32\(\$v1\) + 17c: f7df 9b40 lw \$v0,-64\(\$v1\) + 180: f79f 9b40 lw \$v0,-128\(\$v1\) + 184: f71f 9b40 lw \$v0,-256\(\$v1\) + 188: f61f 9b40 lw \$v0,-512\(\$v1\) + 18c: f41f 9b40 lw \$v0,-1024\(\$v1\) + 190: f01f 9b40 lw \$v0,-2048\(\$v1\) + 194: f67f b20c lw \$v0,0 <data1> + 198: f580 b204 lw \$v0,71c <data2> + 19c: f6c0 b20c lw \$v0,868 <bar> + 1a0: f780 b210 lw \$v0,930 <quux> + 1a4: 9200 lw \$v0,0\(\$sp\) + 1a6: f000 9201 lw \$v0,1\(\$sp\) + 1aa: f000 9202 lw \$v0,2\(\$sp\) + 1ae: f000 9203 lw \$v0,3\(\$sp\) + 1b2: 9201 lw \$v0,4\(\$sp\) + 1b4: 9202 lw \$v0,8\(\$sp\) + 1b6: 9204 lw \$v0,16\(\$sp\) + 1b8: 9208 lw \$v0,32\(\$sp\) + 1ba: 9210 lw \$v0,64\(\$sp\) + 1bc: 9220 lw \$v0,128\(\$sp\) + 1be: 9240 lw \$v0,256\(\$sp\) + 1c0: 9280 lw \$v0,512\(\$sp\) + 1c2: f400 9200 lw \$v0,1024\(\$sp\) + 1c6: f001 9200 lw \$v0,2048\(\$sp\) + 1ca: f7ff 921f lw \$v0,-1\(\$sp\) + 1ce: f7ff 921e lw \$v0,-2\(\$sp\) + 1d2: f7ff 921d lw \$v0,-3\(\$sp\) + 1d6: f7ff 921c lw \$v0,-4\(\$sp\) + 1da: f7ff 9218 lw \$v0,-8\(\$sp\) + 1de: f7ff 9210 lw \$v0,-16\(\$sp\) + 1e2: f7ff 9200 lw \$v0,-32\(\$sp\) + 1e6: f7df 9200 lw \$v0,-64\(\$sp\) + 1ea: f79f 9200 lw \$v0,-128\(\$sp\) + 1ee: f71f 9200 lw \$v0,-256\(\$sp\) + 1f2: f61f 9200 lw \$v0,-512\(\$sp\) + 1f6: f41f 9200 lw \$v0,-1024\(\$sp\) + 1fa: f01f 9200 lw \$v0,-2048\(\$sp\) + 1fe: 8b40 lh \$v0,0\(\$v1\) + 200: f000 8b41 lh \$v0,1\(\$v1\) + 204: 8b41 lh \$v0,2\(\$v1\) + 206: f000 8b43 lh \$v0,3\(\$v1\) + 20a: 8b42 lh \$v0,4\(\$v1\) + 20c: 8b44 lh \$v0,8\(\$v1\) + 20e: 8b48 lh \$v0,16\(\$v1\) + 210: 8b50 lh \$v0,32\(\$v1\) + 212: f040 8b40 lh \$v0,64\(\$v1\) + 216: f080 8b40 lh \$v0,128\(\$v1\) + 21a: f100 8b40 lh \$v0,256\(\$v1\) + 21e: f200 8b40 lh \$v0,512\(\$v1\) + 222: f400 8b40 lh \$v0,1024\(\$v1\) + 226: f001 8b40 lh \$v0,2048\(\$v1\) + 22a: f7ff 8b5f lh \$v0,-1\(\$v1\) + 22e: f7ff 8b5e lh \$v0,-2\(\$v1\) + 232: f7ff 8b5d lh \$v0,-3\(\$v1\) + 236: f7ff 8b5c lh \$v0,-4\(\$v1\) + 23a: f7ff 8b58 lh \$v0,-8\(\$v1\) + 23e: f7ff 8b50 lh \$v0,-16\(\$v1\) + 242: f7ff 8b40 lh \$v0,-32\(\$v1\) + 246: f7df 8b40 lh \$v0,-64\(\$v1\) + 24a: f79f 8b40 lh \$v0,-128\(\$v1\) + 24e: f71f 8b40 lh \$v0,-256\(\$v1\) + 252: f61f 8b40 lh \$v0,-512\(\$v1\) + 256: f41f 8b40 lh \$v0,-1024\(\$v1\) + 25a: f01f 8b40 lh \$v0,-2048\(\$v1\) + 25e: ab40 lhu \$v0,0\(\$v1\) + 260: f000 ab41 lhu \$v0,1\(\$v1\) + 264: ab41 lhu \$v0,2\(\$v1\) + 266: f000 ab43 lhu \$v0,3\(\$v1\) + 26a: ab42 lhu \$v0,4\(\$v1\) + 26c: ab44 lhu \$v0,8\(\$v1\) + 26e: ab48 lhu \$v0,16\(\$v1\) + 270: ab50 lhu \$v0,32\(\$v1\) + 272: f040 ab40 lhu \$v0,64\(\$v1\) + 276: f080 ab40 lhu \$v0,128\(\$v1\) + 27a: f100 ab40 lhu \$v0,256\(\$v1\) + 27e: f200 ab40 lhu \$v0,512\(\$v1\) + 282: f400 ab40 lhu \$v0,1024\(\$v1\) + 286: f001 ab40 lhu \$v0,2048\(\$v1\) + 28a: f7ff ab5f lhu \$v0,-1\(\$v1\) + 28e: f7ff ab5e lhu \$v0,-2\(\$v1\) + 292: f7ff ab5d lhu \$v0,-3\(\$v1\) + 296: f7ff ab5c lhu \$v0,-4\(\$v1\) + 29a: f7ff ab58 lhu \$v0,-8\(\$v1\) + 29e: f7ff ab50 lhu \$v0,-16\(\$v1\) + 2a2: f7ff ab40 lhu \$v0,-32\(\$v1\) + 2a6: f7df ab40 lhu \$v0,-64\(\$v1\) + 2aa: f79f ab40 lhu \$v0,-128\(\$v1\) + 2ae: f71f ab40 lhu \$v0,-256\(\$v1\) + 2b2: f61f ab40 lhu \$v0,-512\(\$v1\) + 2b6: f41f ab40 lhu \$v0,-1024\(\$v1\) + 2ba: f01f ab40 lhu \$v0,-2048\(\$v1\) + 2be: 8340 lb \$v0,0\(\$v1\) + 2c0: 8341 lb \$v0,1\(\$v1\) + 2c2: 8342 lb \$v0,2\(\$v1\) + 2c4: 8343 lb \$v0,3\(\$v1\) + 2c6: 8344 lb \$v0,4\(\$v1\) + 2c8: 8348 lb \$v0,8\(\$v1\) + 2ca: 8350 lb \$v0,16\(\$v1\) + 2cc: f020 8340 lb \$v0,32\(\$v1\) + 2d0: f040 8340 lb \$v0,64\(\$v1\) + 2d4: f080 8340 lb \$v0,128\(\$v1\) + 2d8: f100 8340 lb \$v0,256\(\$v1\) + 2dc: f200 8340 lb \$v0,512\(\$v1\) + 2e0: f400 8340 lb \$v0,1024\(\$v1\) + 2e4: f001 8340 lb \$v0,2048\(\$v1\) + 2e8: f7ff 835f lb \$v0,-1\(\$v1\) + 2ec: f7ff 835e lb \$v0,-2\(\$v1\) + 2f0: f7ff 835d lb \$v0,-3\(\$v1\) + 2f4: f7ff 835c lb \$v0,-4\(\$v1\) + 2f8: f7ff 8358 lb \$v0,-8\(\$v1\) + 2fc: f7ff 8350 lb \$v0,-16\(\$v1\) + 300: f7ff 8340 lb \$v0,-32\(\$v1\) + 304: f7df 8340 lb \$v0,-64\(\$v1\) + 308: f79f 8340 lb \$v0,-128\(\$v1\) + 30c: f71f 8340 lb \$v0,-256\(\$v1\) + 310: f61f 8340 lb \$v0,-512\(\$v1\) + 314: f41f 8340 lb \$v0,-1024\(\$v1\) + 318: f01f 8340 lb \$v0,-2048\(\$v1\) + 31c: a340 lbu \$v0,0\(\$v1\) + 31e: a341 lbu \$v0,1\(\$v1\) + 320: a342 lbu \$v0,2\(\$v1\) + 322: a343 lbu \$v0,3\(\$v1\) + 324: a344 lbu \$v0,4\(\$v1\) + 326: a348 lbu \$v0,8\(\$v1\) + 328: a350 lbu \$v0,16\(\$v1\) + 32a: f020 a340 lbu \$v0,32\(\$v1\) + 32e: f040 a340 lbu \$v0,64\(\$v1\) + 332: f080 a340 lbu \$v0,128\(\$v1\) + 336: f100 a340 lbu \$v0,256\(\$v1\) + 33a: f200 a340 lbu \$v0,512\(\$v1\) + 33e: f400 a340 lbu \$v0,1024\(\$v1\) + 342: f001 a340 lbu \$v0,2048\(\$v1\) + 346: f7ff a35f lbu \$v0,-1\(\$v1\) + 34a: f7ff a35e lbu \$v0,-2\(\$v1\) + 34e: f7ff a35d lbu \$v0,-3\(\$v1\) + 352: f7ff a35c lbu \$v0,-4\(\$v1\) + 356: f7ff a358 lbu \$v0,-8\(\$v1\) + 35a: f7ff a350 lbu \$v0,-16\(\$v1\) + 35e: f7ff a340 lbu \$v0,-32\(\$v1\) + 362: f7df a340 lbu \$v0,-64\(\$v1\) + 366: f79f a340 lbu \$v0,-128\(\$v1\) + 36a: f71f a340 lbu \$v0,-256\(\$v1\) + 36e: f61f a340 lbu \$v0,-512\(\$v1\) + 372: f41f a340 lbu \$v0,-1024\(\$v1\) + 376: f01f a340 lbu \$v0,-2048\(\$v1\) + 37a: 7b40 sd \$v0,0\(\$v1\) + 37c: f000 7b41 sd \$v0,1\(\$v1\) + 380: f000 7b42 sd \$v0,2\(\$v1\) + 384: f000 7b43 sd \$v0,3\(\$v1\) + 388: f000 7b44 sd \$v0,4\(\$v1\) + 38c: 7b41 sd \$v0,8\(\$v1\) + 38e: 7b42 sd \$v0,16\(\$v1\) + 390: 7b44 sd \$v0,32\(\$v1\) + 392: 7b48 sd \$v0,64\(\$v1\) + 394: 7b50 sd \$v0,128\(\$v1\) + 396: f100 7b40 sd \$v0,256\(\$v1\) + 39a: f200 7b40 sd \$v0,512\(\$v1\) + 39e: f400 7b40 sd \$v0,1024\(\$v1\) + 3a2: f001 7b40 sd \$v0,2048\(\$v1\) + 3a6: f7ff 7b5f sd \$v0,-1\(\$v1\) + 3aa: f7ff 7b5e sd \$v0,-2\(\$v1\) + 3ae: f7ff 7b5d sd \$v0,-3\(\$v1\) + 3b2: f7ff 7b5c sd \$v0,-4\(\$v1\) + 3b6: f7ff 7b58 sd \$v0,-8\(\$v1\) + 3ba: f7ff 7b50 sd \$v0,-16\(\$v1\) + 3be: f7ff 7b40 sd \$v0,-32\(\$v1\) + 3c2: f7df 7b40 sd \$v0,-64\(\$v1\) + 3c6: f79f 7b40 sd \$v0,-128\(\$v1\) + 3ca: f71f 7b40 sd \$v0,-256\(\$v1\) + 3ce: f61f 7b40 sd \$v0,-512\(\$v1\) + 3d2: f41f 7b40 sd \$v0,-1024\(\$v1\) + 3d6: f01f 7b40 sd \$v0,-2048\(\$v1\) + 3da: f940 sd \$v0,0\(\$sp\) + 3dc: f000 f941 sd \$v0,1\(\$sp\) + 3e0: f000 f942 sd \$v0,2\(\$sp\) + 3e4: f000 f943 sd \$v0,3\(\$sp\) + 3e8: f000 f944 sd \$v0,4\(\$sp\) + 3ec: f941 sd \$v0,8\(\$sp\) + 3ee: f942 sd \$v0,16\(\$sp\) + 3f0: f944 sd \$v0,32\(\$sp\) + 3f2: f948 sd \$v0,64\(\$sp\) + 3f4: f950 sd \$v0,128\(\$sp\) + 3f6: f100 f940 sd \$v0,256\(\$sp\) + 3fa: f200 f940 sd \$v0,512\(\$sp\) + 3fe: f400 f940 sd \$v0,1024\(\$sp\) + 402: f001 f940 sd \$v0,2048\(\$sp\) + 406: f7ff f95f sd \$v0,-1\(\$sp\) + 40a: f7ff f95e sd \$v0,-2\(\$sp\) + 40e: f7ff f95d sd \$v0,-3\(\$sp\) + 412: f7ff f95c sd \$v0,-4\(\$sp\) + 416: f7ff f958 sd \$v0,-8\(\$sp\) + 41a: f7ff f950 sd \$v0,-16\(\$sp\) + 41e: f7ff f940 sd \$v0,-32\(\$sp\) + 422: f7df f940 sd \$v0,-64\(\$sp\) + 426: f79f f940 sd \$v0,-128\(\$sp\) + 42a: f71f f940 sd \$v0,-256\(\$sp\) + 42e: f61f f940 sd \$v0,-512\(\$sp\) + 432: f41f f940 sd \$v0,-1024\(\$sp\) + 436: f01f f940 sd \$v0,-2048\(\$sp\) + 43a: fa00 sd \$ra,0\(\$sp\) + 43c: f000 fa01 sd \$ra,1\(\$sp\) + 440: f000 fa02 sd \$ra,2\(\$sp\) + 444: f000 fa03 sd \$ra,3\(\$sp\) + 448: f000 fa04 sd \$ra,4\(\$sp\) + 44c: fa01 sd \$ra,8\(\$sp\) + 44e: fa02 sd \$ra,16\(\$sp\) + 450: fa04 sd \$ra,32\(\$sp\) + 452: fa08 sd \$ra,64\(\$sp\) + 454: fa10 sd \$ra,128\(\$sp\) + 456: fa20 sd \$ra,256\(\$sp\) + 458: fa40 sd \$ra,512\(\$sp\) + 45a: fa80 sd \$ra,1024\(\$sp\) + 45c: f001 fa00 sd \$ra,2048\(\$sp\) + 460: f7ff fa1f sd \$ra,-1\(\$sp\) + 464: f7ff fa1e sd \$ra,-2\(\$sp\) + 468: f7ff fa1d sd \$ra,-3\(\$sp\) + 46c: f7ff fa1c sd \$ra,-4\(\$sp\) + 470: f7ff fa18 sd \$ra,-8\(\$sp\) + 474: f7ff fa10 sd \$ra,-16\(\$sp\) + 478: f7ff fa00 sd \$ra,-32\(\$sp\) + 47c: f7df fa00 sd \$ra,-64\(\$sp\) + 480: f79f fa00 sd \$ra,-128\(\$sp\) + 484: f71f fa00 sd \$ra,-256\(\$sp\) + 488: f61f fa00 sd \$ra,-512\(\$sp\) + 48c: f41f fa00 sd \$ra,-1024\(\$sp\) + 490: f01f fa00 sd \$ra,-2048\(\$sp\) + 494: db40 sw \$v0,0\(\$v1\) + 496: f000 db41 sw \$v0,1\(\$v1\) + 49a: f000 db42 sw \$v0,2\(\$v1\) + 49e: f000 db43 sw \$v0,3\(\$v1\) + 4a2: db41 sw \$v0,4\(\$v1\) + 4a4: db42 sw \$v0,8\(\$v1\) + 4a6: db44 sw \$v0,16\(\$v1\) + 4a8: db48 sw \$v0,32\(\$v1\) + 4aa: db50 sw \$v0,64\(\$v1\) + 4ac: f080 db40 sw \$v0,128\(\$v1\) + 4b0: f100 db40 sw \$v0,256\(\$v1\) + 4b4: f200 db40 sw \$v0,512\(\$v1\) + 4b8: f400 db40 sw \$v0,1024\(\$v1\) + 4bc: f001 db40 sw \$v0,2048\(\$v1\) + 4c0: f7ff db5f sw \$v0,-1\(\$v1\) + 4c4: f7ff db5e sw \$v0,-2\(\$v1\) + 4c8: f7ff db5d sw \$v0,-3\(\$v1\) + 4cc: f7ff db5c sw \$v0,-4\(\$v1\) + 4d0: f7ff db58 sw \$v0,-8\(\$v1\) + 4d4: f7ff db50 sw \$v0,-16\(\$v1\) + 4d8: f7ff db40 sw \$v0,-32\(\$v1\) + 4dc: f7df db40 sw \$v0,-64\(\$v1\) + 4e0: f79f db40 sw \$v0,-128\(\$v1\) + 4e4: f71f db40 sw \$v0,-256\(\$v1\) + 4e8: f61f db40 sw \$v0,-512\(\$v1\) + 4ec: f41f db40 sw \$v0,-1024\(\$v1\) + 4f0: f01f db40 sw \$v0,-2048\(\$v1\) + 4f4: d200 sw \$v0,0\(\$sp\) + 4f6: f000 d201 sw \$v0,1\(\$sp\) + 4fa: f000 d202 sw \$v0,2\(\$sp\) + 4fe: f000 d203 sw \$v0,3\(\$sp\) + 502: d201 sw \$v0,4\(\$sp\) + 504: d202 sw \$v0,8\(\$sp\) + 506: d204 sw \$v0,16\(\$sp\) + 508: d208 sw \$v0,32\(\$sp\) + 50a: d210 sw \$v0,64\(\$sp\) + 50c: d220 sw \$v0,128\(\$sp\) + 50e: d240 sw \$v0,256\(\$sp\) + 510: d280 sw \$v0,512\(\$sp\) + 512: f400 d200 sw \$v0,1024\(\$sp\) + 516: f001 d200 sw \$v0,2048\(\$sp\) + 51a: f7ff d21f sw \$v0,-1\(\$sp\) + 51e: f7ff d21e sw \$v0,-2\(\$sp\) + 522: f7ff d21d sw \$v0,-3\(\$sp\) + 526: f7ff d21c sw \$v0,-4\(\$sp\) + 52a: f7ff d218 sw \$v0,-8\(\$sp\) + 52e: f7ff d210 sw \$v0,-16\(\$sp\) + 532: f7ff d200 sw \$v0,-32\(\$sp\) + 536: f7df d200 sw \$v0,-64\(\$sp\) + 53a: f79f d200 sw \$v0,-128\(\$sp\) + 53e: f71f d200 sw \$v0,-256\(\$sp\) + 542: f61f d200 sw \$v0,-512\(\$sp\) + 546: f41f d200 sw \$v0,-1024\(\$sp\) + 54a: f01f d200 sw \$v0,-2048\(\$sp\) + 54e: 6200 sw \$ra,0\(\$sp\) + 550: f000 6201 sw \$ra,1\(\$sp\) + 554: f000 6202 sw \$ra,2\(\$sp\) + 558: f000 6203 sw \$ra,3\(\$sp\) + 55c: 6201 sw \$ra,4\(\$sp\) + 55e: 6202 sw \$ra,8\(\$sp\) + 560: 6204 sw \$ra,16\(\$sp\) + 562: 6208 sw \$ra,32\(\$sp\) + 564: 6210 sw \$ra,64\(\$sp\) + 566: 6220 sw \$ra,128\(\$sp\) + 568: 6240 sw \$ra,256\(\$sp\) + 56a: 6280 sw \$ra,512\(\$sp\) + 56c: f400 6200 sw \$ra,1024\(\$sp\) + 570: f001 6200 sw \$ra,2048\(\$sp\) + 574: f7ff 621f sw \$ra,-1\(\$sp\) + 578: f7ff 621e sw \$ra,-2\(\$sp\) + 57c: f7ff 621d sw \$ra,-3\(\$sp\) + 580: f7ff 621c sw \$ra,-4\(\$sp\) + 584: f7ff 6218 sw \$ra,-8\(\$sp\) + 588: f7ff 6210 sw \$ra,-16\(\$sp\) + 58c: f7ff 6200 sw \$ra,-32\(\$sp\) + 590: f7df 6200 sw \$ra,-64\(\$sp\) + 594: f79f 6200 sw \$ra,-128\(\$sp\) + 598: f71f 6200 sw \$ra,-256\(\$sp\) + 59c: f61f 6200 sw \$ra,-512\(\$sp\) + 5a0: f41f 6200 sw \$ra,-1024\(\$sp\) + 5a4: f01f 6200 sw \$ra,-2048\(\$sp\) + 5a8: cb40 sh \$v0,0\(\$v1\) + 5aa: f000 cb41 sh \$v0,1\(\$v1\) + 5ae: cb41 sh \$v0,2\(\$v1\) + 5b0: f000 cb43 sh \$v0,3\(\$v1\) + 5b4: cb42 sh \$v0,4\(\$v1\) + 5b6: cb44 sh \$v0,8\(\$v1\) + 5b8: cb48 sh \$v0,16\(\$v1\) + 5ba: cb50 sh \$v0,32\(\$v1\) + 5bc: f040 cb40 sh \$v0,64\(\$v1\) + 5c0: f080 cb40 sh \$v0,128\(\$v1\) + 5c4: f100 cb40 sh \$v0,256\(\$v1\) + 5c8: f200 cb40 sh \$v0,512\(\$v1\) + 5cc: f400 cb40 sh \$v0,1024\(\$v1\) + 5d0: f001 cb40 sh \$v0,2048\(\$v1\) + 5d4: f7ff cb5f sh \$v0,-1\(\$v1\) + 5d8: f7ff cb5e sh \$v0,-2\(\$v1\) + 5dc: f7ff cb5d sh \$v0,-3\(\$v1\) + 5e0: f7ff cb5c sh \$v0,-4\(\$v1\) + 5e4: f7ff cb58 sh \$v0,-8\(\$v1\) + 5e8: f7ff cb50 sh \$v0,-16\(\$v1\) + 5ec: f7ff cb40 sh \$v0,-32\(\$v1\) + 5f0: f7df cb40 sh \$v0,-64\(\$v1\) + 5f4: f79f cb40 sh \$v0,-128\(\$v1\) + 5f8: f71f cb40 sh \$v0,-256\(\$v1\) + 5fc: f61f cb40 sh \$v0,-512\(\$v1\) + 600: f41f cb40 sh \$v0,-1024\(\$v1\) + 604: f01f cb40 sh \$v0,-2048\(\$v1\) + 608: c340 sb \$v0,0\(\$v1\) + 60a: c341 sb \$v0,1\(\$v1\) + 60c: c342 sb \$v0,2\(\$v1\) + 60e: c343 sb \$v0,3\(\$v1\) + 610: c344 sb \$v0,4\(\$v1\) + 612: c348 sb \$v0,8\(\$v1\) + 614: c350 sb \$v0,16\(\$v1\) + 616: f020 c340 sb \$v0,32\(\$v1\) + 61a: f040 c340 sb \$v0,64\(\$v1\) + 61e: f080 c340 sb \$v0,128\(\$v1\) + 622: f100 c340 sb \$v0,256\(\$v1\) + 626: f200 c340 sb \$v0,512\(\$v1\) + 62a: f400 c340 sb \$v0,1024\(\$v1\) + 62e: f001 c340 sb \$v0,2048\(\$v1\) + 632: f7ff c35f sb \$v0,-1\(\$v1\) + 636: f7ff c35e sb \$v0,-2\(\$v1\) + 63a: f7ff c35d sb \$v0,-3\(\$v1\) + 63e: f7ff c35c sb \$v0,-4\(\$v1\) + 642: f7ff c358 sb \$v0,-8\(\$v1\) + 646: f7ff c350 sb \$v0,-16\(\$v1\) + 64a: f7ff c340 sb \$v0,-32\(\$v1\) + 64e: f7df c340 sb \$v0,-64\(\$v1\) + 652: f79f c340 sb \$v0,-128\(\$v1\) + 656: f71f c340 sb \$v0,-256\(\$v1\) + 65a: f61f c340 sb \$v0,-512\(\$v1\) + 65e: f41f c340 sb \$v0,-1024\(\$v1\) + 662: f01f c340 sb \$v0,-2048\(\$v1\) + 666: 6a00 li \$v0,0 + 668: 6a01 li \$v0,1 + 66a: f100 6a00 li \$v0,256 + 66e: 675e move \$v0,\$s8 + 670: 6592 move \$s4,\$v0 + 672: 4350 daddiu \$v0,\$v1,0 + 674: 4351 daddiu \$v0,\$v1,1 + 676: 435f daddiu \$v0,\$v1,-1 + 678: f010 4350 daddiu \$v0,\$v1,16 + 67c: f7ff 4350 daddiu \$v0,\$v1,-16 + 680: e388 daddu \$v0,\$v1,\$a0 + 682: fd40 daddiu \$v0,0 + 684: fd41 daddiu \$v0,1 + 686: fd5f daddiu \$v0,-1 + 688: f020 fd40 daddiu \$v0,32 + 68c: f7ff fd40 daddiu \$v0,-32 + 690: f080 fd40 daddiu \$v0,128 + 694: f79f fd40 daddiu \$v0,-128 + 698: f17f fe48 dla \$v0,0 <data1> + 69c: f080 fe40 dla \$v0,71c <data2> + 6a0: f1c0 fe48 dla \$v0,868 <bar> + 6a4: f280 fe4c dla \$v0,930 <quux> + 6a8: fb00 daddiu \$sp,0 + 6aa: f000 fb01 daddiu \$sp,1 + 6ae: f7ff fb1f daddiu \$sp,-1 + 6b2: fb20 daddiu \$sp,256 + 6b4: fbe0 daddiu \$sp,-256 + 6b6: ff40 daddiu \$v0,\$sp,0 + 6b8: f000 ff41 daddiu \$v0,\$sp,1 + 6bc: f7ff ff5f daddiu \$v0,\$sp,-1 + 6c0: ff48 daddiu \$v0,\$sp,32 + 6c2: f7ff ff40 daddiu \$v0,\$sp,-32 + 6c6: f080 ff40 daddiu \$v0,\$sp,128 + 6ca: f79f ff40 daddiu \$v0,\$sp,-128 + 6ce: 4340 addiu \$v0,\$v1,0 + 6d0: 4341 addiu \$v0,\$v1,1 + 6d2: 434f addiu \$v0,\$v1,-1 + 6d4: f010 4340 addiu \$v0,\$v1,16 + 6d8: f7ff 4340 addiu \$v0,\$v1,-16 + 6dc: e389 addu \$v0,\$v1,\$a0 + 6de: 4a00 addiu \$v0,0 + 6e0: 4a01 addiu \$v0,1 + 6e2: 4aff addiu \$v0,-1 + 6e4: 4a20 addiu \$v0,32 + 6e6: 4ae0 addiu \$v0,-32 + 6e8: f080 4a00 addiu \$v0,128 + 6ec: 4a80 addiu \$v0,-128 + 6ee: f11f 0a14 la \$v0,0 <data1> + 6f2: 0a0b la \$v0,71c <data2> + 6f4: 0a5d la \$v0,868 <bar> + 6f6: 0a8f la \$v0,930 <quux> + 6f8: 6300 addiu \$sp,0 + 6fa: f000 6301 addiu \$sp,1 + 6fe: f7ff 631f addiu \$sp,-1 + 702: 6320 addiu \$sp,256 + 704: 63e0 addiu \$sp,-256 + 706: 0200 addiu \$v0,\$sp,0 + 708: f000 0201 addiu \$v0,\$sp,1 + 70c: f7ff 021f addiu \$v0,\$sp,-1 + 710: 0208 addiu \$v0,\$sp,32 + 712: f7ff 0200 addiu \$v0,\$sp,-32 + 716: 0220 addiu \$v0,\$sp,128 + 718: f79f 0200 addiu \$v0,\$sp,-128 + +0+00071c <data2>: + 71c: 00000000 nop + +0+000720 <insns2>: + 720: e38a dsubu \$v0,\$v1,\$a0 + 722: e38b subu \$v0,\$v1,\$a0 + 724: ea6b neg \$v0,\$v1 + 726: ea6c and \$v0,\$v1 + 728: ea6d or \$v0,\$v1 + 72a: ea6e xor \$v0,\$v1 + 72c: ea6f not \$v0,\$v1 + 72e: 5200 slti \$v0,0 + 730: 5201 slti \$v0,1 + 732: f7ff 521f slti \$v0,-1 + 736: 52ff slti \$v0,255 + 738: f100 5200 slti \$v0,256 + 73c: ea62 slt \$v0,\$v1 + 73e: 5a00 sltiu \$v0,0 + 740: 5a01 sltiu \$v0,1 + 742: f7ff 5a1f sltiu \$v0,-1 + 746: 5aff sltiu \$v0,255 + 748: f100 5a00 sltiu \$v0,256 + 74c: ea63 sltu \$v0,\$v1 + 74e: 7200 cmpi \$v0,0 + 750: 7201 cmpi \$v0,1 + 752: 72ff cmpi \$v0,255 + 754: f100 7200 cmpi \$v0,256 + 758: ea6a cmp \$v0,\$v1 + 75a: f000 3261 dsll \$v0,\$v1,0 + 75e: 3265 dsll \$v0,\$v1,1 + 760: 3261 dsll \$v0,\$v1,8 + 762: f240 3261 dsll \$v0,\$v1,9 + 766: f7e0 3261 dsll \$v0,\$v1,63 + 76a: eb54 dsllv \$v0,\$v1 + 76c: f000 e848 dsrl \$v0,0 + 770: e948 dsrl \$v0,1 + 772: e848 dsrl \$v0,0 + 774: f240 e848 dsrl \$v0,9 + 778: f7e0 e848 dsrl \$v0,63 + 77c: eb56 dsrlv \$v0,\$v1 + 77e: f000 e853 dsra \$v0,0 + 782: e953 dsra \$v0,1 + 784: e853 dsra \$v0,0 + 786: f240 e853 dsra \$v0,9 + 78a: f7e0 e853 dsra \$v0,63 + 78e: eb57 dsrav \$v0,\$v1 + 790: ea12 mflo \$v0 + 792: eb10 mfhi \$v1 + 794: f000 3260 sll \$v0,\$v1,0 + 798: 3264 sll \$v0,\$v1,1 + 79a: 3260 sll \$v0,\$v1,8 + 79c: f240 3260 sll \$v0,\$v1,9 + 7a0: f7c0 3260 sll \$v0,\$v1,31 + 7a4: eb44 sllv \$v0,\$v1 + 7a6: f000 3262 srl \$v0,\$v1,0 + 7aa: 3266 srl \$v0,\$v1,1 + 7ac: 3262 srl \$v0,\$v1,8 + 7ae: f240 3262 srl \$v0,\$v1,9 + 7b2: f7c0 3262 srl \$v0,\$v1,31 + 7b6: eb46 srlv \$v0,\$v1 + 7b8: f000 3263 sra \$v0,\$v1,0 + 7bc: 3267 sra \$v0,\$v1,1 + 7be: 3263 sra \$v0,\$v1,8 + 7c0: f240 3263 sra \$v0,\$v1,9 + 7c4: f7c0 3263 sra \$v0,\$v1,31 + 7c8: eb47 srav \$v0,\$v1 + 7ca: ea7c dmult \$v0,\$v1 + 7cc: ea7d dmultu \$v0,\$v1 + 7ce: ea7e ddiv \$zero,\$v0,\$v1 + 7d0: 2b01 bnez \$v1,7d4 <insns2\+b4> + 7d2: e8e5 break 7 + 7d4: ea12 mflo \$v0 + 7d6: 6500 nop + 7d8: 6500 nop + 7da: ea7f ddivu \$zero,\$v0,\$v1 + 7dc: 2b01 bnez \$v1,7e0 <insns2\+c0> + 7de: e8e5 break 7 + 7e0: ea12 mflo \$v0 + 7e2: 6500 nop + 7e4: 6500 nop + 7e6: ea78 mult \$v0,\$v1 + 7e8: ea79 multu \$v0,\$v1 + 7ea: ea7a div \$zero,\$v0,\$v1 + 7ec: 2b01 bnez \$v1,7f0 <insns2\+d0> + 7ee: e8e5 break 7 + 7f0: ea12 mflo \$v0 + 7f2: 6500 nop + 7f4: 6500 nop + 7f6: ea7b divu \$zero,\$v0,\$v1 + 7f8: 2b01 bnez \$v1,7fc <insns2\+dc> + 7fa: e8e5 break 7 + 7fc: ea12 mflo \$v0 + 7fe: ea00 jr \$v0 + 800: 6500 nop + 802: e820 jr \$ra + 804: 6500 nop + 806: ea40 jalr \$v0 + 808: 6500 nop + 80a: f3ff 221b beqz \$v0,4 <insns1> + 80e: 2288 beqz \$v0,720 <insns2> + 810: 222b beqz \$v0,868 <bar> + 812: f080 220d beqz \$v0,930 <quux> + 816: f3ff 2a15 bnez \$v0,4 <insns1> + 81a: 2a82 bnez \$v0,720 <insns2> + 81c: 2a25 bnez \$v0,868 <bar> + 81e: f080 2a07 bnez \$v0,930 <quux> + 822: f3ff 600f bteqz 4 <insns1> + 826: f77f 601b bteqz 720 <insns2> + 82a: 601e bteqz 868 <bar> + 82c: f080 6000 bteqz 930 <quux> + 830: f3ff 6108 btnez 4 <insns1> + 834: f77f 6114 btnez 720 <insns2> + 838: 6117 btnez 868 <bar> + 83a: 617a btnez 930 <quux> + 83c: f3ff 1002 b 4 <insns1> + 840: 176f b 720 <insns2> + 842: 1012 b 868 <bar> + 844: 1075 b 930 <quux> + 846: e805 break 0 + 848: e825 break 1 + 84a: efe5 break 63 + 84c: 1800 0000 jal 0 <data1> + 84c: R_MIPS16_26 extern + 850: 6500 nop + 852: e809 entry + 854: e909 entry \$a0 + 856: eb49 entry \$a0-\$a2,\$s0 + 858: e8a9 entry \$s0-\$s1,\$ra + 85a: e829 entry \$ra + 85c: ef09 exit + 85e: ef49 exit \$s0 + 860: efa9 exit \$s0-\$s1,\$ra + 862: ef29 exit \$ra + 864: 0000 addiu \$s0,\$sp,0 + ... + +0+000868 <bar>: + ... diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/mips/mips16.s b/gnu/usr.bin/binutils/gas/testsuite/gas/mips/mips16.s new file mode 100644 index 00000000000..6268fb16506 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/mips/mips16.s @@ -0,0 +1,258 @@ +# Test the mips16 instruction set. + + .set mips16 + + .macro ldst op, reg, base + \op \reg,0(\base) + \op \reg,1(\base) + \op \reg,2(\base) + \op \reg,3(\base) + \op \reg,4(\base) + \op \reg,8(\base) + \op \reg,16(\base) + \op \reg,32(\base) + \op \reg,64(\base) + \op \reg,128(\base) + \op \reg,256(\base) + \op \reg,512(\base) + \op \reg,1024(\base) + \op \reg,2048(\base) + \op \reg,-1(\base) + \op \reg,-2(\base) + \op \reg,-3(\base) + \op \reg,-4(\base) + \op \reg,-8(\base) + \op \reg,-16(\base) + \op \reg,-32(\base) + \op \reg,-64(\base) + \op \reg,-128(\base) + \op \reg,-256(\base) + \op \reg,-512(\base) + \op \reg,-1024(\base) + \op \reg,-2048(\base) + .endm + + .p2align 3 +data1: + .word 0 +insns1: + ldst ld, $2, $3 + ld $2,data1 + ld $2,data2 + ld $2,bar + ld $2,quux + ldst ld, $2, $sp + ldst lwu, $2, $3 + ldst lw, $2, $3 + lw $2,data1 + lw $2,data2 + lw $2,bar + lw $2,quux + ldst lw, $2, $sp + ldst lh, $2, $3 + ldst lhu, $2, $3 + ldst lb, $2, $3 + ldst lbu, $2, $3 + ldst sd, $2, $3 + ldst sd, $2, $sp + ldst sd, $31, $sp + ldst sw, $2, $3 + ldst sw, $2, $sp + ldst sw, $31, $sp + ldst sh, $2, $3 + ldst sb, $2, $3 + + li $2,0 + li $2,1 + li $2,256 + + move $2,$30 + move $20,$2 + + daddu $2,$3,0 + daddu $2,$3,1 + daddu $2,$3,-1 + daddu $2,$3,16 + daddu $2,$3,-16 + daddu $2,$3,$4 + daddu $2,0 + daddu $2,1 + daddu $2,-1 + daddu $2,32 + daddu $2,-32 + daddu $2,128 + daddu $2,-128 + dla $2,data1 + dla $2,data2 + dla $2,bar + dla $2,quux + daddu $sp,0 + daddu $sp,1 + daddu $sp,-1 + daddu $sp,256 + daddu $sp,-256 + daddu $2,$sp,0 + daddu $2,$sp,1 + daddu $2,$sp,-1 + daddu $2,$sp,32 + daddu $2,$sp,-32 + daddu $2,$sp,128 + daddu $2,$sp,-128 + + addu $2,$3,0 + addu $2,$3,1 + addu $2,$3,-1 + addu $2,$3,16 + addu $2,$3,-16 + addu $2,$3,$4 + addu $2,0 + addu $2,1 + addu $2,-1 + addu $2,32 + addu $2,-32 + addu $2,128 + addu $2,-128 + la $2,data1 + la $2,data2 + la $2,bar + la $2,quux + addu $sp,0 + addu $sp,1 + addu $sp,-1 + addu $sp,256 + addu $sp,-256 + addu $2,$sp,0 + addu $2,$sp,1 + addu $2,$sp,-1 + addu $2,$sp,32 + addu $2,$sp,-32 + addu $2,$sp,128 + addu $2,$sp,-128 + +data2: + .word 0 +insns2: + dsubu $2,$3,$4 + subu $2,$3,$4 + neg $2,$3 + + and $2,$3 + or $2,$3 + xor $2,$3 + not $2,$3 + + slt $2,0 + slt $2,1 + slt $2,-1 + slt $2,255 + slt $2,256 + slt $2,$3 + sltu $2,0 + sltu $2,1 + sltu $2,-1 + sltu $2,255 + sltu $2,256 + sltu $2,$3 + cmp $2,0 + cmp $2,1 + cmp $2,255 + cmp $2,256 + cmp $2,$3 + + dsll $2,$3,0 + dsll $2,$3,1 + dsll $2,$3,8 + dsll $2,$3,9 + dsll $2,$3,63 + dsll $2,$3 + dsrl $2,0 + dsrl $2,1 + dsrl $2,8 + dsrl $2,9 + dsrl $2,63 + dsrl $2,$3 + dsra $2,0 + dsra $2,1 + dsra $2,8 + dsra $2,9 + dsra $2,63 + dsra $2,$3 + + mflo $2 + mfhi $3 + + sll $2,$3,0 + sll $2,$3,1 + sll $2,$3,8 + sll $2,$3,9 + sll $2,$3,31 + sll $2,$3 + srl $2,$3,0 + srl $2,$3,1 + srl $2,$3,8 + srl $2,$3,9 + srl $2,$3,31 + srl $2,$3 + sra $2,$3,0 + sra $2,$3,1 + sra $2,$3,8 + sra $2,$3,9 + sra $2,$3,31 + sra $2,$3 + + dmult $2,$3 + dmultu $2,$3 + ddiv $2,$3 + ddivu $2,$3 + + mult $2,$3 + multu $2,$3 + div $2,$3 + divu $2,$3 + + jr $2 + jr $31 + jalr $31,$2 + + beqz $2,insns1 + beqz $2,insns2 + beqz $2,bar + beqz $2,quux + bnez $2,insns1 + bnez $2,insns2 + bnez $2,bar + bnez $2,quux + bteqz insns1 + bteqz insns2 + bteqz bar + bteqz quux + btnez insns1 + btnez insns2 + btnez bar + btnez quux + b insns1 + b insns2 + b bar + b quux + + break 0 + break 1 + break 63 + + jal extern + + entry + entry $4 + entry $4-$6,$16 + entry $16-$17,$31 + entry $31 + exit + exit $16 + exit $16-$17,$31 + exit $31 + + .p2align 3 +bar: + + .skip 200 +quux: diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/add.s b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/add.s new file mode 100644 index 00000000000..ed251bc55ec --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/add.s @@ -0,0 +1,13 @@ + .text + add d1,d2 + add d2,a3 + add a2,d1 + add a3,a2 + add 16,d1 + add 256,d2 + add 131071,d3 + add 16,a1 + add 256,a2 + add 131071,a3 + addc d1,d2 + addnf 16,a2 diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/basic.exp b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/basic.exp new file mode 100644 index 00000000000..3793eb17ed3 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/basic.exp @@ -0,0 +1,836 @@ +# Copyright (C) 1996 Free Software Foundation, Inc. + +# 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +# Please email any bugs, comments, and/or additions to this file to: +# DejaGnu@cygnus.com + +# Written by Cygnus Support. + +proc do_add {} { + set testname "add.s: Add operations" + set x 0 + + gas_start "add.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 96\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0001 F20B\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0003 F2C9\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0005 F24E\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0007 D510\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0009 F71A0001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000d F463FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +8 +01\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0012 D110\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0014 F70A0001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0018 F467FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +11 +01\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 001d F286\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 001f F50E10\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==14] then { pass $testname } else { fail $testname } +} + +proc do_bcc {} { + set testname "bcc.s: Bcc tests" + set x 0 + + gas_start "bcc.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 E800\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0002 E900\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0004 E100\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0006 E200\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0008 E300\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000a E000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000c E500\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000e E600\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0010 E700\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0012 E400\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0014 F5FC00\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0017 F5FD00\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 001a F5FE00\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 001d F5FF00\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0020 EA00\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==15] then { pass $testname } else { fail $testname } +} + +proc do_bccx {} { + set testname "bccx.s: Bccx tests" + set x 0 + + gas_start "bccx.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 F5E800\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0003 F5E900\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0006 F5E100\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0009 F5E200\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000c F5E300\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000f F5E000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0012 F5E500\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0015 F5E600\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0018 F5E700\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 001b F5E400\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 001e F5EC00\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0021 F5ED00\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0024 F5EE00\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0027 F5EF00\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==14] then { pass $testname } else { fail $testname } +} + +proc do_bit {} { + set testname "bit.s: bit tests" + set x 0 + + gas_start "bit.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 F50540\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0003 F7060020\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0007 F029\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0009 F039\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +12 +FFFF40\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==4] then { pass $testname } else { fail $testname } +} + + +proc do_cmp {} { + set testname "cmp.s: cmp tests" + set x 0 + + gas_start "cmp.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 F396\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0002 F22B\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0004 F2EF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0006 F26E\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0008 DB10\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000a F74A0001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000e F479FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +8 +01\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0013 EE0001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0016 F47DFFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +10 +01\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==11] then { pass $testname } else { fail $testname } +} + +proc do_ext {} { + set testname "ext.s: ext tests" + set x 0 + + gas_start "ext.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 F3C5\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0002 B2\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0003 B7\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0004 BA\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0005 BD\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==5] then { pass $testname } else { fail $testname } +} + +proc do_extend {} { + set testname "extend.s: extended instruction tests" + set x 0 + + gas_start "extend.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 F505\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0002 F6FA\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0004 F606\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0006 F90210\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0009 FB030100\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000d FD030001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +7 +FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0013 F616\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0015 F91610\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0018 FB170100\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 001c FD170001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +11 +FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0022 F64B\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0024 F65E\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0026 F676\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==15] then { pass $testname } else { fail $testname } +} + +proc do_logical {} { + set testname "logical.s: logical tests" + set x 0 + + gas_start "logical.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 F306\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0002 F5027F\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0005 F703FF7F\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0009 F710FF7F\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000d F316\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000f F50A7F\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0012 F743FF7F\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0016 F714FF7F\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 001a F326\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 001c F74FFF7F\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0020 F3E7\[^\n\]*\n" { set x [expr $x+1] } + -re "^\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==11] then { pass $testname } else { fail $testname } +} + +proc do_loop {} { + set testname "loop.s: loop tests" + set x 0 + + gas_start "loop.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 D8\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0001 D9\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0002 D1\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0003 D2\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0004 D3\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0005 D0\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0006 D5\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0007 D6\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0008 D7\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0009 D4\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000a DA\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000b DB\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==12] then { pass $testname } else { fail $testname } +} + +proc do_mov1 {} { + set testname "mov1.s: mov1 tests" + set x 0 + + gas_start "mov1.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 F236\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0002 F2F9\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0004 86\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0005 F279\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0007 F3F3\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0009 F3D8\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000b F3E1\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000d F3C8\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000f 29\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0010 6908\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0012 F7C90001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0016 F489FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +13 +01\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==13] then { pass $testname } else { fail $testname } +} + +proc do_mov2 {} { + set testname "mov2.s: mov2 tests" + set x 0 + + gas_start "mov2.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 F156\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0002 C90080\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0005 F4C1FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +4 +01\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000a 7908\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000c F7B90001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0010 F4F9FFFF \[^\n\]*\n" { set x [expr $x+1] } + -re "^ +7 +01\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0015 F116\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0017 F7310080\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 001b F4D1FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +10 +01\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==12] then { pass $testname } else { fail $testname } +} + +proc do_mov3 {} { + set testname "mov3.s: mov3 tests" + set x 0 + + gas_start "mov3.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 09\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0001 4920\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0003 F7890001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0007 F409FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +5 +01\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000c F1E9\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000e C18000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0011 F441FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +8 +01\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0016 5920\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0018 F7A90001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 001c F419FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +11 +01\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==13] then { pass $testname } else { fail $testname } +} + +proc do_mov4 {} { + set testname "mov4.s: mov4 tests" + set x 0 + + gas_start "mov4.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 F1A9\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0002 F7218000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0006 F451FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +4 +01\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000b 8508\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000d F90001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0010 F471FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +7 +01\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0015 DD0001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0018 F475FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +9 +01\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==11] then { pass $testname } else { fail $testname } +} + +proc do_movx {} { + set testname "movx.s: movx tests" + set x 0 + + gas_start "movx.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 F57908\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0003 F7790001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0007 F4B9FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +4 +01\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000c F55908\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000f F7690001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0013 F439FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +7 +01\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==8] then { pass $testname } else { fail $testname } +} + +proc do_movb {} { + set testname "movb.s: movb tests" + set x 0 + + gas_start "movb.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 F52908\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0003 F7D90001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0007 F4A9FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +4 +01\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000c F06B\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000e F4C6FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +6 +01\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0013 19\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0014 F51908\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0017 F7990001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 001b F429FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +10 +01\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0020 F0E9\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0022 C50001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0025 F445FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +13 +01\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==16] then { pass $testname } else { fail $testname } +} + +proc do_movbu {} { + set testname "movbu.s: movbu tests" + set x 0 + + gas_start "movbu.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 39\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0001 F53908\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0004 F7590001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0008 F499FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +5 +01\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000d F096\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000f CD0080\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0012 F4C9FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +8 +01\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==9] then { pass $testname } else { fail $testname } +} + +proc do_movhu {} { + set testname "movhu.s: movhu tests" + set x 0 + + gas_start "movhu.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 F066\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0002 F86608\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0005 FA660100\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0009 FC660001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +5 +FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000f F8BD08\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0012 FABD0100\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0016 FCBD0001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +8 +FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 001c F4A5\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 001e 398000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0021 FCAD0001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +11 +FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0027 F076\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0029 F87620\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 002c FA760100\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0030 FC760001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +15 +FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0036 F89720\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0039 FA978000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 003d FC970001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +18 +FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0043 F4DA\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0045 070080\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0048 FC870001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +21 +FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==26] then { pass $testname } else { fail $testname } +} + +proc do_movm {} { + set testname "movm.s: movm tests" + set x 0 + + gas_start "movm.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 CE30\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0002 CEF8\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0004 CF30\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0006 CFF8\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==4] then { pass $testname } else { fail $testname } +} + +proc do_muldiv {} { + set testname "muldiv.s: muldiv tests" + set x 0 + + gas_start "muldiv.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 F346\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0002 F35B\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0004 F36E\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==3] then { pass $testname } else { fail $testname } +} + +proc do_other {} { + set testname "other.s: other tests" + set x 0 + + gas_start "other.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 FC0001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0003 F4E0FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +3 +01\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0008 F008\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000a FD0001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000d F4E1FFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +6 +01\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0012 F009\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0014 FE\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0015 EB\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0016 F6\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==11] then { pass $testname } else { fail $testname } +} + +proc do_shift {} { + set testname "shift.s: shift tests" + set x 0 + + gas_start "shift.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 F33A\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0002 F33F\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0004 F335\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0006 F332\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==4] then { pass $testname } else { fail $testname } +} + +proc do_sub {} { + set testname "sub.s: sub tests" + set x 0 + + gas_start "sub.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 A6\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0001 F21B\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0003 F2DF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0005 F25E\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0007 F71EFF7F \[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000b F46AFFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +7 +01\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0010 F70EFF7F \[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0014 F46EFFFF\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +9 +01\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0019 F296 \[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==11] then { pass $testname } else { fail $testname } +} + +if [istarget mn10200*-*-*] then { + # Test the basic instruction parser. + do_add + do_bcc + do_bccx + do_bit + do_cmp + do_ext + do_logical + do_mov1 + do_mov2 + do_mov3 + do_mov4 + do_movb + do_movx + do_movbu + do_muldiv + do_other + do_shift + do_sub +} diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/bcc.s b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/bcc.s new file mode 100644 index 00000000000..8292dce04fd --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/bcc.s @@ -0,0 +1,17 @@ + .text +foo: + beq foo + bne foo + bgt foo + bge foo + ble foo + blt foo + bhi foo + bcc foo + bls foo + bcs foo + bvc foo + bvs foo + bnc foo + bns foo + bra foo diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/bccx.s b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/bccx.s new file mode 100644 index 00000000000..e4e7edf5e30 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/bccx.s @@ -0,0 +1,16 @@ + .text +foo: + beqx foo + bnex foo + bgtx foo + bgex foo + blex foo + bltx foo + bhix foo + bccx foo + blsx foo + bcsx foo + bvcx foo + bvsx foo + bncx foo + bnsx foo diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/bit.s b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/bit.s new file mode 100644 index 00000000000..5db60d495bc --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/bit.s @@ -0,0 +1,5 @@ + .text + btst 64,d1 + btst 8192,d2 + bset d1,(a2) + bclr d1,(a2) diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/cmp.s b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/cmp.s new file mode 100644 index 00000000000..133925b38c5 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/cmp.s @@ -0,0 +1,10 @@ + .text + cmp d1,d2 + cmp d2,a3 + cmp a3,d3 + cmp a3,a2 + cmp 16,d3 + cmp 256,d2 + cmp 131071,d1 + cmp 256,a2 + cmp 131071,a1 diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/ext.s b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/ext.s new file mode 100644 index 00000000000..1be01bac89c --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/ext.s @@ -0,0 +1,7 @@ + .text + ext d1 + extx d2 + extxu d3 + extxb d2 + extxbu d1 + diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/logical.s b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/logical.s new file mode 100644 index 00000000000..0809d7f387f --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/logical.s @@ -0,0 +1,12 @@ + .text + and d1,d2 + and 127,d2 + and 32767,d3 + and 32767,psw + or d1,d2 + or 127,d2 + or 32767,d3 + or 32767,psw + xor d1,d2 + xor 32767,d3 + not d3 diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/mov1.s b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/mov1.s new file mode 100644 index 00000000000..c828e32e59d --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/mov1.s @@ -0,0 +1,13 @@ + .text + mov d1,a2 + mov a2,d1 + mov d1,d2 + mov a2,a1 + mov psw,d3 + mov d2,psw + mov mdr,d1 + mov d2,mdr + mov (a2),d1 + mov (8,a2),d1 + mov (256,a2),d1 + mov (131071,a2),d1 diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/mov2.s b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/mov2.s new file mode 100644 index 00000000000..8df6e2544c4 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/mov2.s @@ -0,0 +1,10 @@ + .text + mov (d1,a1),d2 + mov (32768),d1 + mov (131071),d1 + mov (8,a2),a1 + mov (256,a2),a1 + mov (131071,a2),a1 + mov (d1,a1),a2 + mov (32768),a1 + mov (131071),a1 diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/mov3.s b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/mov3.s new file mode 100644 index 00000000000..bd7490a35a6 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/mov3.s @@ -0,0 +1,11 @@ + .text + mov d1,(a2) + mov d1,(32,a2) + mov d1,(256,a2) + mov d1,(131071,a2) + mov d1,(d2,a2) + mov d1,(128) + mov d1,(131071) + mov a1,(32,a2) + mov a1,(256,a2) + mov a1,(131071,a2) diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/mov4.s b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/mov4.s new file mode 100644 index 00000000000..f1187e01fe8 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/mov4.s @@ -0,0 +1,9 @@ + .text + mov a1,(d2,a2) + mov a1,(128) + mov a1,(131071) + mov 8,d1 + mov 256,d1 + mov 131071,d1 + mov 256,a1 + mov 131071,a1 diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/movb.s b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/movb.s new file mode 100644 index 00000000000..25566147546 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/movb.s @@ -0,0 +1,13 @@ + .text + movb (8,a2),d1 + movb (256,a2),d1 + movb (131071,a2),d1 + movb (d2,a2),d3 + movb (131071),d2 + movb d1,(a2) + movb d1,(8,a2) + movb d1,(256,a2) + movb d1,(131071,a2) + movb d1,(d2,a2) + movb d1,(256) + movb d1,(131071) diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/movbu.s b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/movbu.s new file mode 100644 index 00000000000..01d973a1b14 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/movbu.s @@ -0,0 +1,8 @@ + .text + movbu (a2),d1 + movbu (8,a2),d1 + movbu (256,a2),d1 + movbu (131071,a2),d1 + movbu (d1,a1),d2 + movbu (32768),d1 + movbu (131071),d1 diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/movx.s b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/movx.s new file mode 100644 index 00000000000..70e1d714f5a --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/movx.s @@ -0,0 +1,7 @@ + .text + movx (8,a2),d1 + movx (256,a2),d1 + movx (131071,a2),d1 + movx d1,(8,a2) + movx d1,(256,a2) + movx d1,(131071,a2) diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/muldiv.s b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/muldiv.s new file mode 100644 index 00000000000..0f170265c8d --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/muldiv.s @@ -0,0 +1,4 @@ + .text + mul d1,d2 + mulu d2,d3 + divu d3,d2 diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/other.s b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/other.s new file mode 100644 index 00000000000..ecf94bdfd68 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/other.s @@ -0,0 +1,10 @@ + .text + jmp 256 + jmp 131071 + jmp (a2) + jsr 256 + jsr 131071 + jsr (a2) + rts + rti + nop diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/shift.s b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/shift.s new file mode 100644 index 00000000000..568e769f6fa --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/shift.s @@ -0,0 +1,5 @@ + .text + asr d2 + lsr d3 + ror d1 + rol d2 diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/sub.s b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/sub.s new file mode 100644 index 00000000000..25516548f57 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/mn10200/sub.s @@ -0,0 +1,10 @@ + .text + sub d1,d2 + sub d2,a3 + sub a3,d3 + sub a3,a2 + sub 32767,d2 + sub 131071,d2 + sub 32767,a2 + sub 131071,a2 + subc d1,d2 diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/mri/semi.d b/gnu/usr.bin/binutils/gas/testsuite/gas/mri/semi.d new file mode 100644 index 00000000000..0decce18472 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/mri/semi.d @@ -0,0 +1,9 @@ +#objdump: -s -j .text +#name: MRI semi +#as: -M + +.*: .* + +Contents of section .text: + 0000 3b203b20 3a203a20 00000000 00000000 ; ; : : ........ + 0010 00000000 00000000 00000000 00000000 ................ diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/mri/semi.s b/gnu/usr.bin/binutils/gas/testsuite/gas/mri/semi.s new file mode 100644 index 00000000000..5b30677c470 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/testsuite/gas/mri/semi.s @@ -0,0 +1,14 @@ +semicolon macro + dc.b '; ' + endm + +colon macro + dc.b ': ' + endm + + semicolon + dc.b '; ' + colon + dc.b ': ' + + p2align 5 diff --git a/gnu/usr.bin/binutils/include/callback.h b/gnu/usr.bin/binutils/include/callback.h new file mode 100644 index 00000000000..b2a7fe247d9 --- /dev/null +++ b/gnu/usr.bin/binutils/include/callback.h @@ -0,0 +1,99 @@ +/* Remote target system call callback support. + Copyright 1997 Free Software Foundation, Inc. + +This file is part of GDB. + +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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef CALLBACK_H +#define CALLBACK_H + +#ifndef va_start +#include <ansidecl.h> +#ifdef ANSI_PROTOTYPES +#include <stdarg.h> +#else +#include <varargs.h> +#endif +#endif + +typedef struct host_callback_struct host_callback; + +#define MAX_CALLBACK_FDS 10 + +struct host_callback_struct +{ + int (*close) PARAMS ((host_callback *,int)); + int (*get_errno) PARAMS ((host_callback *)); + int (*isatty) PARAMS ((host_callback *, int)); + int (*lseek) PARAMS ((host_callback *, int, long , int)); + int (*open) PARAMS ((host_callback *, const char*, int mode)); + int (*read) PARAMS ((host_callback *,int, char *, int)); + int (*read_stdin) PARAMS (( host_callback *, char *, int)); + int (*rename) PARAMS ((host_callback *, const char *, const char *)); + int (*system) PARAMS ((host_callback *, const char *)); + long (*time) PARAMS ((host_callback *, long *)); + int (*unlink) PARAMS ((host_callback *, const char *)); + int (*write) PARAMS ((host_callback *,int, const char *, int)); + int (*write_stdout) PARAMS ((host_callback *, const char *, int)); + void (*flush_stdout) PARAMS ((host_callback *)); + int (*write_stderr) PARAMS ((host_callback *, const char *, int)); + void (*flush_stderr) PARAMS ((host_callback *)); + + /* Used when the target has gone away, so we can close open + handles and free memory etc etc. */ + int (*shutdown) PARAMS ((host_callback *)); + int (*init) PARAMS ((host_callback *)); + + /* depreciated, use vprintf_filtered - Talk to the user on a console. */ + void (*printf_filtered) PARAMS ((host_callback *, const char *, ...)); + + /* Talk to the user on a console. + The `void *' is actually `va_list *'. */ + void (*vprintf_filtered) PARAMS ((host_callback *, const char *, va_list)); + + /* Same as vprintf_filtered but to stderr. */ + void (*evprintf_filtered) PARAMS ((host_callback *, const char *, va_list)); + + /* Print an error message and "exit". + In the case of gdb "exiting" means doing a longjmp back to the main + command loop. */ + void (*error) PARAMS ((host_callback *, const char *, ...)); + + int last_errno; /* host format */ + + int fdmap[MAX_CALLBACK_FDS]; + char fdopen[MAX_CALLBACK_FDS]; + char alwaysopen[MAX_CALLBACK_FDS]; +}; + +extern host_callback default_callback; + +/* Mapping of host/target values. */ +/* ??? For debugging purposes, one might want to add a string of the + name of the symbol. */ + +typedef struct { + int host_val; + int target_val; +} target_defs_map; + +extern target_defs_map errno_map[]; +extern target_defs_map open_map[]; + +extern int host_to_target_errno PARAMS ((int)); +extern int target_to_host_open PARAMS ((int)); + +#endif diff --git a/gnu/usr.bin/binutils/include/elf/alpha.h b/gnu/usr.bin/binutils/include/elf/alpha.h index 04ce3691412..8e12dd9aa32 100644 --- a/gnu/usr.bin/binutils/include/elf/alpha.h +++ b/gnu/usr.bin/binutils/include/elf/alpha.h @@ -64,10 +64,14 @@ typedef struct #define R_ALPHA_SREL16 9 /* PC relative 16 bit */ #define R_ALPHA_SREL32 10 /* PC relative 32 bit */ #define R_ALPHA_SREL64 11 /* PC relative 64 bit */ + +/* Inherited these from ECOFF, but they are not particularly useful + and are depreciated. And not implemented in the BFD, btw. */ #define R_ALPHA_OP_PUSH 12 /* OP stack push */ #define R_ALPHA_OP_STORE 13 /* OP stack pop and store */ #define R_ALPHA_OP_PSUB 14 /* OP stack subtract */ #define R_ALPHA_OP_PRSHIFT 15 /* OP stack right shift */ + #define R_ALPHA_GPVALUE 16 #define R_ALPHA_GPRELHIGH 17 #define R_ALPHA_GPRELLOW 18 @@ -76,6 +80,8 @@ typedef struct #define R_ALPHA_IMMED_SCN_HI32 21 #define R_ALPHA_IMMED_BR_HI32 22 #define R_ALPHA_IMMED_LO32 23 + +/* These relocations are specific to shared libraries. */ #define R_ALPHA_COPY 24 /* Copy symbol at runtime */ #define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */ #define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */ diff --git a/gnu/usr.bin/binutils/include/elf/dwarf2.h b/gnu/usr.bin/binutils/include/elf/dwarf2.h index 085ab797575..f2b2510f152 100644 --- a/gnu/usr.bin/binutils/include/elf/dwarf2.h +++ b/gnu/usr.bin/binutils/include/elf/dwarf2.h @@ -201,6 +201,10 @@ enum dwarf_attribute DW_AT_MIPS_loop_unroll_factor = 0x2005, DW_AT_MIPS_software_pipeline_depth = 0x2006, DW_AT_MIPS_linkage_name = 0x2007, + DW_AT_MIPS_stride = 0x2008, + DW_AT_MIPS_abstract_name = 0x2009, + DW_AT_MIPS_clone_origin = 0x200a, + DW_AT_MIPS_has_inlines = 0x200b, /* GNU extensions. */ DW_AT_sf_names = 0x2101, DW_AT_src_info = 0x2102, @@ -507,82 +511,6 @@ enum dwarf_call_frame_info #define DW_CFA_low_user 0x1c #define DW_CFA_high_user 0x3f -/* SGI/MIPS call frame register usage information */ -enum dwarf_call_reg_usage - { - DW_FRAME_CFA_COL = 0, - DW_FRAME_REG1 = 1, - DW_FRAME_REG2 = 2, - DW_FRAME_REG3 = 3, - DW_FRAME_REG4 = 4, - DW_FRAME_REG5 = 5, - DW_FRAME_REG6 = 6, - DW_FRAME_REG7 = 7, - DW_FRAME_REG8 = 8, - DW_FRAME_REG9 = 9, - DW_FRAME_REG10 = 10, - DW_FRAME_REG11 = 11, - DW_FRAME_REG12 = 12, - DW_FRAME_REG13 = 13, - DW_FRAME_REG14 = 14, - DW_FRAME_REG15 = 15, - DW_FRAME_REG16 = 16, - DW_FRAME_REG17 = 17, - DW_FRAME_REG18 = 18, - DW_FRAME_REG19 = 19, - DW_FRAME_REG20 = 20, - DW_FRAME_REG21 = 21, - DW_FRAME_REG22 = 22, - DW_FRAME_REG23 = 23, - DW_FRAME_REG24 = 24, - DW_FRAME_REG25 = 25, - DW_FRAME_REG26 = 26, - DW_FRAME_REG27 = 27, - DW_FRAME_REG28 = 28, - DW_FRAME_REG29 = 29, - DW_FRAME_REG30 = 30, - DW_FRAME_REG31 = 31, - DW_FRAME_FREG0 = 32, - DW_FRAME_FREG1 = 33, - DW_FRAME_FREG2 = 34, - DW_FRAME_FREG3 = 35, - DW_FRAME_FREG4 = 36, - DW_FRAME_FREG5 = 37, - DW_FRAME_FREG6 = 38, - DW_FRAME_FREG7 = 39, - DW_FRAME_FREG8 = 40, - DW_FRAME_FREG9 = 41, - DW_FRAME_FREG10 = 42, - DW_FRAME_FREG11 = 43, - DW_FRAME_FREG12 = 44, - DW_FRAME_FREG13 = 45, - DW_FRAME_FREG14 = 46, - DW_FRAME_FREG15 = 47, - DW_FRAME_FREG16 = 48, - DW_FRAME_FREG17 = 49, - DW_FRAME_FREG18 = 50, - DW_FRAME_FREG19 = 51, - DW_FRAME_FREG20 = 52, - DW_FRAME_FREG21 = 53, - DW_FRAME_FREG22 = 54, - DW_FRAME_FREG23 = 55, - DW_FRAME_FREG24 = 56, - DW_FRAME_FREG25 = 57, - DW_FRAME_FREG26 = 58, - DW_FRAME_FREG27 = 59, - DW_FRAME_FREG28 = 60, - DW_FRAME_FREG29 = 61, - DW_FRAME_FREG30 = 62, - DW_FRAME_FREG31 = 63, - DW_FRAME_RA_COL = 64, - DW_FRAME_STATIC_LINK = 65 - }; - -/* This is the number of columns in the Frame Table. */ -#define DW_FRAME_LAST_REG_NUM 66 - - - #define DW_CHILDREN_no 0x00 #define DW_CHILDREN_yes 0x01 @@ -609,7 +537,7 @@ enum dwarf_source_language #define DW_LANG_lo_user 0x8000 /* implementation-defined range start */ #define DW_LANG_hi_user 0xffff /* implementation-defined range start */ -/* Names and codes for GNU "macinfo" extension. */ +/* Names and codes for macro information. */ enum dwarf_macinfo_record_type { @@ -617,7 +545,7 @@ enum dwarf_macinfo_record_type DW_MACINFO_undef = 2, DW_MACINFO_start_file = 3, DW_MACINFO_end_file = 4, - DW_MACINFO_vend_ext = 255 + DW_MACINFO_vendor_ext = 255 }; #endif /* _ELF_DWARF2_H */ diff --git a/gnu/usr.bin/binutils/include/elf/m32r.h b/gnu/usr.bin/binutils/include/elf/m32r.h new file mode 100644 index 00000000000..92d9d75c68f --- /dev/null +++ b/gnu/usr.bin/binutils/include/elf/m32r.h @@ -0,0 +1,54 @@ +/* M32R ELF support for BFD. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + +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 2 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., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _ELF_M32R_H +#define _ELF_M32R_H + +enum reloc_type +{ + R_M32R_NONE = 0, + R_M32R_16, + R_M32R_32, + R_M32R_24, + R_M32R_10_PCREL, + R_M32R_18_PCREL, + R_M32R_26_PCREL, + R_M32R_HI16_ULO, + R_M32R_HI16_SLO, + R_M32R_LO16, + R_M32R_SDA16, + R_M32R_max +}; + +/* Processor specific section indices. These sections do not actually + exist. Symbols with a st_shndx field corresponding to one of these + values have a special meaning. */ + +/* Small common symbol. */ +#define SHN_M32R_SCOMMON 0xff00 + +/* Processor specific section flags. */ + +/* This section contains sufficient relocs to be relaxed. + When relaxing, even relocs of branch instructions the assembler could + complete must be present because relaxing may cause the branch target to + move. */ +#define SHF_M32R_CAN_RELAX 0x10000000 + +#endif diff --git a/gnu/usr.bin/binutils/include/objalloc.h b/gnu/usr.bin/binutils/include/objalloc.h new file mode 100644 index 00000000000..24f87f8749d --- /dev/null +++ b/gnu/usr.bin/binutils/include/objalloc.h @@ -0,0 +1,115 @@ +/* objalloc.h -- routines to allocate memory for objects + Copyright 1997 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Cygnus Solutions. + +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 2, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef OBJALLOC_H +#define OBJALLOC_H + +#include "ansidecl.h" + +/* These routines allocate space for an object. The assumption is + that the object will want to allocate space as it goes along, but + will never want to free any particular block. There is a function + to free a block, which also frees all more recently allocated + blocks. There is also a function to free all the allocated space. + + This is essentially a specialization of obstacks. The main + difference is that a block may not be allocated a bit at a time. + Another difference is that these routines are always built on top + of malloc, and always pass an malloc failure back to the caller, + unlike more recent versions of obstacks. */ + +/* This is what an objalloc structure looks like. Callers should not + refer to these fields, nor should they allocate these structure + themselves. Instead, they should only create them via + objalloc_init, and only access them via the functions and macros + listed below. The structure is only defined here so that we can + access it via macros. */ + +struct objalloc +{ + char *current_ptr; + unsigned int current_space; + PTR chunks; +}; + +/* Work out the required alignment. */ + +struct objalloc_align { char x; double d; }; + +#if defined (__STDC__) && __STDC__ +#ifndef offsetof +#include <stddef.h> +#endif +#define OBJALLOC_ALIGN \ + ((ptrdiff_t) ((char *) &((struct objalloc_align *) 0)->d - (char *) 0)) +#else +#define OBJALLOC_ALIGN \ + ((long) ((char *) &((struct objalloc_align *) 0)->d - (char *) 0)) +#endif + +/* Create an objalloc structure. Returns NULL if malloc fails. */ + +extern struct objalloc *objalloc_create PARAMS ((void)); + +/* Allocate space from an objalloc structure. Returns NULL if malloc + fails. */ + +extern PTR _objalloc_alloc PARAMS ((struct objalloc *, unsigned long)); + +/* The macro version of objalloc_alloc. We only define this if using + gcc, because otherwise we would have to evaluate the arguments + multiple times, or use a temporary field as obstack.h does. */ + +#if defined (__GNUC__) && defined (__STDC__) && __STDC__ + +/* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and + does not implement __extension__. But that compiler doesn't define + __GNUC_MINOR__. */ +#if __GNUC__ < 2 || (__NeXT__ && !__GNUC_MINOR__) +#define __extension__ +#endif + +#define objalloc_alloc(o, l) \ + __extension__ \ + ({ struct objalloc *__o = (o); \ + unsigned long __len = (l); \ + if (__len == 0) \ + __len = 1; \ + __len = (__len + OBJALLOC_ALIGN - 1) &~ (OBJALLOC_ALIGN - 1); \ + (__len <= __o->current_space \ + ? (__o->current_ptr += __len, \ + __o->current_space -= __len, \ + (PTR) (__o->current_ptr - __len)) \ + : _objalloc_alloc (__o, __len)); }) + +#else /* ! __GNUC__ */ + +#define objalloc_alloc(o, l) _objalloc_alloc ((o), (l)) + +#endif /* ! __GNUC__ */ + +/* Free an entire objalloc structure. */ + +extern void objalloc_free PARAMS ((struct objalloc *)); + +/* Free a block allocated by objalloc_alloc. This also frees all more + recently allocated blocks. */ + +extern void objalloc_free_block PARAMS ((struct objalloc *, PTR)); + +#endif /* OBJALLOC_H */ diff --git a/gnu/usr.bin/binutils/include/opcode/cgen.h b/gnu/usr.bin/binutils/include/opcode/cgen.h new file mode 100644 index 00000000000..cda3373fd33 --- /dev/null +++ b/gnu/usr.bin/binutils/include/opcode/cgen.h @@ -0,0 +1,686 @@ +/* Header file for targets using CGEN: Cpu tools GENerator. + +Copyright (C) 1996, 1997 Free Software Foundation, Inc. + +This file is part of GDB, the GNU debugger, and the GNU Binutils. + +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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef CGEN_H +#define CGEN_H + +#ifndef CGEN_CAT3 +#if defined(__STDC__) || defined(ALMOST_STDC) +#define CGEN_XCAT3(a,b,c) a ## b ## c +#define CGEN_CAT3(a,b,c) CGEN_XCAT3 (a, b, c) +#else +#define CGEN_CAT3(a,b,c) a/**/b/**/c +#endif +#endif + +/* Prepend the cpu name, defined in cpu-opc.h, and _cgen_ to symbol S. + The lack of spaces in the arg list is important for non-stdc systems. + This file is included by <cpu>-opc.h. + It can be included independently of cpu-opc.h, in which case the cpu + dependent portions will be declared as "unknown_cgen_foo". */ + +#ifndef CGEN_SYM +#define CGEN_SYM(s) CGEN_CAT3 (unknown,_cgen_,s) +#endif + +/* This file contains the static (unchanging) pieces and as much other stuff + as we can reasonably put here. It's generally cleaner to put stuff here + rather than having it machine generated if possible. */ + +/* The assembler syntax is made up of expressions (duh...). + At the lowest level the values are mnemonics, register names, numbers, etc. + Above that are subexpressions, if any (an example might be the + "effective address" in m68k cpus). At the second highest level are the + insns themselves. Above that are pseudo-insns, synthetic insns, and macros, + if any. +*/ + +/* Lots of cpu's have a fixed insn size, or one which rarely changes, + and it's generally easier to handle these by treating the insn as an + integer type, rather than an array of characters. So we allow targets + to control this. */ + +#ifdef CGEN_INT_INSN +typedef unsigned int cgen_insn_t; +#else +typedef char *cgen_insn_t; +#endif + +#ifdef __GNUC__ +#define CGEN_INLINE inline +#else +#define CGEN_INLINE +#endif + +/* Perhaps we should just use bfd.h, but it's not clear + one would want to require that yet. */ +enum cgen_endian { + CGEN_ENDIAN_UNKNOWN, + CGEN_ENDIAN_LITTLE, + CGEN_ENDIAN_BIG +}; + +/* Attributes. + Attributes are used to describe various random things. */ + +/* Struct to record attribute information. */ +typedef struct { + unsigned int num_nonbools; + unsigned int bool; + unsigned int nonbool[1]; +} CGEN_ATTR; + +/* Define a structure member for attributes with N non-boolean entries. + The attributes are sorted so that the non-boolean ones come first. + num_nonbools: count of nonboolean attributes + bool: values of boolean attributes + nonbool: values of non-boolean attributes + There is a maximum of 32 attributes total. */ +#define CGEN_ATTR_TYPE(n) \ +const struct { unsigned int num_nonbools; \ + unsigned int bool; \ + unsigned int nonbool[(n) ? (n) : 1]; } + +/* Given an attribute number, return its mask. */ +#define CGEN_ATTR_MASK(attr) (1 << (attr)) + +/* Return value of attribute ATTR in ATTR_TABLE for OBJ. + OBJ is a pointer to the entity that has the attributes. + It's not used at present but is reserved for future purposes. */ +#define CGEN_ATTR_VALUE(obj, attr_table, attr) \ +((unsigned int) (attr) < (attr_table)->num_nonbools \ + ? ((attr_table)->nonbool[attr]) \ + : (((attr_table)->bool & (1 << (attr))) != 0)) + +/* Parse result (also extraction result). + + The result of parsing an insn is stored here. + To generate the actual insn, this is passed to the insert handler. + When printing an insn, the result of extraction is stored here. + To print the insn, this is passed to the print handler. + + It is machine generated so we don't define it here, + but we do need a forward decl for the handler fns. + + There is one member for each possible field in the insn. + The type depends on the field. + Also recorded here is the computed length of the insn for architectures + where it varies. +*/ + +struct cgen_fields; + +/* Total length of the insn, as recorded in the `fields' struct. */ +/* ??? The field insert handler has lots of opportunities for optimization + if it ever gets inlined. On architectures where insns all have the same + size, may wish to detect that and make this macro a constant - to allow + further optimizations. */ +#define CGEN_FIELDS_BITSIZE(fields) ((fields)->length) + +/* Associated with each insn or expression is a set of "handlers" for + performing operations like parsing, printing, etc. */ + +/* Forward decl. */ +typedef struct cgen_insn CGEN_INSN; + +/* Parse handler. + The first argument is a pointer to a struct describing the insn being + parsed. + The second argument is a pointer to a pointer to the text being parsed. + The third argument is a pointer to a cgen_fields struct + in which the results are placed. + If the expression is successfully parsed, the pointer to the text is + updated. If not it is left alone. + The result is NULL if success or an error message. */ +typedef const char * (cgen_parse_fn) PARAMS ((const struct cgen_insn *, + const char **, + struct cgen_fields *)); + +/* Print handler. + The first argument is a pointer to the disassembly info. + Eg: disassemble_info. It's defined as `PTR' so this file can be included + without dis-asm.h. + The second argument is a pointer to a struct describing the insn being + printed. + The third argument is a pointer to a cgen_fields struct. + The fourth argument is the pc value of the insn. + The fifth argument is the length of the insn, in bytes. */ +/* Don't require bfd.h unnecessarily. */ +#ifdef BFD_VERSION +typedef void (cgen_print_fn) PARAMS ((PTR, const struct cgen_insn *, + struct cgen_fields *, bfd_vma, int)); +#else +typedef void (cgen_print_fn) (); +#endif + +/* Insert handler. + The first argument is a pointer to a struct describing the insn being + parsed. + The second argument is a pointer to a cgen_fields struct + from which the values are fetched. + The third argument is a pointer to a buffer in which to place the insn. */ +typedef void (cgen_insert_fn) PARAMS ((const struct cgen_insn *, + struct cgen_fields *, cgen_insn_t *)); + +/* Extract handler. + The first argument is a pointer to a struct describing the insn being + parsed. + The second argument is a pointer to a struct controlling extraction + (only used for variable length insns). + The third argument is the first CGEN_BASE_INSN_SIZE bytes. + The fourth argument is a pointer to a cgen_fields struct + in which the results are placed. + The result is the length of the insn or zero if not recognized. */ +typedef int (cgen_extract_fn) PARAMS ((const struct cgen_insn *, + void *, cgen_insn_t, + struct cgen_fields *)); + +/* The `parse' and `insert' fields are indices into these tables. + The elements are pointer to specialized handler functions. + Element 0 is special, it means use the default handler. */ +extern cgen_parse_fn * CGEN_SYM (parse_handlers) []; +#define CGEN_PARSE_FN(x) (CGEN_SYM (parse_handlers)[(x)->base.parse]) +extern cgen_insert_fn * CGEN_SYM (insert_handlers) []; +#define CGEN_INSERT_FN(x) (CGEN_SYM (insert_handlers)[(x)->base.insert]) + +/* Likewise for the `extract' and `print' fields. */ +extern cgen_extract_fn * CGEN_SYM (extract_handlers) []; +#define CGEN_EXTRACT_FN(x) (CGEN_SYM (extract_handlers)[(x)->base.extract]) +extern cgen_print_fn * CGEN_SYM (print_handlers) []; +#define CGEN_PRINT_FN(x) (CGEN_SYM (print_handlers)[(x)->base.print]) + +/* Base class of parser/printer. + (Don't read too much into the use of the phrase "base class"). + + Instructions and expressions all share this data in common. + It's a collection of the common elements needed to parse and print + each of them. */ + +#ifndef CGEN_MAX_INSN_ATTRS +#define CGEN_MAX_INSN_ATTRS 1 +#endif + +struct cgen_base { + /* Indices into the handler tables. + We could use pointers here instead, but in the case of the insn table, + 90% of them would be identical and that's a lot of redundant data. + 0 means use the default (what the default is is up to the code). */ + unsigned char parse, insert, extract, print; + + /* Attributes. */ + CGEN_ATTR_TYPE (CGEN_MAX_INSN_ATTRS) attrs; +}; + +/* Syntax table. + + Each insn and subexpression has one of these. + + The syntax "string" consists of characters (n > 0 && n < 128), and operand + values (n >= 128), and is terminated by 0. Operand values are 128 + index + into the operand table. The operand table doesn't exist in C, per se, as + the data is recorded in the parse/insert/extract/print switch statements. + + ??? Whether we want to use yacc instead is unclear, but we do make an + effort to not make doing that difficult. At least that's the intent. +*/ + +struct cgen_syntax { + /* Original syntax string, for debugging purposes. */ + char *orig; + + /* Name of entry (that distinguishes it from all other entries). + This is used, for example, in simulator profiling results. */ + char *name; + +#if 0 /* not needed yet */ + /* Format of this insn. + This doesn't closely follow the notion of instruction formats for more + complex instruction sets. This is the value computed at runtime. */ + enum cgen_fmt_type fmt; +#endif + + /* Mnemonic (or name if expression). */ + char *mnemonic; + + /* Syntax string. */ + /* FIXME: If each insn's mnemonic is constant, do we want to record just + the arguments here? */ +#ifndef CGEN_MAX_SYNTAX_BYTES +#define CGEN_MAX_SYNTAX_BYTES 16 +#endif + unsigned char syntax[CGEN_MAX_SYNTAX_BYTES]; + +#define CGEN_SYNTAX_CHAR_P(c) ((c) < 128) +#define CGEN_SYNTAX_CHAR(c) (c) +#define CGEN_SYNTAX_FIELD(c) ((c) - 128) + + /* recognize insn if (op & mask) == value + For architectures with variable length insns, this is just a preliminary + test. */ + /* FIXME: Might want a selectable type (rather than always + unsigned long). */ + unsigned long mask, value; + + /* length, in bits + This is the size that `mask' and `value' have been calculated to. + Normally it is CGEN_BASE_INSN_BITSIZE. On vliw architectures where + the base insn size may be larger than the size of an insn, this field is + less than CGEN_BASE_INSN_BITSIZE. + On architectures like the 386 and m68k the real size of the insn may + be computed while parsing. */ + /* FIXME: wip, of course */ + int length; +}; + +/* Operand values (keywords, integers, symbols, etc.) */ + +/* Types of assembler elements. */ + +enum cgen_asm_type { + CGEN_ASM_KEYWORD, CGEN_ASM_MAX +}; + +/* List of hardware elements. */ + +typedef struct cgen_hw_entry { + struct cgen_hw_entry *next; + char *name; + enum cgen_asm_type asm_type; + PTR asm_data; +} CGEN_HW_ENTRY; + +extern CGEN_HW_ENTRY *CGEN_SYM (hw_list); + +CGEN_HW_ENTRY *cgen_hw_lookup PARAMS ((const char *)); + +#ifndef CGEN_MAX_KEYWORD_ATTRS +#define CGEN_MAX_KEYWORD_ATTRS 1 +#endif + +/* This struct is used to describe things like register names, etc. */ + +typedef struct cgen_keyword_entry { + /* Name (as in register name). */ + char *name; + + /* Value (as in register number). + The value cannot be -1 as that is used to indicate "not found". + IDEA: Have "FUNCTION" attribute? [function is called to fetch value]. */ + int value; + + /* Attributes. */ + /* FIXME: Not used yet. */ + CGEN_ATTR_TYPE (CGEN_MAX_KEYWORD_ATTRS) attrs; + + /* Next name hash table entry. */ + struct cgen_keyword_entry *next_name; + /* Next value hash table entry. */ + struct cgen_keyword_entry *next_value; +} CGEN_KEYWORD_ENTRY; + +/* Top level struct for describing a set of related keywords + (e.g. register names). + + This struct supports runtime entry of new values, and hashed lookups. */ + +typedef struct cgen_keyword { + /* Pointer to initial [compiled in] values. */ + struct cgen_keyword_entry *init_entries; + /* Number of entries in `init_entries'. */ + unsigned int num_init_entries; + /* Hash table used for name lookup. */ + struct cgen_keyword_entry **name_hash_table; + /* Hash table used for value lookup. */ + struct cgen_keyword_entry **value_hash_table; + /* Number of entries in the hash_tables. */ + unsigned int hash_table_size; +} CGEN_KEYWORD; + +/* Structure used for searching. */ + +typedef struct cgen_keyword_search { + /* Table being searched. */ + const struct cgen_keyword *table; + /* Specification of what is being searched for. */ + const char *spec; + /* Current index in hash table. */ + unsigned int current_hash; + /* Current element in current hash chain. */ + struct cgen_keyword_entry *current_entry; +} CGEN_KEYWORD_SEARCH; + +/* Lookup a keyword from its name. */ +const struct cgen_keyword_entry * cgen_keyword_lookup_name + PARAMS ((struct cgen_keyword *, const char *)); +/* Lookup a keyword from its value. */ +const struct cgen_keyword_entry * cgen_keyword_lookup_value + PARAMS ((struct cgen_keyword *, int)); +/* Add a keyword. */ +void cgen_keyword_add PARAMS ((struct cgen_keyword *, + struct cgen_keyword_entry *)); +/* Keyword searching. + This can be used to retrieve every keyword, or a subset. */ +struct cgen_keyword_search cgen_keyword_search_init + PARAMS ((struct cgen_keyword *, const char *)); +const struct cgen_keyword_entry *cgen_keyword_search_next + PARAMS ((struct cgen_keyword_search *)); + +/* Operand value support routines. */ +/* FIXME: some of the long's here will need to be bfd_vma or some such. */ + +const char * cgen_parse_keyword PARAMS ((const char **, + struct cgen_keyword *, + long *)); +const char * cgen_parse_signed_integer PARAMS ((const char **, int, + long, long, long *)); +const char * cgen_parse_unsigned_integer PARAMS ((const char **, int, + unsigned long, unsigned long, + unsigned long *)); +const char * cgen_parse_address PARAMS ((const char **, int, + int, long *)); +const char * cgen_validate_signed_integer PARAMS ((long, long, long)); +const char * cgen_validate_unsigned_integer PARAMS ((unsigned long, + unsigned long, + unsigned long)); + +/* This struct defines each entry in the operand table. */ + +#ifndef CGEN_MAX_OPERAND_ATTRS +#define CGEN_MAX_OPERAND_ATTRS 1 +#endif + +typedef struct cgen_operand { + /* For debugging. */ + char *name; + + /* Bit position (msb of first byte = bit 0). + May be unused for a modifier. */ + unsigned char start; + + /* The number of bits in the operand. + May be unused for a modifier. */ + unsigned char length; + + /* Attributes. */ + CGEN_ATTR_TYPE (CGEN_MAX_OPERAND_ATTRS) attrs; +#define CGEN_OPERAND_ATTRS(operand) (&(operand)->attrs) + +#if 0 /* ??? Interesting idea but relocs tend to get too complicated for + simple table lookups to work. */ + /* Ideally this would be the internal (external?) reloc type. */ + int reloc_type; +#endif +} CGEN_OPERAND; + +/* Return value of attribute ATTR in OPERAND. */ +#define CGEN_OPERAND_ATTR(operand, attr) \ +CGEN_ATTR_VALUE (operand, CGEN_OPERAND_ATTRS (operand), attr) + +/* The operand table is currently a very static entity. */ +extern const CGEN_OPERAND CGEN_SYM (operand_table)[]; + +enum cgen_operand_type; + +#define CGEN_OPERAND_INDEX(operand) ((int) ((operand) - CGEN_SYM (operand_table))) +/* FIXME: Rename, cpu-opc.h defines this as the typedef of the enum. */ +#define CGEN_OPERAND_TYPE(operand) ((enum cgen_operand_type) CGEN_OPERAND_INDEX (operand)) +#define CGEN_OPERAND_ENTRY(n) (& CGEN_SYM (operand_table) [n]) + +/* This struct defines each entry in the instruction table. */ + +struct cgen_insn { + struct cgen_base base; +/* Given a pointer to a cgen_insn struct, return a pointer to `base'. */ +#define CGEN_INSN_BASE(insn) (&(insn)->base) +#define CGEN_INSN_ATTRS(insn) (&(insn)->base.attrs) + + struct cgen_syntax syntax; +#define CGEN_INSN_SYNTAX(insn) (&(insn)->syntax) +#define CGEN_INSN_FMT(insn) ((insn)->syntax.fmt) +#define CGEN_INSN_BITSIZE(insn) ((insn)->syntax.length) +}; + +/* Return value of attribute ATTR in INSN. */ +#define CGEN_INSN_ATTR(insn, attr) \ +CGEN_ATTR_VALUE (insn, CGEN_INSN_ATTRS (insn), attr) + +/* Instruction lists. + This is used for adding new entries and for creating the hash lists. */ + +typedef struct cgen_insn_list { + struct cgen_insn_list *next; + const struct cgen_insn *insn; +} CGEN_INSN_LIST; + +/* The table of instructions. */ + +typedef struct cgen_insn_table { + /* Pointer to initial [compiled in] entries. */ + const struct cgen_insn *init_entries; + /* Number of entries in `init_entries', including trailing NULL entry. */ + unsigned int num_init_entries; + /* Values added at runtime. */ + struct cgen_insn_list *new_entries; + /* Assembler hash function. */ + unsigned int (*asm_hash) PARAMS ((const char *)); + /* Number of entries in assembler hash table. */ + unsigned int asm_hash_table_size; + /* Disassembler hash function. */ + unsigned int (*dis_hash) PARAMS ((const char *, unsigned long)); + /* Number of entries in disassembler hash table. */ + unsigned int dis_hash_table_size; +} CGEN_INSN_TABLE; + +/* ??? This is currently used by the simulator. + We want this to be fast and the simulator currently doesn't handle + runtime added instructions so this is ok. An alternative would be to + store the index in the table. */ +extern const CGEN_INSN CGEN_SYM (insn_table_entries)[]; +#define CGEN_INSN_INDEX(insn) ((int) ((insn) - CGEN_SYM (insn_table_entries))) +#define CGEN_INSN_ENTRY(n) (& CGEN_SYM (insn_table_entries) [n]) + +/* Return number of instructions. This includes any added at runtime. */ + +int cgen_insn_count PARAMS (()); + +/* The assembler insn table is hashed based on some function of the mnemonic + (the actually hashing done is up to the target, but we provide a few + examples like the first letter or a function of the entire mnemonic). + The index of each entry is the index of the corresponding table entry. + The value of each entry is the index of the next entry, with a 0 + terminating (thus the first entry is reserved). */ + +#ifndef CGEN_ASM_HASH +#ifdef CGEN_MNEMONIC_OPERANDS +#define CGEN_ASM_HASH_SIZE 127 +#define CGEN_ASM_HASH(string) (*(unsigned char *) (string) % CGEN_ASM_HASH_SIZE) +#else +#define CGEN_ASM_HASH_SIZE 128 +#define CGEN_ASM_HASH(string) (*(unsigned char *) (string) % CGEN_ASM_HASH_SIZE) /*FIXME*/ +#endif +#endif + +unsigned int CGEN_SYM (asm_hash_insn) PARAMS ((const char *)); +CGEN_INSN_LIST * cgen_asm_lookup_insn PARAMS ((const char *)); +#define CGEN_ASM_LOOKUP_INSN(insn) cgen_asm_lookup_insn (insn) +#define CGEN_ASM_NEXT_INSN(insn) ((insn)->next) + +/* The disassembler insn table is hashed based on some function of machine + instruction (the actually hashing done is up to the target). */ + +/* It doesn't make much sense to provide a default here, + but while this is under development we do. + BUFFER is a pointer to the bytes of the insn. + INSN is the first CGEN_BASE_INSN_SIZE bytes as an int in host order. */ +#ifndef CGEN_DIS_HASH +#define CGEN_DIS_HASH_SIZE 256 +#define CGEN_DIS_HASH(buffer, insn) (*(unsigned char *) (buffer)) +#endif + +unsigned int CGEN_SYM (dis_hash_insn) PARAMS ((const char *, unsigned long)); +CGEN_INSN_LIST * cgen_dis_lookup_insn PARAMS ((const char *, unsigned long)); +#define CGEN_DIS_LOOKUP_INSN(buf, insn) cgen_dis_lookup_insn (buf, insn) +#define CGEN_DIS_NEXT_INSN(insn) ((insn)->next) + +/* Top level structures and functions. */ + +typedef struct cgen_opcode_data { + CGEN_HW_ENTRY *hw_list; + /*CGEN_OPERAND_TABLE *operand_table; - FIXME:wip */ + CGEN_INSN_TABLE *insn_table; +} CGEN_OPCODE_DATA; + +/* Each CPU has one of these. */ +extern CGEN_OPCODE_DATA CGEN_SYM (opcode_data); + +/* Global state access macros. + Some of these are tucked away and accessed with cover fns. + Simpler things like the current machine and endian are not. */ + +extern int cgen_current_machine; +#define CGEN_CURRENT_MACHINE cgen_current_machine + +extern enum cgen_endian cgen_current_endian; +#define CGEN_CURRENT_ENDIAN cgen_current_endian + +/* Prototypes of major functions. */ + +/* Set the current cpu (+ mach number, endian, etc.). *? +void cgen_set_cpu PARAMS ((CGEN_OPCODE_DATA *, int, enum cgen_endian)); + +/* Initialize the assembler, disassembler. */ +void cgen_asm_init PARAMS ((void)); +void cgen_dis_init PARAMS ((void)); + +/* `init_tables' must be called before `xxx_supported'. */ +void CGEN_SYM (init_tables) PARAMS ((int)); +void CGEN_SYM (init_asm) PARAMS ((int, enum cgen_endian)); +void CGEN_SYM (init_dis) PARAMS ((int, enum cgen_endian)); +void CGEN_SYM (init_parse) PARAMS ((void)); +void CGEN_SYM (init_print) PARAMS ((void)); +void CGEN_SYM (init_insert) PARAMS ((void)); +void CGEN_SYM (init_extract) PARAMS ((void)); +const struct cgen_insn * +CGEN_SYM (assemble_insn) PARAMS ((const char *, struct cgen_fields *, + cgen_insn_t *, char **)); +int CGEN_SYM (insn_supported) PARAMS ((const struct cgen_syntax *)); +#if 0 /* old */ +int CGEN_SYM (opval_supported) PARAMS ((const struct cgen_opval *)); +#endif + +extern const struct cgen_keyword CGEN_SYM (operand_mach); +int CGEN_SYM (get_mach) PARAMS ((const char *)); + +CGEN_INLINE void +CGEN_SYM (put_operand) PARAMS ((int, const long *, + struct cgen_fields *)); +CGEN_INLINE long +CGEN_SYM (get_operand) PARAMS ((int, const struct cgen_fields *)); + +CGEN_INLINE const char * +CGEN_SYM (parse_operand) PARAMS ((int, const char **, struct cgen_fields *)); + +CGEN_INLINE const char * +CGEN_SYM (validate_operand) PARAMS ((int, const struct cgen_fields *)); + +/* Default insn parser, printer. */ +extern cgen_parse_fn CGEN_SYM (parse_insn); +extern cgen_insert_fn CGEN_SYM (insert_insn); +extern cgen_extract_fn CGEN_SYM (extract_insn); +extern cgen_print_fn CGEN_SYM (print_insn); + +/* Read in a cpu description file. */ +const char * cgen_read_cpu_file PARAMS ((const char *)); + +/* Assembler interface. + + The interface to the assembler is intended to be clean in the sense that + libopcodes.a is a standalone entity and could be used with any assembler. + Not that one would necessarily want to do that but rather that it helps + keep a clean interface. The interface will obviously be slanted towards + GAS, but at least it's a start. + + Parsing is controlled by the assembler which calls + CGEN_SYM (assemble_insn). If it can parse and build the entire insn + it doesn't call back to the assembler. If it needs/wants to call back + to the assembler, (*cgen_parse_operand_fn) is called which can either + + - return a number to be inserted in the insn + - return a "register" value to be inserted + (the register might not be a register per pe) + - queue the argument and return a marker saying the expression has been + queued (eg: a fix-up) + - return an error message indicating the expression wasn't recognizable + + The result is an error message or NULL for success. + The parsed value is stored in the bfd_vma *. */ + +/* Values for indicating what the caller wants. */ +enum cgen_parse_operand_type { + CGEN_PARSE_OPERAND_INIT, CGEN_PARSE_OPERAND_INTEGER, + CGEN_PARSE_OPERAND_ADDRESS +}; + +/* Values for indicating what was parsed. + ??? Not too useful at present but in time. */ +enum cgen_parse_operand_result { + CGEN_PARSE_OPERAND_RESULT_NUMBER, CGEN_PARSE_OPERAND_RESULT_REGISTER, + CGEN_PARSE_OPERAND_RESULT_QUEUED, CGEN_PARSE_OPERAND_RESULT_ERROR +}; + +/* Don't require bfd.h unnecessarily. */ +#ifdef BFD_VERSION +extern const char * (*cgen_parse_operand_fn) + PARAMS ((enum cgen_parse_operand_type, const char **, int, int, + enum cgen_parse_operand_result *, bfd_vma *)); +#endif + +/* Called before trying to match a table entry with the insn. */ +void cgen_init_parse_operand PARAMS ((void)); + +/* Called from <cpu>-asm.c to initialize operand parsing. */ + +/* These are GAS specific. They're not here as part of the interface, + but rather that we need to put them somewhere. */ + +/* Call this from md_assemble to initialize the assembler callback. */ +void cgen_asm_init_parse PARAMS ((void)); + +/* Don't require bfd.h unnecessarily. */ +#ifdef BFD_VERSION +/* The result is an error message or NULL for success. + The parsed value is stored in the bfd_vma *. */ +const char *cgen_parse_operand PARAMS ((enum cgen_parse_operand_type, + const char **, int, int, + enum cgen_parse_operand_result *, + bfd_vma *)); +#endif + +/* Add a register to the assembler's hash table. + This makes lets GAS parse registers for us. + ??? This isn't currently used, but it could be in the future. */ +void cgen_asm_record_register PARAMS ((char *, int)); + +/* After CGEN_SYM (assemble_insn) is done, this is called to + output the insn and record any fixups. */ +void cgen_asm_finish_insn PARAMS ((const struct cgen_insn *, cgen_insn_t *, + unsigned int)); + +#endif /* CGEN_H */ diff --git a/gnu/usr.bin/binutils/include/opcode/d10v.h b/gnu/usr.bin/binutils/include/opcode/d10v.h new file mode 100644 index 00000000000..33d1af40c84 --- /dev/null +++ b/gnu/usr.bin/binutils/include/opcode/d10v.h @@ -0,0 +1,185 @@ +/* d10v.h -- Header file for D10V opcode table + Copyright 1996 Free Software Foundation, Inc. + Written by Martin Hunt (hunt@cygnus.com), Cygnus Support + +This file is part of GDB, GAS, and the GNU binutils. + +GDB, GAS, and the GNU binutils are free software; you can redistribute +them and/or modify them under the terms of the GNU General Public +License as published by the Free Software Foundation; either version +1, or (at your option) any later version. + +GDB, GAS, and the GNU binutils are distributed in the hope that they +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 file; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef D10V_H +#define D10V_H + +/* Format Specifier */ +#define FM00 0 +#define FM01 0x40000000 +#define FM10 0x80000000 +#define FM11 0xC0000000 + +#define NOP 0x5e00 +#define OPCODE_DIVS 0x14002800 + +/* The opcode table is an array of struct d10v_opcode. */ + +struct d10v_opcode +{ + /* The opcode name. */ + const char *name; + + /* the opcode format */ + int format; + + /* These numbers were picked so we can do if( i & SHORT_OPCODE) */ +#define SHORT_OPCODE 1 +#define LONG_OPCODE 8 +#define SHORT_2 1 /* short with 2 operands */ +#define SHORT_B 3 /* short with 8-bit branch */ +#define LONG_B 8 /* long with 16-bit branch */ +#define LONG_L 10 /* long with 3 operands */ +#define LONG_R 12 /* reserved */ + + /* just a placeholder for variable-length instructions */ + /* for example, "bra" will be a fake for "bra.s" and bra.l" */ + /* which will immediately follow in the opcode table. */ +#define OPCODE_FAKE 32 + + /* the number of cycles */ + int cycles; + + /* the execution unit(s) used */ + int unit; +#define EITHER 0 +#define IU 1 +#define MU 2 +#define BOTH 3 + + /* execution type; parallel or sequential */ + /* this field is used to decide if two instructions */ + /* can be executed in parallel */ + int exec_type; +#define PARONLY 1 /* parallel only */ +#define SEQ 2 /* must be sequential */ +#define PAR 4 /* may be parallel */ +#define BRANCH_LINK 8 /* subroutine call. must be aligned */ +#define RMEM 16 /* reads memory */ +#define WMEM 32 /* writes memory */ +#define RF0 64 /* reads f0 */ +#define WF0 128 /* modifies f0 */ +#define WCAR 256 /* write Carry */ +#define BRANCH 512 /* branch, no link */ + + /* the opcode */ + long opcode; + + /* mask. if( (i & mask) == opcode ) then match */ + long mask; + + /* An array of operand codes. Each code is an index into the + operand table. They appear in the order which the operands must + appear in assembly code, and are terminated by a zero. */ + unsigned char operands[6]; +}; + +/* The table itself is sorted by major opcode number, and is otherwise + in the order in which the disassembler should consider + instructions. */ +extern const struct d10v_opcode d10v_opcodes[]; +extern const int d10v_num_opcodes; + +/* The operands table is an array of struct d10v_operand. */ +struct d10v_operand +{ + /* The number of bits in the operand. */ + int bits; + + /* How far the operand is left shifted in the instruction. */ + int shift; + + /* One bit syntax flags. */ + int flags; +}; + +/* Elements in the table are retrieved by indexing with values from + the operands field of the d10v_opcodes table. */ + +extern const struct d10v_operand d10v_operands[]; + +/* Values defined for the flags field of a struct d10v_operand. */ + +/* the operand must be an even number */ +#define OPERAND_EVEN (1) + +/* the operand must be an odd number */ +#define OPERAND_ODD (2) + +/* this is the destination register; it will be modified */ +/* this is used by the optimizer */ +#define OPERAND_DEST (4) + +/* number or symbol */ +#define OPERAND_NUM (8) + +/* address or label */ +#define OPERAND_ADDR (0x10) + +/* register */ +#define OPERAND_REG (0x20) + +/* postincrement + */ +#define OPERAND_PLUS (0x40) + +/* postdecrement - */ +#define OPERAND_MINUS (0x80) + +/* @ */ +#define OPERAND_ATSIGN (0x100) + +/* @( */ +#define OPERAND_ATPAR (0x200) + +/* accumulator */ +#define OPERAND_ACC (0x400) + +/* flag register */ +#define OPERAND_FLAG (0x800) + +/* control register */ +#define OPERAND_CONTROL (0x1000) + +/* predecrement mode '@-sp' */ +#define OPERAND_ATMINUS (0x2000) + +/* signed number */ +#define OPERAND_SIGNED (0x4000) + +/* special accumulator shifts need a 4-bit number */ +/* 1 <= x <= 16 */ +#define OPERAND_SHIFT (0x8000) + +/* Structure to hold information about predefined registers. */ +struct pd_reg +{ + char *name; /* name to recognize */ + char *pname; /* name to print for this register */ + int value; +}; + +extern const struct pd_reg d10v_predefined_registers[]; +int d10v_reg_name_cnt(); + +/* an expressionS only has one register type, so we fake it */ +/* by setting high bits to indicate type */ +#define REGISTER_MASK 0xFF + +#endif /* D10V_H */ diff --git a/gnu/usr.bin/binutils/include/remote-sim.h b/gnu/usr.bin/binutils/include/remote-sim.h new file mode 100644 index 00000000000..77685d5eef3 --- /dev/null +++ b/gnu/usr.bin/binutils/include/remote-sim.h @@ -0,0 +1,144 @@ +/* This file defines the interface between the simulator and gdb. + Copyright (C) 1993, 1994, 1996, 1997 Free Software Foundation, Inc. + +This file is part of GDB. + +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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#if !defined (REMOTE_SIM_H) +#define REMOTE_SIM_H 1 + +/* This file is used when building stand-alone simulators, so isolate this + file from gdb. */ + +/* Pick up CORE_ADDR_TYPE if defined (from gdb), otherwise use same value as + gdb does (unsigned int - from defs.h). */ + +#ifndef CORE_ADDR_TYPE +typedef unsigned int SIM_ADDR; +#else +typedef CORE_ADDR_TYPE SIM_ADDR; +#endif + +/* Semi-opaque type used as result of sim_open and passed back to all + other routines. "desc" is short for "descriptor". + It is up to each simulator to define `sim_state'. */ + +typedef struct sim_state *SIM_DESC; + +/* Values for `kind' arg to sim_open. */ +typedef enum { + SIM_OPEN_STANDALONE, /* simulator used standalone (run.c) */ + SIM_OPEN_DEBUG /* simulator used by debugger (gdb) */ +} SIM_OPEN_KIND; + +/* Return codes from various functions. */ +typedef enum { + SIM_RC_FAIL = 0, + SIM_RC_OK = 1 +} SIM_RC; + +/* Main simulator entry points. */ + +/* Initialize the simulator. This function is called when the simulator + is selected from the gdb command line. + KIND specifies how the simulator will be used. Currently there are only + two kinds: standalone and debug. + ARGV is passed from the command line and can be used to select whatever + run time options the simulator provides. + ARGV is the standard NULL terminated array of pointers, with argv[0] + being the program name. + The result is a descriptor that must be passed back to the other sim_foo + functions. */ + +SIM_DESC sim_open PARAMS ((SIM_OPEN_KIND kind, char **argv)); + +/* Terminate usage of the simulator. This may involve freeing target memory + and closing any open files and mmap'd areas. You cannot assume sim_kill + has already been called. + QUITTING is non-zero if we cannot hang on errors. */ + +void sim_close PARAMS ((SIM_DESC sd, int quitting)); + +/* Load program PROG into the simulator. + Return non-zero if you wish the caller to handle it + (it is done this way because most simulators can use gr_load_image, + but defining it as a callback seems awkward). */ + +int sim_load PARAMS ((SIM_DESC sd, char *prog, int from_tty)); + +/* Prepare to run the simulated program. + START_ADDRESS is, yes, you guessed it, the start address of the program. + ARGV and ENV are NULL terminated lists of pointers. + Gdb will set the start address via sim_store_register as well, but + standalone versions of existing simulators are not set up to cleanly call + sim_store_register, so the START_ADDRESS argument is there as a + workaround. */ + +void sim_create_inferior PARAMS ((SIM_DESC sd, SIM_ADDR start_address, + char **argv, char **env)); + +/* Kill the running program. + This may involve closing any open files and deleting any mmap'd areas. */ + +void sim_kill PARAMS ((SIM_DESC sd)); + +/* Read LENGTH bytes of the simulated program's memory and store in BUF. + Result is number of bytes read, or zero if error. */ + +int sim_read PARAMS ((SIM_DESC sd, SIM_ADDR mem, unsigned char *buf, int length)); + +/* Store LENGTH bytes from BUF in the simulated program's memory. + Result is number of bytes write, or zero if error. */ + +int sim_write PARAMS ((SIM_DESC sd, SIM_ADDR mem, unsigned char *buf, int length)); + +/* Fetch register REGNO and store the raw value in BUF. */ + +void sim_fetch_register PARAMS ((SIM_DESC sd, int regno, unsigned char *buf)); + +/* Store register REGNO from BUF (in raw format). */ + +void sim_store_register PARAMS ((SIM_DESC sd, int regno, unsigned char *buf)); + +/* Print some interesting information about the simulator. + VERBOSE is non-zero for the wordy version. */ + +void sim_info PARAMS ((SIM_DESC sd, int verbose)); + +/* Fetch why the program stopped. + SIGRC will contain either the argument to exit() or the signal number. */ + +enum sim_stop { sim_exited, sim_stopped, sim_signalled }; + +void sim_stop_reason PARAMS ((SIM_DESC sd, enum sim_stop *reason, int *sigrc)); + +/* Run (or resume) the program. */ + +void sim_resume PARAMS ((SIM_DESC sd, int step, int siggnal)); + +/* Passthru for other commands that the simulator might support. + If SD is NULL, the command is to be interpreted as refering to + the global state, however the simulator defines that. */ + +void sim_do_command PARAMS ((SIM_DESC sd, char *cmd)); + +/* Provide simulator with a standard host_callback_struct. + If SD is NULL, the command is to be interpreted as refering to + the global state, however the simulator defines that. */ + +void sim_set_callbacks PARAMS ((SIM_DESC sd, struct host_callback_struct *)); + +#endif /* !defined (REMOTE_SIM_H) */ diff --git a/gnu/usr.bin/binutils/ld/configdoc.texi b/gnu/usr.bin/binutils/ld/configdoc.texi new file mode 100644 index 00000000000..3a367277e50 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/configdoc.texi @@ -0,0 +1,13 @@ +@c ------------------------------ CONFIGURATION VARS: +@c 1. Inclusiveness of this manual +@set GENERIC + +@c 2. Specific target machines +@set H8300 +@set I960 + +@c 3. Properties of this configuration +@clear SingleFormat +@set UsesEnvVars +@c ------------------------------ end CONFIGURATION VARS + diff --git a/gnu/usr.bin/binutils/ld/emulparams/d10velf.sh b/gnu/usr.bin/binutils/ld/emulparams/d10velf.sh new file mode 100644 index 00000000000..3597d6a3124 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/emulparams/d10velf.sh @@ -0,0 +1,8 @@ +MACHINE= +SCRIPT_NAME=elfd10v +OUTPUT_FORMAT="elf32-d10v" +TEXT_START_ADDR=0x1000000 +READONLY_START_ADDR=0x2000004 +ARCH=d10v +MAXPAGESIZE=32 +EMBEDDED=t diff --git a/gnu/usr.bin/binutils/ld/emulparams/elf32ebmip.sh b/gnu/usr.bin/binutils/ld/emulparams/elf32ebmip.sh index 3bc284e6d0c..a81a25dfe20 100644 --- a/gnu/usr.bin/binutils/ld/emulparams/elf32ebmip.sh +++ b/gnu/usr.bin/binutils/ld/emulparams/elf32ebmip.sh @@ -23,6 +23,7 @@ OTHER_SECTIONS=' .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) } ' ARCH=mips +MACHINE= TEMPLATE_NAME=elf32 GENERATE_SHLIB_SCRIPT=yes EMBEDDED=yes diff --git a/gnu/usr.bin/binutils/ld/emulparams/elf32elmip.sh b/gnu/usr.bin/binutils/ld/emulparams/elf32elmip.sh index c892dc17cbb..c3a69d93823 100644 --- a/gnu/usr.bin/binutils/ld/emulparams/elf32elmip.sh +++ b/gnu/usr.bin/binutils/ld/emulparams/elf32elmip.sh @@ -23,6 +23,7 @@ OTHER_SECTIONS=' .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) } ' ARCH=mips +MACHINE= TEMPLATE_NAME=elf32 GENERATE_SHLIB_SCRIPT=yes EMBEDDED=yes diff --git a/gnu/usr.bin/binutils/ld/emulparams/m32relf.sh b/gnu/usr.bin/binutils/ld/emulparams/m32relf.sh new file mode 100644 index 00000000000..eed56091d43 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/emulparams/m32relf.sh @@ -0,0 +1,12 @@ +MACHINE= +SCRIPT_NAME=elf +OUTPUT_FORMAT="elf32-m32r" +TEXT_START_ADDR=0x100 +ARCH=m32r +MACHINE= +MAXPAGESIZE=32 +EMBEDDED=yes + +# Hmmm, there's got to be a better way. This sets the stack to the +# top of the simulator memory (currently 1M). +OTHER_RELOCATING_SECTIONS='PROVIDE (_stack = 0x100000);' diff --git a/gnu/usr.bin/binutils/ld/emulparams/mipslnews.sh b/gnu/usr.bin/binutils/ld/emulparams/mipslnews.sh new file mode 100644 index 00000000000..d0bb91c1dc2 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/emulparams/mipslnews.sh @@ -0,0 +1,9 @@ +SCRIPT_NAME=mips +OUTPUT_FORMAT="ecoff-littlemips" +BIG_OUTPUT_FORMAT="ecoff-bigmips" +LITTLE_OUTPUT_FORMAT="ecoff-littlemips" +TARGET_PAGE_SIZE=0x1000000 +ARCH=mips +TEXT_START_ADDR=0x80080000 +DATA_ADDR=. +EMBEDDED=yes diff --git a/gnu/usr.bin/binutils/ld/emulparams/mn10200.sh b/gnu/usr.bin/binutils/ld/emulparams/mn10200.sh new file mode 100644 index 00000000000..afa46e2aa30 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/emulparams/mn10200.sh @@ -0,0 +1,20 @@ +MACHINE= +SCRIPT_NAME=elf +OUTPUT_FORMAT="elf32-mn10200" +TEXT_START_ADDR=0x0 +ARCH=mn10200 +MACHINE= +MAXPAGESIZE=256 +ENTRY=_start +EMBEDDED=yes + +# Hmmm, there's got to be a better way. This sets the stack to the +# top of the simulator memory (2^19 bytes). +OTHER_RELOCATING_SECTIONS='.stack 0x80000 : { _stack = .; *(.stack) }' + +# These are for compatibility with the COFF toolchain. +# XXX These should definitely disappear. +CTOR_START='___ctors = .;' +CTOR_END='___ctors_end = .;' +DTOR_START='___dtors = .;' +DTOR_END='___dtors_end = .;' diff --git a/gnu/usr.bin/binutils/ld/emulparams/mn10300.sh b/gnu/usr.bin/binutils/ld/emulparams/mn10300.sh new file mode 100644 index 00000000000..b5ae3b7ee87 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/emulparams/mn10300.sh @@ -0,0 +1,20 @@ +MACHINE= +SCRIPT_NAME=elf +OUTPUT_FORMAT="elf32-mn10300" +TEXT_START_ADDR=0x0 +ARCH=mn10300 +MACHINE= +MAXPAGESIZE=256 +ENTRY=_start +EMBEDDED=yes + +# Hmmm, there's got to be a better way. This sets the stack to the +# top of the simulator memory (2^19 bytes). +OTHER_RELOCATING_SECTIONS='.stack 0x80000 : { _stack = .; *(.stack) }' + +# These are for compatibility with the COFF toolchain. +# XXX These should definitely disappear. +CTOR_START='___ctors = .;' +CTOR_END='___ctors_end = .;' +DTOR_START='___dtors = .;' +DTOR_END='___dtors_end = .;' diff --git a/gnu/usr.bin/binutils/ld/emulparams/shelf.sh b/gnu/usr.bin/binutils/ld/emulparams/shelf.sh index a392e933c42..95db5877d7f 100644 --- a/gnu/usr.bin/binutils/ld/emulparams/shelf.sh +++ b/gnu/usr.bin/binutils/ld/emulparams/shelf.sh @@ -3,6 +3,7 @@ OUTPUT_FORMAT="elf32-sh" TEXT_START_ADDR=0x1000 MAXPAGESIZE=128 ARCH=sh +MACHINE= TEMPLATE_NAME=elf32 GENERATE_SHLIB_SCRIPT=yes EMBEDDED=yes diff --git a/gnu/usr.bin/binutils/ld/emulparams/shlelf.sh b/gnu/usr.bin/binutils/ld/emulparams/shlelf.sh index 93777f63de3..bb27f86af6c 100644 --- a/gnu/usr.bin/binutils/ld/emulparams/shlelf.sh +++ b/gnu/usr.bin/binutils/ld/emulparams/shlelf.sh @@ -3,6 +3,7 @@ OUTPUT_FORMAT="elf32-shl" TEXT_START_ADDR=0x1000 MAXPAGESIZE=128 ARCH=sh +MACHINE= TEMPLATE_NAME=elf32 GENERATE_SHLIB_SCRIPT=yes EMBEDDED=yes diff --git a/gnu/usr.bin/binutils/ld/emulparams/sparclinux.sh b/gnu/usr.bin/binutils/ld/emulparams/sparclinux.sh new file mode 100644 index 00000000000..7ccb0bec90c --- /dev/null +++ b/gnu/usr.bin/binutils/ld/emulparams/sparclinux.sh @@ -0,0 +1,7 @@ +SCRIPT_NAME=aout +OUTPUT_FORMAT="a.out-sparc-linux" +TARGET_PAGE_SIZE=0x1000 +TEXT_START_ADDR=0x1020 +NONPAGED_TEXT_START_ADDR=0 +ARCH=sparc +TEMPLATE_NAME=linux diff --git a/gnu/usr.bin/binutils/ld/ld.info-4 b/gnu/usr.bin/binutils/ld/ld.info-4 new file mode 100644 index 00000000000..2352b4ccae5 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/ld.info-4 @@ -0,0 +1,420 @@ +This is Info file ld.info, produced by Makeinfo-1.64 from the input +file ./ld.texinfo. + +START-INFO-DIR-ENTRY +* Ld: (ld). The GNU linker. +END-INFO-DIR-ENTRY + + This file documents the GNU linker LD. + + Copyright (C) 1991, 92, 93, 94, 95, 96, 1997 Free Software +Foundation, Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + + Permission is granted to copy and distribute modified versions of +this manual under the conditions for verbatim copying, provided also +that the entire resulting derived work is distributed under the terms +of a permission notice identical to this one. + + Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions. + + +File: ld.info, Node: Index, Prev: MRI, Up: Top + +Index +***** + +* Menu: + +* ": Symbols. +* *( COMMON ): Section Placement. +* *(SECTION): Section Placement. +* -(: Options. +* -architecture=ARCH: Options. +* -auxiliary: Options. +* -cref: Options. +* -defsym SYMBOL=EXP: Options. +* -discard-all: Options. +* -discard-locals: Options. +* -dynamic-linker FILE: Options. +* -embedded-relocs: Options. +* -entry=ENTRY: Options. +* -export-dynamic: Options. +* -filter: Options. +* -force-exe-suffix: Options. +* -format=FORMAT: Options. +* -gpsize: Options. +* -help: Options. +* -just-symbols=FILE: Options. +* -library-path=DIR: Options. +* -library=ARCHIVE: Options. +* -mri-script=MRI-CMDFILE: Options. +* -nmagic: Options. +* -no-keep-memory: Options. +* -no-whole-archive: Options. +* -noinhibit-exec: Options. +* -oformat: Options. +* -omagic: Options. +* -output=OUTPUT: Options. +* -print-map: Options. +* -relax: Options. +* -relocateable: Options. +* -script=SCRIPT: Options. +* -sort-common: Options. +* -split-by-file: Options. +* -split-by-reloc: Options. +* -stats: Options. +* -strip-all: Options. +* -strip-debug: Options. +* -trace: Options. +* -trace-symbol=SYMBOL: Options. +* -traditional-format: Options. +* -undefined=SYMBOL: Options. +* -verbose: Options. +* -version: Options. +* -version-script=VERSION-SCRIPTFILE: Options. +* -warn-comon: Options. +* -warn-constructors: Options. +* -warn-multiple-gp: Options. +* -warn-once: Options. +* -warn-section-align: Options. +* -whole-archive: Options. +* -wrap: Options. +* -AARCH: Options. +* -aKEYWORD: Options. +* -assert KEYWORD: Options. +* -b FORMAT: Options. +* -Bdynamic: Options. +* -Bshareable: Options. +* -Bstatic: Options. +* -Bsymbolic: Options. +* -c MRI-CMDFILE: Options. +* -call_shared: Options. +* -d: Options. +* -dc: Options. +* -dn: Options. +* -dp: Options. +* -dy: Options. +* -E: Options. +* -e ENTRY: Options. +* -EB: Options. +* -EL: Options. +* -f: Options. +* -G: Options. +* -hNAME: Options. +* -i: Options. +* -lARCHIVE: Options. +* -LDIR: Options. +* -M: Options. +* -m EMULATION: Options. +* -Map: Options. +* -n: Options. +* -non_shared: Options. +* -o OUTPUT: Options. +* -qmagic: Options. +* -Qy: Options. +* -r: Options. +* -R FILE: Options. +* -rpath: Options. +* -rpath-link: Options. +* -S: Options. +* -shared: Options. +* -soname=NAME: Options. +* -static: Options. +* -t: Options. +* -T SCRIPT: Options. +* -Tbss ORG: Options. +* -Tdata ORG: Options. +* -Ttext ORG: Options. +* -u SYMBOL: Options. +* -Ur: Options. +* -V: Options. +* -X: Options. +* -Y PATH: Options. +* -y SYMBOL: Options. +* -z KEYWORD: Options. +* .: Location Counter. +* 0x: Integers. +* :PHDR: Section Options. +* ;: Assignment. +* =FILL: Section Options. +* >REGION: Section Options. +* -relax on i960: i960. +* [SECTION...], not supported: Section Placement. +* ABSOLUTE (MRI): MRI. +* ALIAS (MRI): MRI. +* ALIGN (MRI): MRI. +* BASE (MRI): MRI. +* CHIP (MRI): MRI. +* END (MRI): MRI. +* FORMAT (MRI): MRI. +* ld bugs, reporting: Bug Reporting. +* LIST (MRI): MRI. +* LOAD (MRI): MRI. +* NAME (MRI): MRI. +* ORDER (MRI): MRI. +* PUBLIC (MRI): MRI. +* SECT (MRI): MRI. +* GNU linker: Overview. +* FILENAME: Section Placement. +* FILENAME(SECTION): Section Placement. +* SYMBOL = EXPRESSION ;: Section Data Expressions. +* SYMBOL F= EXPRESSION ;: Section Data Expressions. +* absolute and relocatable symbols: Assignment. +* ABSOLUTE(EXP): Arithmetic Functions. +* ADDR(SECTION): Arithmetic Functions. +* ALIGN(EXP): Arithmetic Functions. +* aligning sections: Section Options. +* allocating memory: MEMORY. +* architectures: Options. +* archive files, from cmd line: Options. +* arithmetic: Expressions. +* arithmetic operators: Operators. +* assignment in scripts: Assignment. +* assignment, in section defn: Section Data Expressions. +* AT ( LDADR ): Section Options. +* back end: BFD. +* BFD canonical format: Canonical format. +* BFD requirements: BFD. +* big-endian objects: Options. +* binary input files: Option Commands. +* binary input format: Options. +* BLOCK(ALIGN): Section Options. +* bug criteria: Bug Criteria. +* bug reports: Bug Reporting. +* bugs in ld: Reporting Bugs. +* BYTE(EXPRESSION): Section Data Expressions. +* C++ constructors, arranging in link: Option Commands. +* combining symbols, warnings on: Options. +* command files: Commands. +* command line: Options. +* commands, fundamental: Scripts. +* comments: Scripts. +* common allocation <1>: Option Commands. +* common allocation: Options. +* commons in output: Section Placement. +* compatibility, MRI: Options. +* CONSTRUCTORS: Option Commands. +* constructors: Options. +* constructors, arranging in link: Option Commands. +* contents of a section: Section Placement. +* crash of linker: Bug Criteria. +* CREATE_OBJECT_SYMBOLS: Section Data Expressions. +* cross reference table: Options. +* cross references: Option Commands. +* current output location: Location Counter. +* dbx: Options. +* decimal integers: Integers. +* default input format: Environment. +* DEFINED(SYMBOL): Arithmetic Functions. +* deleting local symbols: Options. +* direct output: Section Data Expressions. +* discontinuous memory: MEMORY. +* dot: Location Counter. +* dynamic linker, from command line: Options. +* dynamic symbol table: Options. +* ELF program headers: PHDRS. +* emulation: Options. +* endianness: Options. +* entry point, defaults: Entry Point. +* entry point, from command line: Options. +* ENTRY(SYMBOL): Entry Point. +* error on valid input: Bug Criteria. +* expression evaluation order: Evaluation. +* expression syntax: Expressions. +* expression, absolute: Arithmetic Functions. +* expressions in a section: Section Data Expressions. +* fatal signal: Bug Criteria. +* filename symbols: Section Data Expressions. +* files and sections, section defn: Section Placement. +* files, including in output sections: Section Placement. +* fill pattern, entire section: Section Options. +* FILL(EXPRESSION): Section Data Expressions. +* first input file: Option Commands. +* first instruction: Entry Point. +* FLOAT: Option Commands. +* FORCE_COMMON_ALLOCATION: Option Commands. +* format, output file: Option Commands. +* functions in expression language: Arithmetic Functions. +* fundamental script commands: Scripts. +* GNUTARGET <1>: Option Commands. +* GNUTARGET: Environment. +* GROUP ( FILES ): Option Commands. +* grouping input files: Option Commands. +* groups of archives: Options. +* H8/300 support: H8/300. +* header size: Arithmetic Functions. +* help: Options. +* hexadecimal integers: Integers. +* holes: Location Counter. +* holes, filling: Section Data Expressions. +* i960 support: i960. +* INCLUDE FILENAME: Option Commands. +* including a linker script: Option Commands. +* including an entire archive: Options. +* incremental link: Options. +* INPUT ( FILES ): Option Commands. +* input file format: Option Commands. +* input filename symbols: Section Data Expressions. +* input files, displaying: Options. +* input files, section defn: Section Placement. +* input format: Options. +* input sections to output section: Section Placement. +* integer notation: Integers. +* integer suffixes: Integers. +* internal object-file format: Canonical format. +* invalid input: Bug Criteria. +* K and M integer suffixes: Integers. +* l =: MEMORY. +* L, deleting symbols beginning: Options. +* layout of output file: Scripts. +* lazy evaluation: Evaluation. +* len =: MEMORY. +* LENGTH =: MEMORY. +* link map: Options. +* link-time runtime library search path: Options. +* linker crash: Bug Criteria. +* little-endian objects: Options. +* load address, specifying: Section Options. +* LOADADDR(SECTION): Arithmetic Functions. +* loading, preventing: Section Options. +* local symbols, deleting: Options. +* location counter: Location Counter. +* LONG(EXPRESSION): Section Data Expressions. +* M and K integer suffixes: Integers. +* machine architecture, output: Option Commands. +* machine dependencies: Machine Dependent. +* MAX: Arithmetic Functions. +* MEMORY: MEMORY. +* memory region attributes: MEMORY. +* memory regions and sections: Section Options. +* memory usage: Options. +* MIN: Arithmetic Functions. +* MIPS embedded PIC code: Options. +* MRI compatibility: MRI. +* names: Symbols. +* naming memory regions: MEMORY. +* naming output sections: Section Definition. +* naming the output file <1>: Option Commands. +* naming the output file: Options. +* negative integers: Integers. +* NEXT(EXP): Arithmetic Functions. +* NMAGIC: Options. +* NOCROSSREFS ( SECTIONS ): Option Commands. +* NOFLOAT: Option Commands. +* NOLOAD: Section Options. +* Non constant expression: Assignment. +* o =: MEMORY. +* objdump -i: BFD. +* object file management: BFD. +* object files: Options. +* object formats available: BFD. +* object size: Options. +* octal integers: Integers. +* OMAGIC: Options. +* opening object files: BFD outline. +* Operators for arithmetic: Operators. +* options: Options. +* org =: MEMORY. +* ORIGIN =: MEMORY. +* OUTPUT ( FILENAME ): Option Commands. +* output file after errors: Options. +* output file layout: Scripts. +* OUTPUT_ARCH ( BFDNAME ): Option Commands. +* OUTPUT_FORMAT ( BFDNAME ): Option Commands. +* OVERLAY: Overlays. +* overlays: Overlays. +* partial link: Options. +* path for libraries: Option Commands. +* PHDRS: PHDRS. +* precedence in expressions: Operators. +* prevent unnecessary loading: Section Options. +* program headers: PHDRS. +* program headers and sections: Section Options. +* provide: Assignment. +* QUAD(EXPRESSION): Section Data Expressions. +* quoted symbol names: Symbols. +* read-only text: Options. +* read/write from cmd line: Options. +* regions of memory: MEMORY. +* relaxing addressing modes: Options. +* relaxing on H8/300: H8/300. +* relaxing on i960: i960. +* relocatable and absolute symbols: Assignment. +* relocatable output: Options. +* reporting bugs in ld: Reporting Bugs. +* requirements for BFD: BFD. +* retaining specified symbols: Options. +* rounding up location counter: Arithmetic Functions. +* runtime library name: Options. +* runtime library search path: Options. +* scaled integers: Integers. +* script files: Options. +* search directory, from cmd line: Options. +* search path, libraries: Option Commands. +* SEARCH_DIR ( PATH ): Option Commands. +* section address <1>: Arithmetic Functions. +* section address: Section Options. +* section alignment: Section Options. +* section alignment, warnings on: Options. +* section definition: Section Definition. +* section defn, full syntax: Section Options. +* section fill pattern: Section Options. +* section load address: Arithmetic Functions. +* section size: Arithmetic Functions. +* section start: Section Options. +* section, assigning to memory region: Section Options. +* section, assigning to program header: Section Options. +* SECTIONS: SECTIONS. +* segment origins, cmd line: Options. +* semicolon: Assignment. +* shared libraries: Options. +* SHORT(EXPRESSION): Section Data Expressions. +* SIZEOF(SECTION): Arithmetic Functions. +* sizeof_headers: Arithmetic Functions. +* specify load address: Section Options. +* standard Unix system: Options. +* start address, section: Section Options. +* start of execution: Entry Point. +* STARTUP ( FILENAME ): Option Commands. +* strip all symbols: Options. +* strip debugger symbols: Options. +* stripping all but some symbols: Options. +* suffixes for integers: Integers. +* symbol defaults: Arithmetic Functions. +* symbol definition, scripts: Assignment. +* symbol names: Symbols. +* symbol tracing: Options. +* symbol versions: Version Script. +* symbol-only input: Options. +* symbols, from command line: Options. +* symbols, relocatable and absolute: Assignment. +* symbols, retaining selectively: Options. +* synthesizing linker: Options. +* synthesizing on H8/300: H8/300. +* TARGET ( FORMAT ): Option Commands. +* traditional format: Options. +* unallocated address, next: Arithmetic Functions. +* undefined symbol: Options. +* undefined symbols, warnings on: Options. +* uninitialized data: Section Placement. +* unspecified memory: Section Data Expressions. +* usage: Options. +* variables, defining: Assignment. +* verbose: Options. +* version: Options. +* VERSION {script text}: Version Script. +* version script: Version Script. +* version script, symbol versions: Options. +* versions of symbols: Version Script. +* warnings, on combining symbols: Options. +* warnings, on section alignment: Options. +* warnings, on undefined symbols: Options. +* what is this?: Overview. + + diff --git a/gnu/usr.bin/binutils/ld/mpw-elfmips.c b/gnu/usr.bin/binutils/ld/mpw-elfmips.c new file mode 100644 index 00000000000..ec88bb7493e --- /dev/null +++ b/gnu/usr.bin/binutils/ld/mpw-elfmips.c @@ -0,0 +1,1470 @@ +/* This file is is generated by a shell script. DO NOT EDIT! */ + +/* 32 bit ELF emulation code for elf32ebmip + Copyright (C) 1991, 93, 94, 95, 1996 Free Software Foundation, Inc. + Written by Steve Chamberlain <sac@cygnus.com> + ELF support by Ian Lance Taylor <ian@cygnus.com> + +This file is part of GLD, the Gnu Linker. + +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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#define TARGET_IS_elf32ebmip + +#include "bfd.h" +#include "sysdep.h" + +#include <ctype.h> + +#include "bfdlink.h" + +#include "ld.h" +#include "ldmain.h" +#include "ldemul.h" +#include "ldfile.h" +#include "ldmisc.h" +#include "ldexp.h" +#include "ldlang.h" +#include "ldgram.h" + +static void gldelf32ebmip_before_parse PARAMS ((void)); +static boolean gldelf32ebmip_open_dynamic_archive + PARAMS ((const char *, search_dirs_type *, lang_input_statement_type *)); +static void gldelf32ebmip_after_open PARAMS ((void)); +static void gldelf32ebmip_check_needed + PARAMS ((lang_input_statement_type *)); +static void gldelf32ebmip_stat_needed + PARAMS ((lang_input_statement_type *)); +static boolean gldelf32ebmip_search_needed + PARAMS ((const char *, const char *)); +static boolean gldelf32ebmip_try_needed PARAMS ((const char *)); +static void gldelf32ebmip_before_allocation PARAMS ((void)); +static void gldelf32ebmip_find_statement_assignment + PARAMS ((lang_statement_union_type *)); +static void gldelf32ebmip_find_exp_assignment PARAMS ((etree_type *)); +static boolean gldelf32ebmip_place_orphan + PARAMS ((lang_input_statement_type *, asection *)); +static void gldelf32ebmip_place_section + PARAMS ((lang_statement_union_type *)); +static char *gldelf32ebmip_get_script PARAMS ((int *isfile)); + +static void +gldelf32ebmip_before_parse() +{ + ldfile_output_architecture = bfd_arch_mips; + config.dynamic_link = true; +} + +/* Try to open a dynamic archive. This is where we know that ELF + dynamic libraries have an extension of .so. */ + +static boolean +gldelf32ebmip_open_dynamic_archive (arch, search, entry) + const char *arch; + search_dirs_type *search; + lang_input_statement_type *entry; +{ + const char *filename; + char *string; + + if (! entry->is_archive) + return false; + + filename = entry->filename; + + string = (char *) xmalloc (strlen (search->name) + + strlen (filename) + + strlen (arch) + + sizeof "/lib.so"); + + sprintf (string, "%s/lib%s%s.so", search->name, filename, arch); + + if (! ldfile_try_open_bfd (string, entry)) + { + free (string); + return false; + } + + entry->filename = string; + + /* We have found a dynamic object to include in the link. The ELF + backend linker will create a DT_NEEDED entry in the .dynamic + section naming this file. If this file includes a DT_SONAME + entry, it will be used. Otherwise, the ELF linker will just use + the name of the file. For an archive found by searching, like + this one, the DT_NEEDED entry should consist of just the name of + the file, without the path information used to find it. Note + that we only need to do this if we have a dynamic object; an + archive will never be referenced by a DT_NEEDED entry. + + FIXME: This approach--using bfd_elf_set_dt_needed_name--is not + very pretty. I haven't been able to think of anything that is + pretty, though. */ + if (bfd_check_format (entry->the_bfd, bfd_object) + && (entry->the_bfd->flags & DYNAMIC) != 0) + { + char *needed_name; + + ASSERT (entry->is_archive && entry->search_dirs_flag); + needed_name = (char *) xmalloc (strlen (filename) + + strlen (arch) + + sizeof "lib.so"); + sprintf (needed_name, "lib%s%s.so", filename, arch); + bfd_elf_set_dt_needed_name (entry->the_bfd, needed_name); + } + + return true; +} + + +/* These variables are required to pass information back and forth + between after_open and check_needed and stat_needed. */ + +static struct bfd_link_needed_list *global_needed; +static struct stat global_stat; +static boolean global_found; + +/* This is called after all the input files have been opened. */ + +static void +gldelf32ebmip_after_open () +{ + struct bfd_link_needed_list *needed, *l; + + /* We only need to worry about this when doing a final link. */ + if (link_info.relocateable || link_info.shared) + return; + + /* Get the list of files which appear in DT_NEEDED entries in + dynamic objects included in the link (often there will be none). + For each such file, we want to track down the corresponding + library, and include the symbol table in the link. This is what + the runtime dynamic linker will do. Tracking the files down here + permits one dynamic object to include another without requiring + special action by the person doing the link. Note that the + needed list can actually grow while we are stepping through this + loop. */ + needed = bfd_elf_get_needed_list (output_bfd, &link_info); + for (l = needed; l != NULL; l = l->next) + { + struct bfd_link_needed_list *ll; + const char *lib_path; + size_t len; + search_dirs_type *search; + + /* If we've already seen this file, skip it. */ + for (ll = needed; ll != l; ll = ll->next) + if (strcmp (ll->name, l->name) == 0) + break; + if (ll != l) + continue; + + /* See if this file was included in the link explicitly. */ + global_needed = l; + global_found = false; + lang_for_each_input_file (gldelf32ebmip_check_needed); + if (global_found) + continue; + + /* We need to find this file and include the symbol table. We + want to search for the file in the same way that the dynamic + linker will search. That means that we want to use + rpath_link, rpath, then the environment variable + LD_LIBRARY_PATH (native only), then the linker script + LIB_SEARCH_DIRS. We do not search using the -L arguments. */ + if (gldelf32ebmip_search_needed (command_line.rpath_link, + l->name)) + continue; + if (gldelf32ebmip_search_needed (command_line.rpath, l->name)) + continue; + if (command_line.rpath_link == NULL + && command_line.rpath == NULL) + { + lib_path = (const char *) getenv ("LD_RUN_PATH"); + if (gldelf32ebmip_search_needed (lib_path, l->name)) + continue; + } + len = strlen (l->name); + for (search = search_head; search != NULL; search = search->next) + { + char *filename; + + if (search->cmdline) + continue; + filename = (char *) xmalloc (strlen (search->name) + len + 2); + sprintf (filename, "%s/%s", search->name, l->name); + if (gldelf32ebmip_try_needed (filename)) + break; + free (filename); + } + if (search != NULL) + continue; + + einfo ("%P: warning: %s, needed by %B, not found\n", + l->name, l->by); + } +} + +/* Search for a needed file in a path. */ + +static boolean +gldelf32ebmip_search_needed (path, name) + const char *path; + const char *name; +{ + const char *s; + size_t len; + + if (path == NULL || *path == '\0') + return false; + len = strlen (name); + while (1) + { + char *filename, *sset; + + s = strchr (path, ':'); + if (s == NULL) + s = path + strlen (path); + + filename = (char *) xmalloc (s - path + len + 2); + if (s == path) + sset = filename; + else + { + memcpy (filename, path, s - path); + filename[s - path] = '/'; + sset = filename + (s - path) + 1; + } + strcpy (sset, name); + + if (gldelf32ebmip_try_needed (filename)) + return true; + + free (filename); + + if (*s == '\0') + break; + path = s + 1; + } + + return false; +} + +/* This function is called for each possible name for a dynamic object + named by a DT_NEEDED entry. */ + +static boolean +gldelf32ebmip_try_needed (name) + const char *name; +{ + bfd *abfd; + + abfd = bfd_openr (name, bfd_get_target (output_bfd)); + if (abfd == NULL) + return false; + if (! bfd_check_format (abfd, bfd_object)) + { + (void) bfd_close (abfd); + return false; + } + if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0) + { + (void) bfd_close (abfd); + return false; + } + + /* We've found a dynamic object matching the DT_NEEDED entry. */ + + /* We have already checked that there is no other input file of the + same name. We must now check again that we are not including the + same file twice. We need to do this because on many systems + libc.so is a symlink to, e.g., libc.so.1. The SONAME entry will + reference libc.so.1. If we have already included libc.so, we + don't want to include libc.so.1 if they are the same file, and we + can only check that using stat. */ + + if (bfd_stat (abfd, &global_stat) != 0) + einfo ("%F%P:%B: bfd_stat failed: %E\n", abfd); + global_found = false; + lang_for_each_input_file (gldelf32ebmip_stat_needed); + if (global_found) + { + /* Return true to indicate that we found the file, even though + we aren't going to do anything with it. */ + return true; + } + + /* Tell the ELF backend that don't want the output file to have a + DT_NEEDED entry for this file. */ + bfd_elf_set_dt_needed_name (abfd, ""); + + /* Add this file into the symbol table. */ + if (! bfd_link_add_symbols (abfd, &link_info)) + einfo ("%F%B: could not read symbols: %E\n", abfd); + + return true; +} + +/* See if an input file matches a DT_NEEDED entry by name. */ + +static void +gldelf32ebmip_check_needed (s) + lang_input_statement_type *s; +{ + if (global_found) + return; + + if (s->filename != NULL + && strcmp (s->filename, global_needed->name) == 0) + { + global_found = true; + return; + } + + if (s->the_bfd != NULL) + { + const char *soname; + + soname = bfd_elf_get_dt_soname (s->the_bfd); + if (soname != NULL + && strcmp (soname, global_needed->name) == 0) + { + global_found = true; + return; + } + } + + if (s->search_dirs_flag + && s->filename != NULL + && strchr (global_needed->name, '/') == NULL) + { + const char *f; + + f = strrchr (s->filename, '/'); + if (f != NULL + && strcmp (f + 1, global_needed->name) == 0) + { + global_found = true; + return; + } + } +} + +/* See if an input file matches a DT_NEEDED entry by running stat on + the file. */ + +static void +gldelf32ebmip_stat_needed (s) + lang_input_statement_type *s; +{ + struct stat st; + const char *suffix; + const char *soname; + const char *f; + + if (global_found) + return; + if (s->the_bfd == NULL) + return; + + if (bfd_stat (s->the_bfd, &st) != 0) + { + einfo ("%P:%B: bfd_stat failed: %E\n", s->the_bfd); + return; + } + + if (st.st_dev == global_stat.st_dev + && st.st_ino == global_stat.st_ino) + { + global_found = true; + return; + } + + /* We issue a warning if it looks like we are including two + different versions of the same shared library. For example, + there may be a problem if -lc picks up libc.so.6 but some other + shared library has a DT_NEEDED entry of libc.so.5. This is a + hueristic test, and it will only work if the name looks like + NAME.so.VERSION. FIXME: Depending on file names is error-prone. + If we really want to issue warnings about mixing version numbers + of shared libraries, we need to find a better way. */ + + if (strchr (global_needed->name, '/') != NULL) + return; + suffix = strstr (global_needed->name, ".so."); + if (suffix == NULL) + return; + suffix += sizeof ".so." - 1; + + soname = bfd_elf_get_dt_soname (s->the_bfd); + if (soname == NULL) + soname = s->filename; + + f = strrchr (soname, '/'); + if (f != NULL) + ++f; + else + f = soname; + + if (strncmp (f, global_needed->name, suffix - global_needed->name) == 0) + einfo ("%P: warning: %s, needed by %B, may conflict with %s\n", + global_needed->name, global_needed->by, f); +} + +/* This is called after the sections have been attached to output + sections, but before any sizes or addresses have been set. */ + +static void +gldelf32ebmip_before_allocation () +{ + const char *rpath; + asection *sinterp; + + /* If we are going to make any variable assignments, we need to let + the ELF backend know about them in case the variables are + referred to by dynamic objects. */ + lang_for_each_statement (gldelf32ebmip_find_statement_assignment); + + /* Let the ELF backend work out the sizes of any sections required + by dynamic linking. */ + rpath = command_line.rpath; + if (rpath == NULL) + rpath = (const char *) getenv ("LD_RUN_PATH"); + if (! bfd_elf32_size_dynamic_sections (output_bfd, + command_line.soname, + rpath, + command_line.export_dynamic, + &link_info, + &sinterp)) + einfo ("%P%F: failed to set dynamic section sizes: %E\n"); + + /* Let the user override the dynamic linker we are using. */ + if (command_line.interpreter != NULL + && sinterp != NULL) + { + sinterp->contents = (bfd_byte *) command_line.interpreter; + sinterp->_raw_size = strlen (command_line.interpreter) + 1; + } + + /* Look for any sections named .gnu.warning. As a GNU extensions, + we treat such sections as containing warning messages. We print + out the warning message, and then zero out the section size so + that it does not get copied into the output file. */ + + { + LANG_FOR_EACH_INPUT_STATEMENT (is) + { + asection *s; + bfd_size_type sz; + char *msg; + boolean ret; + + if (is->just_syms_flag) + continue; + + s = bfd_get_section_by_name (is->the_bfd, ".gnu.warning"); + if (s == NULL) + continue; + + sz = bfd_section_size (is->the_bfd, s); + msg = xmalloc ((size_t) sz + 1); + if (! bfd_get_section_contents (is->the_bfd, s, msg, (file_ptr) 0, sz)) + einfo ("%F%B: Can't read contents of section .gnu.warning: %E\n", + is->the_bfd); + msg[sz] = '\0'; + ret = link_info.callbacks->warning (&link_info, msg, + (const char *) NULL, + is->the_bfd, (asection *) NULL, + (bfd_vma) 0); + ASSERT (ret); + free (msg); + + /* Clobber the section size, so that we don't waste copying the + warning into the output file. */ + s->_raw_size = 0; + } + } + +#if defined (TARGET_IS_elf32bmip) || defined (TARGET_IS_elf32lmip) + /* For MIPS ELF the .reginfo section requires special handling. + Each input section is 24 bytes, and the final output section must + also be 24 bytes. We handle this by clobbering all but the first + input section size to 0. The .reginfo section is handled + specially by the backend code anyhow. */ + { + boolean found = false; + LANG_FOR_EACH_INPUT_STATEMENT (is) + { + asection *s; + + if (is->just_syms_flag) + continue; + + s = bfd_get_section_by_name (is->the_bfd, ".reginfo"); + if (s == NULL) + continue; + + if (! found) + { + found = true; + continue; + } + + s->_raw_size = 0; + s->_cooked_size = 0; + } + } +#endif +} + +/* This is called by the before_allocation routine via + lang_for_each_statement. It locates any assignment statements, and + tells the ELF backend about them, in case they are assignments to + symbols which are referred to by dynamic objects. */ + +static void +gldelf32ebmip_find_statement_assignment (s) + lang_statement_union_type *s; +{ + if (s->header.type == lang_assignment_statement_enum) + gldelf32ebmip_find_exp_assignment (s->assignment_statement.exp); +} + +/* Look through an expression for an assignment statement. */ + +static void +gldelf32ebmip_find_exp_assignment (exp) + etree_type *exp; +{ + struct bfd_link_hash_entry *h; + + switch (exp->type.node_class) + { + case etree_provide: + h = bfd_link_hash_lookup (link_info.hash, exp->assign.dst, + false, false, false); + if (h == NULL) + break; + + /* We call record_link_assignment even if the symbol is defined. + This is because if it is defined by a dynamic object, we + actually want to use the value defined by the linker script, + not the value from the dynamic object (because we are setting + symbols like etext). If the symbol is defined by a regular + object, then, as it happens, calling record_link_assignment + will do no harm. */ + + /* Fall through. */ + case etree_assign: + if (strcmp (exp->assign.dst, ".") != 0) + { + if (! (bfd_elf32_record_link_assignment + (output_bfd, &link_info, exp->assign.dst, + exp->type.node_class == etree_provide ? true : false))) + einfo ("%P%F: failed to record assignment to %s: %E\n", + exp->assign.dst); + } + gldelf32ebmip_find_exp_assignment (exp->assign.src); + break; + + case etree_binary: + gldelf32ebmip_find_exp_assignment (exp->binary.lhs); + gldelf32ebmip_find_exp_assignment (exp->binary.rhs); + break; + + case etree_trinary: + gldelf32ebmip_find_exp_assignment (exp->trinary.cond); + gldelf32ebmip_find_exp_assignment (exp->trinary.lhs); + gldelf32ebmip_find_exp_assignment (exp->trinary.rhs); + break; + + case etree_unary: + gldelf32ebmip_find_exp_assignment (exp->unary.child); + break; + + default: + break; + } +} + +/* Place an orphan section. We use this to put random SHF_ALLOC + sections in the right segment. */ + +static asection *hold_section; +static lang_output_section_statement_type *hold_use; +static lang_output_section_statement_type *hold_text; +static lang_output_section_statement_type *hold_rodata; +static lang_output_section_statement_type *hold_data; +static lang_output_section_statement_type *hold_bss; +static lang_output_section_statement_type *hold_rel; + +/*ARGSUSED*/ +static boolean +gldelf32ebmip_place_orphan (file, s) + lang_input_statement_type *file; + asection *s; +{ + lang_output_section_statement_type *place; + asection *snew, **pps; + lang_statement_list_type *old; + lang_statement_list_type add; + etree_type *address; + const char *secname, *ps; + lang_output_section_statement_type *os; + + if ((s->flags & SEC_ALLOC) == 0) + return false; + + /* Look through the script to see where to place this section. */ + hold_section = s; + hold_use = NULL; + lang_for_each_statement (gldelf32ebmip_place_section); + + if (hold_use != NULL) + { + /* We have already placed a section with this name. */ + wild_doit (&hold_use->children, s, hold_use, file); + return true; + } + + secname = bfd_get_section_name (s->owner, s); + + /* If this is a final link, then always put .gnu.warning.SYMBOL + sections into the .text section to get them out of the way. */ + if (! link_info.shared + && ! link_info.relocateable + && strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0 + && hold_text != NULL) + { + wild_doit (&hold_text->children, s, hold_text, file); + return true; + } + + /* Decide which segment the section should go in based on the + section name and section flags. */ + place = NULL; + if ((s->flags & SEC_HAS_CONTENTS) == 0 + && hold_bss != NULL) + place = hold_bss; + else if ((s->flags & SEC_READONLY) == 0 + && hold_data != NULL) + place = hold_data; + else if (strncmp (secname, ".rel", 4) == 0 + && hold_rel != NULL) + place = hold_rel; + else if ((s->flags & SEC_CODE) == 0 + && (s->flags & SEC_READONLY) != 0 + && hold_rodata != NULL) + place = hold_rodata; + else if ((s->flags & SEC_READONLY) != 0 + && hold_text != NULL) + place = hold_text; + if (place == NULL) + return false; + + /* Create the section in the output file, and put it in the right + place. This shuffling is to make the output file look neater. */ + snew = bfd_make_section (output_bfd, secname); + if (snew == NULL) + einfo ("%P%F: output format %s cannot represent section called %s\n", + output_bfd->xvec->name, secname); + if (place->bfd_section != NULL) + { + for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next) + ; + *pps = snew->next; + snew->next = place->bfd_section->next; + place->bfd_section->next = snew; + } + + /* Start building a list of statements for this section. */ + old = stat_ptr; + stat_ptr = &add; + lang_list_init (stat_ptr); + + /* If the name of the section is representable in C, then create + symbols to mark the start and the end of the section. */ + for (ps = secname; *ps != '\0'; ps++) + if (! isalnum (*ps) && *ps != '_') + break; + if (*ps == '\0' && config.build_constructors) + { + char *symname; + + symname = (char *) xmalloc (ps - secname + sizeof "__start_"); + sprintf (symname, "__start_%s", secname); + lang_add_assignment (exp_assop ('=', symname, + exp_unop (ALIGN_K, + exp_intop ((bfd_vma) 1 + << s->alignment_power)))); + } + + if (! link_info.relocateable) + address = NULL; + else + address = exp_intop ((bfd_vma) 0); + + lang_enter_output_section_statement (secname, address, 0, + (bfd_vma) 0, + (etree_type *) NULL, + (etree_type *) NULL, + (etree_type *) NULL); + + os = lang_output_section_statement_lookup (secname); + wild_doit (&os->children, s, os, file); + + lang_leave_output_section_statement ((bfd_vma) 0, "*default*"); + stat_ptr = &add; + + if (*ps == '\0' && config.build_constructors) + { + char *symname; + + symname = (char *) xmalloc (ps - secname + sizeof "__stop_"); + sprintf (symname, "__stop_%s", secname); + lang_add_assignment (exp_assop ('=', symname, + exp_nameop (NAME, "."))); + } + + /* Now stick the new statement list right after PLACE. */ + *add.tail = place->header.next; + place->header.next = add.head; + + stat_ptr = old; + + return true; +} + +static void +gldelf32ebmip_place_section (s) + lang_statement_union_type *s; +{ + lang_output_section_statement_type *os; + + if (s->header.type != lang_output_section_statement_enum) + return; + + os = &s->output_section_statement; + + if (strcmp (os->name, hold_section->name) == 0) + hold_use = os; + + if (strcmp (os->name, ".text") == 0) + hold_text = os; + else if (strcmp (os->name, ".rodata") == 0) + hold_rodata = os; + else if (strcmp (os->name, ".data") == 0) + hold_data = os; + else if (strcmp (os->name, ".bss") == 0) + hold_bss = os; + else if (hold_rel == NULL + && os->bfd_section != NULL + && strncmp (os->name, ".rel", 4) == 0) + hold_rel = os; +} + +static char * +gldelf32ebmip_get_script(isfile) + int *isfile; +{ + *isfile = 0; + + if (link_info.relocateable == true && config.build_constructors == true) + return "OUTPUT_FORMAT(\"elf32-bigmips\", \"elf32-bigmips\",\n\ + \"elf32-littlemips\")\n\ +OUTPUT_ARCH(mips)\n\ +ENTRY(_start)\n\ + /* For some reason, the Solaris linker makes bad executables\n\ + if gld -r is used and the intermediate file has sections starting\n\ + at non-zero addresses. Could be a Solaris ld bug, could be a GNU ld\n\ + bug. But for now assigning the zero vmas works. */\n\ +SECTIONS\n\ +{\n\ + /* Read-only sections, merged into text segment: */\n\ + .interp 0 : { *(.interp) }\n\ + .reginfo 0 : { *(.reginfo) }\n\ + .dynamic 0 : { *(.dynamic) }\n\ + .dynstr 0 : { *(.dynstr) }\n\ + .dynsym 0 : { *(.dynsym) }\n\ + .hash 0 : { *(.hash) }\n\ + .rel.text 0 : { *(.rel.text) }\n\ + .rela.text 0 : { *(.rela.text) }\n\ + .rel.data 0 : { *(.rel.data) }\n\ + .rela.data 0 : { *(.rela.data) }\n\ + .rel.rodata 0 : { *(.rel.rodata) }\n\ + .rela.rodata 0 : { *(.rela.rodata) }\n\ + .rel.got 0 : { *(.rel.got) }\n\ + .rela.got 0 : { *(.rela.got) }\n\ + .rel.ctors 0 : { *(.rel.ctors) }\n\ + .rela.ctors 0 : { *(.rela.ctors) }\n\ + .rel.dtors 0 : { *(.rel.dtors) }\n\ + .rela.dtors 0 : { *(.rela.dtors) }\n\ + .rel.init 0 : { *(.rel.init) }\n\ + .rela.init 0 : { *(.rela.init) }\n\ + .rel.fini 0 : { *(.rel.fini) }\n\ + .rela.fini 0 : { *(.rela.fini) }\n\ + .rel.bss 0 : { *(.rel.bss) }\n\ + .rela.bss 0 : { *(.rela.bss) }\n\ + .rel.plt 0 : { *(.rel.plt) }\n\ + .rela.plt 0 : { *(.rela.plt) }\n\ + .rodata 0 : { *(.rodata) }\n\ + .rodata1 0 : { *(.rodata1) }\n\ + .init 0 : { *(.init) } =0\n\ + .text 0 :\n\ + {\n\ + *(.text)\n\ + *(.stub)\n\ + /* .gnu.warning sections are handled specially by elf32.em. */\n\ + *(.gnu.warning)\n\ + } =0\n\ + .fini 0 : { *(.fini) } =0\n\ + /* Adjust the address for the data segment. We want to adjust up to\n\ + the same address within the page on the next page up. It would\n\ + be more correct to do this:\n\ + The current expression does not correctly handle the case of a\n\ + text segment ending precisely at the end of a page; it causes the\n\ + data segment to skip a page. The above expression does not have\n\ + this problem, but it will currently (2/95) cause BFD to allocate\n\ + a single segment, combining both text and data, for this case.\n\ + This will prevent the text segment from being shared among\n\ + multiple executions of the program; I think that is more\n\ + important than losing a page of the virtual address space (note\n\ + that no actual memory is lost; the page which is skipped can not\n\ + be referenced). */\n\ + .data 0 :\n\ + {\n\ + *(.data)\n\ + CONSTRUCTORS\n\ + }\n\ + .data1 0 : { *(.data1) }\n\ + .ctors 0 : { *(.ctors) }\n\ + .dtors 0 : { *(.dtors) }\n\ + .got 0 :\n\ + {\n\ + *(.got.plt) *(.got)\n\ + }\n\ + /* We want the small data sections together, so single-instruction offsets\n\ + can access them all, and initialized data all before uninitialized, so\n\ + we can shorten the on-disk segment size. */\n\ + .sdata 0 : { *(.sdata) }\n\ + .sbss 0 : { *(.sbss) *(.scommon) }\n\ + .bss 0 :\n\ + {\n\ + *(.dynbss)\n\ + *(.bss)\n\ + *(COMMON)\n\ + }\n\ + /* These are needed for ELF backends which have not yet been\n\ + converted to the new style linker. */\n\ + .stab 0 : { *(.stab) }\n\ + .stabstr 0 : { *(.stabstr) }\n\ + /* DWARF debug sections.\n\ + Symbols in the .debug DWARF section are relative to the beginning of the\n\ + section so we begin .debug at 0. It's not clear yet what needs to happen\n\ + for the others. */\n\ + .debug 0 : { *(.debug) }\n\ + .debug_srcinfo 0 : { *(.debug_srcinfo) }\n\ + .debug_aranges 0 : { *(.debug_aranges) }\n\ + .debug_pubnames 0 : { *(.debug_pubnames) }\n\ + .debug_sfnames 0 : { *(.debug_sfnames) }\n\ + .line 0 : { *(.line) }\n\ + /* These must appear regardless of . */\n\ + .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }\n\ + .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }\n\ +}\n\n"; + else if (link_info.relocateable == true) + return "OUTPUT_FORMAT(\"elf32-bigmips\", \"elf32-bigmips\",\n\ + \"elf32-littlemips\")\n\ +OUTPUT_ARCH(mips)\n\ +ENTRY(_start)\n\ + /* For some reason, the Solaris linker makes bad executables\n\ + if gld -r is used and the intermediate file has sections starting\n\ + at non-zero addresses. Could be a Solaris ld bug, could be a GNU ld\n\ + bug. But for now assigning the zero vmas works. */\n\ +SECTIONS\n\ +{\n\ + /* Read-only sections, merged into text segment: */\n\ + .interp 0 : { *(.interp) }\n\ + .reginfo 0 : { *(.reginfo) }\n\ + .dynamic 0 : { *(.dynamic) }\n\ + .dynstr 0 : { *(.dynstr) }\n\ + .dynsym 0 : { *(.dynsym) }\n\ + .hash 0 : { *(.hash) }\n\ + .rel.text 0 : { *(.rel.text) }\n\ + .rela.text 0 : { *(.rela.text) }\n\ + .rel.data 0 : { *(.rel.data) }\n\ + .rela.data 0 : { *(.rela.data) }\n\ + .rel.rodata 0 : { *(.rel.rodata) }\n\ + .rela.rodata 0 : { *(.rela.rodata) }\n\ + .rel.got 0 : { *(.rel.got) }\n\ + .rela.got 0 : { *(.rela.got) }\n\ + .rel.ctors 0 : { *(.rel.ctors) }\n\ + .rela.ctors 0 : { *(.rela.ctors) }\n\ + .rel.dtors 0 : { *(.rel.dtors) }\n\ + .rela.dtors 0 : { *(.rela.dtors) }\n\ + .rel.init 0 : { *(.rel.init) }\n\ + .rela.init 0 : { *(.rela.init) }\n\ + .rel.fini 0 : { *(.rel.fini) }\n\ + .rela.fini 0 : { *(.rela.fini) }\n\ + .rel.bss 0 : { *(.rel.bss) }\n\ + .rela.bss 0 : { *(.rela.bss) }\n\ + .rel.plt 0 : { *(.rel.plt) }\n\ + .rela.plt 0 : { *(.rela.plt) }\n\ + .rodata 0 : { *(.rodata) }\n\ + .rodata1 0 : { *(.rodata1) }\n\ + .init 0 : { *(.init) } =0\n\ + .text 0 :\n\ + {\n\ + *(.text)\n\ + *(.stub)\n\ + /* .gnu.warning sections are handled specially by elf32.em. */\n\ + *(.gnu.warning)\n\ + } =0\n\ + .fini 0 : { *(.fini) } =0\n\ + /* Adjust the address for the data segment. We want to adjust up to\n\ + the same address within the page on the next page up. It would\n\ + be more correct to do this:\n\ + The current expression does not correctly handle the case of a\n\ + text segment ending precisely at the end of a page; it causes the\n\ + data segment to skip a page. The above expression does not have\n\ + this problem, but it will currently (2/95) cause BFD to allocate\n\ + a single segment, combining both text and data, for this case.\n\ + This will prevent the text segment from being shared among\n\ + multiple executions of the program; I think that is more\n\ + important than losing a page of the virtual address space (note\n\ + that no actual memory is lost; the page which is skipped can not\n\ + be referenced). */\n\ + .data 0 :\n\ + {\n\ + *(.data)\n\ + }\n\ + .data1 0 : { *(.data1) }\n\ + .ctors 0 : { *(.ctors) }\n\ + .dtors 0 : { *(.dtors) }\n\ + .got 0 :\n\ + {\n\ + *(.got.plt) *(.got)\n\ + }\n\ + /* We want the small data sections together, so single-instruction offsets\n\ + can access them all, and initialized data all before uninitialized, so\n\ + we can shorten the on-disk segment size. */\n\ + .sdata 0 : { *(.sdata) }\n\ + .sbss 0 : { *(.sbss) *(.scommon) }\n\ + .bss 0 :\n\ + {\n\ + *(.dynbss)\n\ + *(.bss)\n\ + *(COMMON)\n\ + }\n\ + /* These are needed for ELF backends which have not yet been\n\ + converted to the new style linker. */\n\ + .stab 0 : { *(.stab) }\n\ + .stabstr 0 : { *(.stabstr) }\n\ + /* DWARF debug sections.\n\ + Symbols in the .debug DWARF section are relative to the beginning of the\n\ + section so we begin .debug at 0. It's not clear yet what needs to happen\n\ + for the others. */\n\ + .debug 0 : { *(.debug) }\n\ + .debug_srcinfo 0 : { *(.debug_srcinfo) }\n\ + .debug_aranges 0 : { *(.debug_aranges) }\n\ + .debug_pubnames 0 : { *(.debug_pubnames) }\n\ + .debug_sfnames 0 : { *(.debug_sfnames) }\n\ + .line 0 : { *(.line) }\n\ + /* These must appear regardless of . */\n\ + .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }\n\ + .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }\n\ +}\n\n"; + else if (!config.text_read_only) + return "OUTPUT_FORMAT(\"elf32-bigmips\", \"elf32-bigmips\",\n\ + \"elf32-littlemips\")\n\ +OUTPUT_ARCH(mips)\n\ +ENTRY(_start)\n\ + SEARCH_DIR(/usr/local/mips-elf/lib);\n\ +/* Do we need any of these for elf?\n\ + __DYNAMIC = 0; */\n\ +SECTIONS\n\ +{\n\ + /* Read-only sections, merged into text segment: */\n\ + . = 0x0400000;\n\ + .interp : { *(.interp) }\n\ + .reginfo : { *(.reginfo) }\n\ + .dynamic : { *(.dynamic) }\n\ + .dynstr : { *(.dynstr) }\n\ + .dynsym : { *(.dynsym) }\n\ + .hash : { *(.hash) }\n\ + .rel.text : { *(.rel.text) }\n\ + .rela.text : { *(.rela.text) }\n\ + .rel.data : { *(.rel.data) }\n\ + .rela.data : { *(.rela.data) }\n\ + .rel.rodata : { *(.rel.rodata) }\n\ + .rela.rodata : { *(.rela.rodata) }\n\ + .rel.got : { *(.rel.got) }\n\ + .rela.got : { *(.rela.got) }\n\ + .rel.ctors : { *(.rel.ctors) }\n\ + .rela.ctors : { *(.rela.ctors) }\n\ + .rel.dtors : { *(.rel.dtors) }\n\ + .rela.dtors : { *(.rela.dtors) }\n\ + .rel.init : { *(.rel.init) }\n\ + .rela.init : { *(.rela.init) }\n\ + .rel.fini : { *(.rel.fini) }\n\ + .rela.fini : { *(.rela.fini) }\n\ + .rel.bss : { *(.rel.bss) }\n\ + .rela.bss : { *(.rela.bss) }\n\ + .rel.plt : { *(.rel.plt) }\n\ + .rela.plt : { *(.rela.plt) }\n\ + .rodata : { *(.rodata) }\n\ + .rodata1 : { *(.rodata1) }\n\ + .init : { *(.init) } =0\n\ + .text :\n\ + {\n\ + _ftext = . ;\n\ + *(.text)\n\ + *(.stub)\n\ + /* .gnu.warning sections are handled specially by elf32.em. */\n\ + *(.gnu.warning)\n\ + } =0\n\ + _etext = .;\n\ + PROVIDE (etext = .);\n\ + .fini : { *(.fini) } =0\n\ + /* Adjust the address for the data segment. We want to adjust up to\n\ + the same address within the page on the next page up. It would\n\ + be more correct to do this:\n\ + . = .;\n\ + The current expression does not correctly handle the case of a\n\ + text segment ending precisely at the end of a page; it causes the\n\ + data segment to skip a page. The above expression does not have\n\ + this problem, but it will currently (2/95) cause BFD to allocate\n\ + a single segment, combining both text and data, for this case.\n\ + This will prevent the text segment from being shared among\n\ + multiple executions of the program; I think that is more\n\ + important than losing a page of the virtual address space (note\n\ + that no actual memory is lost; the page which is skipped can not\n\ + be referenced). */\n\ + . += . - 0x0400000;\n\ + .data :\n\ + {\n\ + _fdata = . ;\n\ + *(.data)\n\ + CONSTRUCTORS\n\ + }\n\ + .data1 : { *(.data1) }\n\ + .ctors : { *(.ctors) }\n\ + .dtors : { *(.dtors) }\n\ + _gp = ALIGN(16) + 0x7ff0;\n\ + .got :\n\ + {\n\ + *(.got.plt) *(.got)\n\ + }\n\ + /* We want the small data sections together, so single-instruction offsets\n\ + can access them all, and initialized data all before uninitialized, so\n\ + we can shorten the on-disk segment size. */\n\ + .sdata : { *(.sdata) }\n\ + .lit8 : { *(.lit8) }\n\ + .lit4 : { *(.lit4) }\n\ + _edata = .;\n\ + PROVIDE (edata = .);\n\ + __bss_start = .;\n\ + _fbss = .;\n\ + .sbss : { *(.sbss) *(.scommon) }\n\ + .bss :\n\ + {\n\ + *(.dynbss)\n\ + *(.bss)\n\ + *(COMMON)\n\ + }\n\ + _end = . ;\n\ + PROVIDE (end = .);\n\ + /* These are needed for ELF backends which have not yet been\n\ + converted to the new style linker. */\n\ + .stab 0 : { *(.stab) }\n\ + .stabstr 0 : { *(.stabstr) }\n\ + /* DWARF debug sections.\n\ + Symbols in the .debug DWARF section are relative to the beginning of the\n\ + section so we begin .debug at 0. It's not clear yet what needs to happen\n\ + for the others. */\n\ + .debug 0 : { *(.debug) }\n\ + .debug_srcinfo 0 : { *(.debug_srcinfo) }\n\ + .debug_aranges 0 : { *(.debug_aranges) }\n\ + .debug_pubnames 0 : { *(.debug_pubnames) }\n\ + .debug_sfnames 0 : { *(.debug_sfnames) }\n\ + .line 0 : { *(.line) }\n\ + /* These must appear regardless of . */\n\ + .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }\n\ + .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }\n\ +}\n\n"; + else if (!config.magic_demand_paged) + return "OUTPUT_FORMAT(\"elf32-bigmips\", \"elf32-bigmips\",\n\ + \"elf32-littlemips\")\n\ +OUTPUT_ARCH(mips)\n\ +ENTRY(_start)\n\ + SEARCH_DIR(/usr/local/mips-elf/lib);\n\ +/* Do we need any of these for elf?\n\ + __DYNAMIC = 0; */\n\ +SECTIONS\n\ +{\n\ + /* Read-only sections, merged into text segment: */\n\ + . = 0x0400000;\n\ + .interp : { *(.interp) }\n\ + .reginfo : { *(.reginfo) }\n\ + .dynamic : { *(.dynamic) }\n\ + .dynstr : { *(.dynstr) }\n\ + .dynsym : { *(.dynsym) }\n\ + .hash : { *(.hash) }\n\ + .rel.text : { *(.rel.text) }\n\ + .rela.text : { *(.rela.text) }\n\ + .rel.data : { *(.rel.data) }\n\ + .rela.data : { *(.rela.data) }\n\ + .rel.rodata : { *(.rel.rodata) }\n\ + .rela.rodata : { *(.rela.rodata) }\n\ + .rel.got : { *(.rel.got) }\n\ + .rela.got : { *(.rela.got) }\n\ + .rel.ctors : { *(.rel.ctors) }\n\ + .rela.ctors : { *(.rela.ctors) }\n\ + .rel.dtors : { *(.rel.dtors) }\n\ + .rela.dtors : { *(.rela.dtors) }\n\ + .rel.init : { *(.rel.init) }\n\ + .rela.init : { *(.rela.init) }\n\ + .rel.fini : { *(.rel.fini) }\n\ + .rela.fini : { *(.rela.fini) }\n\ + .rel.bss : { *(.rel.bss) }\n\ + .rela.bss : { *(.rela.bss) }\n\ + .rel.plt : { *(.rel.plt) }\n\ + .rela.plt : { *(.rela.plt) }\n\ + .rodata : { *(.rodata) }\n\ + .rodata1 : { *(.rodata1) }\n\ + .init : { *(.init) } =0\n\ + .text :\n\ + {\n\ + _ftext = . ;\n\ + *(.text)\n\ + *(.stub)\n\ + /* .gnu.warning sections are handled specially by elf32.em. */\n\ + *(.gnu.warning)\n\ + } =0\n\ + _etext = .;\n\ + PROVIDE (etext = .);\n\ + .fini : { *(.fini) } =0\n\ + /* Adjust the address for the data segment. We want to adjust up to\n\ + the same address within the page on the next page up. It would\n\ + be more correct to do this:\n\ + . = 0x10000000;\n\ + The current expression does not correctly handle the case of a\n\ + text segment ending precisely at the end of a page; it causes the\n\ + data segment to skip a page. The above expression does not have\n\ + this problem, but it will currently (2/95) cause BFD to allocate\n\ + a single segment, combining both text and data, for this case.\n\ + This will prevent the text segment from being shared among\n\ + multiple executions of the program; I think that is more\n\ + important than losing a page of the virtual address space (note\n\ + that no actual memory is lost; the page which is skipped can not\n\ + be referenced). */\n\ + . += 0x10000000 - 0x0400000;\n\ + .data :\n\ + {\n\ + _fdata = . ;\n\ + *(.data)\n\ + CONSTRUCTORS\n\ + }\n\ + .data1 : { *(.data1) }\n\ + .ctors : { *(.ctors) }\n\ + .dtors : { *(.dtors) }\n\ + _gp = ALIGN(16) + 0x7ff0;\n\ + .got :\n\ + {\n\ + *(.got.plt) *(.got)\n\ + }\n\ + /* We want the small data sections together, so single-instruction offsets\n\ + can access them all, and initialized data all before uninitialized, so\n\ + we can shorten the on-disk segment size. */\n\ + .sdata : { *(.sdata) }\n\ + .lit8 : { *(.lit8) }\n\ + .lit4 : { *(.lit4) }\n\ + _edata = .;\n\ + PROVIDE (edata = .);\n\ + __bss_start = .;\n\ + _fbss = .;\n\ + .sbss : { *(.sbss) *(.scommon) }\n\ + .bss :\n\ + {\n\ + *(.dynbss)\n\ + *(.bss)\n\ + *(COMMON)\n\ + }\n\ + _end = . ;\n\ + PROVIDE (end = .);\n\ + /* These are needed for ELF backends which have not yet been\n\ + converted to the new style linker. */\n\ + .stab 0 : { *(.stab) }\n\ + .stabstr 0 : { *(.stabstr) }\n\ + /* DWARF debug sections.\n\ + Symbols in the .debug DWARF section are relative to the beginning of the\n\ + section so we begin .debug at 0. It's not clear yet what needs to happen\n\ + for the others. */\n\ + .debug 0 : { *(.debug) }\n\ + .debug_srcinfo 0 : { *(.debug_srcinfo) }\n\ + .debug_aranges 0 : { *(.debug_aranges) }\n\ + .debug_pubnames 0 : { *(.debug_pubnames) }\n\ + .debug_sfnames 0 : { *(.debug_sfnames) }\n\ + .line 0 : { *(.line) }\n\ + /* These must appear regardless of . */\n\ + .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }\n\ + .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }\n\ +}\n\n"; + else if (link_info.shared) + return "OUTPUT_FORMAT(\"elf32-bigmips\", \"elf32-bigmips\",\n\ + \"elf32-littlemips\")\n\ +OUTPUT_ARCH(mips)\n\ +ENTRY(_start)\n\ + SEARCH_DIR(/usr/local/mips-elf/lib);\n\ +/* Do we need any of these for elf?\n\ + __DYNAMIC = 0; */\n\ +SECTIONS\n\ +{\n\ + /* Read-only sections, merged into text segment: */\n\ + . = 0x5ffe0000 + SIZEOF_HEADERS;\n\ + .reginfo : { *(.reginfo) }\n\ + .dynamic : { *(.dynamic) }\n\ + .dynstr : { *(.dynstr) }\n\ + .dynsym : { *(.dynsym) }\n\ + .hash : { *(.hash) }\n\ + .rel.text : { *(.rel.text) }\n\ + .rela.text : { *(.rela.text) }\n\ + .rel.data : { *(.rel.data) }\n\ + .rela.data : { *(.rela.data) }\n\ + .rel.rodata : { *(.rel.rodata) }\n\ + .rela.rodata : { *(.rela.rodata) }\n\ + .rel.got : { *(.rel.got) }\n\ + .rela.got : { *(.rela.got) }\n\ + .rel.ctors : { *(.rel.ctors) }\n\ + .rela.ctors : { *(.rela.ctors) }\n\ + .rel.dtors : { *(.rel.dtors) }\n\ + .rela.dtors : { *(.rela.dtors) }\n\ + .rel.init : { *(.rel.init) }\n\ + .rela.init : { *(.rela.init) }\n\ + .rel.fini : { *(.rel.fini) }\n\ + .rela.fini : { *(.rela.fini) }\n\ + .rel.bss : { *(.rel.bss) }\n\ + .rela.bss : { *(.rela.bss) }\n\ + .rel.plt : { *(.rel.plt) }\n\ + .rela.plt : { *(.rela.plt) }\n\ + .rodata : { *(.rodata) }\n\ + .rodata1 : { *(.rodata1) }\n\ + .init : { *(.init) } =0\n\ + .text :\n\ + {\n\ + *(.text)\n\ + *(.stub)\n\ + /* .gnu.warning sections are handled specially by elf32.em. */\n\ + *(.gnu.warning)\n\ + } =0\n\ + .fini : { *(.fini) } =0\n\ + /* Adjust the address for the data segment. We want to adjust up to\n\ + the same address within the page on the next page up. It would\n\ + be more correct to do this:\n\ + . = 0x10000000;\n\ + The current expression does not correctly handle the case of a\n\ + text segment ending precisely at the end of a page; it causes the\n\ + data segment to skip a page. The above expression does not have\n\ + this problem, but it will currently (2/95) cause BFD to allocate\n\ + a single segment, combining both text and data, for this case.\n\ + This will prevent the text segment from being shared among\n\ + multiple executions of the program; I think that is more\n\ + important than losing a page of the virtual address space (note\n\ + that no actual memory is lost; the page which is skipped can not\n\ + be referenced). */\n\ + . += 0x10000;\n\ + .data :\n\ + {\n\ + *(.data)\n\ + CONSTRUCTORS\n\ + }\n\ + .data1 : { *(.data1) }\n\ + .ctors : { *(.ctors) }\n\ + .dtors : { *(.dtors) }\n\ + _gp = ALIGN(16) + 0x7ff0;\n\ + .got :\n\ + {\n\ + *(.got.plt) *(.got)\n\ + }\n\ + /* We want the small data sections together, so single-instruction offsets\n\ + can access them all, and initialized data all before uninitialized, so\n\ + we can shorten the on-disk segment size. */\n\ + .sdata : { *(.sdata) }\n\ + .lit8 : { *(.lit8) }\n\ + .lit4 : { *(.lit4) }\n\ + .sbss : { *(.sbss) *(.scommon) }\n\ + .bss :\n\ + {\n\ + *(.dynbss)\n\ + *(.bss)\n\ + *(COMMON)\n\ + }\n\ + /* These are needed for ELF backends which have not yet been\n\ + converted to the new style linker. */\n\ + .stab 0 : { *(.stab) }\n\ + .stabstr 0 : { *(.stabstr) }\n\ + /* DWARF debug sections.\n\ + Symbols in the .debug DWARF section are relative to the beginning of the\n\ + section so we begin .debug at 0. It's not clear yet what needs to happen\n\ + for the others. */\n\ + .debug 0 : { *(.debug) }\n\ + .debug_srcinfo 0 : { *(.debug_srcinfo) }\n\ + .debug_aranges 0 : { *(.debug_aranges) }\n\ + .debug_pubnames 0 : { *(.debug_pubnames) }\n\ + .debug_sfnames 0 : { *(.debug_sfnames) }\n\ + .line 0 : { *(.line) }\n\ + /* These must appear regardless of . */\n\ + .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }\n\ + .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }\n\ +}\n\n"; + else + return "OUTPUT_FORMAT(\"elf32-bigmips\", \"elf32-bigmips\",\n\ + \"elf32-littlemips\")\n\ +OUTPUT_ARCH(mips)\n\ +ENTRY(_start)\n\ + SEARCH_DIR(/usr/local/mips-elf/lib);\n\ +/* Do we need any of these for elf?\n\ + __DYNAMIC = 0; */\n\ +SECTIONS\n\ +{\n\ + /* Read-only sections, merged into text segment: */\n\ + . = 0x0400000;\n\ + .interp : { *(.interp) }\n\ + .reginfo : { *(.reginfo) }\n\ + .dynamic : { *(.dynamic) }\n\ + .dynstr : { *(.dynstr) }\n\ + .dynsym : { *(.dynsym) }\n\ + .hash : { *(.hash) }\n\ + .rel.text : { *(.rel.text) }\n\ + .rela.text : { *(.rela.text) }\n\ + .rel.data : { *(.rel.data) }\n\ + .rela.data : { *(.rela.data) }\n\ + .rel.rodata : { *(.rel.rodata) }\n\ + .rela.rodata : { *(.rela.rodata) }\n\ + .rel.got : { *(.rel.got) }\n\ + .rela.got : { *(.rela.got) }\n\ + .rel.ctors : { *(.rel.ctors) }\n\ + .rela.ctors : { *(.rela.ctors) }\n\ + .rel.dtors : { *(.rel.dtors) }\n\ + .rela.dtors : { *(.rela.dtors) }\n\ + .rel.init : { *(.rel.init) }\n\ + .rela.init : { *(.rela.init) }\n\ + .rel.fini : { *(.rel.fini) }\n\ + .rela.fini : { *(.rela.fini) }\n\ + .rel.bss : { *(.rel.bss) }\n\ + .rela.bss : { *(.rela.bss) }\n\ + .rel.plt : { *(.rel.plt) }\n\ + .rela.plt : { *(.rela.plt) }\n\ + .rodata : { *(.rodata) }\n\ + .rodata1 : { *(.rodata1) }\n\ + .init : { *(.init) } =0\n\ + .text :\n\ + {\n\ + _ftext = . ;\n\ + *(.text)\n\ + *(.stub)\n\ + /* .gnu.warning sections are handled specially by elf32.em. */\n\ + *(.gnu.warning)\n\ + } =0\n\ + _etext = .;\n\ + PROVIDE (etext = .);\n\ + .fini : { *(.fini) } =0\n\ + /* Adjust the address for the data segment. We want to adjust up to\n\ + the same address within the page on the next page up. It would\n\ + be more correct to do this:\n\ + . = 0x10000000;\n\ + The current expression does not correctly handle the case of a\n\ + text segment ending precisely at the end of a page; it causes the\n\ + data segment to skip a page. The above expression does not have\n\ + this problem, but it will currently (2/95) cause BFD to allocate\n\ + a single segment, combining both text and data, for this case.\n\ + This will prevent the text segment from being shared among\n\ + multiple executions of the program; I think that is more\n\ + important than losing a page of the virtual address space (note\n\ + that no actual memory is lost; the page which is skipped can not\n\ + be referenced). */\n\ + . += 0x10000000 - 0x0400000;\n\ + .data :\n\ + {\n\ + _fdata = . ;\n\ + *(.data)\n\ + CONSTRUCTORS\n\ + }\n\ + .data1 : { *(.data1) }\n\ + .ctors : { *(.ctors) }\n\ + .dtors : { *(.dtors) }\n\ + _gp = ALIGN(16) + 0x7ff0;\n\ + .got :\n\ + {\n\ + *(.got.plt) *(.got)\n\ + }\n\ + /* We want the small data sections together, so single-instruction offsets\n\ + can access them all, and initialized data all before uninitialized, so\n\ + we can shorten the on-disk segment size. */\n\ + .sdata : { *(.sdata) }\n\ + .lit8 : { *(.lit8) }\n\ + .lit4 : { *(.lit4) }\n\ + _edata = .;\n\ + PROVIDE (edata = .);\n\ + __bss_start = .;\n\ + _fbss = .;\n\ + .sbss : { *(.sbss) *(.scommon) }\n\ + .bss :\n\ + {\n\ + *(.dynbss)\n\ + *(.bss)\n\ + *(COMMON)\n\ + }\n\ + _end = . ;\n\ + PROVIDE (end = .);\n\ + /* These are needed for ELF backends which have not yet been\n\ + converted to the new style linker. */\n\ + .stab 0 : { *(.stab) }\n\ + .stabstr 0 : { *(.stabstr) }\n\ + /* DWARF debug sections.\n\ + Symbols in the .debug DWARF section are relative to the beginning of the\n\ + section so we begin .debug at 0. It's not clear yet what needs to happen\n\ + for the others. */\n\ + .debug 0 : { *(.debug) }\n\ + .debug_srcinfo 0 : { *(.debug_srcinfo) }\n\ + .debug_aranges 0 : { *(.debug_aranges) }\n\ + .debug_pubnames 0 : { *(.debug_pubnames) }\n\ + .debug_sfnames 0 : { *(.debug_sfnames) }\n\ + .line 0 : { *(.line) }\n\ + /* These must appear regardless of . */\n\ + .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }\n\ + .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }\n\ +}\n\n"; +} + +struct ld_emulation_xfer_struct ld_elf32ebmip_emulation = +{ + gldelf32ebmip_before_parse, + syslib_default, + hll_default, + after_parse_default, + gldelf32ebmip_after_open, + after_allocation_default, + set_output_arch_default, + ldemul_default_target, + gldelf32ebmip_before_allocation, + gldelf32ebmip_get_script, + "elf32ebmip", + "elf32-bigmips", + NULL, + NULL, + gldelf32ebmip_open_dynamic_archive, + gldelf32ebmip_place_orphan +}; diff --git a/gnu/usr.bin/binutils/ld/mpw-idtmips.c b/gnu/usr.bin/binutils/ld/mpw-idtmips.c new file mode 100644 index 00000000000..554f9a8c50c --- /dev/null +++ b/gnu/usr.bin/binutils/ld/mpw-idtmips.c @@ -0,0 +1,430 @@ +/* This file is is generated by a shell script. DO NOT EDIT! */ + +/* Handle embedded relocs for MIPS. + Copyright 1994 Free Software Foundation, Inc. + Written by Ian Lance Taylor <ian@cygnus.com> based on generic.em. + +This file is part of GLD, the Gnu Linker. + +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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#define TARGET_IS_mipsidt + +#include "libiberty.h" +#include "bfd.h" +#include "sysdep.h" +#include "bfdlink.h" + +#include "ld.h" +#include "ldmain.h" +#include "ldemul.h" +#include "ldfile.h" +#include "ldmisc.h" + +static void gldmipsidt_before_parse PARAMS ((void)); +static void gldmipsidt_after_open PARAMS ((void)); +static void check_sections PARAMS ((bfd *, asection *, PTR)); +static void gldmipsidt_after_allocation PARAMS ((void)); +static char *gldmipsidt_get_script PARAMS ((int *isfile)); + +static void +gldmipsidt_before_parse() +{ +#ifndef TARGET_ /* I.e., if not generic. */ + ldfile_output_architecture = bfd_arch_mips; +#endif /* not TARGET_ */ +} + +/* This function is run after all the input files have been opened. + We create a .rel.sdata section for each input file with a non zero + .sdata section. The BFD backend will fill in these sections with + magic numbers which can be used to relocate the data section at run + time. This will only do the right thing if all the input files + have been compiled using -membedded-pic. */ + +static void +gldmipsidt_after_open () +{ + bfd *abfd; + + if (! command_line.embedded_relocs + || link_info.relocateable) + return; + + for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link_next) + { + asection *datasec; + + datasec = bfd_get_section_by_name (abfd, ".sdata"); + + /* Note that we assume that the reloc_count field has already + been set up. We could call bfd_get_reloc_upper_bound, but + that returns the size of a memory buffer rather than a reloc + count. We do not want to call bfd_canonicalize_reloc, + because although it would always work it would force us to + read in the relocs into BFD canonical form, which would waste + a significant amount of time and memory. */ + if (datasec != NULL && datasec->reloc_count > 0) + { + asection *relsec; + + relsec = bfd_make_section (abfd, ".rel.sdata"); + if (relsec == NULL + || ! bfd_set_section_flags (abfd, relsec, + (SEC_ALLOC + | SEC_LOAD + | SEC_HAS_CONTENTS + | SEC_IN_MEMORY)) + || ! bfd_set_section_alignment (abfd, relsec, 2) + || ! bfd_set_section_size (abfd, relsec, + datasec->reloc_count * 4)) + einfo ("%F%B: can not create .rel.sdata section: %E"); + } + + /* Double check that all other data sections are empty, as is + required for embedded PIC code. */ + bfd_map_over_sections (abfd, check_sections, (PTR) datasec); + } +} + +/* Check that of the data sections, only the .sdata section has + relocs. This is called via bfd_map_over_sections. */ + +static void +check_sections (abfd, sec, sdatasec) + bfd *abfd; + asection *sec; + PTR sdatasec; +{ + if ((bfd_get_section_flags (abfd, sec) & SEC_CODE) == 0 + && sec != (asection *) sdatasec + && sec->reloc_count != 0) + einfo ("%F%X: section %s has relocs; can not use --embedded-relocs", + abfd, bfd_get_section_name (abfd, sec)); +} + +/* This function is called after the section sizes and offsets have + been set. If we are generating embedded relocs, it calls a special + BFD backend routine to do the work. */ + +static void +gldmipsidt_after_allocation () +{ + bfd *abfd; + + if (! command_line.embedded_relocs + || link_info.relocateable) + return; + + for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link_next) + { + asection *datasec, *relsec; + char *errmsg; + + datasec = bfd_get_section_by_name (abfd, ".sdata"); + + if (datasec == NULL || datasec->reloc_count == 0) + continue; + + relsec = bfd_get_section_by_name (abfd, ".rel.sdata"); + ASSERT (relsec != NULL); + + if (! bfd_mips_ecoff_create_embedded_relocs (abfd, &link_info, + datasec, relsec, + &errmsg)) + { + if (errmsg == NULL) + einfo ("%B%X: can not create runtime reloc information: %E", + abfd); + else + einfo ("%X%B: can not create runtime reloc information: %s", + abfd, errmsg); + } + } +} + +static char * +gldmipsidt_get_script(isfile) + int *isfile; +{ + *isfile = 0; + + if (link_info.relocateable == true && config.build_constructors == true) + return +concat( +"OUTPUT_FORMAT(\"ecoff-bigmips\", \"ecoff-bigmips\",\n\ + \"ecoff-littlemips\")\n\ + SEARCH_DIR(/usr/local/mips-idt-ecoff/lib);\n\ +ENTRY(start)\n\ +SECTIONS\n\ +{\n\ + .text : {\n\ + ;\n\ + *(.init)\n\ + ;\n\ + *(.text)\n\ + *(.rel.sdata)\n\ + *(.fini)\n\ + ;\n\ + ;\n\ + }\n\ + "," .rdata : {\n\ + *(.rdata)\n\ + }\n\ + .data : {\n\ + *(.data)\n\ + CONSTRUCTORS\n\ + }\n\ + .lit8 : {\n\ + *(.lit8)\n\ + }\n\ + .lit4 : {\n\ + *(.lit4)\n\ + }\n\ + "," .sdata : {\n\ + *(.sdata)\n\ + }\n\ + .sbss : {\n\ + *(.sbss)\n\ + *(.scommon)\n\ + }\n\ + .bss : {\n\ + *(.bss)\n\ + *(COMMON)\n\ + }\n\ +}\n\n", NULL) + ; else if (link_info.relocateable == true) return +"OUTPUT_FORMAT(\"ecoff-bigmips\", \"ecoff-bigmips\",\n\ + \"ecoff-littlemips\")\n\ + SEARCH_DIR(/usr/local/mips-idt-ecoff/lib);\n\ +ENTRY(start)\n\ +SECTIONS\n\ +{\n\ + .text : {\n\ + ;\n\ + *(.init)\n\ + ;\n\ + *(.text)\n\ + *(.rel.sdata)\n\ + *(.fini)\n\ + ;\n\ + ;\n\ + }\n\ + .rdata : {\n\ + *(.rdata)\n\ + }\n\ + .data : {\n\ + *(.data)\n\ + }\n\ + .lit8 : {\n\ + *(.lit8)\n\ + }\n\ + .lit4 : {\n\ + *(.lit4)\n\ + }\n\ + .sdata : {\n\ + *(.sdata)\n\ + }\n\ + .sbss : {\n\ + *(.sbss)\n\ + *(.scommon)\n\ + }\n\ + .bss : {\n\ + *(.bss)\n\ + *(COMMON)\n\ + }\n\ +}\n\n" + ; else if (!config.text_read_only) return +concat( +"OUTPUT_FORMAT(\"ecoff-bigmips\", \"ecoff-bigmips\",\n\ + \"ecoff-littlemips\")\n\ + SEARCH_DIR(/usr/local/mips-idt-ecoff/lib);\n\ +ENTRY(start)\n\ +SECTIONS\n\ +{\n\ + . = 0xa0012000;\n\ + .text : {\n\ + _ftext = . ;\n\ + *(.init)\n\ + eprol = .;\n\ + *(.text)\n\ + PROVIDE (__runtime_reloc_start = .);\n\ + *(.rel.sdata)\n\ + PROVIDE (__runtime_reloc_stop = .);\n\ + *(.fini)\n\ + etext = .;\n\ + _etext = .;\n\ +"," }\n\ + . = .;\n\ + .rdata : {\n\ + *(.rdata)\n\ + }\n\ + _fdata = ALIGN(16);\n\ + .data : {\n\ + *(.data)\n\ + CONSTRUCTORS\n\ + }\n\ + _gp = ALIGN(16) + 0x8000;\n\ + .lit8 : {\n\ + *(.lit8)\n\ + }\n\ + .lit4 : {\n\ + *(.lit4)\n\ + }\n\ + .sdata : {\n\ + *(.sdata)\n\ + }\n\ +"," edata = .;\n\ + _edata = .;\n\ + _fbss = .;\n\ + .sbss : {\n\ + *(.sbss)\n\ + *(.scommon)\n\ + }\n\ + .bss : {\n\ + *(.bss)\n\ + *(COMMON)\n\ + }\n\ + end = .;\n\ + _end = .;\n\ +}\n\n" +, NULL) + ; else if (!config.magic_demand_paged) return +concat ( +"OUTPUT_FORMAT(\"ecoff-bigmips\", \"ecoff-bigmips\",\n\ + \"ecoff-littlemips\")\n\ + SEARCH_DIR(/usr/local/mips-idt-ecoff/lib);\n\ +ENTRY(start)\n\ +SECTIONS\n\ +{\n\ + . = 0xa0012000;\n\ + .text : {\n\ + _ftext = . ;\n\ + *(.init)\n\ + eprol = .;\n\ + *(.text)\n\ + PROVIDE (__runtime_reloc_start = .);\n\ + *(.rel.sdata)\n\ + PROVIDE (__runtime_reloc_stop = .);\n\ + *(.fini)\n\ + etext = .;\n\ + _etext = .;\n\ + "," }\n\ + . = .;\n\ + .rdata : {\n\ + *(.rdata)\n\ + }\n\ + _fdata = ALIGN(16);\n\ + .data : {\n\ + *(.data)\n\ + CONSTRUCTORS\n\ + }\n\ + _gp = ALIGN(16) + 0x8000;\n\ + .lit8 : {\n\ + *(.lit8)\n\ + "," }\n\ + .lit4 : {\n\ + *(.lit4)\n\ + }\n\ + .sdata : {\n\ + *(.sdata)\n\ + }\n\ + edata = .;\n\ + _edata = .;\n\ + _fbss = .;\n\ + .sbss : {\n\ + *(.sbss)\n\ + *(.scommon)\n\ + "," }\n\ + .bss : {\n\ + *(.bss)\n\ + *(COMMON)\n\ + }\n\ + end = .;\n\ + _end = .;\n\ +}\n\n" +, NULL) + ; else return +concat ( +"OUTPUT_FORMAT(\"ecoff-bigmips\", \"ecoff-bigmips\",\n\ + \"ecoff-littlemips\")\n\ + SEARCH_DIR(/usr/local/mips-idt-ecoff/lib);\n\ +ENTRY(start)\n\ +SECTIONS\n\ +{\n\ + . = 0xa0012000;\n\ + .text : {\n\ + _ftext = . ;\n\ + *(.init)\n\ + eprol = .;\n\ + *(.text)\n\ + PROVIDE (__runtime_reloc_start = .);\n\ + *(.rel.sdata)\n\ + PROVIDE (__runtime_reloc_stop = .);\n\ + *(.fini)\n\ + etext = .;\n\ + _etext = .;\n\ + "," }\n\ + . = .;\n\ + .rdata : {\n\ + *(.rdata)\n\ + }\n\ + _fdata = ALIGN(16);\n\ + .data : {\n\ + *(.data)\n\ + CONSTRUCTORS\n\ + }\n\ + _gp = ALIGN(16) + 0x8000;\n\ + .lit8 : {\n\ + *(.lit8)\n\ + }\n\ + .lit4 : {\n\ + *(.lit4)\n\ + "," }\n\ + .sdata : {\n\ + *(.sdata)\n\ + }\n\ + edata = .;\n\ + _edata = .;\n\ + _fbss = .;\n\ + .sbss : {\n\ + *(.sbss)\n\ + *(.scommon)\n\ + }\n\ + .bss : {\n\ + *(.bss)\n\ + *(COMMON)\n\ + }\n\ + end = .;\n\ + _end = .;\n\ +}\n\n" +, NULL) +; } + +struct ld_emulation_xfer_struct ld_mipsidt_emulation = +{ + gldmipsidt_before_parse, + syslib_default, + hll_default, + after_parse_default, + gldmipsidt_after_open, + gldmipsidt_after_allocation, + set_output_arch_default, + ldemul_default_target, + before_allocation_default, + gldmipsidt_get_script, + "mipsidt", + "ecoff-bigmips" +}; diff --git a/gnu/usr.bin/binutils/ld/scripttempl/elfd10v.sc b/gnu/usr.bin/binutils/ld/scripttempl/elfd10v.sc new file mode 100644 index 00000000000..37b6ce0ceb7 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/scripttempl/elfd10v.sc @@ -0,0 +1,196 @@ +# +# Unusual variables checked by this code: +# NOP - two byte opcode for no-op (defaults to 0) +# DATA_ADDR - if end-of-text-plus-one-page isn't right for data start +# OTHER_READONLY_SECTIONS - other than .text .init .rodata ... +# (e.g., .PARISC.milli) +# OTHER_READWRITE_SECTIONS - other than .data .bss .ctors .sdata ... +# (e.g., .PARISC.global) +# OTHER_SECTIONS - at the end +# EXECUTABLE_SYMBOLS - symbols that must be defined for an +# executable (e.g., _DYNAMIC_LINK) +# TEXT_START_SYMBOLS - symbols that appear at the start of the +# .text section. +# DATA_START_SYMBOLS - symbols that appear at the start of the +# .data section. +# OTHER_BSS_SYMBOLS - symbols that appear at the start of the +# .bss section besides __bss_start. +# DATA_PLT - .plt should be in data segment, not text segment. +# EMBEDDED - whether this is for an embedded system. +# +# When adding sections, do note that the names of some sections are used +# when specifying the start address of the next. +# +test -z "$ENTRY" && ENTRY=_start +test -z "${BIG_OUTPUT_FORMAT}" && BIG_OUTPUT_FORMAT=${OUTPUT_FORMAT} +test -z "${LITTLE_OUTPUT_FORMAT}" && LITTLE_OUTPUT_FORMAT=${OUTPUT_FORMAT} +if [ -z "$MACHINE" ]; then OUTPUT_ARCH=${ARCH}; else OUTPUT_ARCH=${ARCH}:${MACHINE}; fi +test "$LD_FLAG" = "N" && DATA_ADDR=. +INTERP=".interp ${RELOCATING-0} : { *(.interp) }" +PLT=".plt ${RELOCATING-0} : { *(.plt) }" + +# if this is for an embedded system, don't add SIZEOF_HEADERS. +if [ -z "$EMBEDDED" ]; then + test -z "${READONLY_BASE_ADDRESS}" && READONLY_BASE_ADDRESS="${READONLY_START_ADDR} + SIZEOF_HEADERS" +else + test -z "${READONLY_BASE_ADDRESS}" && READONLY_BASE_ADDRESS="${READONLY_START_ADDR}" +fi + +cat <<EOF +OUTPUT_FORMAT("${OUTPUT_FORMAT}", "${BIG_OUTPUT_FORMAT}", + "${LITTLE_OUTPUT_FORMAT}") +OUTPUT_ARCH(${OUTPUT_ARCH}) +ENTRY(${ENTRY}) + +${RELOCATING+${LIB_SEARCH_DIRS}} +${RELOCATING+/* Do we need any of these for elf? + __DYNAMIC = 0; ${STACKZERO+${STACKZERO}} ${SHLIB_PATH+${SHLIB_PATH}} */} +${RELOCATING+${EXECUTABLE_SYMBOLS}} +${RELOCATING- /* For some reason, the Solaris linker makes bad executables + if gld -r is used and the intermediate file has sections starting + at non-zero addresses. Could be a Solaris ld bug, could be a GNU ld + bug. But for now assigning the zero vmas works. */} +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + ${CREATE_SHLIB-${RELOCATING+. = ${READONLY_BASE_ADDRESS};}} + ${CREATE_SHLIB+${RELOCATING+. = SIZEOF_HEADERS;}} + ${CREATE_SHLIB-${INTERP}} + .hash ${RELOCATING-0} : { *(.hash) } + .dynsym ${RELOCATING-0} : { *(.dynsym) } + .dynstr ${RELOCATING-0} : { *(.dynstr) } + .rel.text ${RELOCATING-0} : { *(.rel.text) } + .rela.text ${RELOCATING-0} : { *(.rela.text) } + .rel.data ${RELOCATING-0} : { *(.rel.data) } + .rela.data ${RELOCATING-0} : { *(.rela.data) } + .rel.rodata ${RELOCATING-0} : { *(.rel.rodata) } + .rela.rodata ${RELOCATING-0} : { *(.rela.rodata) } + .rel.got ${RELOCATING-0} : { *(.rel.got) } + .rela.got ${RELOCATING-0} : { *(.rela.got) } + .rel.ctors ${RELOCATING-0} : { *(.rel.ctors) } + .rela.ctors ${RELOCATING-0} : { *(.rela.ctors) } + .rel.dtors ${RELOCATING-0} : { *(.rel.dtors) } + .rela.dtors ${RELOCATING-0} : { *(.rela.dtors) } + .rel.init ${RELOCATING-0} : { *(.rel.init) } + .rela.init ${RELOCATING-0} : { *(.rela.init) } + .rel.fini ${RELOCATING-0} : { *(.rel.fini) } + .rela.fini ${RELOCATING-0} : { *(.rela.fini) } + .rel.bss ${RELOCATING-0} : { *(.rel.bss) } + .rela.bss ${RELOCATING-0} : { *(.rela.bss) } + .rel.plt ${RELOCATING-0} : { *(.rel.plt) } + .rela.plt ${RELOCATING-0} : { *(.rela.plt) } + ${DATA_PLT-${PLT}} + .rodata ${RELOCATING-0} : { *(.rodata) *(.gnu.linkonce.r*) } + .rodata1 ${RELOCATING-0} : { *(.rodata1) } + ${RELOCATING+${OTHER_READONLY_SECTIONS}} + + /* Adjust the address for the data segment. */ + ${RELOCATING+. = ${DATA_ADDR-ALIGN(4);}} + + .data ${RELOCATING-0} : + { + ${RELOCATING+${DATA_START_SYMBOLS}} + *(.data) + *(.gnu.linkonce.d*) + ${CONSTRUCTING+CONSTRUCTORS} + } + .data1 ${RELOCATING-0} : { *(.data1) } + ${RELOCATING+${OTHER_READWRITE_SECTIONS}} + .ctors ${RELOCATING-0} : + { + ${CONSTRUCTING+${CTOR_START}} + *(.ctors) + ${CONSTRUCTING+${CTOR_END}} + } + .dtors ${RELOCATING-0} : + { + ${CONSTRUCTING+${DTOR_START}} + *(.dtors) + ${CONSTRUCTING+${DTOR_END}} + } + .got ${RELOCATING-0} : { *(.got.plt) *(.got) } + .dynamic ${RELOCATING-0} : { *(.dynamic) } + ${DATA_PLT+${PLT}} + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata ${RELOCATING-0} : { *(.sdata) } + ${RELOCATING+_edata = .;} + ${RELOCATING+PROVIDE (edata = .);} + ${RELOCATING+__bss_start = .;} + ${RELOCATING+${OTHER_BSS_SYMBOLS}} + .sbss ${RELOCATING-0} : { *(.sbss) *(.scommon) } + .bss ${RELOCATING-0} : + { + *(.dynbss) + *(.bss) + *(COMMON) + } + ${RELOCATING+_end = . ;} + ${RELOCATING+PROVIDE (end = .);} + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + + .comment 0 : { *(.comment) } + + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + + ${RELOCATING+${OTHER_RELOCATING_SECTIONS}} + + /* These must appear regardless of ${RELOCATING}. */ + ${OTHER_SECTIONS} + + + /* Hmmm, there's got to be a better way. This sets the stack to the + top of the simulator memory (i.e. top of 64K data space). */ + .stack 0x2007FFE : { _stack = .; *(.stack) } + + .text ${RELOCATING+${TEXT_START_ADDR}} : + { + ${RELOCATING+${TEXT_START_SYMBOLS}} + *(.init) + *(.fini) + *(.text) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + } =${NOP-0} + ${RELOCATING+_etext = .;} + ${RELOCATING+PROVIDE (etext = .);} +} +EOF diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers.exp b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers.exp new file mode 100644 index 00000000000..b3a21c91cab --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers.exp @@ -0,0 +1,786 @@ +# Expect script for ld-version tests +# Copyright (C) 1997 Free Software Foundation +# +# This file 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# Written by Eric Youngdale (eric@andante.jic.com) + +# + +# This test can only be run if ld generates native executables. +if ![isnative] then {return} + +# This test can only be run on a couple of ELF platforms. +# Square bracket expressions seem to confuse istarget. +# This is similar to the test that is used in ld-shared, BTW. +if { ![istarget i386-*-sysv4*] \ + && ![istarget i486-*-sysv4*] \ + && ![istarget i586-*-sysv4*] \ + && ![istarget i386-*-unixware] \ + && ![istarget i486-*-unixware] \ + && ![istarget i586-*-unixware] \ + && ![istarget i386-*-elf*] \ + && ![istarget i486-*-elf*] \ + && ![istarget i586-*-elf*] \ + && ![istarget i386-*-linux*] \ + && ![istarget i486-*-linux*] \ + && ![istarget i586-*-linux*] \ + && ![istarget m68k-*-linux*] \ + && ![istarget mips*-*-irix5*] \ + && ![istarget sparc*-*-elf] \ + && ![istarget sparc*-*-solaris2*] } { + return +} + +if { [istarget i386-*-linuxaout*] \ + || [istarget i486-*-linuxaout*] \ + || [istarget i586-*-linuxaout*] \ + || [istarget i386-*-linuxoldld*] \ + || [istarget i486-*-linuxoldld*] \ + || [istarget i586-*-linuxoldld*] \ + || [istarget m68k-*-linuxaout*] } { + return +} + +if { [istarget rs6000*-*-aix*] || [istarget powerpc*-*-aix*] } { + return +} + +set diff diff +set tmpdir tmpdir +set VOBJDUMP_FLAGS --private-headers +set DOBJDUMP_FLAGS --dynamic-syms +set SOBJDUMP_FLAGS --syms +set shared --shared +set script --version-script + +proc test_ar { test lib object expect } { + global ar + global nm + global tmpdir + global srcdir + global subdir + global diff + + verbose -log "$ar -cr $tmpdir/$lib $tmpdir/$object" + catch "exec $ar -cr $tmpdir/$lib $tmpdir/$object" exec_output + set exec_output [prune_warnings $exec_output] + if ![string match "" $exec_output] { + verbose -log "$exec_output" + unresolved "$test" + return + } + + verbose -log "$nm --print-armap $tmpdir/$lib | grep \" in \" | grep \"VERS\\|bar\\|foo\" | sort > $tmpdir/nm.out" + + catch "exec $nm --print-armap $tmpdir/$lib | grep \\\ in\\\ | grep VERS\\\\|bar\\\\|foo | sort > $tmpdir/nm.out" exec_output + if [string match "" $exec_output] then { + catch "exec $diff -q $tmpdir/nm.out $srcdir/$subdir/$expect" exec_output + set exec_output [prune_warnings $exec_output] + if [string match "" $exec_output] then { + pass $test + return + } else { + verbose -log "$exec_output" + fail "$test" + return + } + } else { + verbose -log "$exec_output" + fail "$test" + } +} + +# +# objdump_emptysymstuff +# Check non-dynamic symbols and make sure there are none with '@'. +# +proc objdump_emptysymstuff { objdump object } { + global SOBJDUMP_FLAGS + global version_output + global diff + + if ![info exists SOBJDUMP_FLAGS] { set SOBJDUMP_FLAGS "" } + + verbose -log "$objdump $SOBJDUMP_FLAGS $object | sed -n /\@/p" + + catch "exec $objdump $SOBJDUMP_FLAGS $object | sed -n /\@/p" exec_output + set exec_output [prune_warnings $exec_output] + if [string match "" $exec_output] then { +# We shouldn't get anything here. + return 1 + } else { +# it is not normal to come here - we have no output to compare. + verbose -log "$exec_output" + verbose -log "objdump_emptysymstuff: did not expect any output from objdump" + return 0 + } + +} + +# +# objdump_emptydynsymstuff +# Check dynamic symbols and make sure there are none with '@'. +# +proc objdump_emptydynsymstuff { objdump object } { + global DOBJDUMP_FLAGS + global version_output + global diff + + if ![info exists VOBJDUMP_FLAGS] { set VOBJDUMP_FLAGS "" } + + verbose -log "$objdump $DOBJDUMP_FLAGS $object | sed -n /VERS/p\\\;/show/p" + + catch "exec $objdump $DOBJDUMP_FLAGS $object | sed -n /VERS/p\\\;/show/p" exec_output + set exec_output [prune_warnings $exec_output] + if [string match "" $exec_output] then { +# We shouldn't get anything here. + return 1 + } else { if [string match "*objdump: *: not a dynamic object" $exec_output] then { + return 1 + } else { +# it is not normal to come here - we have no output to compare. + verbose -log "$exec_output" + verbose -log "objdump_emptydynsymstuff: did not expect any output from objdump" + return 0 + } } +} + +# +# objdump_emptyverstuff +# Make sure there is no version information +# +proc objdump_emptyverstuff { objdump object } { + global VOBJDUMP_FLAGS + global version_output + global diff + global tmpdir + + if {[which $objdump] == 0} then { + perror "$objdump does not exist" + return 0 + } + + if ![info exists VOBJDUMP_FLAGS] { set VOBJDUMP_FLAGS "" } + + verbose -log "$objdump $VOBJDUMP_FLAGS $object | sed -n /Version/,\\\$p > $tmpdir/objdump.out" + + catch "exec $objdump $VOBJDUMP_FLAGS $object | sed -n /Version/,\\\$p" exec_output + set exec_output [prune_warnings $exec_output] + if [string match "" $exec_output] then { +# it is normal to fail here - we have no output to compare. + return 1 + } else { + verbose -log "$exec_output" + verbose -log "objdump_emptyverstuff: did not expect any output from objdump" + return 0 + } + +} + +# +# objdump_symstuff +# Dump non-dynamic symbol stuff and make sure that it is sane. +# +proc objdump_symstuff { objdump object expectfile } { + global SOBJDUMP_FLAGS + global version_output + global diff + global tmpdir + + if ![info exists SOBJDUMP_FLAGS] { set SOBJDUMP_FLAGS "" } + + verbose -log "$objdump $SOBJDUMP_FLAGS $object | grep \@ | sort > $tmpdir/objdump.out" + + catch "exec $objdump $SOBJDUMP_FLAGS $object | grep \@ | sort > $tmpdir/objdump.out" exec_output + set exec_output [prune_warnings $exec_output] + if [string match "" $exec_output] then { + +# Now do a line-by-line comparison to effectively diff the darned things +# The stuff coming from the expectfile is actually a regex, so we can +# skip over the actual addresses and so forth. This is currently very +# simpleminded - it expects a one-to-one correspondence in terms of line +# numbers. + + if [file exists $expectfile] then { + set file_a [open $expectfile r] + } else { + perror "$expectfile doesn't exist" + return 0 + } + + if [file exists $tmpdir/objdump.out] then { + set file_b [open $tmpdir/objdump.out r] + } else { + perror "$tmpdir/objdump.out doesn't exist" + return 0 + } + + verbose "# Diff'ing: $expectfile $tmpdir/objdump.out" 2 + + set eof -1 + set differences 0 + + while { [gets $file_a line] != $eof } { + if [regexp "^#.*$" $line] then { + continue + } else { + lappend list_a $line + } + } + close $file_a + + while { [gets $file_b line] != $eof } { + if [regexp "^#.*$" $line] then { + continue + } else { + lappend list_b $line + } + } + close $file_b + + for { set i 0 } { $i < [llength $list_a] } { incr i } { + set line_a [lindex $list_a $i] + set line_b [lindex $list_b $i] + + + verbose "\t$expectfile: $i: $line_a" 3 + verbose "\t/tmp/objdump.out: $i: $line_b" 3 + if [regexp $line_a $line_b] then { + continue + } else { + verbose -log "\t$expectfile: $i: $line_a" + verbose -log "\t$tmpdir/objdump.out: $i: $line_b" + + return 0 + } + } + + if { [llength $list_a] != [llength $list_b] } { + verbose -log "Line count" + return 0 + } + + if $differences<1 then { + return 1 + } + + return 0 + } else { + verbose -log "$exec_output" + return 0 + } + +} + +# +# objdump_dymsymstuff +# Dump dynamic symbol stuff and make sure that it is sane. +# +proc objdump_dynsymstuff { objdump object expectfile } { + global DOBJDUMP_FLAGS + global version_output + global diff + global tmpdir + + if ![info exists DOBJDUMP_FLAGS] { set DOBJDUMP_FLAGS "" } + + verbose -log "$objdump $DOBJDUMP_FLAGS $object | sed -n /VERS/p\\\;/show/p | sort | uniq > $tmpdir/objdump.out" + + catch "exec $objdump $DOBJDUMP_FLAGS $object | sed -n /VERS/p\\\;/show/p | sort | uniq > $tmpdir/objdump.out" exec_output + set exec_output [prune_warnings $exec_output] + if [string match "" $exec_output] then { + +# Now do a line-by-line comparison to effectively diff the darned things +# The stuff coming from the expectfile is actually a regex, so we can +# skip over the actual addresses and so forth. This is currently very +# simpleminded - it expects a one-to-one correspondence in terms of line +# numbers. + + if [file exists $expectfile] then { + set file_a [open $expectfile r] + } else { + warning "$expectfile doesn't exist" + return 0 + } + + if [file exists $tmpdir/objdump.out] then { + set file_b [open $tmpdir/objdump.out r] + } else { + fail "$tmpdir/objdump.out doesn't exist" + return 0 + } + + verbose "# Diff'ing: $expectfile $tmpdir/objdump.out" 2 + + set eof -1 + set differences 0 + + while { [gets $file_a line] != $eof } { + if [regexp "^#.*$" $line] then { + continue + } else { + lappend list_a $line + } + } + close $file_a + + while { [gets $file_b line] != $eof } { + if [regexp "^#.*$" $line] then { + continue + } else { + lappend list_b $line + } + } + close $file_b + + for { set i 0 } { $i < [llength $list_b] } { incr i } { + set line_b [lindex $list_b $i] + +# The tests are rigged so that we should never export a symbol with the +# word 'hide' in it. Thus we just search for it, and bail if we find it. + if [regexp "hide" $line_b] then { + verbose -log "\t$tmpdir/objdump.out: $i: $line_b" + + return 0 + } + + verbose "\t$expectfile: $i: $line_b" 3 + + # We can't assume that the sort is consistent across + # systems, so we must check each regexp. When we find a + # regexp, we null it out, so we don't match it twice. + for { set j 0 } { $j < [llength $list_a] } { incr j } { + set line_a [lindex $list_a $j] + + if [regexp $line_a $line_b] then { + lreplace $list_a $j $j "CAN NOT MATCH" + break + } + } + + if { $j >= [llength $list_a] } { + verbose -log "\t$tmpdir/objdump.out: $i: $line_b" + + return 0 + } + } + + if { [llength $list_a] != [llength $list_b] } { + verbose -log "Line count" + return 0 + } + + if $differences<1 then { + return 1 + } + + return 0 + } else { + verbose -log "$exec_output" + return 0 + } + +} + +# +# objdump_versionstuff +# Dump version definitions/references and make sure that it is sane. +# +proc objdump_versionstuff { objdump object expectfile } { + global VOBJDUMP_FLAGS + global version_output + global diff + global tmpdir + + if {[which $objdump] == 0} then { + perror "$objdump does not exist" + return 0 + } + + if ![info exists VOBJDUMP_FLAGS] { set VOBJDUMP_FLAGS "" } + + verbose -log "$objdump $VOBJDUMP_FLAGS $object | sed -n /Version/,\\\$p > $tmpdir/objdump.out" + + catch "exec $objdump $VOBJDUMP_FLAGS $object | sed -n /Version/,\\\$p > $tmpdir/objdump.out" exec_output + set exec_output [prune_warnings $exec_output] + if [string match "" $exec_output] then { + +# now perform differences against the expected output. + verbose -log "$diff -q $tmpdir/objdump.out $expectfile" + catch "exec $diff -q $tmpdir/objdump.out $expectfile" exec_output + set exec_output [prune_warnings $exec_output] + if [string match "" $exec_output] then { + return 1 + } else { + verbose -log "$exec_output" + return 0 + } + + return 1 + } else { + verbose -log "$exec_output" + return 0 + } +} + +proc build_vers_lib { test source libname other mapfile verexp versymexp symexp } { + global ld + global srcdir + global subdir + global exec_output + global host_triplet + global tmpdir + global as + global objdump + global CC + global CFLAGS + global shared + global script + + if ![ld_compile "$CC -S $CFLAGS" $srcdir/$subdir/$source $tmpdir/$libname.s] { + unresolved "$test" + return + } + + if ![ld_assemble $as $tmpdir/$libname.s $tmpdir/$libname.o ] { + unresolved "$test" + return + } + + if [string match "" $other] then { + set other_lib "" + } else { + set other_lib $tmpdir/$other + } + + if [string match "" $mapfile] then { + set script_arg "" + } else { + set script_arg "$script $srcdir/$subdir/$mapfile" + } + + if {![ld_simple_link $ld $tmpdir/$libname.so "$shared $tmpdir/$libname.o $other_lib $script_arg"]} { + fail "$test" + return + } + + if {![objdump_versionstuff $objdump $tmpdir/$libname.so $srcdir/$subdir/$verexp ]} { + fail "$test" + return + } + + if {![objdump_dynsymstuff $objdump $tmpdir/$libname.so $srcdir/$subdir/$versymexp ]} { + fail "$test" + return + } + + if [string match "" $symexp] then { + if {![objdump_emptysymstuff $objdump $tmpdir/$libname.o ]} { + fail "$test" + return + } + } else { + if {![objdump_symstuff $objdump $tmpdir/$libname.o $srcdir/$subdir/$symexp ]} { + fail "$test" + return + } + } + + pass $test + +} + +proc test_ldfail { test flag source execname other mapfile whyfail } { + global ld + global srcdir + global subdir + global exec_output + global host_triplet + global tmpdir + global as + global objdump + global CC + global CFLAGS + global script + + if [string match "" $other] then { + set other_lib "" + } else { + set other_lib $tmpdir/$other + } + + if ![ld_compile "$CC -S $flag $CFLAGS" $srcdir/$subdir/$source $tmpdir/$execname.s] { + unresolved "$test" + return + } + + if ![ld_assemble $as $tmpdir/$execname.s $tmpdir/$execname.o ] { + unresolved "$test" + return + } + + verbose -log "This link should fail because of $whyfail" + + if [string match "" $mapfile] then { + set script_arg "" + } else { + set script_arg "$script $srcdir/$subdir/$mapfile" + } + + if {![ld_link $ld $tmpdir/$execname "$tmpdir/$execname.o $other_lib $script_arg"]} { + pass "$test" + return + } + fail "$test" +} + +proc test_asfail { test flag source execname whyfail } { + global srcdir + global subdir + global tmpdir + global as + global CC + global CFLAGS + + if ![ld_compile "$CC -S $flag $CFLAGS" $srcdir/$subdir/$source $tmpdir/$execname.s] { + unresolved "$test" + return + } + + verbose -log "This assemble should fail because of $whyfail" + catch "exec $as -o $tmpdir/$execname.o $tmpdir/$execname.s" exec_output + set exec_output [prune_warnings $exec_output] + if [string match "" $exec_output] then { + fail "$test" + return + } + verbose -log "$exec_output" + pass "$test" +} + +proc test_strip_vers_lib { test srclib libname verexp versymexp } { + global strip + global srcdir + global subdir + global exec_output + global host_triplet + global tmpdir + global objdump + + verbose -log "cp $tmpdir/$srclib $tmpdir/$libname.so" + exec cp $tmpdir/$srclib $tmpdir/$libname.so + + verbose -log "$strip $tmpdir/$libname.so" + catch "exec $strip $tmpdir/$libname.so" exec_output + if [string match "" $exec_output] then { + +# If strip went OK, then run the usual tests on the thing to make sure that +# it is sane. + if {![objdump_versionstuff $objdump $tmpdir/$libname.so $srcdir/$subdir/$verexp ]} { + fail "$test" + return + } + + if {![objdump_dynsymstuff $objdump $tmpdir/$libname.so $srcdir/$subdir/$versymexp ]} { + fail "$test" + return + } + + } else { + verbose -log "$exec_output" + fail "$test" + return + } + pass $test +} + + +proc build_exec { test source execname flags solibname verexp versymexp symexp } { + global ld + global srcdir + global subdir + global exec_output + global host_triplet + global tmpdir + global as + global objdump + global CC + global CFLAGS + + set shared --shared + set script --version-script + if ![ld_compile "$CC -S $CFLAGS" $srcdir/$subdir/$source $tmpdir/$execname.s] { + unresolved "$test" + return + } + + if ![ld_assemble $as $tmpdir/$execname.s $tmpdir/$execname.o ] { + unresolved "$test" + return + } + + if [string match "" $solibname] then { + set solibname_lib "" + } else { + set solibname_lib $tmpdir/$solibname + } + + if {![ld_link $ld $tmpdir/$execname "$flags $tmpdir/$execname.o $solibname_lib"]} { + fail "$test" + return + } + + if [string match "" $verexp] then { +# +# Make sure we get nothing back. +# + if {![objdump_emptyverstuff $objdump $tmpdir/$execname ]} { + fail "$test" + return + } + } else { + if {![objdump_versionstuff $objdump $tmpdir/$execname $srcdir/$subdir/$verexp ]} { + fail "$test" + return + } + } + + if [string match "" $versymexp] then { + if {![objdump_emptydynsymstuff $objdump $tmpdir/$execname ]} { + fail "$test" + return + } + } else { + if {![objdump_dynsymstuff $objdump $tmpdir/$execname $srcdir/$subdir/$versymexp ]} { + fail "$test" + return + } + } + + if [string match "" $symexp] then { + if {![objdump_emptysymstuff $objdump $tmpdir/$execname.o ]} { + fail "$test" + return + } + } else { + if {![objdump_symstuff $objdump $tmpdir/$execname.o $srcdir/$subdir/$symexp ]} { + fail "$test" + return + } + } + + pass $test +} + + +# +# Basic test - build a library with versioned symbols. +# +build_vers_lib "vers1" vers1.c vers1 "" vers1.map vers1.ver vers1.dsym vers1.sym + + +# +# Test #2 - build a library, and link it against the library we built in step +# 1. +# +build_vers_lib "vers2" vers2.c vers2 vers1.so vers2.map vers2.ver vers2.dsym "" + +# +# Test #3 - build an executable, and link it against vers1.so. +# +build_exec "vers3" vers3.c vers3 "" vers1.so vers3.ver vers3.dsym "" + +# +# Test #4 - Make sure a version implicitly defined in an executable +# causes a version node to be created. Verify this both with and without +# --export-dynamic. +# + +# This test fails on MIPS. On the MIPS we must put foo in the dynamic +# symbol table, which the test does not expect. +setup_xfail "mips*-*-*" +build_exec "vers4" vers4.c vers4 "" "" "" "" vers4.sym + +build_exec "vers4a" vers4.c vers4a "-export-dynamic" "" vers4a.ver vers4a.dsym vers4a.sym + + +# +# Try multiple definitions foo@BAR and foo@@BAR and make sure the linker +# complains. +# +test_ldfail "vers5" "" vers5.c vers5 "" "" "multiple definition of foo@VERS_1.2" + +# +# +# Now build a test that should reference a bunch of versioned symbols. +# All of them should be correctly referenced. +# +build_exec "vers6" vers6.c vers6 "" vers1.so vers6.ver vers6.dsym vers6.sym + +# +# Another test to verify that something made local via 'local' is truly not +# accessible. +# +build_vers_lib "vers7a" vers7a.c vers7a "" vers7.map vers7a.ver vers7a.dsym vers7a.sym + +test_ldfail "vers7" "" vers7.c vers7 vers7a.so "" "undefined reference to hide_a" + + +# +# This test is designed to verify that we can pass a linker script on the +# command line as if it were a normal .o file. +# +catch "exec cp $srcdir/$subdir/vers8.map $tmpdir/" ignore_output +build_vers_lib "vers8" vers1.c vers8 vers8.map "" vers8.ver vers1.dsym vers1.sym + +# +# This test tries to make sure that version references to versioned symbols +# don't collide with default definitions with the same symbol. +# +build_exec "vers9" vers9.c vers9 "-export-dynamic" "" vers9.ver vers9.dsym vers9.sym + + +# +# Try and use a non-existant version node. The linker should fail with +# an error message. +# +test_ldfail "vers10" "-DDO_TEST10" vers1.c vers10 "" "vers1.map --shared" "invalid version" + +# +# Try and some things the assembler should complain about. +# +test_asfail "vers11" "-DDO_TEST11" vers1.c vers11 "no @ in symver" + +test_asfail "vers12" "-DDO_TEST12" vers1.c vers12 "extern version definition" + +# +# Put a shared library in an archive library, and make sure the global +# archive symbol table is sane. +# +test_ar "ar with versioned solib" vers13.a vers1.so vers13.asym + +# +# Strip a shared library, and make sure we didn't screw something up in there. +# +test_strip_vers_lib "vers14" vers1.so vers14 vers1.ver vers1.dsym + + +# +# Build another test with some versioned symbols. Here we are going to +# try and override something from the library, and we shouldn't get +# any errors. +# +build_exec "vers15" vers15.c vers15 "" vers1.so vers15.ver vers15.dsym vers15.sym diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers1.c b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers1.c new file mode 100644 index 00000000000..cba1a0db383 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers1.c @@ -0,0 +1,90 @@ +/* + * Basic test of versioning. The idea with this is that we define + * a bunch of definitions of the same symbol, and we can theoretically + * then link applications against varying sets of these. + */ +const char * show_bar1 = "asdf"; +const char * show_bar2 = "asdf"; + +int bar() +{ + return 3; +} + +/* + * The 'hide' prefix is something so that we can automatically search the + * symbol table and verify that none of these symbols were actually exported. + */ +hide_original_foo() +{ + return 1+bar(); + +} + +hide_old_foo() +{ + return 10+bar(); + +} + +hide_old_foo1() +{ + return 100+bar(); + +} + +hide_new_foo() +{ + return 1000+bar(); + +} + +__asm__(".symver hide_original_foo,show_foo@"); +__asm__(".symver hide_old_foo,show_foo@VERS_1.1"); +__asm__(".symver hide_old_foo1,show_foo@VERS_1.2"); +__asm__(".symver hide_new_foo,show_foo@@VERS_2.0"); + + + +#ifdef DO_TEST10 +/* In test 10, we try and define a non-existant version node. The linker + * should catch this and complain. */ +hide_new_bogus_foo() +{ + return 1000+bar(); + +} +__asm__(".symver hide_new_bogus_foo,show_foo@VERS_2.2"); +#endif + + + + +#ifdef DO_TEST11 +/* + * This test is designed to catch a couple of syntactic errors. The assembler + * should complain about both of the directives below. + */ +xyzzz() +{ + new2_foo(); + bar33(); +} + +__asm__(".symver new2_foo,fooVERS_2.0"); +__asm__(".symver bar33,bar@@VERS_2.0"); +#endif + +#ifdef DO_TEST12 +/* + * This test is designed to catch a couple of syntactic errors. The assembler + * should complain about both of the directives below. + */ +xyzzz() +{ + new2_foo(); + bar33(); +} + +__asm__(".symver bar33,bar@@VERS_2.0"); +#endif diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers1.dsym b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers1.dsym new file mode 100644 index 00000000000..d0637849c99 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers1.dsym @@ -0,0 +1,9 @@ +[0]* g DO \*ABS\* [0]* VERS_1.1 VERS_1.1 +[0]* g DO \*ABS\* [0]* VERS_1.2 VERS_1.2 +[0]* g DO \*ABS\* [0]* VERS_2.0 VERS_2.0 +[0-9a-f]* g DF (.text|\*ABS\*) [0-9a-f]* \(Base\) show_foo +[0-9a-f]* g DF (.text|\*ABS\*) [0-9a-f]* \(VERS_1.1\) show_foo +[0-9a-f]* g DF (.text|\*ABS\*) [0-9a-f]* \(VERS_1.2\) show_foo +[0-9a-f]* g DF (.text|\*ABS\*) [0-9a-f]* VERS_2.0 show_foo +[0-9a-f]* g DO (.data|\*ABS\*) [0-9a-f]* VERS_2.0 show_bar1 +[0-9a-f]* g DO (.data|\*ABS\*) [0-9a-f]* VERS_2.0 show_bar2 diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers1.map b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers1.map new file mode 100644 index 00000000000..8fc37bcaf0f --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers1.map @@ -0,0 +1,16 @@ +VERS_1.1 { + global: + foo1; + local: + hide_old*; + hide_original*; + hide_new*; +}; + +VERS_1.2 { + foo2; +} VERS_1.1; + +VERS_2.0 { + show_bar1; show_bar2; +} VERS_1.2; diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers1.sym b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers1.sym new file mode 100644 index 00000000000..8e2f55295c9 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers1.sym @@ -0,0 +1,4 @@ +[0-9a-f]* g F .text [0-9a-f]* show_foo@ +[0-9a-f]* g F .text [0-9a-f]* show_foo@VERS_1.1 +[0-9a-f]* g F .text [0-9a-f]* show_foo@VERS_1.2 +[0-9a-f]* g F .text [0-9a-f]* show_foo@@VERS_2.0 diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers1.ver b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers1.ver new file mode 100644 index 00000000000..3e7312b643e --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers1.ver @@ -0,0 +1,8 @@ +Version definitions: +1 0x01 0x0a26881f tmpdir/vers1.so +2 0x00 0x0a7927b1 VERS_1.1 +3 0x00 0x0a7927b2 VERS_1.2 + VERS_1.1 +4 0x00 0x0a7922b0 VERS_2.0 + VERS_1.2 + diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers13.asym b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers13.asym new file mode 100644 index 00000000000..d446144e2d2 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers13.asym @@ -0,0 +1,10 @@ +VERS_1.1 in vers1.so +VERS_1.2 in vers1.so +VERS_2.0 in vers1.so +bar in vers1.so +show_bar1 in vers1.so +show_bar2 in vers1.so +show_foo@ in vers1.so +show_foo@@VERS_2.0 in vers1.so +show_foo@VERS_1.1 in vers1.so +show_foo@VERS_1.2 in vers1.so diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers15.c b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers15.c new file mode 100644 index 00000000000..9e781c58caa --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers15.c @@ -0,0 +1,31 @@ +/* + * Testcase to make sure that if we externally reference a versioned symbol + * that we always get the right one. + */ + + +foo_1() +{ + return 1034; +} + +foo_2() +{ + return 1343; +} + +foo_3() +{ + return 1334; +} + +main() +{ + printf("Expect 4, get %d\n", foo_1()); + printf("Expect 13, get %d\n", foo_2()); + printf("Expect 103, get %d\n", foo_3()); +} + +__asm__(".symver foo_1,show_foo@"); +__asm__(".symver foo_2,show_foo@VERS_1.1"); +__asm__(".symver foo_3,show_foo@@VERS_1.2"); diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers15.dsym b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers15.dsym new file mode 100644 index 00000000000..61155a6d042 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers15.dsym @@ -0,0 +1,5 @@ +[0]* g DO \*ABS\* [0]* VERS_1.1 VERS_1.1 +[0]* g DO \*ABS\* [0]* VERS_1.2 VERS_1.2 +[0-9a-f]* g DF (.text|\*ABS\*) [0-9a-f]* \(Base\) show_foo +[0-9a-f]* g DF (.text|\*ABS\*) [0-9a-f]* \(VERS_1.1\) show_foo +[0-9a-f]* g DF (.text|\*ABS\*) [0-9a-f]* VERS_1.2 show_foo diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers15.sym b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers15.sym new file mode 100644 index 00000000000..49ec78bed56 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers15.sym @@ -0,0 +1,3 @@ +[0-9a-f]* g F .text [0-9a-f]* show_foo@ +[0-9a-f]* g F .text [0-9a-f]* show_foo@VERS_1.1 +[0-9a-f]* g F .text [0-9a-f]* show_foo@@VERS_1.2 diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers15.ver b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers15.ver new file mode 100644 index 00000000000..3d2ec588ffc --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers15.ver @@ -0,0 +1,5 @@ +Version definitions: +1 0x01 0x0d8a2605 tmpdir/vers15 +2 0x00 0x0a7927b2 VERS_1.2 +3 0x00 0x0a7927b1 VERS_1.1 + diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers2.c b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers2.c new file mode 100644 index 00000000000..fbc6a9517eb --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers2.c @@ -0,0 +1,9 @@ +/* + * Test function. This is built into a shared library, and references a + * versioned symbol foo that is in test.so. + */ + +show_xyzzy() +{ + printf("%d", show_foo()); +} diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers2.dsym b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers2.dsym new file mode 100644 index 00000000000..a7b54c76399 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers2.dsym @@ -0,0 +1,3 @@ +[0-9a-f]* DF \*UND\* [0-9a-f]* VERS_2.0 show_foo +[0]* g DO \*ABS\* [0]* VERS_XXX_1.1 VERS_XXX_1.1 +[0-9a-f]* g DF (.text|\*ABS\*) [0-9a-f]* VERS_XXX_1.1 show_xyzzy diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers2.map b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers2.map new file mode 100644 index 00000000000..cd57d7e53bb --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers2.map @@ -0,0 +1,4 @@ + +VERS_XXX_1.1 { + show_xyzzy; +}; diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers2.ver b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers2.ver new file mode 100644 index 00000000000..b52634359b6 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers2.ver @@ -0,0 +1,8 @@ +Version definitions: +1 0x01 0x0a26181f tmpdir/vers2.so +2 0x00 0x08785b51 VERS_XXX_1.1 + +Version References: + required from tmpdir/vers1.so: + 0x0a7922b0 0x00 03 VERS_2.0 + diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers3.c b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers3.c new file mode 100644 index 00000000000..0c81790bce3 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers3.c @@ -0,0 +1,9 @@ +/* + * Main program for test1, test2. + */ + + +main() +{ + printf("%d\n", show_foo()); +} diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers3.dsym b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers3.dsym new file mode 100644 index 00000000000..e824031b0d2 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers3.dsym @@ -0,0 +1 @@ +[0-9a-f]* DF \*UND\* [0-9a-f]* VERS_2.0 show_foo diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers3.ver b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers3.ver new file mode 100644 index 00000000000..aa230eea3ee --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers3.ver @@ -0,0 +1,4 @@ +Version References: + required from tmpdir/vers1.so: + 0x0a7922b0 0x00 02 VERS_2.0 + diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers4.c b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers4.c new file mode 100644 index 00000000000..0a0f212c4aa --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers4.c @@ -0,0 +1,23 @@ +/* + * Testcase to make sure that a versioned symbol definition in an + * application correctly defines the version node, if and only if + * the actual symbol is exported. This is built both with and without + * -export-dynamic. + */ +int bar() +{ + return 3; +} + +new_foo() +{ + return 1000+bar(); + +} + +__asm__(".symver new_foo,foo@@VERS_2.0"); + +main() +{ + printf("%d\n", foo()); +} diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers4.sym b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers4.sym new file mode 100644 index 00000000000..7fffb77e324 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers4.sym @@ -0,0 +1 @@ +[0-9a-f]* g F .text [0-9a-f]* foo@@VERS_2.0 diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers4a.dsym b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers4a.dsym new file mode 100644 index 00000000000..571f5ca9fe0 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers4a.dsym @@ -0,0 +1,2 @@ +[0]* g DO \*ABS\* [0]* VERS_2.0 VERS_2.0 +[0-9a-f]* g DF (.text|\*ABS\*) [0-9a-f]* VERS_2.0 foo diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers4a.sym b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers4a.sym new file mode 100644 index 00000000000..7fffb77e324 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers4a.sym @@ -0,0 +1 @@ +[0-9a-f]* g F .text [0-9a-f]* foo@@VERS_2.0 diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers4a.ver b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers4a.ver new file mode 100644 index 00000000000..876cedc87b3 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers4a.ver @@ -0,0 +1,4 @@ +Version definitions: +1 0x01 0x0d8a26e1 tmpdir/vers4a +2 0x00 0x0a7922b0 VERS_2.0 + diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers5.c b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers5.c new file mode 100644 index 00000000000..bf31817bdc2 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers5.c @@ -0,0 +1,46 @@ +/* + * Testcase to verify that foo@BAR and foo@@BAR are correctly detected + * as a multiply defined symbol. + */ +const char * bar1 = "asdf"; +const char * bar2 = "asdf"; + +int bar() +{ + return 3; +} + +original_foo() +{ + return 1+bar(); + +} + +old_foo() +{ + return 10+bar(); + +} + +old_foo1() +{ + return 100+bar(); + +} + +new_foo() +{ + return 1000+bar(); + +} + +__asm__(".symver original_foo,foo@"); +__asm__(".symver old_foo,foo@VERS_1.1"); +__asm__(".symver old_foo1,foo@VERS_1.2"); +__asm__(".symver new_foo,foo@@VERS_1.2"); + +int +main () +{ + return 0; +} diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers6.c b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers6.c new file mode 100644 index 00000000000..ca8a40dd266 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers6.c @@ -0,0 +1,17 @@ +/* + * Testcase to make sure that if we externally reference a versioned symbol + * that we always get the right one. + */ + +main() +{ + printf("Expect 4, get %d\n", foo_1()); + printf("Expect 13, get %d\n", foo_2()); + printf("Expect 103, get %d\n", foo_3()); + printf("Expect 1003, get %d\n", foo_4()); +} + +__asm__(".symver foo_1,show_foo@"); +__asm__(".symver foo_2,show_foo@VERS_1.1"); +__asm__(".symver foo_3,show_foo@VERS_1.2"); +__asm__(".symver foo_4,show_foo@VERS_2.0"); diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers6.dsym b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers6.dsym new file mode 100644 index 00000000000..2b06e8ff3bc --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers6.dsym @@ -0,0 +1,4 @@ +[0-9a-f]* DF \*UND\* [0-9a-f]* show_foo +[0-9a-f]* DF \*UND\* [0-9a-f]* VERS_2.0 show_foo +[0-9a-f]* DF \*UND\* [0-9a-f]* VERS_1.2 show_foo +[0-9a-f]* DF \*UND\* [0-9a-f]* VERS_1.1 show_foo diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers6.sym b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers6.sym new file mode 100644 index 00000000000..d7b5cc75bbe --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers6.sym @@ -0,0 +1,4 @@ +[0]* *F? *\*UND\* [0]* show_foo@ +[0]* *F? *\*UND\* [0]* show_foo@VERS_1.1 +[0]* *F? *\*UND\* [0]* show_foo@VERS_1.2 +[0]* *F? *\*UND\* [0]* show_foo@VERS_2.0 diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers6.ver b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers6.ver new file mode 100644 index 00000000000..fc72d2fd9d5 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers6.ver @@ -0,0 +1,8 @@ +Version References: + required from tmpdir/vers1.so: + 0x0a7927b1 0x00 04 VERS_1.1 + required from tmpdir/vers1.so: + 0x0a7927b2 0x00 03 VERS_1.2 + required from tmpdir/vers1.so: + 0x0a7922b0 0x00 02 VERS_2.0 + diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers7.c b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers7.c new file mode 100644 index 00000000000..2dd56c58d6d --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers7.c @@ -0,0 +1,10 @@ +/* + * Test program that goes with test7.so + */ + + +int +main() +{ + return hide_a(1) + show_b(1); +} diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers7.map b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers7.map new file mode 100644 index 00000000000..65fd501d2c3 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers7.map @@ -0,0 +1,6 @@ +VERS_1 { + global: + show_b ; + local: + hide_a; +}; diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers7a.c b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers7a.c new file mode 100644 index 00000000000..7bee8c70bfe --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers7a.c @@ -0,0 +1,18 @@ +/* + * Test supplied by Ulrich. Verify that we can correctly force 'a' + * to local scope. + */ +int +__a_internal (int e) +{ + return e + 10; +} + +int +__b_internal (int e) +{ + return e + 42; +} + +asm (".symver __a_internal,hide_a@@VERS_1"); +asm (".symver __b_internal,show_b@@VERS_1"); diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers7a.dsym b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers7a.dsym new file mode 100644 index 00000000000..5acbdeb70b8 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers7a.dsym @@ -0,0 +1,2 @@ +[0]* g DO \*ABS\* [0]* VERS_1 VERS_1 +[0-9a-f]* g DF (.text|\*ABS\*) [0-9a-f]* VERS_1 show_b diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers7a.sym b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers7a.sym new file mode 100644 index 00000000000..c577c4a32f1 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers7a.sym @@ -0,0 +1,2 @@ +[0-9a-f]* g F .text [0-9a-f]* hide_a@@VERS_1 +[0-9a-f]* g F .text [0-9a-f]* show_b@@VERS_1 diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers7a.ver b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers7a.ver new file mode 100644 index 00000000000..37ef8a824cc --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers7a.ver @@ -0,0 +1,4 @@ +Version definitions: +1 0x01 0x0269fd3f tmpdir/vers7a.so +2 0x00 0x05aa7921 VERS_1 + diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers8.c b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers8.c new file mode 100644 index 00000000000..a14586cbc8a --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers8.c @@ -0,0 +1,5 @@ +int +main() +{ + return a(1) + b(1); +} diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers8.map b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers8.map new file mode 100644 index 00000000000..26359559d9f --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers8.map @@ -0,0 +1,18 @@ +VERSION { + VERS_1.1 { + global: + foo1; + local: + hide_old*; + hide_original*; + hide_new*; + }; + + VERS_1.2 { + foo2; + } VERS_1.1; + + VERS_2.0 { + show_bar1; show_bar2; + } VERS_1.2; +} diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers8.ver b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers8.ver new file mode 100644 index 00000000000..ef59023ccee --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers8.ver @@ -0,0 +1,8 @@ +Version definitions: +1 0x01 0x0a26f81f tmpdir/vers8.so +2 0x00 0x0a7927b1 VERS_1.1 +3 0x00 0x0a7927b2 VERS_1.2 + VERS_1.1 +4 0x00 0x0a7922b0 VERS_2.0 + VERS_1.2 + diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers9.c b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers9.c new file mode 100644 index 00000000000..7ef4310783d --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers9.c @@ -0,0 +1,39 @@ +/* + * Testcase to verify that reference to foo@BAR and a definition of foo@@BAR + * are not treated as a multiple def. + */ +const char * bar1 = "asdf"; +const char * bar2 = "asdf"; + +int bar() +{ + return 3; +} + +original_foo() +{ + return 1+bar(); + +} + +old_foo() +{ + return 10+bar(); + +} + +new_foo() +{ + return 1000+bar(); + +} + +main() +{ + old_foo1(); +} + +__asm__(".symver original_foo,foo@"); +__asm__(".symver old_foo,foo@VERS_1.1"); +__asm__(".symver old_foo1,foo@VERS_1.2"); +__asm__(".symver new_foo,foo@@VERS_1.2"); diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers9.dsym b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers9.dsym new file mode 100644 index 00000000000..4842212ff40 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers9.dsym @@ -0,0 +1,4 @@ +[0]* g DO \*ABS\* [0]* VERS_1.1 VERS_1.1 +[0]* g DO \*ABS\* [0]* VERS_1.2 VERS_1.2 +[0-9a-f]* g DF (.text|\*ABS\*) [0-9a-f]* \(VERS_1.1\) foo +[0-9a-f]* g DF (.text|\*ABS\*) [0-9a-f]* VERS_1.2 foo diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers9.sym b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers9.sym new file mode 100644 index 00000000000..23a07e89ef5 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers9.sym @@ -0,0 +1,4 @@ +[0]* *F? *\*UND\* [0]* foo@VERS_1.2 +[0-9a-f]* g F .text [0-9a-f]* foo@ +[0-9a-f]* g F .text [0-9a-f]* foo@VERS_1.1 +[0-9a-f]* g F .text [0-9a-f]* foo@@VERS_1.2 diff --git a/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers9.ver b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers9.ver new file mode 100644 index 00000000000..673ba72ab45 --- /dev/null +++ b/gnu/usr.bin/binutils/ld/testsuite/ld-elfvers/vers9.ver @@ -0,0 +1,5 @@ +Version definitions: +1 0x01 0x04d8a269 tmpdir/vers9 +2 0x00 0x0a7927b1 VERS_1.1 +3 0x00 0x0a7927b2 VERS_1.2 + diff --git a/gnu/usr.bin/binutils/libiberty/objalloc.c b/gnu/usr.bin/binutils/libiberty/objalloc.c new file mode 100644 index 00000000000..34687d3891a --- /dev/null +++ b/gnu/usr.bin/binutils/libiberty/objalloc.c @@ -0,0 +1,289 @@ +/* objalloc.c -- routines to allocate memory for objects + Copyright 1997 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Cygnus Solutions. + +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 2, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "ansidecl.h" +#include "objalloc.h" + +/* Get a definition for NULL. */ +#include <stdio.h> + +#if VMS +#include <stdlib.h> +#include <unixlib.h> +#else + +#ifdef ANSI_PROTOTYPES +/* Get a definition for size_t. */ +#include <stddef.h> +#endif + +/* For systems with larger pointers than ints, this must be declared. */ +extern PTR malloc PARAMS ((size_t)); +#endif + +/* These routines allocate space for an object. Freeing allocated + space may or may not free all more recently allocated space. + + We handle large and small allocation requests differently. If we + don't have enough space in the current block, and the allocation + request is for more than 512 bytes, we simply pass it through to + malloc. */ + +/* The objalloc structure is defined in objalloc.h. */ + +/* This structure appears at the start of each chunk. */ + +struct objalloc_chunk +{ + /* Next chunk. */ + struct objalloc_chunk *next; + /* If this chunk contains large objects, this is the value of + current_ptr when this chunk was allocated. If this chunk + contains small objects, this is NULL. */ + char *current_ptr; +}; + +/* The aligned size of objalloc_chunk. */ + +#define CHUNK_HEADER_SIZE \ + ((sizeof (struct objalloc_chunk) + OBJALLOC_ALIGN - 1) \ + &~ (OBJALLOC_ALIGN - 1)) + +/* We ask for this much memory each time we create a chunk which is to + hold small objects. */ + +#define CHUNK_SIZE (4096 - 32) + +/* A request for this amount or more is just passed through to malloc. */ + +#define BIG_REQUEST (512) + +/* Create an objalloc structure. */ + +struct objalloc * +objalloc_create () +{ + struct objalloc *ret; + struct objalloc_chunk *chunk; + + ret = (struct objalloc *) malloc (sizeof *ret); + if (ret == NULL) + return NULL; + + ret->chunks = (PTR) malloc (CHUNK_SIZE); + if (ret->chunks == NULL) + { + free (ret); + return NULL; + } + + chunk = (struct objalloc_chunk *) ret->chunks; + chunk->next = NULL; + chunk->current_ptr = NULL; + + ret->current_ptr = (char *) chunk + CHUNK_HEADER_SIZE; + ret->current_space = CHUNK_SIZE - CHUNK_HEADER_SIZE; + + return ret; +} + +/* Allocate space from an objalloc structure. */ + +PTR +_objalloc_alloc (o, len) + struct objalloc *o; + unsigned long len; +{ + /* We avoid confusion from zero sized objects by always allocating + at least 1 byte. */ + if (len == 0) + len = 1; + + len = (len + OBJALLOC_ALIGN - 1) &~ (OBJALLOC_ALIGN - 1); + + if (len <= o->current_space) + { + o->current_ptr += len; + o->current_space -= len; + return (PTR) (o->current_ptr - len); + } + + if (len >= BIG_REQUEST) + { + char *ret; + struct objalloc_chunk *chunk; + + ret = (char *) malloc (CHUNK_HEADER_SIZE + len); + if (ret == NULL) + return NULL; + + chunk = (struct objalloc_chunk *) ret; + chunk->next = (struct objalloc_chunk *) o->chunks; + chunk->current_ptr = o->current_ptr; + + o->chunks = (PTR) chunk; + + return (PTR) (ret + CHUNK_HEADER_SIZE); + } + else + { + struct objalloc_chunk *chunk; + + chunk = (struct objalloc_chunk *) malloc (CHUNK_SIZE); + if (chunk == NULL) + return NULL; + chunk->next = (struct objalloc_chunk *) o->chunks; + chunk->current_ptr = NULL; + + o->current_ptr = (char *) chunk + CHUNK_HEADER_SIZE; + o->current_space = CHUNK_SIZE - CHUNK_HEADER_SIZE; + + o->chunks = (PTR) chunk; + + return objalloc_alloc (o, len); + } +} + +/* Free an entire objalloc structure. */ + +void +objalloc_free (o) + struct objalloc *o; +{ + struct objalloc_chunk *l; + + l = (struct objalloc_chunk *) o->chunks; + while (l != NULL) + { + struct objalloc_chunk *next; + + next = l->next; + free (l); + l = next; + } + + free (o); +} + +/* Free a block from an objalloc structure. This also frees all more + recently allocated blocks. */ + +void +objalloc_free_block (o, block) + struct objalloc *o; + PTR block; +{ + struct objalloc_chunk *p, *small; + char *b = (char *) block; + + /* First set P to the chunk which contains the block we are freeing, + and set Q to the last small object chunk we see before P. */ + small = NULL; + for (p = (struct objalloc_chunk *) o->chunks; p != NULL; p = p->next) + { + if (p->current_ptr == NULL) + { + if (b > (char *) p && b < (char *) p + CHUNK_SIZE) + break; + small = p; + } + else + { + if (b == (char *) p + CHUNK_HEADER_SIZE) + break; + } + } + + /* If we can't find the chunk, the caller has made a mistake. */ + if (p == NULL) + abort (); + + if (p->current_ptr == NULL) + { + struct objalloc_chunk *q; + struct objalloc_chunk *first; + + /* The block is in a chunk containing small objects. We can + free every chunk through SMALL, because they have certainly + been allocated more recently. After SMALL, we will not see + any chunks containing small objects; we can free any big + chunk if the current_ptr is greater than or equal to B. We + can then reset the new current_ptr to B. */ + + first = NULL; + q = (struct objalloc_chunk *) o->chunks; + while (q != p) + { + struct objalloc_chunk *next; + + next = q->next; + if (small != NULL) + { + if (small == q) + small = NULL; + free (q); + } + else if (q->current_ptr > b) + free (q); + else if (first == NULL) + first = q; + + q = next; + } + + if (first == NULL) + first = p; + o->chunks = (PTR) first; + + /* Now start allocating from this small block again. */ + o->current_ptr = b; + o->current_space = ((char *) p + CHUNK_SIZE) - b; + } + else + { + struct objalloc_chunk *q; + char *current_ptr; + + /* This block is in a large chunk by itself. We can free + everything on the list up to and including this block. We + then start allocating from the next chunk containing small + objects, setting current_ptr from the value stored with the + large chunk we are freeing. */ + + current_ptr = p->current_ptr; + p = p->next; + + q = (struct objalloc_chunk *) o->chunks; + while (q != p) + { + struct objalloc_chunk *next; + + next = q->next; + free (q); + q = next; + } + + o->chunks = (PTR) p; + + while (p->current_ptr != NULL) + p = p->next; + + o->current_ptr = current_ptr; + o->current_space = ((char *) p + CHUNK_SIZE) - current_ptr; + } +} diff --git a/gnu/usr.bin/binutils/opcodes/cgen-asm.c b/gnu/usr.bin/binutils/opcodes/cgen-asm.c new file mode 100644 index 00000000000..732ba57805f --- /dev/null +++ b/gnu/usr.bin/binutils/opcodes/cgen-asm.c @@ -0,0 +1,291 @@ +/* CGEN generic assembler support code. + +Copyright (C) 1996, 1997 Free Software Foundation, Inc. + +This file is part of the GNU Binutils and GDB, the GNU debugger. + +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 2, 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., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sysdep.h" +#include <stdio.h> +#include "ansidecl.h" +#include "libiberty.h" +#include "bfd.h" +#include "opcode/cgen.h" + +/* Operand parsing callback. */ +const char * (*cgen_parse_operand_fn) + PARAMS ((enum cgen_parse_operand_type, const char **, int, int, + enum cgen_parse_operand_result *, bfd_vma *)); + +/* This is not published as part of the public interface so we don't + declare this in cgen.h. */ +extern CGEN_OPCODE_DATA *cgen_current_opcode_data; + +/* Assembler instruction hash table. */ +static CGEN_INSN_LIST **asm_hash_table; + +/* Called once at startup and whenever machine/endian change. */ + +void +cgen_asm_init () +{ + if (asm_hash_table) + { + free (asm_hash_table); + asm_hash_table = NULL; + } +} + +/* Called whenever starting to parse an insn. */ + +void +cgen_init_parse_operand () +{ + /* This tells the callback to re-initialize. */ + (void) (*cgen_parse_operand_fn) (CGEN_PARSE_OPERAND_INIT, NULL, 0, 0, + NULL, NULL); +} + +/* Build the assembler instruction hash table. */ + +static void +build_asm_hash_table () +{ + int i; + unsigned int hash; + int count = cgen_insn_count (); + CGEN_OPCODE_DATA *data = cgen_current_opcode_data; + CGEN_INSN_TABLE *insn_table = data->insn_table; + unsigned int hash_size = insn_table->asm_hash_table_size; + const CGEN_INSN *insn; + CGEN_INSN_LIST *insn_lists,*new_insns; + + /* The space allocated for the hash table consists of two parts: + the hash table and the hash lists. */ + + asm_hash_table = (CGEN_INSN_LIST **) + xmalloc (hash_size * sizeof (CGEN_INSN_LIST *) + + count * sizeof (CGEN_INSN_LIST)); + memset (asm_hash_table, 0, + hash_size * sizeof (CGEN_INSN_LIST *) + + count * sizeof (CGEN_INSN_LIST)); + insn_lists = (CGEN_INSN_LIST *) (asm_hash_table + hash_size); + + /* Add compiled in insns. + The table is scanned backwards as later additions are inserted in + front of earlier ones and we want earlier ones to be prefered. + We stop at the first one as it is a reserved entry. */ + + for (insn = insn_table->init_entries + insn_table->num_init_entries - 1; + insn > insn_table->init_entries; + --insn, ++insn_lists) + { + hash = (*insn_table->asm_hash) (insn->syntax.mnemonic); + insn_lists->next = asm_hash_table[hash]; + insn_lists->insn = insn; + asm_hash_table[hash] = insn_lists; + } + + /* Add runtime added insns. + ??? Currently later added insns will be prefered over earlier ones. + Not sure this is a bug or not. */ + for (new_insns = insn_table->new_entries; + new_insns != NULL; + new_insns = new_insns->next, ++insn_lists) + { + hash = (*insn_table->asm_hash) (new_insns->insn->syntax.mnemonic); + insn_lists->next = asm_hash_table[hash]; + insn_lists->insn = new_insns->insn; + asm_hash_table[hash] = insn_lists; + } +} + +/* Return the first entry in the hash list for INSN. */ + +CGEN_INSN_LIST * +cgen_asm_lookup_insn (insn) + const char *insn; +{ + unsigned int hash; + + if (asm_hash_table == NULL) + build_asm_hash_table (); + + hash = (*cgen_current_opcode_data->insn_table->asm_hash) (insn); + return asm_hash_table[hash]; +} + +/* Keyword parser. + The result is NULL upon success or an error message. + If successful, *STRP is updated to point passed the keyword. + + ??? At present we have a static notion of how to pick out a keyword. + Later we can allow a target to customize this if necessary [say by + recording something in the keyword table]. */ + +const char * +cgen_parse_keyword (strp, keyword_table, valuep) + const char **strp; + struct cgen_keyword *keyword_table; + long *valuep; +{ + const struct cgen_keyword_entry *ke; + char buf[256]; + const char *p; + + p = *strp; + + /* Allow any first character. */ + if (*p) + ++p; + + /* Now allow letters, digits, and _. */ + while (isalnum (*p) || *p == '_') + ++p; + + if (p - *strp > 255) + return "unrecognized keyword/register name"; + + memcpy (buf, *strp, p - *strp); + buf[p - *strp] = 0; + + ke = cgen_keyword_lookup_name (keyword_table, buf); + + if (ke != NULL) + { + *valuep = ke->value; + *strp = p; + return NULL; + } + + return "unrecognized keyword/register name"; +} + +/* Signed integer parser. */ + +const char * +cgen_parse_signed_integer (strp, opindex, min, max, valuep) + const char **strp; + int opindex; + long min, max; + long *valuep; +{ + long value; + enum cgen_parse_operand_result result; + const char *errmsg; + + errmsg = (*cgen_parse_operand_fn) (CGEN_PARSE_OPERAND_INTEGER, strp, + opindex, BFD_RELOC_NONE, + &result, &value); + /* FIXME: Examine `result'. */ + if (!errmsg) + { + if (value < min || value > max) + return "integer operand out of range"; + *valuep = value; + } + return errmsg; +} + +/* Unsigned integer parser. */ + +const char * +cgen_parse_unsigned_integer (strp, opindex, min, max, valuep) + const char **strp; + int opindex; + unsigned long min, max; + unsigned long *valuep; +{ + unsigned long value; + enum cgen_parse_operand_result result; + const char *errmsg; + + errmsg = (*cgen_parse_operand_fn) (CGEN_PARSE_OPERAND_INTEGER, strp, + opindex, BFD_RELOC_NONE, + &result, &value); + /* FIXME: Examine `result'. */ + if (!errmsg) + { + if (value < min || value > max) + return "integer operand out of range"; + *valuep = value; + } + return errmsg; +} + +/* Address parser. */ + +const char * +cgen_parse_address (strp, opindex, opinfo, valuep) + const char **strp; + int opindex; + int opinfo; + long *valuep; +{ + long value; + enum cgen_parse_operand_result result; + const char *errmsg; + + errmsg = (*cgen_parse_operand_fn) (CGEN_PARSE_OPERAND_ADDRESS, strp, + opindex, opinfo, + &result, &value); + /* FIXME: Examine `result'. */ + if (!errmsg) + { + *valuep = value; + } + return errmsg; +} + +/* Signed integer validation routine. */ + +const char * +cgen_validate_signed_integer (value, min, max) + long value, min, max; +{ + if (value < min || value > max) + { + const char *err = + "operand out of range (%ld not between %ld and %ld)"; + static char buf[100]; + + sprintf (buf, err, value, min, max); + return buf; + } + + return NULL; +} + +/* Unsigned integer validation routine. + Supplying `min' here may seem unnecessary, but we also want to handle + cases where min != 0 (and max > LONG_MAX). */ + +const char * +cgen_validate_unsigned_integer (value, min, max) + unsigned long value, min, max; +{ + if (value < min || value > max) + { + const char *err = + "operand out of range (%lu not between %lu and %lu)"; + static char buf[100]; + + sprintf (buf, err, value, min, max); + return buf; + } + + return NULL; +} diff --git a/gnu/usr.bin/binutils/opcodes/cgen-dis.c b/gnu/usr.bin/binutils/opcodes/cgen-dis.c new file mode 100644 index 00000000000..f239b66326b --- /dev/null +++ b/gnu/usr.bin/binutils/opcodes/cgen-dis.c @@ -0,0 +1,162 @@ +/* CGEN generic disassembler support code. + +Copyright (C) 1996, 1997 Free Software Foundation, Inc. + +This file is part of the GNU Binutils and GDB, the GNU debugger. + +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 2, 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., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sysdep.h" +#include <stdio.h> +#include "ansidecl.h" +#include "libiberty.h" +#include "bfd.h" +#include "opcode/cgen.h" + +/* This is not published as part of the public interface so we don't + declare this in cgen.h. */ +extern CGEN_OPCODE_DATA *cgen_current_opcode_data; + +/* Disassembler instruction hash table. */ +static CGEN_INSN_LIST **dis_hash_table; + +void +cgen_dis_init () +{ + if (dis_hash_table) + { + free (dis_hash_table); + dis_hash_table = NULL; + } +} + +/* Build the disassembler instruction hash table. */ + +static void +build_dis_hash_table () +{ + int i; + int big_p = cgen_current_endian == CGEN_ENDIAN_BIG; + unsigned int hash; + char buf[4]; + unsigned long value; + int count = cgen_insn_count (); + CGEN_OPCODE_DATA *data = cgen_current_opcode_data; + CGEN_INSN_TABLE *insn_table = data->insn_table; + unsigned int hash_size = insn_table->dis_hash_table_size; + const CGEN_INSN *insn; + CGEN_INSN_LIST *insn_lists,*new_insns; + + /* The space allocated for the hash table consists of two parts: + the hash table and the hash lists. */ + + dis_hash_table = (CGEN_INSN_LIST **) + xmalloc (hash_size * sizeof (CGEN_INSN_LIST *) + + count * sizeof (CGEN_INSN_LIST)); + memset (dis_hash_table, 0, + hash_size * sizeof (CGEN_INSN_LIST *) + + count * sizeof (CGEN_INSN_LIST)); + insn_lists = (CGEN_INSN_LIST *) (dis_hash_table + hash_size); + + /* Add compiled in insns. + The table is scanned backwards as later additions are inserted in + front of earlier ones and we want earlier ones to be prefered. + We stop at the first one as it is a reserved entry. */ + + for (insn = insn_table->init_entries + insn_table->num_init_entries - 1; + insn > insn_table->init_entries; + --insn, ++insn_lists) + { + /* We don't know whether the target uses the buffer or the base insn + to hash on, so set both up. */ + value = insn->syntax.value; + switch (CGEN_INSN_BITSIZE (insn)) + { + case 8: + buf[0] = value; + break; + case 16: + if (big_p) + bfd_putb16 ((bfd_vma) value, buf); + else + bfd_putl16 ((bfd_vma) value, buf); + break; + case 32: + if (big_p) + bfd_putb32 ((bfd_vma) value, buf); + else + bfd_putl32 ((bfd_vma) value, buf); + break; + default: + abort (); + } + hash = (*insn_table->dis_hash) (buf, value); + insn_lists->next = dis_hash_table[hash]; + insn_lists->insn = insn; + dis_hash_table[hash] = insn_lists; + } + + /* Add runtime added insns. + ??? Currently later added insns will be prefered over earlier ones. + Not sure this is a bug or not. */ + for (new_insns = insn_table->new_entries; + new_insns != NULL; + new_insns = new_insns->next, ++insn_lists) + { + /* We don't know whether the target uses the buffer or the base insn + to hash on, so set both up. */ + value = new_insns->insn->syntax.value; + switch (CGEN_INSN_BITSIZE (new_insns->insn)) + { + case 8: + buf[0] = value; + break; + case 16: + if (big_p) + bfd_putb16 ((bfd_vma) value, buf); + else + bfd_putl16 ((bfd_vma) value, buf); + break; + case 32: + if (big_p) + bfd_putb32 ((bfd_vma) value, buf); + else + bfd_putl32 ((bfd_vma) value, buf); + break; + default: + abort (); + } + hash = (*insn_table->dis_hash) (buf, value); + insn_lists->next = dis_hash_table[hash]; + insn_lists->insn = new_insns->insn; + dis_hash_table[hash] = insn_lists; + } +} + +/* Return the first entry in the hash list for INSN. */ + +CGEN_INSN_LIST * +cgen_dis_lookup_insn (buf, value) + const char *buf; + unsigned long value; +{ + unsigned int hash; + + if (dis_hash_table == NULL) + build_dis_hash_table (); + + hash = (*cgen_current_opcode_data->insn_table->dis_hash) (buf, value); + return dis_hash_table[hash]; +} diff --git a/gnu/usr.bin/binutils/opcodes/cgen-opc.c b/gnu/usr.bin/binutils/opcodes/cgen-opc.c new file mode 100644 index 00000000000..f9c67c84cce --- /dev/null +++ b/gnu/usr.bin/binutils/opcodes/cgen-opc.c @@ -0,0 +1,306 @@ +/* CGEN generic opcode support. + +Copyright (C) 1996, 1997 Free Software Foundation, Inc. + +This file is part of the GNU Binutils and GDB, the GNU debugger. + +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 2, 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., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sysdep.h" +#include <stdio.h> +#include "ansidecl.h" +#include "libiberty.h" +#include "bfd.h" +#include "opcode/cgen.h" + +/* State variables. + These record the state of the currently selected cpu, machine, endian, etc. + They are set by cgen_set_cpu. */ + +/* Current opcode data. */ +CGEN_OPCODE_DATA *cgen_current_opcode_data; + +/* Current machine (a la BFD machine number). */ +int cgen_current_mach; + +/* Current endian. */ +enum cgen_endian cgen_current_endian = CGEN_ENDIAN_UNKNOWN; + +void +cgen_set_cpu (data, mach, endian) + CGEN_OPCODE_DATA *data; + int mach; + enum cgen_endian endian; +{ + cgen_current_opcode_data = data; + cgen_current_mach = mach; + cgen_current_endian = endian; + +#if 0 /* This isn't done here because it would put assembler support in the + disassembler, etc. The caller is required to call these after calling + us. */ + /* Reset the hash tables. */ + cgen_asm_init (); + cgen_dis_init (); +#endif +} + +static unsigned int hash_keyword_name + PARAMS ((const struct cgen_keyword *, const char *)); +static unsigned int hash_keyword_value + PARAMS ((const struct cgen_keyword *, int)); +static void build_keyword_hash_tables + PARAMS ((struct cgen_keyword *)); + +/* Return number of hash table entries to use for N elements. */ +#define KEYWORD_HASH_SIZE(n) ((n) <= 31 ? 17 : 31) + +/* Look up *NAMEP in the keyword table KT. + The result is the keyword entry or NULL if not found. */ + +const struct cgen_keyword_entry * +cgen_keyword_lookup_name (kt, name) + struct cgen_keyword *kt; + const char *name; +{ + const struct cgen_keyword_entry *ke; + const char *p,*n; + + if (kt->name_hash_table == NULL) + build_keyword_hash_tables (kt); + + ke = kt->name_hash_table[hash_keyword_name (kt, name)]; + + /* We do case insensitive comparisons. + If that ever becomes a problem, add an attribute that denotes + "do case sensitive comparisons". */ + + while (ke != NULL) + { + n = name; + p = ke->name; + + while (*p + && (*p == *n + || (isalpha (*p) && tolower (*p) == tolower (*n)))) + ++n, ++p; + + if (!*p && !*n) + return ke; + + ke = ke->next_name; + } + + return NULL; +} + +/* Look up VALUE in the keyword table KT. + The result is the keyword entry or NULL if not found. */ + +const struct cgen_keyword_entry * +cgen_keyword_lookup_value (kt, value) + struct cgen_keyword *kt; + int value; +{ + const struct cgen_keyword_entry *ke; + + if (kt->name_hash_table == NULL) + build_keyword_hash_tables (kt); + + ke = kt->value_hash_table[hash_keyword_value (kt, value)]; + + while (ke != NULL) + { + if (value == ke->value) + return ke; + ke = ke->next_value; + } + + return NULL; +} + +/* Add an entry to a keyword table. */ + +void +cgen_keyword_add (kt, ke) + struct cgen_keyword *kt; + struct cgen_keyword_entry *ke; +{ + unsigned int hash; + + if (kt->name_hash_table == NULL) + build_keyword_hash_tables (kt); + + hash = hash_keyword_name (kt, ke->name); + ke->next_name = kt->name_hash_table[hash]; + kt->name_hash_table[hash] = ke; + + hash = hash_keyword_value (kt, ke->value); + ke->next_value = kt->value_hash_table[hash]; + kt->value_hash_table[hash] = ke; +} + +/* FIXME: Need function to return count of keywords. */ + +/* Initialize a keyword table search. + SPEC is a specification of what to search for. + A value of NULL means to find every keyword. + Currently NULL is the only acceptable value [further specification + deferred]. + The result is an opaque data item used to record the search status. + It is passed to each call to cgen_keyword_search_next. */ + +struct cgen_keyword_search +cgen_keyword_search_init (kt, spec) + struct cgen_keyword *kt; + const char *spec; +{ + struct cgen_keyword_search search; + + /* FIXME: Need to specify format of PARAMS. */ + if (spec != NULL) + abort (); + + if (kt->name_hash_table == NULL) + build_keyword_hash_tables (kt); + + search.table = kt; + search.spec = spec; + search.current_hash = 0; + search.current_entry = NULL; + return search; +} + +/* Return the next keyword specified by SEARCH. + The result is the next entry or NULL if there are no more. */ + +const struct cgen_keyword_entry * +cgen_keyword_search_next (search) + struct cgen_keyword_search *search; +{ + const struct cgen_keyword_entry *ke; + + /* Has search finished? */ + if (search->current_hash == search->table->hash_table_size) + return NULL; + + /* Search in progress? */ + if (search->current_entry != NULL + /* Anything left on this hash chain? */ + && search->current_entry->next_name != NULL) + { + search->current_entry = search->current_entry->next_name; + return search->current_entry; + } + + /* Move to next hash chain [unless we haven't started yet]. */ + if (search->current_entry != NULL) + ++search->current_hash; + + while (search->current_hash < search->table->hash_table_size) + { + search->current_entry = search->table->name_hash_table[search->current_hash]; + if (search->current_entry != NULL) + return search->current_entry; + ++search->current_hash; + } + + return NULL; +} + +/* Return first entry in hash chain for NAME. */ + +static unsigned int +hash_keyword_name (kt, name) + const struct cgen_keyword *kt; + const char *name; +{ + unsigned int hash; + + for (hash = 0; *name; ++name) + hash = (hash * 97) + (unsigned char) *name; + return hash % kt->hash_table_size; +} + +/* Return first entry in hash chain for VALUE. */ + +static unsigned int +hash_keyword_value (kt, value) + const struct cgen_keyword *kt; + int value; +{ + return value % kt->hash_table_size; +} + +/* Build a keyword table's hash tables. + We probably needn't build the value hash table for the assembler when + we're using the disassembler, but we keep things simple. */ + +static void +build_keyword_hash_tables (kt) + struct cgen_keyword *kt; +{ + int i; + /* Use the number of compiled in entries as an estimate for the + typical sized table [not too many added at runtime]. */ + unsigned int size = KEYWORD_HASH_SIZE (kt->num_init_entries); + + kt->hash_table_size = size; + kt->name_hash_table = (struct cgen_keyword_entry **) + xmalloc (size * sizeof (struct cgen_keyword_entry *)); + memset (kt->name_hash_table, 0, size * sizeof (struct cgen_keyword_entry *)); + kt->value_hash_table = (struct cgen_keyword_entry **) + xmalloc (size * sizeof (struct cgen_keyword_entry *)); + memset (kt->value_hash_table, 0, size * sizeof (struct cgen_keyword_entry *)); + + /* The table is scanned backwards as we want keywords appearing earlier to + be prefered over later ones. */ + for (i = kt->num_init_entries - 1; i >= 0; --i) + cgen_keyword_add (kt, &kt->init_entries[i]); +} + +/* Hardware support. */ + +CGEN_HW_ENTRY * +cgen_hw_lookup (name) + const char *name; +{ + CGEN_HW_ENTRY *hw = cgen_current_opcode_data->hw_list; + + while (hw != NULL) + { + if (strcmp (name, hw->name) == 0) + return hw; + hw = hw->next; + } + + return NULL; +} + +/* Instruction support. */ + +/* Return number of instructions. This includes any added at runtime. */ + +int +cgen_insn_count () +{ + int count = cgen_current_opcode_data->insn_table->num_init_entries; + CGEN_INSN_LIST *insn = cgen_current_opcode_data->insn_table->new_entries; + + for ( ; insn != NULL; insn = insn->next) + ++count; + + return count; +} diff --git a/gnu/usr.bin/binutils/opcodes/d10v-dis.c b/gnu/usr.bin/binutils/opcodes/d10v-dis.c new file mode 100644 index 00000000000..90495211862 --- /dev/null +++ b/gnu/usr.bin/binutils/opcodes/d10v-dis.c @@ -0,0 +1,293 @@ +/* Disassemble D10V instructions. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + +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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +#include <stdio.h> + +#include "ansidecl.h" +#include "opcode/d10v.h" +#include "dis-asm.h" + +/* the PC wraps at 18 bits, except for the segment number */ +/* so use this mask to keep the parts we want */ +#define PC_MASK 0x03003FFF + +static void dis_2_short PARAMS ((unsigned long insn, bfd_vma memaddr, + struct disassemble_info *info, int order)); +static void dis_long PARAMS ((unsigned long insn, bfd_vma memaddr, + struct disassemble_info *info)); + +int +print_insn_d10v (memaddr, info) + bfd_vma memaddr; + struct disassemble_info *info; +{ + int status; + bfd_byte buffer[4]; + unsigned long insn; + + status = (*info->read_memory_func) (memaddr, buffer, 4, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + insn = bfd_getb32 (buffer); + + status = insn & FM11; + switch (status) { + case 0: + dis_2_short (insn, memaddr, info, 2); + break; + case FM01: + dis_2_short (insn, memaddr, info, 0); + break; + case FM10: + dis_2_short (insn, memaddr, info, 1); + break; + case FM11: + dis_long (insn, memaddr, info); + break; + } + return 4; +} + +static void +print_operand (oper, insn, op, memaddr, info) + struct d10v_operand *oper; + unsigned long insn; + struct d10v_opcode *op; + bfd_vma memaddr; + struct disassemble_info *info; +{ + int num, shift; + + if (oper->flags == OPERAND_ATMINUS) + { + (*info->fprintf_func) (info->stream, "@-"); + return; + } + if (oper->flags == OPERAND_MINUS) + { + (*info->fprintf_func) (info->stream, "-"); + return; + } + if (oper->flags == OPERAND_PLUS) + { + (*info->fprintf_func) (info->stream, "+"); + return; + } + if (oper->flags == OPERAND_ATSIGN) + { + (*info->fprintf_func) (info->stream, "@"); + return; + } + if (oper->flags == OPERAND_ATPAR) + { + (*info->fprintf_func) (info->stream, "@("); + return; + } + + shift = oper->shift; + + /* the LONG_L format shifts registers over by 15 */ + if (op->format == LONG_L && (oper->flags & OPERAND_REG)) + shift += 15; + + num = (insn >> shift) & (0x7FFFFFFF >> (31 - oper->bits)); + + if (oper->flags & OPERAND_REG) + { + int i; + int match=0; + num += oper->flags & (OPERAND_ACC|OPERAND_FLAG|OPERAND_CONTROL); + for (i = 0; i < d10v_reg_name_cnt(); i++) + { + if (num == d10v_predefined_registers[i].value) + { + if (d10v_predefined_registers[i].pname) + (*info->fprintf_func) (info->stream, "%s",d10v_predefined_registers[i].pname); + else + (*info->fprintf_func) (info->stream, "%s",d10v_predefined_registers[i].name); + match=1; + break; + } + } + if (match == 0) + { + /* this would only get executed if a register was not in the + register table */ + if (oper->flags & OPERAND_ACC) + (*info->fprintf_func) (info->stream, "a"); + else if (oper->flags & OPERAND_CONTROL) + (*info->fprintf_func) (info->stream, "cr"); + else if(oper->flags & OPERAND_REG) + (*info->fprintf_func) (info->stream, "r"); + (*info->fprintf_func) (info->stream, "%d",num); + } + } + else + { + /* addresses are right-shifted by 2 */ + if (oper->flags & OPERAND_ADDR) + { + long max; + int neg=0; + max = (1 << (oper->bits - 1)); + if (num & max) + { + num = -num & ((1 << oper->bits)-1); + neg = 1; + } + num = num<<2; + if (neg) + (*info->print_address_func) ((memaddr - num) & PC_MASK, info); + else + (*info->print_address_func) ((memaddr + num) & PC_MASK, info); + } + else + { + if (oper->flags & OPERAND_SIGNED) + { + int max = (1 << (oper->bits - 1)); + if (num & max) + { + num = -num & ((1 << oper->bits)-1); + (*info->fprintf_func) (info->stream, "-"); + } + } + (*info->fprintf_func) (info->stream, "0x%x",num); + } + } +} + + +static void +dis_long (insn, memaddr, info) + unsigned long insn; + bfd_vma memaddr; + struct disassemble_info *info; +{ + int i; + char buf[32]; + struct d10v_opcode *op = (struct d10v_opcode *)d10v_opcodes; + struct d10v_operand *oper; + int need_paren = 0; + int match = 0; + + while (op->name) + { + if ((op->format & LONG_OPCODE) && ((op->mask & insn) == op->opcode)) + { + match = 1; + (*info->fprintf_func) (info->stream, "%s\t", op->name); + for ( i=0; op->operands[i]; i++) + { + oper = (struct d10v_operand *)&d10v_operands[op->operands[i]]; + if (oper->flags == OPERAND_ATPAR) + need_paren = 1; + print_operand (oper, insn, op, memaddr, info); + if (op->operands[i+1] && oper->bits && + d10v_operands[op->operands[i+1]].flags != OPERAND_PLUS && + d10v_operands[op->operands[i+1]].flags != OPERAND_MINUS) + (*info->fprintf_func) (info->stream, ", "); + } + break; + } + op++; + } + + if (!match) + (*info->fprintf_func) (info->stream, ".long\t0x%08x",insn); + + if (need_paren) + (*info->fprintf_func) (info->stream, ")"); +} + +static void +dis_2_short (insn, memaddr, info, order) + unsigned long insn; + bfd_vma memaddr; + struct disassemble_info *info; + int order; +{ + int i,j; + char astr[2][32]; + unsigned int ins[2]; + struct d10v_opcode *op; + char buf[32]; + int match, num_match=0; + struct d10v_operand *oper; + int need_paren = 0; + + ins[0] = (insn & 0x3FFFFFFF) >> 15; + ins[1] = insn & 0x00007FFF; + + for(j=0;j<2;j++) + { + op = (struct d10v_opcode *)d10v_opcodes; + match=0; + while (op->name) + { + if ((op->format & SHORT_OPCODE) && ((op->mask & ins[j]) == op->opcode)) + { + (*info->fprintf_func) (info->stream, "%s\t",op->name); + for (i=0; op->operands[i]; i++) + { + oper = (struct d10v_operand *)&d10v_operands[op->operands[i]]; + if (oper->flags == OPERAND_ATPAR) + need_paren = 1; + print_operand (oper, ins[j], op, memaddr, info); + if (op->operands[i+1] && oper->bits && + d10v_operands[op->operands[i+1]].flags != OPERAND_PLUS && + d10v_operands[op->operands[i+1]].flags != OPERAND_MINUS) + (*info->fprintf_func) (info->stream, ", "); + } + match = 1; + num_match++; + break; + } + op++; + } + if (!match) + (*info->fprintf_func) (info->stream, "unknown"); + + switch (order) + { + case 0: + (*info->fprintf_func) (info->stream, "\t->\t"); + order = -1; + break; + case 1: + (*info->fprintf_func) (info->stream, "\t<-\t"); + order = -1; + break; + case 2: + (*info->fprintf_func) (info->stream, "\t||\t"); + order = -1; + break; + default: + break; + } + } + + if (num_match == 0) + (*info->fprintf_func) (info->stream, ".long\t0x%08x",insn); + + if (need_paren) + (*info->fprintf_func) (info->stream, ")"); +} diff --git a/gnu/usr.bin/binutils/opcodes/d10v-opc.c b/gnu/usr.bin/binutils/opcodes/d10v-opc.c new file mode 100644 index 00000000000..6a457bb5051 --- /dev/null +++ b/gnu/usr.bin/binutils/opcodes/d10v-opc.c @@ -0,0 +1,329 @@ +/* d10v-opc.c -- D10V opcode list + Copyright 1996 Free Software Foundation, Inc. + Written by Martin Hunt, Cygnus Support + +This file is part of GDB, GAS, and the GNU binutils. + +GDB, GAS, and the GNU binutils are free software; you can redistribute +them and/or modify them under the terms of the GNU General Public +License as published by the Free Software Foundation; either version +2, or (at your option) any later version. + +GDB, GAS, and the GNU binutils are distributed in the hope that they +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 file; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <stdio.h> +#include "ansidecl.h" +#include "opcode/d10v.h" + + +/* The table is sorted. Suitable for searching by a binary search. */ +const struct pd_reg d10v_predefined_registers[] = +{ + { "a0", NULL, OPERAND_ACC+0 }, + { "a1", NULL, OPERAND_ACC+1 }, + { "bpc", NULL, OPERAND_CONTROL+3 }, + { "bpsw", NULL, OPERAND_CONTROL+1 }, + { "c", NULL, OPERAND_FLAG+3 }, + { "cr0", "psw", OPERAND_CONTROL }, + { "cr1", "bpsw", OPERAND_CONTROL+1 }, + { "cr10", "mod_s", OPERAND_CONTROL+10 }, + { "cr11", "mod_e", OPERAND_CONTROL+11 }, + { "cr12", NULL, OPERAND_CONTROL+12 }, + { "cr13", NULL, OPERAND_CONTROL+13 }, + { "cr14", "iba", OPERAND_CONTROL+14 }, + { "cr15", NULL, OPERAND_CONTROL+15 }, + { "cr2", "pc", OPERAND_CONTROL+2 }, + { "cr3", "bpc", OPERAND_CONTROL+3 }, + { "cr4", "dpsw", OPERAND_CONTROL+4 }, + { "cr5", "dpc", OPERAND_CONTROL+5 }, + { "cr6", NULL, OPERAND_CONTROL+6 }, + { "cr7", "rpt_c", OPERAND_CONTROL+7 }, + { "cr8", "rpt_s", OPERAND_CONTROL+8 }, + { "cr9", "rpt_e", OPERAND_CONTROL+9 }, + { "dpc", NULL, OPERAND_CONTROL+5 }, + { "dpsw", NULL, OPERAND_CONTROL+4 }, + { "f0", NULL, OPERAND_FLAG+0 }, + { "f1", NULL, OPERAND_FLAG+1 }, + { "iba", NULL, OPERAND_CONTROL+14 }, + { "link", "r13", 13 }, + { "mod_e", NULL, OPERAND_CONTROL+11 }, + { "mod_s", NULL, OPERAND_CONTROL+10 }, + { "pc", NULL, OPERAND_CONTROL+2 }, + { "psw", NULL, OPERAND_CONTROL+0 }, + { "r0", NULL, 0 }, + { "r0-r1", NULL, 0}, + { "r1", NULL, 1 }, + { "r1", NULL, 1 }, + { "r10", NULL, 10 }, + { "r10-r11", NULL, 10 }, + { "r11", NULL, 11 }, + { "r12", NULL, 12 }, + { "r12-r13", NULL, 12 }, + { "r13", NULL, 13 }, + { "r14", NULL, 14 }, + { "r14-r15", NULL, 14 }, + { "r15", "sp", 15 }, + { "r2", NULL, 2 }, + { "r2-r3", NULL, 2 }, + { "r3", NULL, 3 }, + { "r4", NULL, 4 }, + { "r4-r5", NULL, 4 }, + { "r5", NULL, 5 }, + { "r6", NULL, 6 }, + { "r6-r7", NULL, 6 }, + { "r7", NULL, 7 }, + { "r8", NULL, 8 }, + { "r8-r9", NULL, 8 }, + { "r9", NULL, 9 }, + { "rpt_c", NULL, OPERAND_CONTROL+7 }, + { "rpt_e", NULL, OPERAND_CONTROL+9 }, + { "rpt_s", NULL, OPERAND_CONTROL+8 }, + { "sp", NULL, 15 }, +}; + +int +d10v_reg_name_cnt() +{ + return (sizeof(d10v_predefined_registers) / sizeof(struct pd_reg)); +} + +const struct d10v_operand d10v_operands[] = +{ +#define UNUSED (0) + { 0, 0, 0 }, +#define RSRC (UNUSED + 1) + { 4, 1, OPERAND_REG }, +#define RDST (RSRC + 1) + { 4, 5, OPERAND_DEST|OPERAND_REG }, +#define ASRC (RDST + 1) + { 1, 4, OPERAND_ACC|OPERAND_REG }, +#define ADST (ASRC + 1) + { 1, 8, OPERAND_DEST|OPERAND_ACC|OPERAND_REG }, +#define RSRCE (ADST + 1) + { 4, 1, OPERAND_EVEN|OPERAND_REG }, +#define RDSTE (RSRCE + 1) + { 4, 5, OPERAND_EVEN|OPERAND_DEST|OPERAND_REG }, +#define NUM16 (RDSTE + 1) + { 16, 0, OPERAND_NUM|OPERAND_SIGNED }, +#define NUM3 (NUM16 + 1) /* rac, rachi */ + { 3, 1, OPERAND_NUM|OPERAND_SIGNED }, +#define NUM4 (NUM3 + 1) + { 4, 1, OPERAND_NUM|OPERAND_SIGNED }, +#define UNUM4 (NUM4 + 1) + { 4, 1, OPERAND_NUM }, +#define UNUM4S (UNUM4 + 1) /* addi, slli, srai, srli, subi */ + { 4, 1, OPERAND_NUM|OPERAND_SHIFT }, +#define UNUM8 (UNUM4S + 1) /* repi */ + { 8, 16, OPERAND_NUM }, +#define UNUM16 (UNUM8 + 1) /* cmpui */ + { 16, 0, OPERAND_NUM }, +#define ANUM16 (UNUM16 + 1) + { 16, 0, OPERAND_ADDR|OPERAND_SIGNED }, +#define ANUM8 (ANUM16 + 1) + { 8, 0, OPERAND_ADDR|OPERAND_SIGNED }, +#define ASRC2 (ANUM8 + 1) + { 1, 8, OPERAND_ACC|OPERAND_REG }, +#define RSRC2 (ASRC2 + 1) + { 4, 5, OPERAND_REG }, +#define RSRC2E (RSRC2 + 1) + { 4, 5, OPERAND_REG|OPERAND_EVEN }, +#define ASRC0 (RSRC2E + 1) + { 1, 0, OPERAND_ACC|OPERAND_REG }, +#define ADST0 (ASRC0 + 1) + { 1, 0, OPERAND_ACC|OPERAND_REG|OPERAND_DEST }, +#define FSRC (ADST0 + 1) + { 2, 1, OPERAND_REG | OPERAND_FLAG }, +#define FDST (FSRC + 1) + { 1, 5, OPERAND_REG | OPERAND_FLAG | OPERAND_DEST}, +#define ATSIGN (FDST + 1) + { 0, 0, OPERAND_ATSIGN}, +#define ATPAR (ATSIGN + 1) /* "@(" */ + { 0, 0, OPERAND_ATPAR}, +#define PLUS (ATPAR + 1) /* postincrement */ + { 0, 0, OPERAND_PLUS}, +#define MINUS (PLUS + 1) /* postdecrement */ + { 0, 0, OPERAND_MINUS}, +#define ATMINUS (MINUS + 1) /* predecrement */ + { 0, 0, OPERAND_ATMINUS}, +#define CSRC (ATMINUS + 1) /* control register */ + { 4, 1, OPERAND_REG|OPERAND_CONTROL}, +#define CDST (CSRC + 1) /* control register */ + { 4, 5, OPERAND_REG|OPERAND_CONTROL|OPERAND_DEST}, +}; + +const struct d10v_opcode d10v_opcodes[] = { + { "abs", SHORT_2, 1, EITHER, PAR|WF0, 0x4607, 0x7e1f, { RDST } }, + { "abs", SHORT_2, 1, IU, PAR|WF0, 0x5607, 0x7eff, { ADST } }, + { "add", SHORT_2, 1, EITHER, PAR|WCAR, 0x0200, 0x7e01, { RDST, RSRC } }, + { "add", SHORT_2, 1, IU, PAR, 0x1201, 0x7ee3, { ADST, RSRCE } }, + { "add", SHORT_2, 1, IU, PAR, 0x1203, 0x7eef, { ADST, ASRC } }, + { "add2w", SHORT_2, 2, IU, PAR|WCAR, 0x1200, 0x7e23, { RDSTE, RSRCE } }, + { "add3", LONG_L, 1, MU, SEQ|WCAR, 0x1000000, 0x3f000000, { RDST, RSRC, NUM16 } }, + { "addac3", LONG_R, 1, IU, SEQ, 0x17000200, 0x3ffffe22, { RDSTE, RSRCE, ASRC0 } }, + { "addac3", LONG_R, 1, IU, SEQ, 0x17000202, 0x3ffffe2e, { RDSTE, ASRC, ASRC0 } }, + { "addac3s", LONG_R, 1, IU, SEQ, 0x17001200, 0x3ffffe22, { RDSTE, RSRCE, ASRC0 } }, + { "addac3s", LONG_R, 1, IU, SEQ, 0x17001202, 0x3ffffe2e, { RDSTE, ASRC, ASRC0 } }, + { "addi", SHORT_2, 1, EITHER, PAR|WCAR, 0x201, 0x7e01, { RDST, UNUM4S } }, + { "and", SHORT_2, 1, EITHER, PAR, 0xc00, 0x7e01, { RDST, RSRC } }, + { "and3", LONG_L, 1, MU, SEQ, 0x6000000, 0x3f000000, { RDST, RSRC, NUM16 } }, + { "bclri", SHORT_2, 1, IU, PAR, 0xc01, 0x7e01, { RDST, UNUM4 } }, + { "bl", OPCODE_FAKE, 0, 0, 0, 0, 0, { 0, 8, 16, 0 } }, + { "bl.s", SHORT_B, 3, MU, BRANCH_LINK|PAR, 0x4900, 0x7f00, { ANUM8 } }, + { "bl.l", LONG_B, 3, MU, BRANCH_LINK|SEQ, 0x24800000, 0x3fff0000, { ANUM16 } }, + { "bnoti", SHORT_2, 1, IU, PAR, 0xa01, 0x7e01, { RDST, UNUM4 } }, + { "bra", OPCODE_FAKE, 0, 0, 0, 0, 0, { 0, 8, 16, 0 } }, + { "bra.s", SHORT_B, 3, MU, BRANCH|PAR, 0x4800, 0x7f00, { ANUM8 } }, + { "bra.l", LONG_B, 3, MU, BRANCH|SEQ, 0x24000000, 0x3fff0000, { ANUM16 } }, + { "brf0f", OPCODE_FAKE, 0, 0, 0, 0, 0, { 0, 8, 16, 0 } }, + { "brf0f.s", SHORT_B, 3, MU, BRANCH|PAR|RF0, 0x4a00, 0x7f00, { ANUM8 } }, + { "brf0f.l", LONG_B, 3, MU, SEQ, 0x25000000, 0x3fff0000, { ANUM16 } }, + { "brf0t", OPCODE_FAKE, 0, 0, 0, 0, 0, { 0, 8, 16, 0 } }, + { "brf0t.s", SHORT_B, 3, MU, BRANCH|PAR|RF0, 0x4b00, 0x7f00, { ANUM8 } }, + { "brf0t.l", LONG_B, 3, MU, SEQ, 0x25800000, 0x3fff0000, { ANUM16 } }, + { "bseti", SHORT_2, 1, IU, PAR, 0x801, 0x7e01, { RDST, UNUM4 } }, + { "btsti", SHORT_2, 1, IU, PAR|WF0, 0xe01, 0x7e01, { RDST, UNUM4 } }, + { "clrac", SHORT_2, 1, IU, PAR, 0x5601, 0x7eff, { ADST } }, + { "cmp", SHORT_2, 1, EITHER, PAR|WF0, 0x600, 0x7e01, { RSRC2, RSRC } }, + { "cmp", SHORT_2, 1, IU, PAR|WF0, 0x1603, 0x7eef, { ASRC2, ASRC } }, + { "cmpeq", SHORT_2, 1, EITHER, PAR|WF0, 0x400, 0x7e01, { RSRC2, RSRC } }, + { "cmpeq", SHORT_2, 1, IU, PAR|WF0, 0x1403, 0x7eef, { ASRC2, ASRC } }, + { "cmpeqi", OPCODE_FAKE, 0, 0, 0, 0, 0, { 1, 4, 16, 0 } }, + { "cmpeqi.s", SHORT_2, 1, EITHER, PAR|WF0, 0x401, 0x7e01, { RSRC2, NUM4 } }, + { "cmpeqi.l", LONG_L, 1, MU, SEQ, 0x2000000, 0x3f0f0000, { RSRC2, NUM16 } }, + { "cmpi", OPCODE_FAKE, 0, 0, 0, 0, 0, { 1, 4, 16, 0 } }, + { "cmpi.s", SHORT_2, 1, EITHER, PAR|WF0, 0x601, 0x7e01, { RSRC2, NUM4 } }, + { "cmpi.l", LONG_L, 1, MU, SEQ, 0x3000000, 0x3f0f0000, { RSRC2, NUM16 } }, + { "cmpu", SHORT_2, 1, EITHER, PAR|WF0, 0x4600, 0x7e01, { RSRC2, RSRC } }, + { "cmpui", LONG_L, 1, MU, SEQ, 0x23000000, 0x3f0f0000, { RSRC2, UNUM16 } }, + { "cpfg", SHORT_2, 1, MU, PAR, 0x4e09, 0x7fd9, { FDST, FSRC } }, + { "dbt", SHORT_2, 5, MU, PAR, 0x5f20, 0x7fff, { 0 } }, + { "divs", LONG_L, 1, BOTH, SEQ, 0x14002800, 0x3f10fe21, { RDSTE, RSRC } }, + { "exef0f", SHORT_2, 1, EITHER, PARONLY, 0x4e04, 0x7fff, { 0 } }, + { "exef0t", SHORT_2, 1, EITHER, PARONLY, 0x4e24, 0x7fff, { 0 } }, + { "exef1f", SHORT_2, 1, EITHER, PARONLY, 0x4e40, 0x7fff, { 0 } }, + { "exef1t", SHORT_2, 1, EITHER, PARONLY, 0x4e42, 0x7fff, { 0 } }, + { "exefaf", SHORT_2, 1, EITHER, PARONLY, 0x4e00, 0x7fff, { 0 } }, + { "exefat", SHORT_2, 1, EITHER, PARONLY, 0x4e02, 0x7fff, { 0 } }, + { "exetaf", SHORT_2, 1, EITHER, PARONLY, 0x4e20, 0x7fff, { 0 } }, + { "exetat", SHORT_2, 1, EITHER, PARONLY, 0x4e22, 0x7fff, { 0 } }, + { "exp", LONG_R, 1, IU, SEQ, 0x15002a00, 0x3ffffe03, { RDST, RSRCE } }, + { "exp", LONG_R, 1, IU, SEQ, 0x15002a02, 0x3ffffe0f, { RDST, ASRC } }, + { "jl", SHORT_2, 3, MU, BRANCH_LINK|PAR, 0x4d00, 0x7fe1, { RSRC } }, + { "jmp", SHORT_2, 3, MU, BRANCH|PAR, 0x4c00, 0x7fe1, { RSRC } }, + { "ld", LONG_L, 1, MU, SEQ, 0x30000000, 0x3f000000, { RDST, ATPAR, NUM16, RSRC } }, + { "ld", SHORT_2, 1, MU, PAR|RMEM, 0x6401, 0x7e01, { RDST, ATSIGN, RSRC, MINUS } }, + { "ld", SHORT_2, 1, MU, PAR|RMEM, 0x6001, 0x7e01, { RDST, ATSIGN, RSRC, PLUS } }, + { "ld", SHORT_2, 1, MU, PAR|RMEM, 0x6000, 0x7e01, { RDST, ATSIGN, RSRC } }, + { "ld2w", LONG_L, 1, MU, SEQ, 0x31000000, 0x3f100000, { RDSTE, ATPAR, NUM16, RSRC } }, + { "ld2w", SHORT_2, 1, MU, PAR|RMEM, 0x6601, 0x7e21, { RDSTE, ATSIGN, RSRC, MINUS } }, + { "ld2w", SHORT_2, 1, MU, PAR|RMEM, 0x6201, 0x7e21, { RDSTE, ATSIGN, RSRC, PLUS } }, + { "ld2w", SHORT_2, 1, MU, PAR|RMEM, 0x6200, 0x7e21, { RDSTE, ATSIGN, RSRC } }, + { "ldb", LONG_L, 1, MU, SEQ, 0x38000000, 0x3f000000, { RDST, ATPAR, NUM16, RSRC } }, + { "ldb", SHORT_2, 1, MU, PAR|RMEM, 0x7000, 0x7e01, { RDST, ATSIGN, RSRC } }, + { "ldi", OPCODE_FAKE, 0, 0, 0, 0, 0, { 1, 4, 16, 0 } }, + { "ldi.s", SHORT_2, 1, EITHER, PAR|RMEM, 0x4001, 0x7e01 , { RDST, NUM4 } }, + { "ldi.l", LONG_L, 1, MU, SEQ, 0x20000000, 0x3f0f0000, { RDST, NUM16 } }, + { "ldub", LONG_L, 1, MU, SEQ, 0x39000000, 0x3f000000, { RDST, ATPAR, NUM16, RSRC } }, + { "ldub", SHORT_2, 1, MU, PAR|RMEM, 0x7200, 0x7e01, { RDST, ATSIGN, RSRC } }, + { "mac", SHORT_2, 1, IU, PAR, 0x2a00, 0x7e00, { ADST0, RSRC2, RSRC } }, + { "macsu", SHORT_2, 1, IU, PAR, 0x1a00, 0x7e00, { ADST0, RSRC2, RSRC } }, + { "macu", SHORT_2, 1, IU, PAR, 0x3a00, 0x7e00, { ADST0, RSRC2, RSRC } }, + { "max", SHORT_2, 1, IU, PAR|WF0, 0x2600, 0x7e01, { RDST, RSRC } }, + { "max", SHORT_2, 1, IU, PAR|WF0, 0x3600, 0x7ee3, { ADST, RSRCE } }, + { "max", SHORT_2, 1, IU, PAR|WF0, 0x3602, 0x7eef, { ADST, ASRC } }, + { "min", SHORT_2, 1, IU, PAR|WF0, 0x2601, 0x7e01 , { RDST, RSRC } }, + { "min", SHORT_2, 1, IU, PAR|WF0, 0x3601, 0x7ee3 , { ADST, RSRCE } }, + { "min", SHORT_2, 1, IU, PAR|WF0, 0x3603, 0x7eef, { ADST, ASRC } }, + { "msb", SHORT_2, 1, IU, PAR, 0x2800, 0x7e00, { ADST0, RSRC2, RSRC } }, + { "msbsu", SHORT_2, 1, IU, PAR, 0x1800, 0x7e00, { ADST0, RSRC2, RSRC } }, + { "msbu", SHORT_2, 1, IU, PAR, 0x3800, 0x7e00, { ADST0, RSRC2, RSRC } }, + { "mul", SHORT_2, 1, IU, PAR, 0x2e00, 0x7e01 , { RDST, RSRC } }, + { "mulx", SHORT_2, 1, IU, PAR, 0x2c00, 0x7e00, { ADST0, RSRC2, RSRC } }, + { "mulxsu", SHORT_2, 1, IU, PAR, 0x1c00, 0x7e00, { ADST0, RSRC2, RSRC } }, + { "mulxu", SHORT_2, 1, IU, PAR, 0x3c00, 0x7e00, { ADST0, RSRC2, RSRC } }, + { "mv", SHORT_2, 1, EITHER, PAR, 0x4000, 0x7e01, { RDST, RSRC } }, + { "mv2w", SHORT_2, 1, IU, PAR, 0x5000, 0x7e23, { RDSTE, RSRCE } }, + { "mv2wfac", SHORT_2, 1, IU, PAR, 0x3e00, 0x7e2f, { RDSTE, ASRC } }, + { "mv2wtac", SHORT_2, 1, IU, PAR, 0x3e01, 0x7ee3, { RSRCE, ADST } }, + { "mvac", SHORT_2, 1, IU, PAR, 0x3e03, 0x7eef, { ADST, ASRC } }, + { "mvb", SHORT_2, 1, IU, PAR, 0x5400, 0x7e01, { RDST, RSRC } }, + { "mvf0f", SHORT_2, 1, EITHER, PAR|RF0, 0x4400, 0x7e01, { RDST, RSRC } }, + { "mvf0t", SHORT_2, 1, EITHER, PAR|RF0, 0x4401, 0x7e01, { RDST, RSRC } }, + { "mvfacg", SHORT_2, 1, IU, PAR, 0x1e04, 0x7e0f, { RDST, ASRC } }, + { "mvfachi", SHORT_2, 1, IU, PAR, 0x1e00, 0x7e0f, { RDST, ASRC } }, + { "mvfaclo", SHORT_2, 1, IU, PAR, 0x1e02, 0x7e0f, { RDST, ASRC } }, + { "mvfc", SHORT_2, 1, MU, PAR, 0x5200, 0x7e01, { RDST, CSRC } }, + { "mvtacg", SHORT_2, 1, IU, PAR, 0x1e41, 0x7ee1, { RSRC, ADST } }, + { "mvtachi", SHORT_2, 1, IU, PAR, 0x1e01, 0x7ee1, { RSRC, ADST } }, + { "mvtaclo", SHORT_2, 1, IU, PAR, 0x1e21, 0x7ee1, { RSRC, ADST } }, + { "mvtc", SHORT_2, 1, MU, PAR, 0x5600, 0x7e01, { RSRC, CDST } }, + { "mvub", SHORT_2, 1, IU, PAR, 0x5401, 0x7e01, { RDST, RSRC } }, + { "neg", SHORT_2, 1, EITHER, PAR, 0x4605, 0x7e1f, { RDST } }, + { "neg", SHORT_2, 1, IU, PAR, 0x5605, 0x7eff, { ADST } }, + { "nop", SHORT_2, 1, EITHER, PAR, 0x5e00, 0x7fff, { 0 } }, + { "not", SHORT_2, 1, EITHER, PAR, 0x4603, 0x7e1f, { RDST } }, + { "or", SHORT_2, 1, EITHER, PAR, 0x800, 0x7e01, { RDST, RSRC } }, + { "or3", LONG_L, 1, MU, SEQ, 0x4000000, 0x3f000000, { RDST, RSRC, NUM16 } }, + { "rac", SHORT_2, 1, IU, PAR|WF0, 0x5201, 0x7e21, { RDSTE, ASRC, NUM3 } }, + { "rachi", SHORT_2, 1, IU, PAR|WF0, 0x4201, 0x7e01, { RDST, ASRC, NUM3 } }, + { "rep", LONG_L, 2, MU, SEQ, 0x27000000, 0x3ff00000, { RSRC, ANUM16 } }, + { "repi", LONG_L, 2, MU, SEQ, 0x2f000000, 0x3f000000, { UNUM8, ANUM16 } }, + { "rtd", SHORT_2, 3, MU, PAR, 0x5f60, 0x7fff, { 0 } }, + { "rte", SHORT_2, 3, MU, PAR, 0x5f40, 0x7ff, { 0 } }, + { "sadd", SHORT_2, 1, IU, PAR, 0x1223, 0x7eef, { ADST, ASRC } }, + { "setf0f", SHORT_2, 1, MU, PAR|RF0, 0x4611, 0x7e1f, { RDST } }, + { "setf0t", SHORT_2, 1, MU, PAR|RF0, 0x4613, 0x7e1f, { RDST } }, + { "sleep", SHORT_2, 1, MU, PAR, 0x5fc0, 0x7fff, { 0 } }, + { "sll", SHORT_2, 1, IU, PAR, 0x2200, 0x7e01, { RDST, RSRC } }, + { "sll", SHORT_2, 1, IU, PAR, 0x3200, 0x7ee1, { ADST, RSRC } }, + { "slli", SHORT_2, 1, IU, PAR, 0x2201, 0x7e01, { RDST, UNUM4 } }, + { "slli", SHORT_2, 1, IU, PAR, 0x3201, 0x7ee1, { ADST, UNUM4S } }, + { "slx", SHORT_2, 1, IU, PAR|RF0, 0x460b, 0x7e1f, { RDST } }, + { "sra", SHORT_2, 1, IU, PAR, 0x2400, 0x7e01, { RDST, RSRC } }, + { "sra", SHORT_2, 1, IU, PAR, 0x3400, 0x7ee1, { ADST, RSRC } }, + { "srai", SHORT_2, 1, IU, PAR, 0x2401, 0x7e01, { RDST, UNUM4 } }, + { "srai", SHORT_2, 1, IU, PAR, 0x3401, 0x7ee1, { ADST, UNUM4S } }, + { "srl", SHORT_2, 1, IU, PAR, 0x2000, 0x7e01, { RDST, RSRC } }, + { "srl", SHORT_2, 1, IU, PAR, 0x3000, 0x7ee1, { ADST, RSRC } }, + { "srli", SHORT_2, 1, IU, PAR, 0x2001, 0x7e01, { RDST, UNUM4 } }, + { "srli", SHORT_2, 1, IU, PAR, 0x3001, 0x7ee1, { ADST, UNUM4S } }, + { "srx", SHORT_2, 1, IU, PAR|RF0, 0x4609, 0x7e1f, { RDST } }, + { "st", LONG_L, 1, MU, SEQ, 0x34000000, 0x3f000000, { RSRC2, ATPAR, NUM16, RSRC } }, + { "st", SHORT_2, 1, MU, PAR|WMEM, 0x6800, 0x7e01, { RSRC2, ATSIGN, RSRC } }, + { "st", SHORT_2, 1, MU, PAR|WMEM, 0x6c1f, 0x7e1f, { RSRC2, ATMINUS, RSRC } }, + { "st", SHORT_2, 1, MU, PAR|WMEM, 0x6801, 0x7e01, { RSRC2, ATSIGN, RSRC, PLUS } }, + { "st", SHORT_2, 1, MU, PAR|WMEM, 0x6c01, 0x7e01, { RSRC2, ATSIGN, RSRC, MINUS } }, + { "st2w", LONG_L, 1, MU, SEQ, 0x35000000, 0x3f100000, { RSRC2E, ATPAR, NUM16, RSRC } }, + { "st2w", SHORT_2, 1, MU, PAR|WMEM, 0x6a00, 0x7e21, { RSRC2E, ATSIGN, RSRC } }, + { "st2w", SHORT_2, 1, MU, PAR|WMEM, 0x6e1f, 0x7e3f, { RSRC2E, ATMINUS, RSRC } }, + { "st2w", SHORT_2, 1, MU, PAR|WMEM, 0x6a01, 0x7e21, { RSRC2E, ATSIGN, RSRC, PLUS } }, + { "st2w", SHORT_2, 1, MU, PAR|WMEM, 0x6e01, 0x7e21, { RSRC2E, ATSIGN, RSRC, MINUS } }, + { "stb", LONG_L, 1, MU, SEQ, 0x3c000000, 0x3f000000, { RSRC2, ATPAR, NUM16, RSRC } }, + { "stb", SHORT_2, 1, MU, PAR|WMEM, 0x7800, 0x7e01, { RSRC2, ATSIGN, RSRC } }, + { "stop", SHORT_2, 1, MU, PAR, 0x5fe0, 0x7fff, { 0 } }, + { "sub", SHORT_2, 1, EITHER, PAR|WCAR, 0x0, 0x7e01, { RDST, RSRC } }, + { "sub", SHORT_2, 1, IU, PAR, 0x1001, 0x7ee3, { ADST, RSRC } }, + { "sub", SHORT_2, 1, IU, PAR, 0x1003, 0x7eef, { ADST, ASRC } }, + { "sub2w", SHORT_2, 1, IU, PAR|WCAR, 0x1000, 0x7e23, { RDSTE, RSRCE } }, + { "subac3", LONG_R, 1, IU, SEQ, 0x17000000, 0x3ffffe22, { RDSTE, RSRCE, ASRC0 } }, + { "subac3", LONG_R, 1, IU, SEQ, 0x17000002, 0x3ffffe2e, { RDSTE, ASRC, ASRC0 } }, + { "subac3s", LONG_R, 1, IU, SEQ, 0x17001000, 0x3ffffe22, { RDSTE, RSRCE, ASRC0 } }, + { "subac3s", LONG_R, 1, IU, SEQ, 0x17001002, 0x3ffffe2e, { RDSTE, ASRC, ASRC0 } }, + { "subi", SHORT_2, 1, EITHER, PAR, 0x1, 0x7e01, { RDST, UNUM4S } }, + { "trap", SHORT_2, 5, MU, PAR, 0x5f00, 0x7fe1, { UNUM4 } }, + { "tst0i", LONG_L, 1, MU, SEQ, 0x7000000, 0x3f0f0000, { RSRC2, NUM16 } }, + { "tst1i", LONG_L, 1, MU, SEQ, 0xf000000, 0x3f0f0000, { RSRC2, NUM16 } }, + { "wait", SHORT_2, 1, MU, PAR, 0x5f80, 0x7fff, { 0 } }, + { "xor", SHORT_2, 1, EITHER, PAR, 0xa00, 0x7e01, { RDST, RSRC } }, + { "xor3", LONG_L, 1, MU, SEQ, 0x5000000, 0x3f000000, { RDST, RSRC, NUM16 } }, + { 0, 0, 0, 0, 0, 0, 0, { 0 } }, +}; + + diff --git a/gnu/usr.bin/binutils/opcodes/dep-in.sed b/gnu/usr.bin/binutils/opcodes/dep-in.sed new file mode 100644 index 00000000000..ebf69ebf4b1 --- /dev/null +++ b/gnu/usr.bin/binutils/opcodes/dep-in.sed @@ -0,0 +1,19 @@ +:loop +/\\$/N +s/\\\n */ /g +t loop + +s! @BFD_H@! $(BFD_H)!g +s!@INCDIR@!$(INCDIR)!g +s!@BFDDIR@!$(BFDDIR)!g +s!@SRCDIR@/!!g + +s/\\\n */ /g + +s/ *$// +s/ */ /g +s/ *:/:/g +/:$/d + +s/\(.\{50\}[^ ]*\) /\1 \\\ + /g diff --git a/gnu/usr.bin/binutils/opcodes/m10200-dis.c b/gnu/usr.bin/binutils/opcodes/m10200-dis.c new file mode 100644 index 00000000000..7d37517e52d --- /dev/null +++ b/gnu/usr.bin/binutils/opcodes/m10200-dis.c @@ -0,0 +1,334 @@ +/* Disassemble MN10200 instructions. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + +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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +#include <stdio.h> + +#include "ansidecl.h" +#include "opcode/mn10200.h" +#include "dis-asm.h" + +static void disassemble PARAMS ((bfd_vma, struct disassemble_info *, + unsigned long insn, unsigned long, + unsigned int)); + +int +print_insn_mn10200 (memaddr, info) + bfd_vma memaddr; + struct disassemble_info *info; +{ + int status; + bfd_byte buffer[4]; + unsigned long insn, extension; + unsigned int consume; + + /* First figure out how big the opcode is. */ + status = (*info->read_memory_func) (memaddr, buffer, 1, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + insn = *(unsigned char *) buffer; + + /* These are one byte insns. */ + if ((insn & 0xf0) == 0x00 + || (insn & 0xf0) == 0x10 + || (insn & 0xf0) == 0x20 + || (insn & 0xf0) == 0x30 + || ((insn & 0xf0) == 0x80 + && (insn & 0x0c) >> 2 != (insn & 0x03)) + || (insn & 0xf0) == 0x90 + || (insn & 0xf0) == 0xa0 + || (insn & 0xf0) == 0xb0 + || (insn & 0xff) == 0xeb + || (insn & 0xff) == 0xf6 + || (insn & 0xff) == 0xfe) + { + extension = 0; + consume = 1; + } + + /* These are two byte insns. */ + else if ((insn & 0xf0) == 0x40 + || (insn & 0xf0) == 0x50 + || (insn & 0xf0) == 0x60 + || (insn & 0xf0) == 0x70 + || (insn & 0xf0) == 0x80 + || (insn & 0xfc) == 0xd0 + || (insn & 0xfc) == 0xd4 + || (insn & 0xfc) == 0xd8 + || (insn & 0xfc) == 0xe0 + || (insn & 0xfc) == 0xe4 + || (insn & 0xff) == 0xe8 + || (insn & 0xff) == 0xe9 + || (insn & 0xff) == 0xea + || (insn & 0xff) == 0xf0 + || (insn & 0xff) == 0xf1 + || (insn & 0xff) == 0xf2 + || (insn & 0xff) == 0xf3) + { + status = (*info->read_memory_func) (memaddr, buffer, 2, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + insn = bfd_getb16 (buffer); + consume = 2; + } + + /* These are three byte insns with a 16bit operand in little + endian form. */ + else if ((insn & 0xf0) == 0xc0 + || (insn & 0xfc) == 0xdc + || (insn & 0xfc) == 0xec + || (insn & 0xff) == 0xf8 + || (insn & 0xff) == 0xf9 + || (insn & 0xff) == 0xfa + || (insn & 0xff) == 0xfb + || (insn & 0xff) == 0xfc + || (insn & 0xff) == 0xfd) + { + status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + insn <<= 16; + insn |= bfd_getl16 (buffer); + extension = 0; + consume = 3; + } + /* These are three byte insns too, but we don't have to mess with + endianness stuff. */ + else if ((insn & 0xff) == 0xf5) + { + status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + insn <<= 16; + insn |= bfd_getb16 (buffer); + extension = 0; + consume = 3; + } + + /* These are four byte insns. */ + else if ((insn & 0xff) == 0xf7) + { + status = (*info->read_memory_func) (memaddr, buffer, 2, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + insn = bfd_getb16 (buffer); + insn <<= 16; + status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + insn |= bfd_getl16 (buffer); + extension = 0; + consume = 4; + } + + /* These are five byte insns. */ + else if ((insn & 0xff) == 0xf4) + { + status = (*info->read_memory_func) (memaddr, buffer, 2, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + insn = bfd_getb16 (buffer); + insn <<= 16; + + status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + insn |= *(unsigned char *)buffer << 8; + + status = (*info->read_memory_func) (memaddr + 3, buffer, 1, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + insn |= *(unsigned char *)buffer; + + status = (*info->read_memory_func) (memaddr + 2, buffer, 1, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + extension = *(unsigned char *)buffer; + consume = 5; + } + else + return -1; + + disassemble (memaddr, info, insn, extension, consume); + + return consume; +} + +static void +disassemble (memaddr, info, insn, extension, size) + bfd_vma memaddr; + struct disassemble_info *info; + unsigned long insn; + unsigned long extension; + unsigned int size; +{ + struct mn10200_opcode *op = (struct mn10200_opcode *)mn10200_opcodes; + const struct mn10200_operand *operand; + int match = 0; + + /* Find the opcode. */ + while (op->name) + { + int mysize, extra_shift; + + if (op->format == FMT_1) + mysize = 1; + else if (op->format == FMT_2 + || op->format == FMT_4) + mysize = 2; + else if (op->format == FMT_3 + || op->format == FMT_5) + mysize = 3; + else if (op->format == FMT_6) + mysize = 4; + else if (op->format == FMT_7) + mysize = 5; + else + abort (); + + if (op->format == FMT_2 || op->format == FMT_5) + extra_shift = 8; + else if (op->format == FMT_3 + || op->format == FMT_6 + || op->format == FMT_7) + extra_shift = 16; + else + extra_shift = 0; + + if ((op->mask & insn) == op->opcode + && size == mysize) + { + const unsigned char *opindex_ptr; + unsigned int nocomma; + int paren = 0; + + match = 1; + (*info->fprintf_func) (info->stream, "%s\t", op->name); + + /* Now print the operands. */ + for (opindex_ptr = op->operands, nocomma = 1; + *opindex_ptr != 0; + opindex_ptr++) + { + unsigned long value; + + operand = &mn10200_operands[*opindex_ptr]; + + if ((operand->flags & MN10200_OPERAND_EXTENDED) != 0) + { + value = (insn & 0xffff) << 8; + value |= extension; + } + else + { + value = ((insn >> (operand->shift)) + & ((1 << operand->bits) - 1)); + } + + if ((operand->flags & MN10200_OPERAND_SIGNED) != 0) + value = ((long)(value << (32 - operand->bits)) + >> (32 - operand->bits)); + + if (!nocomma + && (!paren + || ((operand->flags & MN10200_OPERAND_PAREN) == 0))) + (*info->fprintf_func) (info->stream, ","); + + nocomma = 0; + + if ((operand->flags & MN10200_OPERAND_DREG) != 0) + { + value = ((insn >> (operand->shift + extra_shift)) + & ((1 << operand->bits) - 1)); + (*info->fprintf_func) (info->stream, "d%d", value); + } + + else if ((operand->flags & MN10200_OPERAND_AREG) != 0) + { + value = ((insn >> (operand->shift + extra_shift)) + & ((1 << operand->bits) - 1)); + (*info->fprintf_func) (info->stream, "a%d", value); + } + + else if ((operand->flags & MN10200_OPERAND_PSW) != 0) + (*info->fprintf_func) (info->stream, "psw"); + + else if ((operand->flags & MN10200_OPERAND_MDR) != 0) + (*info->fprintf_func) (info->stream, "mdr"); + + else if ((operand->flags & MN10200_OPERAND_PAREN) != 0) + { + if (paren) + (*info->fprintf_func) (info->stream, ")"); + else + { + (*info->fprintf_func) (info->stream, "("); + nocomma = 1; + } + paren = !paren; + } + + else if ((operand->flags & MN10200_OPERAND_PCREL) != 0) + (*info->print_address_func) ((value + memaddr) & 0xffffff, info); + + else if ((operand->flags & MN10200_OPERAND_MEMADDR) != 0) + (*info->print_address_func) (value, info); + + else + (*info->fprintf_func) (info->stream, "%d", value); + } + /* All done. */ + break; + } + op++; + } + + if (!match) + { + (*info->fprintf_func) (info->stream, "unknown\t0x%04x", insn); + } +} diff --git a/gnu/usr.bin/binutils/opcodes/m10200-opc.c b/gnu/usr.bin/binutils/opcodes/m10200-opc.c new file mode 100644 index 00000000000..2f70b9081ae --- /dev/null +++ b/gnu/usr.bin/binutils/opcodes/m10200-opc.c @@ -0,0 +1,360 @@ +/* Assemble Matsushita MN10200 instructions. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + +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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "ansidecl.h" +#include "opcode/mn10200.h" + + +const struct mn10200_operand mn10200_operands[] = { +#define UNUSED 0 + {0, 0, 0}, + +/* dn register in the first register operand position. */ +#define DN0 (UNUSED+1) + {2, 0, MN10200_OPERAND_DREG}, + +/* dn register in the second register operand position. */ +#define DN1 (DN0+1) + {2, 2, MN10200_OPERAND_DREG}, + +/* dm register in the first register operand position. */ +#define DM0 (DN1+1) + {2, 0, MN10200_OPERAND_DREG}, + +/* dm register in the second register operand position. */ +#define DM1 (DM0+1) + {2, 2, MN10200_OPERAND_DREG}, + +/* an register in the first register operand position. */ +#define AN0 (DM1+1) + {2, 0, MN10200_OPERAND_AREG}, + +/* an register in the second register operand position. */ +#define AN1 (AN0+1) + {2, 2, MN10200_OPERAND_AREG}, + +/* am register in the first register operand position. */ +#define AM0 (AN1+1) + {2, 0, MN10200_OPERAND_AREG}, + +/* am register in the second register operand position. */ +#define AM1 (AM0+1) + {2, 2, MN10200_OPERAND_AREG}, + +/* 8 bit unsigned immediate which may promote to a 16bit + unsigned immediate. */ +#define IMM8 (AM1+1) + {8, 0, MN10200_OPERAND_PROMOTE}, + +/* 16 bit unsigned immediate which may promote to a 32bit + unsigned immediate. */ +#define IMM16 (IMM8+1) + {16, 0, MN10200_OPERAND_PROMOTE}, + +/* 16 bit pc-relative immediate which may promote to a 16bit + pc-relative immediate. */ +#define IMM16_PCREL (IMM16+1) + {16, 0, MN10200_OPERAND_PCREL | MN10200_OPERAND_RELAX | MN10200_OPERAND_SIGNED}, + +/* 16bit unsigned dispacement in a memory operation which + may promote to a 32bit displacement. */ +#define IMM16_MEM (IMM16_PCREL+1) + {16, 0, MN10200_OPERAND_PROMOTE | MN10200_OPERAND_MEMADDR}, + +/* 24 immediate, low 16 bits in the main instruction + word, 8 in the extension word. */ + +#define IMM24 (IMM16_MEM+1) + {24, 0, MN10200_OPERAND_EXTENDED}, + +/* 32bit pc-relative offset. */ +#define IMM24_PCREL (IMM24+1) + {24, 0, MN10200_OPERAND_EXTENDED | MN10200_OPERAND_PCREL | MN10200_OPERAND_SIGNED}, + +/* 32bit memory offset. */ +#define IMM24_MEM (IMM24_PCREL+1) + {24, 0, MN10200_OPERAND_EXTENDED | MN10200_OPERAND_MEMADDR}, + +/* Processor status word. */ +#define PSW (IMM24_MEM+1) + {0, 0, MN10200_OPERAND_PSW}, + +/* MDR register. */ +#define MDR (PSW+1) + {0, 0, MN10200_OPERAND_MDR}, + +/* Index register. */ +#define DI (MDR+1) + {2, 4, MN10200_OPERAND_DREG}, + +/* 8 bit signed displacement, may promote to 16bit signed dispacement. */ +#define SD8 (DI+1) + {8, 0, MN10200_OPERAND_SIGNED | MN10200_OPERAND_PROMOTE}, + +/* 16 bit signed displacement, may promote to 32bit dispacement. */ +#define SD16 (SD8+1) + {16, 0, MN10200_OPERAND_SIGNED | MN10200_OPERAND_PROMOTE}, + +/* 8 bit pc-relative displacement. */ +#define SD8N_PCREL (SD16+1) + {8, 0, MN10200_OPERAND_SIGNED | MN10200_OPERAND_PCREL | MN10200_OPERAND_RELAX}, + +/* 8 bit signed immediate which may promote to 16bit signed immediate. */ +#define SIMM8 (SD8N_PCREL+1) + {8, 0, MN10200_OPERAND_SIGNED | MN10200_OPERAND_PROMOTE}, + +/* 16 bit signed immediate which may promote to 32bit immediate. */ +#define SIMM16 (SIMM8+1) + {16, 0, MN10200_OPERAND_SIGNED | MN10200_OPERAND_PROMOTE}, + +/* 16 bit signed immediate which may not promote. */ +#define SIMM16N (SIMM16+1) + {16, 0, MN10200_OPERAND_SIGNED | MN10200_OPERAND_NOCHECK}, + +/* Either an open paren or close paren. */ +#define PAREN (SIMM16N+1) + {0, 0, MN10200_OPERAND_PAREN}, + +/* dn register that appears in the first and second register positions. */ +#define DN01 (PAREN+1) + {2, 0, MN10200_OPERAND_DREG | MN10200_OPERAND_REPEATED}, + +/* an register that appears in the first and second register positions. */ +#define AN01 (DN01+1) + {2, 0, MN10200_OPERAND_AREG | MN10200_OPERAND_REPEATED}, +} ; + +#define MEM(ADDR) PAREN, ADDR, PAREN +#define MEM2(ADDR1,ADDR2) PAREN, ADDR1, ADDR2, PAREN + +/* The opcode table. + + The format of the opcode table is: + + NAME OPCODE MASK { OPERANDS } + + NAME is the name of the instruction. + OPCODE is the instruction opcode. + MASK is the opcode mask; this is used to tell the disassembler + which bits in the actual opcode must match OPCODE. + OPERANDS is the list of operands. + + The disassembler reads the table in order and prints the first + instruction which matches, so this table is sorted to put more + specific instructions before more general instructions. It is also + sorted by major opcode. */ + +const struct mn10200_opcode mn10200_opcodes[] = { +{ "mov", 0x8000, 0xf000, FMT_2, {SIMM8, DN01}}, +{ "mov", 0x80, 0xf0, FMT_1, {DN1, DM0}}, +{ "mov", 0xf230, 0xfff0, FMT_4, {DM1, AN0}}, +{ "mov", 0xf2f0, 0xfff0, FMT_4, {AN1, DM0}}, +{ "mov", 0xf270, 0xfff0, FMT_4, {AN1, AM0}}, +{ "mov", 0xf3f0, 0xfffc, FMT_4, {PSW, DN0}}, +{ "mov", 0xf3d0, 0xfff3, FMT_4, {DN1, PSW}}, +{ "mov", 0xf3e0, 0xfffc, FMT_4, {MDR, DN0}}, +{ "mov", 0xf3c0, 0xfff3, FMT_4, {DN1, MDR}}, +{ "mov", 0x20, 0xf0, FMT_1, {MEM(AN1), DM0}}, +{ "mov", 0x6000, 0xf000, FMT_2, {MEM2(SD8, AN1), DM0}}, +{ "mov", 0xf7c00000, 0xfff00000, FMT_6, {MEM2(SD16, AN1), DM0}}, +{ "mov", 0xf4800000, 0xfff00000, FMT_7, {MEM2(IMM24,AN1), DM0}}, +{ "mov", 0xf140, 0xffc0, FMT_4, {MEM2(DI, AN1), DM0}}, +{ "mov", 0xc80000, 0xfc0000, FMT_3, {MEM(IMM16_MEM), DN0}}, +{ "mov", 0xf4c00000, 0xfffc0000, FMT_7, {MEM(IMM24_MEM), DN0}}, +{ "mov", 0x7000, 0xf000, FMT_2, {MEM2(SD8,AN1), AM0}}, +{ "mov", 0x7000, 0xf000, FMT_2, {MEM(AN1), AM0}}, +{ "mov", 0xf7b00000, 0xfff00000, FMT_6, {MEM2(SD16, AN1), AM0}}, +{ "mov", 0xf4f00000, 0xfff00000, FMT_7, {MEM2(IMM24,AN1), AM0}}, +{ "mov", 0xf100, 0xffc0, FMT_4, {MEM2(DI, AN1), AM0}}, +{ "mov", 0xf7300000, 0xfffc0000, FMT_6, {MEM(IMM16_MEM), AN0}}, +{ "mov", 0xf4d00000, 0xfffc0000, FMT_7, {MEM(IMM24_MEM), AN0}}, +{ "mov", 0x00, 0xf0, FMT_1, {DM0, MEM(AN1)}}, +{ "mov", 0x4000, 0xf000, FMT_2, {DM0, MEM2(SD8, AN1)}}, +{ "mov", 0xf7800000, 0xfff00000, FMT_6, {DM0, MEM2(SD16, AN1)}}, +{ "mov", 0xf4000000, 0xfff00000, FMT_7, {DM0, MEM2(IMM24, AN1)}}, +{ "mov", 0xf1c0, 0xffc0, FMT_4, {DM0, MEM2(DI, AN1)}}, +{ "mov", 0xc00000, 0xfc0000, FMT_3, {DN0, MEM(IMM16_MEM)}}, +{ "mov", 0xf4400000, 0xfffc0000, FMT_7, {DN0, MEM(IMM24_MEM)}}, +{ "mov", 0x5000, 0xf000, FMT_2, {AM0, MEM2(SD8, AN1)}}, +{ "mov", 0x5000, 0xf000, FMT_2, {AM0, MEM(AN1)}}, +{ "mov", 0xf7a00000, 0xfff00000, FMT_6, {AM0, MEM2(SD16, AN1)}}, +{ "mov", 0xf4100000, 0xfff00000, FMT_7, {AM0, MEM2(IMM24,AN1)}}, +{ "mov", 0xf180, 0xffc0, FMT_4, {AM0, MEM2(DI, AN1)}}, +{ "mov", 0xf7200000, 0xfffc0000, FMT_6, {AN0, MEM(IMM16_MEM)}}, +{ "mov", 0xf4500000, 0xfffc0000, FMT_7, {AN0, MEM(IMM24_MEM)}}, +{ "mov", 0xf80000, 0xfc0000, FMT_3, {SIMM16, DN0}}, +{ "mov", 0xf4700000, 0xfffc0000, FMT_7, {IMM24, DN0}}, +{ "mov", 0xdc0000, 0xfc0000, FMT_3, {IMM16, AN0}}, +{ "mov", 0xf4740000, 0xfffc0000, FMT_7, {IMM24, AN0}}, + +{ "movx", 0xf57000, 0xfff000, FMT_5, {MEM2(SD8, AN1), DM0}}, +{ "movx", 0xf7700000, 0xfff00000, FMT_6, {MEM2(SD16, AN1), DM0}}, +{ "movx", 0xf4b00000, 0xfff00000, FMT_7, {MEM2(IMM24,AN1), DM0}}, +{ "movx", 0xf55000, 0xfff000, FMT_5, {DM0, MEM2(SD8, AN1)}}, +{ "movx", 0xf7600000, 0xfff00000, FMT_6, {DM0, MEM2(SD16, AN1)}}, +{ "movx", 0xf4300000, 0xfff00000, FMT_7, {DM0, MEM2(IMM24, AN1)}}, + +{ "movb", 0xf52000, 0xfff000, FMT_5, {MEM2(SD8, AN1), DM0}}, +{ "movb", 0xf7d00000, 0xfff00000, FMT_6, {MEM2(SD16, AN1), DM0}}, +{ "movb", 0xf4a00000, 0xfff00000, FMT_7, {MEM2(IMM24,AN1), DM0}}, +{ "movb", 0xf040, 0xffc0, FMT_4, {MEM2(DI, AN1), DM0}}, +{ "movb", 0xf4c40000, 0xfffc0000, FMT_7, {MEM(IMM24_MEM), DN0}}, +{ "movb", 0x10, 0xf0, FMT_1, {DM0, MEM(AN1)}}, +{ "movb", 0xf51000, 0xfff000, FMT_5, {DM0, MEM2(SD8, AN1)}}, +{ "movb", 0xf7900000, 0xfff00000, FMT_6, {DM0, MEM2(SD16, AN1)}}, +{ "movb", 0xf4200000, 0xfff00000, FMT_7, {DM0, MEM2(IMM24, AN1)}}, +{ "movb", 0xf0c0, 0xffc0, FMT_4, {DM0, MEM2(DI, AN1)}}, +{ "movb", 0xc40000, 0xfc0000, FMT_3, {DN0, MEM(IMM16_MEM)}}, +{ "movb", 0xf4440000, 0xfffc0000, FMT_7, {DN0, MEM(IMM24_MEM)}}, + +{ "movbu", 0x30, 0xf0, FMT_1, {MEM(AN1), DM0}}, +{ "movbu", 0xf53000, 0xfff000, FMT_5, {MEM2(SD8, AN1), DM0}}, +{ "movbu", 0xf7500000, 0xfff00000, FMT_6, {MEM2(SD16, AN1), DM0}}, +{ "movbu", 0xf4900000, 0xfff00000, FMT_7, {MEM2(IMM24,AN1), DM0}}, +{ "movbu", 0xf080, 0xffc0, FMT_4, {MEM2(DI, AN1), DM0}}, +{ "movbu", 0xcc0000, 0xfc0000, FMT_3, {MEM(IMM16_MEM), DN0}}, +{ "movbu", 0xf4c80000, 0xfffc0000, FMT_7, {MEM(IMM24_MEM), DN0}}, + +{ "ext", 0xf3c1, 0xfff3, FMT_4, {DN1}}, +{ "extx", 0xb0, 0xfc, FMT_1, {DN0}}, +{ "extxu", 0xb4, 0xfc, FMT_1, {DN0}}, +{ "extxb", 0xb8, 0xfc, FMT_1, {DN0}}, +{ "extxbu", 0xbc, 0xfc, FMT_1, {DN0}}, + +{ "add", 0x90, 0xf0, FMT_1, {DN1, DM0}}, +{ "add", 0xf200, 0xfff0, FMT_4, {DM1, AN0}}, +{ "add", 0xf2c0, 0xfff0, FMT_4, {AN1, DM0}}, +{ "add", 0xf240, 0xfff0, FMT_4, {AN1, AM0}}, +{ "add", 0xd400, 0xfc00, FMT_2, {SIMM8, DN0}}, +{ "add", 0xf7180000, 0xfffc0000, FMT_6, {SIMM16, DN0}}, +{ "add", 0xf4600000, 0xfffc0000, FMT_7, {IMM24, DN0}}, +{ "add", 0xd000, 0xfc00, FMT_2, {SIMM8, AN0}}, +{ "add", 0xf7080000, 0xfffc0000, FMT_6, {SIMM16, AN0}}, +{ "add", 0xf4640000, 0xfffc0000, FMT_7, {IMM24, AN0}}, +{ "addc", 0xf280, 0xfff0, FMT_4, {DN1, DM0}}, +{ "addnf", 0xf50c00, 0xfffc00, FMT_5, {SIMM8, AN0}}, + +{ "sub", 0xa0, 0xf0, FMT_1, {DN1, DM0}}, +{ "sub", 0xf210, 0xfff0, FMT_4, {DN1, AN0}}, +{ "sub", 0xf2d0, 0xfff0, FMT_4, {AN1, DM0}}, +{ "sub", 0xf250, 0xfff0, FMT_4, {AN1, AM0}}, +{ "sub", 0xf71c0000, 0xfffc0000, FMT_6, {IMM16, DN0}}, +{ "sub", 0xf4680000, 0xfffc0000, FMT_7, {IMM24, DN0}}, +{ "sub", 0xf70c0000, 0xfffc0000, FMT_6, {IMM16, AN0}}, +{ "sub", 0xf46c0000, 0xfffc0000, FMT_7, {IMM24, AN0}}, +{ "subc", 0xf290, 0xfff0, FMT_4, {DN1, DM0}}, + +{ "mul", 0xf340, 0xfff0, FMT_4, {DN1, DM0}}, +{ "mulu", 0xf350, 0xfff0, FMT_4, {DN1, DM0}}, + +{ "divu", 0xf360, 0xfff0, FMT_4, {DN1, DM0}}, + +{ "cmp", 0xf390, 0xfff0, FMT_4, {DN1, DM0}}, +{ "cmp", 0xf220, 0xfff0, FMT_4, {DM1, AN0}}, +{ "cmp", 0xf2e0, 0xfff0, FMT_4, {AN1, DM0}}, +{ "cmp", 0xf260, 0xfff0, FMT_4, {AN1, AM0}}, +{ "cmp", 0xd800, 0xfc00, FMT_2, {SIMM8, DN0}}, +{ "cmp", 0xf7480000, 0xfffc0000, FMT_6, {SIMM16, DN0}}, +{ "cmp", 0xf4780000, 0xfffc0000, FMT_7, {IMM24, DN0}}, +{ "cmp", 0xec0000, 0xfc0000, FMT_3, {IMM16, AN0}}, +{ "cmp", 0xf47c0000, 0xfffc0000, FMT_7, {IMM24, AN0}}, + +{ "and", 0xf300, 0xfff0, FMT_4, {DN1, DM0}}, +{ "and", 0xf50000, 0xfffc00, FMT_5, {IMM8, DN0}}, +{ "and", 0xf7000000, 0xfffc0000, FMT_6, {SIMM16N, DN0}}, +{ "and", 0xf7100000, 0xffff0000, FMT_6, {SIMM16N, PSW}}, +{ "or", 0xf310, 0xfff0, FMT_4, {DN1, DM0}}, +{ "or", 0xf50800, 0xfffc00, FMT_5, {IMM8, DN0}}, +{ "or", 0xf7400000, 0xfffc0000, FMT_6, {SIMM16N, DN0}}, +{ "or", 0xf7140000, 0xffff0000, FMT_6, {SIMM16N, PSW}}, +{ "xor", 0xf320, 0xfff0, FMT_4, {DN1, DM0}}, +{ "xor", 0xf74c0000, 0xfffc0000, FMT_6, {SIMM16N, DN0}}, +{ "not", 0xf3e4, 0xfffc, FMT_4, {DN0}}, + +{ "asr", 0xf338, 0xfffc, FMT_4, {DN0}}, +{ "lsr", 0xf33c, 0xfffc, FMT_4, {DN0}}, +{ "ror", 0xf334, 0xfffc, FMT_4, {DN0}}, +{ "rol", 0xf330, 0xfffc, FMT_4, {DN0}}, + +{ "btst", 0xf50400, 0xfffc00, FMT_5, {IMM8, DN0}}, +{ "btst", 0xf7040000, 0xfffc0000, FMT_6, {SIMM16N, DN0}}, +{ "bset", 0xf020, 0xfff0, FMT_4, {DM0, MEM(AN1)}}, +{ "bclr", 0xf030, 0xfff0, FMT_4, {DM0, MEM(AN1)}}, + +{ "beq", 0xe800, 0xff00, FMT_2, {SD8N_PCREL}}, +{ "bne", 0xe900, 0xff00, FMT_2, {SD8N_PCREL}}, +{ "blt", 0xe000, 0xff00, FMT_2, {SD8N_PCREL}}, +{ "ble", 0xe300, 0xff00, FMT_2, {SD8N_PCREL}}, +{ "bge", 0xe200, 0xff00, FMT_2, {SD8N_PCREL}}, +{ "bgt", 0xe100, 0xff00, FMT_2, {SD8N_PCREL}}, +{ "bcs", 0xe400, 0xff00, FMT_2, {SD8N_PCREL}}, +{ "bls", 0xe700, 0xff00, FMT_2, {SD8N_PCREL}}, +{ "bcc", 0xe600, 0xff00, FMT_2, {SD8N_PCREL}}, +{ "bhi", 0xe500, 0xff00, FMT_2, {SD8N_PCREL}}, +{ "bvc", 0xf5fc00, 0xffff00, FMT_5, {SD8N_PCREL}}, +{ "bvs", 0xf5fd00, 0xffff00, FMT_5, {SD8N_PCREL}}, +{ "bnc", 0xf5fe00, 0xffff00, FMT_5, {SD8N_PCREL}}, +{ "bns", 0xf5ff00, 0xffff00, FMT_5, {SD8N_PCREL}}, +{ "bra", 0xea00, 0xff00, FMT_2, {SD8N_PCREL}}, + +{ "beqx", 0xf5e800, 0xffff00, FMT_5, {SD8N_PCREL}}, +{ "bnex", 0xf5e900, 0xffff00, FMT_5, {SD8N_PCREL}}, +{ "bltx", 0xf5e000, 0xffff00, FMT_5, {SD8N_PCREL}}, +{ "blex", 0xf5e300, 0xffff00, FMT_5, {SD8N_PCREL}}, +{ "bgex", 0xf5e200, 0xffff00, FMT_5, {SD8N_PCREL}}, +{ "bgtx", 0xf5e100, 0xffff00, FMT_5, {SD8N_PCREL}}, +{ "bcsx", 0xf5e400, 0xffff00, FMT_5, {SD8N_PCREL}}, +{ "blsx", 0xf5e700, 0xffff00, FMT_5, {SD8N_PCREL}}, +{ "bccx", 0xf5e600, 0xffff00, FMT_5, {SD8N_PCREL}}, +{ "bhix", 0xf5e500, 0xffff00, FMT_5, {SD8N_PCREL}}, +{ "bvcx", 0xf5ec00, 0xffff00, FMT_5, {SD8N_PCREL}}, +{ "bvsx", 0xf5ed00, 0xffff00, FMT_5, {SD8N_PCREL}}, +{ "bncx", 0xf5ee00, 0xffff00, FMT_5, {SD8N_PCREL}}, +{ "bnsx", 0xf5ef00, 0xffff00, FMT_5, {SD8N_PCREL}}, + +{ "jmp", 0xfc0000, 0xff0000, FMT_3, {IMM16_PCREL}}, +{ "jmp", 0xf4e00000, 0xffff0000, FMT_7, {IMM24_PCREL}}, +{ "jmp", 0xf000, 0xfff3, FMT_4, {PAREN,AN1,PAREN}}, +{ "jsr", 0xfd0000, 0xff0000, FMT_3, {IMM16_PCREL}}, +{ "jsr", 0xf4e10000, 0xffff0000, FMT_7, {IMM24_PCREL}}, +{ "jsr", 0xf001, 0xfff3, FMT_4, {PAREN,AN1,PAREN}}, + +{ "nop", 0xf6, 0xff, FMT_1, {UNUSED}}, + +{ "rts", 0xfe, 0xff, FMT_1, {UNUSED}}, +{ "rti", 0xeb, 0xff, FMT_1, {UNUSED}}, + +/* Extension. We need some instruction to trigger "emulated syscalls" + for our simulator. */ +{ "syscall", 0xf010, 0xffff, FMT_4, {UNUSED}}, + +/* Extension. When talking to the simulator, gdb requires some instruction + that will trigger a "breakpoint" (really just an instruction that isn't + otherwise used by the tools. This instruction must be the same size + as the smallest instruction on the target machine. In the case of the + mn10x00 the "break" instruction must be one byte. 0xff is available on + both mn10x00 architectures. */ +{ "break", 0xff, 0xff, FMT_1, {UNUSED}}, + +{ 0, 0, 0, 0, {0}}, + +} ; + +const int mn10200_num_opcodes = + sizeof (mn10200_opcodes) / sizeof (mn10200_opcodes[0]); + + diff --git a/gnu/usr.bin/binutils/opcodes/m10300-dis.c b/gnu/usr.bin/binutils/opcodes/m10300-dis.c new file mode 100644 index 00000000000..cf5d321c91a --- /dev/null +++ b/gnu/usr.bin/binutils/opcodes/m10300-dis.c @@ -0,0 +1,539 @@ +/* Disassemble MN10300 instructions. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + +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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +#include <stdio.h> + +#include "ansidecl.h" +#include "opcode/mn10300.h" +#include "dis-asm.h" + +static void disassemble PARAMS ((bfd_vma, struct disassemble_info *, + unsigned long insn, unsigned int)); + +int +print_insn_mn10300 (memaddr, info) + bfd_vma memaddr; + struct disassemble_info *info; +{ + int status; + bfd_byte buffer[4]; + unsigned long insn; + unsigned int consume; + + /* First figure out how big the opcode is. */ + status = (*info->read_memory_func) (memaddr, buffer, 1, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + insn = *(unsigned char *) buffer; + + /* These are one byte insns. */ + if ((insn & 0xf3) == 0x00 + || (insn & 0xf0) == 0x10 + || (insn & 0xfc) == 0x3c + || (insn & 0xf3) == 0x41 + || (insn & 0xf3) == 0x40 + || (insn & 0xfc) == 0x50 + || (insn & 0xfc) == 0x54 + || (insn & 0xf0) == 0x60 + || (insn & 0xf0) == 0x70 + || ((insn & 0xf0) == 0x80 + && (insn & 0x0c) >> 2 != (insn & 0x03)) + || ((insn & 0xf0) == 0x90 + && (insn & 0x0c) >> 2 != (insn & 0x03)) + || ((insn & 0xf0) == 0xa0 + && (insn & 0x0c) >> 2 != (insn & 0x03)) + || ((insn & 0xf0) == 0xb0 + && (insn & 0x0c) >> 2 != (insn & 0x03)) + || (insn & 0xff) == 0xcb + || (insn & 0xfc) == 0xd0 + || (insn & 0xfc) == 0xd4 + || (insn & 0xfc) == 0xd8 + || (insn & 0xf0) == 0xe0) + { + consume = 1; + } + + /* These are two byte insns. */ + else if ((insn & 0xf0) == 0x80 + || (insn & 0xf0) == 0x90 + || (insn & 0xf0) == 0xa0 + || (insn & 0xf0) == 0xb0 + || (insn & 0xfc) == 0x20 + || (insn & 0xfc) == 0x28 + || (insn & 0xf3) == 0x43 + || (insn & 0xf3) == 0x42 + || (insn & 0xfc) == 0x58 + || (insn & 0xfc) == 0x5c + || ((insn & 0xf0) == 0xc0 + && (insn & 0xff) != 0xcb + && (insn & 0xff) != 0xcc + && (insn & 0xff) != 0xcd) + || (insn & 0xff) == 0xf0 + || (insn & 0xff) == 0xf1 + || (insn & 0xff) == 0xf2 + || (insn & 0xff) == 0xf3 + || (insn & 0xff) == 0xf4 + || (insn & 0xff) == 0xf5 + || (insn & 0xff) == 0xf6) + { + status = (*info->read_memory_func) (memaddr, buffer, 2, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + insn = bfd_getb16 (buffer); + consume = 2; + } + + /* These are three byte insns. */ + else if ((insn & 0xff) == 0xf8 + || (insn & 0xff) == 0xcc + || (insn & 0xff) == 0xf9 + || (insn & 0xf3) == 0x01 + || (insn & 0xf3) == 0x02 + || (insn & 0xf3) == 0x03 + || (insn & 0xfc) == 0x24 + || (insn & 0xfc) == 0x2c + || (insn & 0xfc) == 0x30 + || (insn & 0xfc) == 0x34 + || (insn & 0xfc) == 0x38 + || (insn & 0xff) == 0xde + || (insn & 0xff) == 0xdf + || (insn & 0xff) == 0xcc) + { + status = (*info->read_memory_func) (memaddr, buffer, 2, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + insn = bfd_getb16 (buffer); + insn <<= 8; + status = (*info->read_memory_func) (memaddr + 2, buffer, 1, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + insn |= *(unsigned char *)buffer; + consume = 3; + } + + /* These are four byte insns. */ + else if ((insn & 0xff) == 0xfa + || (insn & 0xff) == 0xfb) + { + status = (*info->read_memory_func) (memaddr, buffer, 4, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + insn = bfd_getb32 (buffer); + consume = 4; + } + + /* These are five byte insns. */ + else if ((insn & 0xff) == 0xcd + || (insn & 0xff) == 0xdc) + { + status = (*info->read_memory_func) (memaddr, buffer, 4, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + insn = bfd_getb32 (buffer); + consume = 5; + } + + /* These are six byte insns. */ + else if ((insn & 0xff) == 0xfd + || (insn & 0xff) == 0xfc) + { + status = (*info->read_memory_func) (memaddr, buffer, 4, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + + insn = bfd_getb32 (buffer); + consume = 6; + } + + /* Else its a seven byte insns (in theory). */ + else + { + status = (*info->read_memory_func) (memaddr, buffer, 4, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + + insn = bfd_getb32 (buffer); + consume = 7; + } + + disassemble (memaddr, info, insn, consume); + + return consume; +} + +static void +disassemble (memaddr, info, insn, size) + bfd_vma memaddr; + struct disassemble_info *info; + unsigned long insn; + unsigned int size; +{ + struct mn10300_opcode *op = (struct mn10300_opcode *)mn10300_opcodes; + const struct mn10300_operand *operand; + bfd_byte buffer[4]; + unsigned long extension = 0; + int status, match = 0; + + /* Find the opcode. */ + while (op->name) + { + int mysize, extra_shift; + + if (op->format == FMT_S0) + mysize = 1; + else if (op->format == FMT_S1 + || op->format == FMT_D0) + mysize = 2; + else if (op->format == FMT_S2 + || op->format == FMT_D1) + mysize = 3; + else if (op->format == FMT_S4) + mysize = 5; + else if (op->format == FMT_D2) + mysize = 4; + else if (op->format == FMT_D4) + mysize = 6; + else + mysize = 7; + + if ((op->mask & insn) == op->opcode + && size == mysize) + { + const unsigned char *opindex_ptr; + unsigned int nocomma; + int paren = 0; + + if (op->format == FMT_D1 || op->format == FMT_S1) + extra_shift = 8; + else if (op->format == FMT_D2 || op->format == FMT_D4 + || op->format == FMT_S2 || op->format == FMT_S4 + || op->format == FMT_S6 || op->format == FMT_D5) + extra_shift = 16; + else + extra_shift = 0; + + if (size == 1 || size == 2) + { + extension = 0; + } + else if (size == 3 + && (op->format == FMT_D1 + || op->opcode == 0xdf0000 + || op->opcode == 0xde0000)) + { + extension = 0; + } + else if (size == 3) + { + insn &= 0xff0000; + status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return; + } + + insn |= bfd_getl16 (buffer); + extension = 0; + } + else if (size == 4 + && (op->opcode == 0xfaf80000 + || op->opcode == 0xfaf00000 + || op->opcode == 0xfaf40000)) + { + extension = 0; + } + else if (size == 4) + { + insn &= 0xffff0000; + status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return; + } + + insn |= bfd_getl16 (buffer); + extension = 0; + } + else if (size == 5 && op->opcode == 0xdc000000) + { + unsigned long temp = 0; + status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return; + } + temp |= bfd_getl32 (buffer); + + insn &= 0xff000000; + insn |= (temp & 0xffffff00) >> 8; + extension = temp & 0xff; + } + else if (size == 5) + { + unsigned long temp = 0; + status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return; + } + temp |= bfd_getl16 (buffer); + + insn &= 0xff0000ff; + insn |= temp << 8; + + status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return; + } + extension = *(unsigned char *)buffer; + } + else if (size == 6) + { + unsigned long temp = 0; + status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return; + } + temp |= bfd_getl32 (buffer); + + insn &= 0xffff0000; + insn |= (temp >> 16) & 0xffff; + extension = temp & 0xffff; + } + else if (size == 7 && op->opcode == 0xdd000000) + { + unsigned long temp = 0; + status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return; + } + temp |= bfd_getl32 (buffer); + + insn &= 0xff000000; + insn |= (temp >> 8) & 0xffffff; + extension = (temp & 0xff) << 16; + + status = (*info->read_memory_func) (memaddr + 5, buffer, 2, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return; + } + extension |= bfd_getb16 (buffer); + } + else if (size == 7) + { + unsigned long temp = 0; + status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return; + } + temp |= bfd_getl32 (buffer); + + insn &= 0xffff0000; + insn |= (temp >> 16) & 0xffff; + extension = (temp & 0xffff) << 8; + + status = (*info->read_memory_func) (memaddr + 6, buffer, 1, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return; + } + extension |= *(unsigned char *)buffer; + } + + match = 1; + (*info->fprintf_func) (info->stream, "%s\t", op->name); + + /* Now print the operands. */ + for (opindex_ptr = op->operands, nocomma = 1; + *opindex_ptr != 0; + opindex_ptr++) + { + unsigned long value; + + operand = &mn10300_operands[*opindex_ptr]; + + if ((operand->flags & MN10300_OPERAND_SPLIT) != 0) + { + unsigned long temp; + value = insn & ((1 << operand->bits) - 1); + value <<= (32 - operand->bits); + temp = extension >> operand->shift; + temp &= ((1 << (32 - operand->bits)) - 1); + value |= temp; + } + else if ((operand->flags & MN10300_OPERAND_EXTENDED) != 0) + { + value = ((extension >> (operand->shift)) + & ((1 << operand->bits) - 1)); + } + else + { + value = ((insn >> (operand->shift)) + & ((1 << operand->bits) - 1)); + } + + if ((operand->flags & MN10300_OPERAND_SIGNED) != 0) + value = ((long)(value << (32 - operand->bits)) + >> (32 - operand->bits)); + + if (!nocomma + && (!paren + || ((operand->flags & MN10300_OPERAND_PAREN) == 0))) + (*info->fprintf_func) (info->stream, ","); + + nocomma = 0; + + if ((operand->flags & MN10300_OPERAND_DREG) != 0) + { + value = ((insn >> (operand->shift + extra_shift)) + & ((1 << operand->bits) - 1)); + (*info->fprintf_func) (info->stream, "d%d", value); + } + + else if ((operand->flags & MN10300_OPERAND_AREG) != 0) + { + value = ((insn >> (operand->shift + extra_shift)) + & ((1 << operand->bits) - 1)); + (*info->fprintf_func) (info->stream, "a%d", value); + } + + else if ((operand->flags & MN10300_OPERAND_SP) != 0) + (*info->fprintf_func) (info->stream, "sp"); + + else if ((operand->flags & MN10300_OPERAND_PSW) != 0) + (*info->fprintf_func) (info->stream, "psw"); + + else if ((operand->flags & MN10300_OPERAND_MDR) != 0) + (*info->fprintf_func) (info->stream, "mdr"); + + else if ((operand->flags & MN10300_OPERAND_PAREN) != 0) + { + if (paren) + (*info->fprintf_func) (info->stream, ")"); + else + { + (*info->fprintf_func) (info->stream, "("); + nocomma = 1; + } + paren = !paren; + } + + else if ((operand->flags & MN10300_OPERAND_PCREL) != 0) + (*info->print_address_func) (value + memaddr, info); + + else if ((operand->flags & MN10300_OPERAND_MEMADDR) != 0) + (*info->print_address_func) (value, info); + + else if ((operand->flags & MN10300_OPERAND_REG_LIST) != 0) + { + int comma = 0; + + (*info->fprintf_func) (info->stream, "["); + if (value & 0x80) + { + (*info->fprintf_func) (info->stream, "d2"); + comma = 1; + } + + if (value & 0x40) + { + if (comma) + (*info->fprintf_func) (info->stream, ","); + (*info->fprintf_func) (info->stream, "d3"); + comma = 1; + } + + if (value & 0x20) + { + if (comma) + (*info->fprintf_func) (info->stream, ","); + (*info->fprintf_func) (info->stream, "a2"); + comma = 1; + } + + if (value & 0x10) + { + if (comma) + (*info->fprintf_func) (info->stream, ","); + (*info->fprintf_func) (info->stream, "a3"); + comma = 1; + } + + if (value & 0x08) + { + if (comma) + (*info->fprintf_func) (info->stream, ","); + (*info->fprintf_func) (info->stream, "other"); + comma = 1; + } + (*info->fprintf_func) (info->stream, "]"); + } + + else + (*info->fprintf_func) (info->stream, "%d", value); + } + /* All done. */ + break; + } + op++; + } + + if (!match) + { + (*info->fprintf_func) (info->stream, "unknown\t0x%04x", insn); + } +} diff --git a/gnu/usr.bin/binutils/opcodes/m10300-opc.c b/gnu/usr.bin/binutils/opcodes/m10300-opc.c new file mode 100644 index 00000000000..9b469814152 --- /dev/null +++ b/gnu/usr.bin/binutils/opcodes/m10300-opc.c @@ -0,0 +1,514 @@ +/* Assemble Matsushita MN10300 instructions. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + +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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "ansidecl.h" +#include "opcode/mn10300.h" + + +const struct mn10300_operand mn10300_operands[] = { +#define UNUSED 0 + {0, 0, 0}, + +/* dn register in the first register operand position. */ +#define DN0 (UNUSED+1) + {2, 0, MN10300_OPERAND_DREG}, + +/* dn register in the second register operand position. */ +#define DN1 (DN0+1) + {2, 2, MN10300_OPERAND_DREG}, + +/* dn register in the third register operand position. */ +#define DN2 (DN1+1) + {2, 4, MN10300_OPERAND_DREG}, + +/* dm register in the first register operand position. */ +#define DM0 (DN2+1) + {2, 0, MN10300_OPERAND_DREG}, + +/* dm register in the second register operand position. */ +#define DM1 (DM0+1) + {2, 2, MN10300_OPERAND_DREG}, + +/* dm register in the third register operand position. */ +#define DM2 (DM1+1) + {2, 4, MN10300_OPERAND_DREG}, + +/* an register in the first register operand position. */ +#define AN0 (DM2+1) + {2, 0, MN10300_OPERAND_AREG}, + +/* an register in the second register operand position. */ +#define AN1 (AN0+1) + {2, 2, MN10300_OPERAND_AREG}, + +/* an register in the third register operand position. */ +#define AN2 (AN1+1) + {2, 4, MN10300_OPERAND_AREG}, + +/* am register in the first register operand position. */ +#define AM0 (AN2+1) + {2, 0, MN10300_OPERAND_AREG}, + +/* am register in the second register operand position. */ +#define AM1 (AM0+1) + {2, 2, MN10300_OPERAND_AREG}, + +/* am register in the third register operand position. */ +#define AM2 (AM1+1) + {2, 4, MN10300_OPERAND_AREG}, + +/* 8 bit unsigned immediate which may promote to a 16bit + unsigned immediate. */ +#define IMM8 (AM2+1) + {8, 0, MN10300_OPERAND_PROMOTE}, + +/* 16 bit unsigned immediate which may promote to a 32bit + unsigned immediate. */ +#define IMM16 (IMM8+1) + {16, 0, MN10300_OPERAND_PROMOTE}, + +/* 16 bit pc-relative immediate which may promote to a 16bit + pc-relative immediate. */ +#define IMM16_PCREL (IMM16+1) + {16, 0, MN10300_OPERAND_PCREL | MN10300_OPERAND_RELAX | MN10300_OPERAND_SIGNED}, + +/* 16bit unsigned dispacement in a memory operation which + may promote to a 32bit displacement. */ +#define IMM16_MEM (IMM16_PCREL+1) + {16, 0, MN10300_OPERAND_PROMOTE | MN10300_OPERAND_MEMADDR}, + +/* 32bit immediate, high 16 bits in the main instruction + word, 16bits in the extension word. + + The "bits" field indicates how many bits are in the + main instruction word for MN10300_OPERAND_SPLIT! */ +#define IMM32 (IMM16_MEM+1) + {16, 0, MN10300_OPERAND_SPLIT}, + +/* 32bit pc-relative offset. */ +#define IMM32_PCREL (IMM32+1) + {16, 0, MN10300_OPERAND_SPLIT | MN10300_OPERAND_PCREL}, + +/* 32bit memory offset. */ +#define IMM32_MEM (IMM32_PCREL+1) + {16, 0, MN10300_OPERAND_SPLIT | MN10300_OPERAND_MEMADDR}, + +/* 32bit immediate, high 16 bits in the main instruction + word, 16bits in the extension word, low 16bits are left + shifted 8 places. + + The "bits" field indicates how many bits are in the + main instruction word for MN10300_OPERAND_SPLIT! */ +#define IMM32_LOWSHIFT8 (IMM32_MEM+1) + {16, 8, MN10300_OPERAND_SPLIT | MN10300_OPERAND_MEMADDR}, + +/* 32bit immediate, high 24 bits in the main instruction + word, 8 in the extension word. + + The "bits" field indicates how many bits are in the + main instruction word for MN10300_OPERAND_SPLIT! */ +#define IMM32_HIGH24 (IMM32_LOWSHIFT8+1) + {24, 0, MN10300_OPERAND_SPLIT | MN10300_OPERAND_PCREL}, + +/* 32bit immediate, high 24 bits in the main instruction + word, 8 in the extension word, low 8 bits are left + shifted 16 places. + + The "bits" field indicates how many bits are in the + main instruction word for MN10300_OPERAND_SPLIT! */ +#define IMM32_HIGH24_LOWSHIFT16 (IMM32_HIGH24+1) + {24, 16, MN10300_OPERAND_SPLIT | MN10300_OPERAND_PCREL}, + +/* Stack pointer. */ +#define SP (IMM32_HIGH24_LOWSHIFT16+1) + {8, 0, MN10300_OPERAND_SP}, + +/* Processor status word. */ +#define PSW (SP+1) + {0, 0, MN10300_OPERAND_PSW}, + +/* MDR register. */ +#define MDR (PSW+1) + {0, 0, MN10300_OPERAND_MDR}, + +/* Index register. */ +#define DI (MDR+1) + {2, 2, MN10300_OPERAND_DREG}, + +/* 8 bit signed displacement, may promote to 16bit signed dispacement. */ +#define SD8 (DI+1) + {8, 0, MN10300_OPERAND_SIGNED | MN10300_OPERAND_PROMOTE}, + +/* 16 bit signed displacement, may promote to 32bit dispacement. */ +#define SD16 (SD8+1) + {16, 0, MN10300_OPERAND_SIGNED | MN10300_OPERAND_PROMOTE}, + +/* 8 bit signed displacement that can not promote. */ +#define SD8N (SD16+1) + {8, 0, MN10300_OPERAND_SIGNED}, + +/* 8 bit pc-relative displacement. */ +#define SD8N_PCREL (SD8N+1) + {8, 0, MN10300_OPERAND_SIGNED | MN10300_OPERAND_PCREL | MN10300_OPERAND_RELAX}, + +/* 8 bit signed displacement shifted left 8 bits in the instruction. */ +#define SD8N_SHIFT8 (SD8N_PCREL+1) + {8, 8, MN10300_OPERAND_SIGNED}, + +/* 8 bit signed immediate which may promote to 16bit signed immediate. */ +#define SIMM8 (SD8N_SHIFT8+1) + {8, 0, MN10300_OPERAND_SIGNED | MN10300_OPERAND_PROMOTE}, + +/* 16 bit signed immediate which may promote to 32bit immediate. */ +#define SIMM16 (SIMM8+1) + {16, 0, MN10300_OPERAND_SIGNED | MN10300_OPERAND_PROMOTE}, + +/* Either an open paren or close paren. */ +#define PAREN (SIMM16+1) + {0, 0, MN10300_OPERAND_PAREN}, + +/* dn register that appears in the first and second register positions. */ +#define DN01 (PAREN+1) + {2, 0, MN10300_OPERAND_DREG | MN10300_OPERAND_REPEATED}, + +/* an register that appears in the first and second register positions. */ +#define AN01 (DN01+1) + {2, 0, MN10300_OPERAND_AREG | MN10300_OPERAND_REPEATED}, + +/* 16bit pc-relative displacement which may promote to 32bit pc-relative + displacement. */ +#define D16_SHIFT (AN01+1) + {16, 8, MN10300_OPERAND_PCREL | MN10300_OPERAND_RELAX | MN10300_OPERAND_SIGNED}, + +/* 8 bit immediate found in the extension word. */ +#define IMM8E (D16_SHIFT+1) + {8, 0, MN10300_OPERAND_EXTENDED}, + +/* Register list found in the extension word shifted 8 bits left. */ +#define REGSE_SHIFT8 (IMM8E+1) + {8, 8, MN10300_OPERAND_EXTENDED | MN10300_OPERAND_REG_LIST}, + +/* Register list shifted 8 bits left. */ +#define REGS_SHIFT8 (REGSE_SHIFT8 + 1) + {8, 8, MN10300_OPERAND_REG_LIST}, + +/* Reigster list. */ +#define REGS (REGS_SHIFT8+1) + {8, 0, MN10300_OPERAND_REG_LIST}, +} ; + +#define MEM(ADDR) PAREN, ADDR, PAREN +#define MEM2(ADDR1,ADDR2) PAREN, ADDR1, ADDR2, PAREN + +/* The opcode table. + + The format of the opcode table is: + + NAME OPCODE MASK { OPERANDS } + + NAME is the name of the instruction. + OPCODE is the instruction opcode. + MASK is the opcode mask; this is used to tell the disassembler + which bits in the actual opcode must match OPCODE. + OPERANDS is the list of operands. + + The disassembler reads the table in order and prints the first + instruction which matches, so this table is sorted to put more + specific instructions before more general instructions. It is also + sorted by major opcode. */ + +const struct mn10300_opcode mn10300_opcodes[] = { +{ "mov", 0x8000, 0xf000, FMT_S1, {SIMM8, DN01}}, +{ "mov", 0x80, 0xf0, FMT_S0, {DM1, DN0}}, +{ "mov", 0xf1e0, 0xfff0, FMT_D0, {DM1, AN0}}, +{ "mov", 0xf1d0, 0xfff0, FMT_D0, {AM1, DN0}}, +{ "mov", 0x9000, 0xf000, FMT_S1, {IMM8, AN01}}, +{ "mov", 0x90, 0xf0, FMT_S0, {AM1, AN0}}, +{ "mov", 0x3c, 0xfc, FMT_S0, {SP, AN0}}, +{ "mov", 0xf2f0, 0xfff3, FMT_D0, {AM1, SP}}, +{ "mov", 0xf2e4, 0xfffc, FMT_D0, {PSW, DN0}}, +{ "mov", 0xf2f3, 0xfff3, FMT_D0, {DM1, PSW}}, +{ "mov", 0xf2e0, 0xfffc, FMT_D0, {MDR, DN0}}, +{ "mov", 0xf2f2, 0xfff3, FMT_D0, {DM1, MDR}}, +{ "mov", 0x70, 0xf0, FMT_S0, {MEM(AM0), DN1}}, +{ "mov", 0xf80000, 0xfff000, FMT_D1, {MEM2(SD8, AM0), DN1}}, +{ "mov", 0xfa000000, 0xfff00000, FMT_D2, {MEM2(SD16, AM0), DN1}}, +{ "mov", 0xfc000000, 0xfff00000, FMT_D4, {MEM2(IMM32,AM0), DN1}}, +{ "mov", 0x5800, 0xfc00, FMT_S1, {MEM2(IMM8, SP), DN0}}, +{ "mov", 0xfab40000, 0xfffc0000, FMT_D2, {MEM2(IMM16, SP), DN0}}, +{ "mov", 0xfcb40000, 0xfffc0000, FMT_D4, {MEM2(IMM32, SP), DN0}}, +{ "mov", 0xf300, 0xffc0, FMT_D0, {MEM2(DI, AM0), DN2}}, +{ "mov", 0x300000, 0xfc0000, FMT_S2, {MEM(IMM16_MEM), DN0}}, +{ "mov", 0xfca40000, 0xfffc0000, FMT_D4, {MEM(IMM32_MEM), DN0}}, +{ "mov", 0xf000, 0xfff0, FMT_D0, {MEM(AM0), AN1}}, +{ "mov", 0xf82000, 0xfff000, FMT_D1, {MEM2(SD8,AM0), AN1}}, +{ "mov", 0xfa200000, 0xfff00000, FMT_D2, {MEM2(SD16, AM0), AN1}}, +{ "mov", 0xfc200000, 0xfff00000, FMT_D4, {MEM2(IMM32,AM0), AN1}}, +{ "mov", 0x5c00, 0xfc00, FMT_S1, {MEM2(IMM8, SP), AN0}}, +{ "mov", 0xfab00000, 0xfffc0000, FMT_D2, {MEM2(IMM16, SP), AN0}}, +{ "mov", 0xfcb00000, 0xfffc0000, FMT_D4, {MEM2(IMM32, SP), AN0}}, +{ "mov", 0xf380, 0xffc0, FMT_D0, {MEM2(DI, AM0), AN2}}, +{ "mov", 0xfaa00000, 0xfffc0000, FMT_D2, {MEM(IMM16_MEM), AN0}}, +{ "mov", 0xfca00000, 0xfffc0000, FMT_D4, {MEM(IMM32_MEM), AN0}}, +{ "mov", 0xf8f000, 0xfffc00, FMT_D1, {MEM2(SD8N, AM0), SP}}, +{ "mov", 0x60, 0xf0, FMT_S0, {DM1, MEM(AN0)}}, +{ "mov", 0xf81000, 0xfff000, FMT_D1, {DM1, MEM2(SD8, AN0)}}, +{ "mov", 0xfa100000, 0xfff00000, FMT_D2, {DM1, MEM2(SD16, AN0)}}, +{ "mov", 0xfc100000, 0xfff00000, FMT_D4, {DM1, MEM2(IMM32,AN0)}}, +{ "mov", 0x4200, 0xf300, FMT_S1, {DM1, MEM2(IMM8, SP)}}, +{ "mov", 0xfa910000, 0xfff30000, FMT_D2, {DM1, MEM2(IMM16, SP)}}, +{ "mov", 0xfc910000, 0xfff30000, FMT_D4, {DM1, MEM2(IMM32, SP)}}, +{ "mov", 0xf340, 0xffc0, FMT_D0, {DM2, MEM2(DI, AN0)}}, +{ "mov", 0x010000, 0xf30000, FMT_S2, {DM1, MEM(IMM16_MEM)}}, +{ "mov", 0xfc810000, 0xfff30000, FMT_D4, {DM1, MEM(IMM32_MEM)}}, +{ "mov", 0xf010, 0xfff0, FMT_D0, {AM1, MEM(AN0)}}, +{ "mov", 0xf83000, 0xfff000, FMT_D1, {AM1, MEM2(SD8, AN0)}}, +{ "mov", 0xfa300000, 0xfff00000, FMT_D2, {AM1, MEM2(SD16, AN0)}}, +{ "mov", 0xfc300000, 0xfff00000, FMT_D4, {AM1, MEM2(IMM32,AN0)}}, +{ "mov", 0x4300, 0xf300, FMT_S1, {AM1, MEM2(IMM8, SP)}}, +{ "mov", 0xfa900000, 0xfff30000, FMT_D2, {AM1, MEM2(IMM16, SP)}}, +{ "mov", 0xfc900000, 0xfff30000, FMT_D4, {AM1, MEM2(IMM32, SP)}}, +{ "mov", 0xf3c0, 0xffc0, FMT_D0, {AM2, MEM2(DI, AN0)}}, +{ "mov", 0xfa800000, 0xfff30000, FMT_D2, {AM1, MEM(IMM16_MEM)}}, +{ "mov", 0xfc800000, 0xfff30000, FMT_D4, {AM1, MEM(IMM32_MEM)}}, +{ "mov", 0xf8f400, 0xfffc00, FMT_D1, {SP, MEM2(SD8N, AN0)}}, +{ "mov", 0x2c0000, 0xfc0000, FMT_S2, {SIMM16, DN0}}, +{ "mov", 0xfccc0000, 0xfffc0000, FMT_D4, {IMM32, DN0}}, +{ "mov", 0x240000, 0xfc0000, FMT_S2, {IMM16, AN0}}, +{ "mov", 0xfcdc0000, 0xfffc0000, FMT_D4, {IMM32, AN0}}, + +{ "movbu", 0xf040, 0xfff0, FMT_D0, {MEM(AM0), DN1}}, +{ "movbu", 0xf84000, 0xfff000, FMT_D1, {MEM2(SD8, AM0), DN1}}, +{ "movbu", 0xfa400000, 0xfff00000, FMT_D2, {MEM2(SD16, AM0), DN1}}, +{ "movbu", 0xfc400000, 0xfff00000, FMT_D4, {MEM2(IMM32,AM0), DN1}}, +{ "movbu", 0xf8b800, 0xfffc00, FMT_D1, {MEM2(IMM8, SP), DN0}}, +{ "movbu", 0xfab80000, 0xfffc0000, FMT_D2, {MEM2(IMM16, SP), DN0}}, +{ "movbu", 0xfcb80000, 0xfffc0000, FMT_D4, {MEM2(IMM32, SP), DN0}}, +{ "movbu", 0xf400, 0xffc0, FMT_D0, {MEM2(DI, AM0), DN2}}, +{ "movbu", 0x340000, 0xfc0000, FMT_S2, {MEM(IMM16_MEM), DN0}}, +{ "movbu", 0xfca80000, 0xfffc0000, FMT_D4, {MEM(IMM32_MEM), DN0}}, +{ "movbu", 0xf050, 0xfff0, FMT_D0, {DM1, MEM(AN0)}}, +{ "movbu", 0xf85000, 0xfff000, FMT_D1, {DM1, MEM2(SD8, AN0)}}, +{ "movbu", 0xfa500000, 0xfff00000, FMT_D2, {DM1, MEM2(SD16, AN0)}}, +{ "movbu", 0xfc500000, 0xfff00000, FMT_D4, {DM1, MEM2(IMM32,AN0)}}, +{ "movbu", 0xf89200, 0xfff300, FMT_D1, {DM1, MEM2(IMM8, SP)}}, +{ "movbu", 0xfa920000, 0xfff30000, FMT_D2, {DM1, MEM2(IMM16, SP)}}, +{ "movbu", 0xfc920000, 0xfff30000, FMT_D4, {DM1, MEM2(IMM32, SP)}}, +{ "movbu", 0xf440, 0xffc0, FMT_D0, {DM2, MEM2(DI, AN0)}}, +{ "movbu", 0x020000, 0xf30000, FMT_S2, {DM1, MEM(IMM16_MEM)}}, +{ "movbu", 0xfc820000, 0xfff30000, FMT_D4, {DM1, MEM(IMM32_MEM)}}, + +{ "movhu", 0xf060, 0xfff0, FMT_D0, {MEM(AM0), DN1}}, +{ "movhu", 0xf86000, 0xfff000, FMT_D1, {MEM2(SD8, AM0), DN1}}, +{ "movhu", 0xfa600000, 0xfff00000, FMT_D2, {MEM2(SD16, AM0), DN1}}, +{ "movhu", 0xfc600000, 0xfff00000, FMT_D4, {MEM2(IMM32,AM0), DN1}}, +{ "movhu", 0xf8bc00, 0xfffc00, FMT_D1, {MEM2(IMM8, SP), DN0}}, +{ "movhu", 0xfabc0000, 0xfffc0000, FMT_D2, {MEM2(IMM16, SP), DN0}}, +{ "movhu", 0xfcbc0000, 0xfffc0000, FMT_D4, {MEM2(IMM32, SP), DN0}}, +{ "movhu", 0xf480, 0xffc0, FMT_D0, {MEM2(DI, AM0), DN2}}, +{ "movhu", 0x380000, 0xfc0000, FMT_S2, {MEM(IMM16_MEM), DN0}}, +{ "movhu", 0xfcac0000, 0xfffc0000, FMT_D4, {MEM(IMM32_MEM), DN0}}, +{ "movhu", 0xf070, 0xfff0, FMT_D0, {DM1, MEM(AN0)}}, +{ "movhu", 0xf87000, 0xfff000, FMT_D1, {DM1, MEM2(SD8, AN0)}}, +{ "movhu", 0xfa700000, 0xfff00000, FMT_D2, {DM1, MEM2(SD16, AN0)}}, +{ "movhu", 0xfc700000, 0xfff00000, FMT_D4, {DM1, MEM2(IMM32,AN0)}}, +{ "movhu", 0xf89300, 0xfff300, FMT_D1, {DM1, MEM2(IMM8, SP)}}, +{ "movhu", 0xfa930000, 0xfff30000, FMT_D2, {DM1, MEM2(IMM16, SP)}}, +{ "movhu", 0xfc930000, 0xfff30000, FMT_D4, {DM1, MEM2(IMM32, SP)}}, +{ "movhu", 0xf4c0, 0xffc0, FMT_D0, {DM2, MEM2(DI, AN0)}}, +{ "movhu", 0x030000, 0xf30000, FMT_S2, {DM1, MEM(IMM16_MEM)}}, +{ "movhu", 0xfc830000, 0xfff30000, FMT_D4, {DM1, MEM(IMM32_MEM)}}, + +{ "ext", 0xf2d0, 0xfffc, FMT_D0, {DN0}}, +{ "extb", 0x10, 0xfc, FMT_S0, {DN0}}, +{ "extbu", 0x14, 0xfc, FMT_S0, {DN0}}, +{ "exth", 0x18, 0xfc, FMT_S0, {DN0}}, +{ "exthu", 0x1c, 0xfc, FMT_S0, {DN0}}, + +{ "movm", 0xce00, 0xff00, FMT_S1, {MEM(SP), REGS}}, +{ "movm", 0xcf00, 0xff00, FMT_S1, {REGS, MEM(SP)}}, + +{ "clr", 0x00, 0xf3, FMT_S0, {DN1}}, + +{ "add", 0xe0, 0xf0, FMT_S0, {DM1, DN0}}, +{ "add", 0xf160, 0xfff0, FMT_D0, {DM1, AN0}}, +{ "add", 0xf150, 0xfff0, FMT_D0, {AM1, DN0}}, +{ "add", 0xf170, 0xfff0, FMT_D0, {AM1, AN0}}, +{ "add", 0x2800, 0xfc00, FMT_S1, {SIMM8, DN0}}, +{ "add", 0xfac00000, 0xfffc0000, FMT_D2, {SIMM16, DN0}}, +{ "add", 0xfcc00000, 0xfffc0000, FMT_D4, {IMM32, DN0}}, +{ "add", 0x2000, 0xfc00, FMT_S1, {SIMM8, AN0}}, +{ "add", 0xfad00000, 0xfffc0000, FMT_D2, {SIMM16, AN0}}, +{ "add", 0xfcd00000, 0xfffc0000, FMT_D4, {IMM32, AN0}}, +{ "add", 0xf8fe00, 0xffff00, FMT_D1, {SIMM8, SP}}, +{ "add", 0xfafe0000, 0xffff0000, FMT_D2, {SIMM16, SP}}, +{ "add", 0xfcfe0000, 0xffff0000, FMT_D4, {IMM32, SP}}, +{ "addc", 0xf140, 0xfff0, FMT_D0, {DM1, DN0}}, + +{ "sub", 0xf100, 0xfff0, FMT_D0, {DM1, DN0}}, +{ "sub", 0xf120, 0xfff0, FMT_D0, {DM1, AN0}}, +{ "sub", 0xf110, 0xfff0, FMT_D0, {AM1, DN0}}, +{ "sub", 0xf130, 0xfff0, FMT_D0, {AM1, AN0}}, +{ "sub", 0xfcc40000, 0xfffc0000, FMT_D4, {IMM32, DN0}}, +{ "sub", 0xfcd40000, 0xfffc0000, FMT_D4, {IMM32, AN0}}, +{ "subc", 0xf180, 0xfff0, FMT_D0, {DM1, DN0}}, + +{ "mul", 0xf240, 0xfff0, FMT_D0, {DM1, DN0}}, +{ "mulu", 0xf250, 0xfff0, FMT_D0, {DM1, DN0}}, + +{ "div", 0xf260, 0xfff0, FMT_D0, {DM1, DN0}}, +{ "divu", 0xf270, 0xfff0, FMT_D0, {DM1, DN0}}, + +{ "inc", 0x40, 0xf3, FMT_S0, {DN1}}, +{ "inc", 0x41, 0xf3, FMT_S0, {AN1}}, +{ "inc4", 0x50, 0xfc, FMT_S0, {AN0}}, + +{ "cmp", 0xa000, 0xf000, FMT_S1, {SIMM8, DN01}}, +{ "cmp", 0xa0, 0xf0, FMT_S0, {DM1, DN0}}, +{ "cmp", 0xf1a0, 0xfff0, FMT_D0, {DM1, AN0}}, +{ "cmp", 0xf190, 0xfff0, FMT_D0, {AM1, DN0}}, +{ "cmp", 0xb000, 0xf000, FMT_S1, {IMM8, AN01}}, +{ "cmp", 0xb0, 0xf0, FMT_S0, {AM1, AN0}}, +{ "cmp", 0xfac80000, 0xfffc0000, FMT_D2, {SIMM16, DN0}}, +{ "cmp", 0xfcc80000, 0xfffc0000, FMT_D4, {IMM32, DN0}}, +{ "cmp", 0xfad80000, 0xfffc0000, FMT_D2, {IMM16, AN0}}, +{ "cmp", 0xfcd80000, 0xfffc0000, FMT_D4, {IMM32, AN0}}, + +{ "and", 0xf200, 0xfff0, FMT_D0, {DM1, DN0}}, +{ "and", 0xf8e000, 0xfffc00, FMT_D1, {IMM8, DN0}}, +{ "and", 0xfae00000, 0xfffc0000, FMT_D2, {IMM16, DN0}}, +{ "and", 0xfce00000, 0xfffc0000, FMT_D4, {IMM32, DN0}}, +{ "and", 0xfafc0000, 0xffff0000, FMT_D2, {IMM16, PSW}}, +{ "or", 0xf210, 0xfff0, FMT_D0, {DM1, DN0}}, +{ "or", 0xf8e400, 0xfffc00, FMT_D1, {IMM8, DN0}}, +{ "or", 0xfae40000, 0xfffc0000, FMT_D2, {IMM16, DN0}}, +{ "or", 0xfce40000, 0xfffc0000, FMT_D4, {IMM32, DN0}}, +{ "or", 0xfafd0000, 0xffff0000, FMT_D2, {IMM16, PSW}}, +{ "xor", 0xf220, 0xfff0, FMT_D0, {DM1, DN0}}, +{ "xor", 0xfae80000, 0xfffc0000, FMT_D2, {IMM16, DN0}}, +{ "xor", 0xfce80000, 0xfffc0000, FMT_D4, {IMM32, DN0}}, +{ "not", 0xf230, 0xfffc, FMT_D0, {DN0}}, + +{ "btst", 0xf8ec00, 0xfffc00, FMT_D1, {IMM8, DN0}}, +{ "btst", 0xfaec0000, 0xfffc0000, FMT_D2, {IMM16, DN0}}, +{ "btst", 0xfcec0000, 0xfffc0000, FMT_D4, {IMM32, DN0}}, +{ "btst", 0xfe020000, 0xffff0000, FMT_D5, {IMM8E, + MEM(IMM32_LOWSHIFT8)}}, +{ "btst", 0xfaf80000, 0xfffc0000, FMT_D2, + {IMM8, MEM2(SD8N_SHIFT8,AN0)}}, +{ "bset", 0xf080, 0xfff0, FMT_D0, {DM1, MEM(AN0)}}, +{ "bset", 0xfe000000, 0xffff0000, FMT_D5, {IMM8E, + MEM(IMM32_LOWSHIFT8)}}, +{ "bset", 0xfaf00000, 0xfffc0000, FMT_D2, + {IMM8, MEM2(SD8N_SHIFT8,AN0)}}, +{ "bclr", 0xf090, 0xfff0, FMT_D0, {DM1, MEM(AN0)}}, +{ "bclr", 0xfe010000, 0xffff0000, FMT_D5, {IMM8E, + MEM(IMM32_LOWSHIFT8)}}, +{ "bclr", 0xfaf40000, 0xfffc0000, FMT_D2, {IMM8, + MEM2(SD8N_SHIFT8,AN0)}}, + +{ "asr", 0xf2b0, 0xfff0, FMT_D0, {DM1, DN0}}, +{ "asr", 0xf8c800, 0xfffc00, FMT_D1, {IMM8, DN0}}, +{ "lsr", 0xf2a0, 0xfff0, FMT_D0, {DM1, DN0}}, +{ "lsr", 0xf8c400, 0xfffc00, FMT_D1, {IMM8, DN0}}, +{ "asl", 0xf290, 0xfff0, FMT_D0, {DM1, DN0}}, +{ "asl", 0xf8c000, 0xfffc00, FMT_D1, {IMM8, DN0}}, +{ "asl2", 0x54, 0xfc, FMT_S0, {DN0}}, +{ "ror", 0xf284, 0xfffc, FMT_D0, {DN0}}, +{ "rol", 0xf280, 0xfffc, FMT_D0, {DN0}}, + +{ "beq", 0xc800, 0xff00, FMT_S1, {SD8N_PCREL}}, +{ "bne", 0xc900, 0xff00, FMT_S1, {SD8N_PCREL}}, +{ "bgt", 0xc100, 0xff00, FMT_S1, {SD8N_PCREL}}, +{ "bge", 0xc200, 0xff00, FMT_S1, {SD8N_PCREL}}, +{ "ble", 0xc300, 0xff00, FMT_S1, {SD8N_PCREL}}, +{ "blt", 0xc000, 0xff00, FMT_S1, {SD8N_PCREL}}, +{ "bhi", 0xc500, 0xff00, FMT_S1, {SD8N_PCREL}}, +{ "bcc", 0xc600, 0xff00, FMT_S1, {SD8N_PCREL}}, +{ "bls", 0xc700, 0xff00, FMT_S1, {SD8N_PCREL}}, +{ "bcs", 0xc400, 0xff00, FMT_S1, {SD8N_PCREL}}, +{ "bvc", 0xf8e800, 0xffff00, FMT_D1, {SD8N_PCREL}}, +{ "bvs", 0xf8e900, 0xffff00, FMT_D1, {SD8N_PCREL}}, +{ "bnc", 0xf8ea00, 0xffff00, FMT_D1, {SD8N_PCREL}}, +{ "bns", 0xf8eb00, 0xffff00, FMT_D1, {SD8N_PCREL}}, +{ "bra", 0xca00, 0xff00, FMT_S1, {SD8N_PCREL}}, + +{ "leq", 0xd8, 0xff, FMT_S0, {UNUSED}}, +{ "lne", 0xd9, 0xff, FMT_S0, {UNUSED}}, +{ "lgt", 0xd1, 0xff, FMT_S0, {UNUSED}}, +{ "lge", 0xd2, 0xff, FMT_S0, {UNUSED}}, +{ "lle", 0xd3, 0xff, FMT_S0, {UNUSED}}, +{ "llt", 0xd0, 0xff, FMT_S0, {UNUSED}}, +{ "lhi", 0xd5, 0xff, FMT_S0, {UNUSED}}, +{ "lcc", 0xd6, 0xff, FMT_S0, {UNUSED}}, +{ "lls", 0xd7, 0xff, FMT_S0, {UNUSED}}, +{ "lcs", 0xd4, 0xff, FMT_S0, {UNUSED}}, +{ "lra", 0xda, 0xff, FMT_S0, {UNUSED}}, +{ "setlb", 0xdb, 0xff, FMT_S0, {UNUSED}}, + +{ "jmp", 0xf0f4, 0xfffc, FMT_D0, {PAREN,AN0,PAREN}}, +{ "jmp", 0xcc0000, 0xff0000, FMT_S2, {IMM16_PCREL}}, +{ "jmp", 0xdc000000, 0xff000000, FMT_S4, {IMM32_HIGH24}}, +{ "call", 0xcd000000, 0xff000000, FMT_S4, {D16_SHIFT,REGS,IMM8E}}, +{ "call", 0xdd000000, 0xff000000, FMT_S6, + {IMM32_HIGH24_LOWSHIFT16,REGSE_SHIFT8,IMM8E}}, +{ "calls", 0xf0f0, 0xfffc, FMT_D0, {PAREN,AN0,PAREN}}, +{ "calls", 0xfaff0000, 0xffff0000, FMT_D2, {IMM16_PCREL}}, +{ "calls", 0xfcff0000, 0xffff0000, FMT_D4, {IMM32_PCREL}}, + +{ "ret", 0xdf0000, 0xff0000, FMT_S2, {REGS_SHIFT8, IMM8}}, +{ "retf", 0xde0000, 0xff0000, FMT_S2, {REGS_SHIFT8, IMM8}}, +{ "rets", 0xf0fc, 0xffff, FMT_D0, {UNUSED}}, +{ "rti", 0xf0fd, 0xffff, FMT_D0, {UNUSED}}, +{ "trap", 0xf0fe, 0xffff, FMT_D0, {UNUSED}}, +{ "rtm", 0xf0ff, 0xffff, FMT_D0, {UNUSED}}, +{ "nop", 0xcb, 0xff, FMT_S0, {UNUSED}}, +/* { "udf", 0, 0, {0}}, */ + +{ "putx", 0xf500, 0xfff0, FMT_D0, {DN01}}, +{ "getx", 0xf6f0, 0xfff0, FMT_D0, {DN01}}, +{ "mulq", 0xf600, 0xfff0, FMT_D0, {DM1, DN0}}, +{ "mulq", 0xf90000, 0xfffc00, FMT_D1, {SIMM8, DN0}}, +{ "mulq", 0xfb000000, 0xfffc0000, FMT_D2, {SIMM16, DN0}}, +{ "mulq", 0xfd000000, 0xfffc0000, FMT_D4, {IMM32, DN0}}, +{ "mulqu", 0xf610, 0xfff0, FMT_D0, {DM1, DN0}}, +{ "mulqu", 0xf91400, 0xfffc00, FMT_D1, {SIMM8, DN0}}, +{ "mulqu", 0xfb140000, 0xfffc0000, FMT_D2, {SIMM16, DN0}}, +{ "mulqu", 0xfd140000, 0xfffc0000, FMT_D4, {IMM32, DN0}}, +{ "sat16", 0xf640, 0xfff0, FMT_D0, {DM1, DN0}}, +{ "sat24", 0xf650, 0xfff0, FMT_D0, {DM1, DN0}}, +{ "bsch", 0xf670, 0xfff0, FMT_D0, {DM1, DN0}}, + +/* Extension. We need some instruction to trigger "emulated syscalls" + for our simulator. */ +{ "syscall", 0xf020, 0xffff, FMT_D0, {UNUSED}}, + +/* Extension. When talking to the simulator, gdb requires some instruction + that will trigger a "breakpoint" (really just an instruction that isn't + otherwise used by the tools. This instruction must be the same size + as the smallest instruction on the target machine. In the case of the + mn10x00 the "break" instruction must be one byte. 0xff is available on + both mn10x00 architectures. */ +{ "break", 0xff, 0xff, FMT_S0, {UNUSED}}, +{ 0, 0, 0, 0, {0}}, + +} ; + +const int mn10300_num_opcodes = + sizeof (mn10300_opcodes) / sizeof (mn10300_opcodes[0]); + + diff --git a/gnu/usr.bin/binutils/opcodes/m32r-asm.c b/gnu/usr.bin/binutils/opcodes/m32r-asm.c new file mode 100644 index 00000000000..80965cb8c51 --- /dev/null +++ b/gnu/usr.bin/binutils/opcodes/m32r-asm.c @@ -0,0 +1,779 @@ +/* Assembler interface for targets using CGEN. -*- C -*- + CGEN: Cpu tools GENerator + +This file is used to generate m32r-asm.c. + +Copyright (C) 1996, 1997 Free Software Foundation, Inc. + +This file is part of the GNU Binutils and GDB, the GNU debugger. + +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 2, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sysdep.h" +#include <ctype.h> +#include <stdio.h> +#include "ansidecl.h" +#include "bfd.h" +#include "m32r-opc.h" + +/* ??? The layout of this stuff is still work in progress. + For speed in assembly/disassembly, we use inline functions. That of course + will only work for GCC. When this stuff is finished, we can decide whether + to keep the inline functions (and only get the performance increase when + compiled with GCC), or switch to macros, or use something else. +*/ + +static const char *parse_insn_normal + PARAMS ((const struct cgen_insn *, const char **, struct cgen_fields *)); +static void insert_insn_normal + PARAMS ((const struct cgen_insn *, struct cgen_fields *, cgen_insn_t *)); + +/* Default insertion routine. + + SHIFT is negative for left shifts, positive for right shifts. + All bits of VALUE to be inserted must be valid as we don't handle + signed vs unsigned shifts. + + ATTRS is a mask of the boolean attributes. We don't need any at the + moment, but for consistency with extract_normal we have them. */ + +/* FIXME: This duplicates functionality with bfd's howto table and + bfd_install_relocation. */ +/* FIXME: For architectures where insns can be representable as ints, + store insn in `field' struct and add registers, etc. while parsing. */ + +static CGEN_INLINE void +insert_normal (value, attrs, start, length, shift, total_length, buffer) + long value; + unsigned int attrs; + int start, length, shift, total_length; + char *buffer; +{ + bfd_vma x; + +#if 0 /*def CGEN_INT_INSN*/ + *buffer |= ((value & ((1 << length) - 1)) + << (total_length - (start + length))); +#else + switch (total_length) + { + case 8: + x = *(unsigned char *) buffer; + break; + case 16: + if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG) + x = bfd_getb16 (buffer); + else + x = bfd_getl16 (buffer); + break; + case 32: + if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG) + x = bfd_getb32 (buffer); + else + x = bfd_getl32 (buffer); + break; + default : + abort (); + } + + if (shift < 0) + value <<= -shift; + else + value >>= shift; + + x |= ((value & ((1 << length) - 1)) + << (total_length - (start + length))); + + switch (total_length) + { + case 8: + *buffer = value; + break; + case 16: + if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG) + bfd_putb16 (x, buffer); + else + bfd_putl16 (x, buffer); + break; + case 32: + if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG) + bfd_putb32 (x, buffer); + else + bfd_putl32 (x, buffer); + break; + default : + abort (); + } +#endif +} + +/* -- assembler routines inserted here */ +/* -- asm.c */ + +/* Handle shigh(), high(). */ + +static const char * +parse_h_hi16 (strp, opindex, min, max, valuep) + const char **strp; + int opindex; + unsigned long min, max; + unsigned long *valuep; +{ + const char *errmsg; + + /* FIXME: Need # in assembler syntax (means '#' is optional). */ + if (**strp == '#') + ++*strp; + + if (strncmp (*strp, "high(", 5) == 0) + { + *strp += 5; + /* FIXME: If value was a number, right shift by 16. */ + errmsg = cgen_parse_address (strp, opindex, BFD_RELOC_M32R_HI16_ULO, valuep); + if (**strp != ')') + return "missing `)'"; + ++*strp; + return errmsg; + } + else if (strncmp (*strp, "shigh(", 6) == 0) + { + *strp += 6; + /* FIXME: If value was a number, right shift by 16 (+ sign test). */ + errmsg = cgen_parse_address (strp, opindex, BFD_RELOC_M32R_HI16_SLO, valuep); + if (**strp != ')') + return "missing `)'"; + ++*strp; + return errmsg; + } + + return cgen_parse_unsigned_integer (strp, opindex, min, max, valuep); +} + +/* Handle low() in a signed context. Also handle sda(). + The signedness of the value doesn't matter to low(), but this also + handles the case where low() isn't present. */ + +static const char * +parse_h_slo16 (strp, opindex, min, max, valuep) + const char **strp; + int opindex; + long min, max; + long *valuep; +{ + const char *errmsg; + + /* FIXME: Need # in assembler syntax (means '#' is optional). */ + if (**strp == '#') + ++*strp; + + if (strncmp (*strp, "low(", 4) == 0) + { + *strp += 4; + errmsg = cgen_parse_address (strp, opindex, BFD_RELOC_M32R_LO16, valuep); + if (**strp != ')') + return "missing `)'"; + ++*strp; + return errmsg; + } + + if (strncmp (*strp, "sda(", 4) == 0) + { + *strp += 4; + errmsg = cgen_parse_address (strp, opindex, BFD_RELOC_M32R_SDA16, valuep); + if (**strp != ')') + return "missing `)'"; + ++*strp; + return errmsg; + } + + return cgen_parse_signed_integer (strp, opindex, min, max, valuep); +} + +/* Handle low() in an unsigned context. + The signedness of the value doesn't matter to low(), but this also + handles the case where low() isn't present. */ + +static const char * +parse_h_ulo16 (strp, opindex, min, max, valuep) + const char **strp; + int opindex; + unsigned long min, max; + unsigned long *valuep; +{ + const char *errmsg; + + /* FIXME: Need # in assembler syntax (means '#' is optional). */ + if (**strp == '#') + ++*strp; + + if (strncmp (*strp, "low(", 4) == 0) + { + *strp += 4; + errmsg = cgen_parse_address (strp, opindex, BFD_RELOC_M32R_LO16, valuep); + if (**strp != ')') + return "missing `)'"; + ++*strp; + return errmsg; + } + + return cgen_parse_unsigned_integer (strp, opindex, min, max, valuep); +} + +/* -- */ + +/* Main entry point for operand parsing. + + This function is basically just a big switch statement. Earlier versions + used tables to look up the function to use, but + - if the table contains both assembler and disassembler functions then + the disassembler contains much of the assembler and vice-versa, + - there's a lot of inlining possibilities as things grow, + - using a switch statement avoids the function call overhead. + + This function could be moved into `parse_insn_normal', but keeping it + separate makes clear the interface between `parse_insn_normal' and each of + the handlers. +*/ + +CGEN_INLINE const char * +m32r_cgen_parse_operand (opindex, strp, fields) + int opindex; + const char **strp; + struct cgen_fields *fields; +{ + const char *errmsg; + + switch (opindex) + { + case 0 : + errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_gr, &fields->f_r2); + break; + case 1 : + errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_gr, &fields->f_r1); + break; + case 2 : + errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_gr, &fields->f_r1); + break; + case 3 : + errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_gr, &fields->f_r2); + break; + case 4 : + errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_cr, &fields->f_r2); + break; + case 5 : + errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_cr, &fields->f_r1); + break; + case 6 : + errmsg = cgen_parse_signed_integer (strp, 6, -128, 127, &fields->f_simm8); + break; + case 7 : + errmsg = cgen_parse_signed_integer (strp, 7, -32768, 32767, &fields->f_simm16); + break; + case 8 : + errmsg = cgen_parse_unsigned_integer (strp, 8, 0, 15, &fields->f_uimm4); + break; + case 9 : + errmsg = cgen_parse_unsigned_integer (strp, 9, 0, 31, &fields->f_uimm5); + break; + case 10 : + errmsg = cgen_parse_unsigned_integer (strp, 10, 0, 65535, &fields->f_uimm16); + break; + case 11 : + errmsg = parse_h_hi16 (strp, 11, 0, 65535, &fields->f_hi16); + break; + case 12 : + errmsg = parse_h_slo16 (strp, 12, -32768, 32767, &fields->f_simm16); + break; + case 13 : + errmsg = parse_h_ulo16 (strp, 13, 0, 65535, &fields->f_uimm16); + break; + case 14 : + errmsg = cgen_parse_address (strp, 14, 0, &fields->f_uimm24); + break; + case 15 : + errmsg = cgen_parse_address (strp, 15, 0, &fields->f_disp8); + break; + case 16 : + errmsg = cgen_parse_address (strp, 16, 0, &fields->f_disp16); + break; + case 17 : + errmsg = cgen_parse_address (strp, 17, 0, &fields->f_disp24); + break; + + default : + fprintf (stderr, "Unrecognized field %d while parsing.\n", opindex); + abort (); + } + + return errmsg; +} + +/* Main entry point for operand insertion. + + This function is basically just a big switch statement. Earlier versions + used tables to look up the function to use, but + - if the table contains both assembler and disassembler functions then + the disassembler contains much of the assembler and vice-versa, + - there's a lot of inlining possibilities as things grow, + - using a switch statement avoids the function call overhead. + + This function could be moved into `parse_insn_normal', but keeping it + separate makes clear the interface between `parse_insn_normal' and each of + the handlers. It's also needed by GAS to insert operands that couldn't be + resolved during parsing. +*/ + +CGEN_INLINE void +m32r_cgen_insert_operand (opindex, fields, buffer) + int opindex; + struct cgen_fields *fields; + cgen_insn_t *buffer; +{ + switch (opindex) + { + case 0 : + insert_normal (fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), buffer); + break; + case 1 : + insert_normal (fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields), buffer); + break; + case 2 : + insert_normal (fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields), buffer); + break; + case 3 : + insert_normal (fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), buffer); + break; + case 4 : + insert_normal (fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), buffer); + break; + case 5 : + insert_normal (fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields), buffer); + break; + case 6 : + insert_normal (fields->f_simm8, 0, 8, 8, 0, CGEN_FIELDS_BITSIZE (fields), buffer); + break; + case 7 : + insert_normal (fields->f_simm16, 0, 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), buffer); + break; + case 8 : + insert_normal (fields->f_uimm4, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), buffer); + break; + case 9 : + insert_normal (fields->f_uimm5, 0|(1<<CGEN_OPERAND_UNSIGNED), 11, 5, 0, CGEN_FIELDS_BITSIZE (fields), buffer); + break; + case 10 : + insert_normal (fields->f_uimm16, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), buffer); + break; + case 11 : + insert_normal (fields->f_hi16, 0|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), buffer); + break; + case 12 : + insert_normal (fields->f_simm16, 0, 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), buffer); + break; + case 13 : + insert_normal (fields->f_uimm16, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), buffer); + break; + case 14 : + insert_normal (fields->f_uimm24, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_UNSIGNED), 8, 24, 0, CGEN_FIELDS_BITSIZE (fields), buffer); + break; + case 15 : + insert_normal (fields->f_disp8, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 8, 8, 2, CGEN_FIELDS_BITSIZE (fields), buffer); + break; + case 16 : + insert_normal (fields->f_disp16, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 16, 16, 2, CGEN_FIELDS_BITSIZE (fields), buffer); + break; + case 17 : + insert_normal (fields->f_disp24, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 8, 24, 2, CGEN_FIELDS_BITSIZE (fields), buffer); + break; + + default : + fprintf (stderr, "Unrecognized field %d while building insn.\n", + opindex); + abort (); + } +} + +/* Main entry point for operand validation. + + This function is called from GAS when it has fully resolved an operand + that couldn't be resolved during parsing. + + The result is NULL for success or an error message (which may be + computed into a static buffer). +*/ + +CGEN_INLINE const char * +m32r_cgen_validate_operand (opindex, fields) + int opindex; + const struct cgen_fields *fields; +{ + const char *errmsg = NULL; + + switch (opindex) + { + case 0 : + /* nothing to do */ + break; + case 1 : + /* nothing to do */ + break; + case 2 : + /* nothing to do */ + break; + case 3 : + /* nothing to do */ + break; + case 4 : + /* nothing to do */ + break; + case 5 : + /* nothing to do */ + break; + case 6 : + errmsg = cgen_validate_signed_integer (fields->f_simm8, -128, 127); + break; + case 7 : + errmsg = cgen_validate_signed_integer (fields->f_simm16, -32768, 32767); + break; + case 8 : + errmsg = cgen_validate_unsigned_integer (fields->f_uimm4, 0, 15); + break; + case 9 : + errmsg = cgen_validate_unsigned_integer (fields->f_uimm5, 0, 31); + break; + case 10 : + errmsg = cgen_validate_unsigned_integer (fields->f_uimm16, 0, 65535); + break; + case 11 : + errmsg = cgen_validate_unsigned_integer (fields->f_hi16, 0, 65535); + break; + case 12 : + errmsg = cgen_validate_signed_integer (fields->f_simm16, -32768, 32767); + break; + case 13 : + errmsg = cgen_validate_unsigned_integer (fields->f_uimm16, 0, 65535); + break; + case 14 : + /* nothing to do */ + break; + case 15 : + /* nothing to do */ + break; + case 16 : + /* nothing to do */ + break; + case 17 : + /* nothing to do */ + break; + + default : + fprintf (stderr, "Unrecognized field %d while validating operand.\n", + opindex); + abort (); + } + + return errmsg; +} + +cgen_parse_fn *m32r_cgen_parse_handlers[] = { + 0, /* default */ + parse_insn_normal, +}; + +cgen_insert_fn *m32r_cgen_insert_handlers[] = { + 0, /* default */ + insert_insn_normal, +}; + +void +m32r_cgen_init_asm (mach, endian) + int mach; + enum cgen_endian endian; +{ + m32r_cgen_init_tables (mach); + cgen_set_cpu (& m32r_cgen_opcode_data, mach, endian); + cgen_asm_init (); +} + + +/* Default insn parser. + + The syntax string is scanned and operands are parsed and stored in FIELDS. + Relocs are queued as we go via other callbacks. + + ??? Note that this is currently an all-or-nothing parser. If we fail to + parse the instruction, we return 0 and the caller will start over from + the beginning. Backtracking will be necessary in parsing subexpressions, + but that can be handled there. Not handling backtracking here may get + expensive in the case of the m68k. Deal with later. + + Returns NULL for success, an error message for failure. +*/ + +static const char * +parse_insn_normal (insn, strp, fields) + const struct cgen_insn *insn; + const char **strp; + struct cgen_fields *fields; +{ + const struct cgen_syntax *syntax = CGEN_INSN_SYNTAX (insn); + const char *str = *strp; + const char *errmsg; + const unsigned char *syn; +#ifdef CGEN_MNEMONIC_OPERANDS + int past_opcode_p; +#endif + + /* If mnemonics are constant, they're not stored with the syntax string. */ +#ifndef CGEN_MNEMONIC_OPERANDS + { + const char *p = syntax->mnemonic; + + while (*p && *p == *str) + ++p, ++str; + if (*p || (*str && !isspace (*str))) + return "unrecognized instruction"; + + while (isspace (*str)) + ++str; + } +#endif + + CGEN_INIT_PARSE (); + cgen_init_parse_operand (); +#ifdef CGEN_MNEMONIC_OPERANDS + past_opcode_p = 0; +#endif + + /* We don't check for (*str != '\0') here because we want to parse + any trailing fake arguments in the syntax string. */ + for (syn = syntax->syntax; *syn != '\0'; ) + { + /* Non operand chars must match exactly. */ + /* FIXME: Need to better handle whitespace. */ + if (CGEN_SYNTAX_CHAR_P (*syn)) + { + if (*str == CGEN_SYNTAX_CHAR (*syn)) + { +#ifdef CGEN_MNEMONIC_OPERANDS + if (*syn == ' ') + past_opcode_p = 1; +#endif + ++syn; + ++str; + } + else + { + /* Syntax char didn't match. Can't be this insn. */ + /* FIXME: would like to return "expected char `c'" */ + return "syntax error"; + } + continue; + } + + /* We have an operand of some sort. */ + errmsg = m32r_cgen_parse_operand (CGEN_SYNTAX_FIELD (*syn), + &str, fields); + if (errmsg) + return errmsg; + + /* Done with this operand, continue with next one. */ + ++syn; + } + + /* If we're at the end of the syntax string, we're done. */ + if (*syn == '\0') + { + /* FIXME: For the moment we assume a valid `str' can only contain + blanks now. IE: We needn't try again with a longer version of + the insn and it is assumed that longer versions of insns appear + before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */ + while (isspace (*str)) + ++str; + + if (*str != '\0') + return "junk at end of line"; /* FIXME: would like to include `str' */ + + return NULL; + } + + /* We couldn't parse it. */ + return "unrecognized instruction"; +} + +/* Default insn builder (insert handler). + The instruction is recorded in target byte order. */ + +static void +insert_insn_normal (insn, fields, buffer) + const struct cgen_insn *insn; + struct cgen_fields *fields; + cgen_insn_t *buffer; +{ + const struct cgen_syntax *syntax = CGEN_INSN_SYNTAX (insn); + bfd_vma value; + const unsigned char *syn; + + CGEN_INIT_INSERT (); + value = syntax->value; + + /* If we're recording insns as numbers (rather than a string of bytes), + target byte order handling is deferred until later. */ +#undef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#if 0 /*def CGEN_INT_INSN*/ + *buffer = value; +#else + switch (min (CGEN_BASE_INSN_BITSIZE, CGEN_FIELDS_BITSIZE (fields))) + { + case 8: + *buffer = value; + break; + case 16: + if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG) + bfd_putb16 (value, (char *) buffer); + else + bfd_putl16 (value, (char *) buffer); + break; + case 32: + if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG) + bfd_putb32 (value, (char *) buffer); + else + bfd_putl32 (value, (char *) buffer); + break; + default: + abort (); + } +#endif + + /* ??? Rather than scanning the syntax string again, we could store + in `fields' a null terminated list of the fields that are present. */ + + for (syn = syntax->syntax; *syn != '\0'; ++syn) + { + if (CGEN_SYNTAX_CHAR_P (*syn)) + continue; + + m32r_cgen_insert_operand (CGEN_SYNTAX_FIELD (*syn), fields, buffer); + } +} + +/* Main entry point. + This routine is called for each instruction to be assembled. + STR points to the insn to be assembled. + We assume all necessary tables have been initialized. + The result is a pointer to the insn's entry in the opcode table, + or NULL if an error occured (an error message will have already been + printed). */ + +const struct cgen_insn * +m32r_cgen_assemble_insn (str, fields, buf, errmsg) + const char *str; + struct cgen_fields *fields; + cgen_insn_t *buf; + char **errmsg; +{ + const char *start; + CGEN_INSN_LIST *ilist; + + /* Skip leading white space. */ + while (isspace (*str)) + ++str; + + /* The instructions are stored in hashed lists. + Get the first in the list. */ + ilist = CGEN_ASM_LOOKUP_INSN (str); + + /* Keep looking until we find a match. */ + + start = str; + for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist)) + { + const struct cgen_insn *insn = ilist->insn; + +#if 0 /* not needed as unsupported opcodes shouldn't be in the hash lists */ + /* Is this insn supported by the selected cpu? */ + if (! m32r_cgen_insn_supported (insn)) + continue; +#endif + +#if 1 /* FIXME: wip */ + /* If the RELAX attribute is set, this is an insn that shouldn't be + chosen immediately. Instead, it is used during assembler/linker + relaxation if possible. */ + if (CGEN_INSN_ATTR (insn, CGEN_INSN_RELAX) != 0) + continue; +#endif + + str = start; + + /* Record a default length for the insn. This will get set to the + correct value while parsing. */ + /* FIXME: wip */ + CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn); + + /* ??? The extent to which moving the parse and insert handlers into + this function (thus removing the function call) will speed things up + is unclear. The simplicity and flexibility of the current scheme is + appropriate for now. One could have the best of both worlds with + inline functions but of course that would only work for gcc. Since + we're machine generating some code we could do that here too. Maybe + later. */ + if (! (*CGEN_PARSE_FN (insn)) (insn, &str, fields)) + { + (*CGEN_INSERT_FN (insn)) (insn, fields, buf); + /* It is up to the caller to actually output the insn and any + queued relocs. */ + return insn; + } + + /* Try the next entry. */ + } + + /* FIXME: We can return a better error message than this. + Need to track why it failed and pick the right one. */ + { + static char errbuf[100]; + sprintf (errbuf, "bad instruction `%.50s%s'", + start, strlen (start) > 50 ? "..." : ""); + *errmsg = errbuf; + return NULL; + } +} + +#if 0 /* This calls back to GAS which we can't do without care. */ + +/* Record each member of OPVALS in the assembler's symbol table. + This lets GAS parse registers for us. + ??? Interesting idea but not currently used. */ + +void +m32r_cgen_asm_hash_keywords (opvals) + struct cgen_keyword *opvals; +{ + struct cgen_keyword_search search = cgen_keyword_search_init (opvals, NULL); + const struct cgen_keyword_entry *ke; + + while ((ke = cgen_keyword_search_next (&search)) != NULL) + { +#if 0 /* Unnecessary, should be done in the search routine. */ + if (! m32r_cgen_opval_supported (ke)) + continue; +#endif + cgen_asm_record_register (ke->name, ke->value); + } +} + +#endif /* 0 */ diff --git a/gnu/usr.bin/binutils/opcodes/m32r-dis.c b/gnu/usr.bin/binutils/opcodes/m32r-dis.c new file mode 100644 index 00000000000..ac9e4df163d --- /dev/null +++ b/gnu/usr.bin/binutils/opcodes/m32r-dis.c @@ -0,0 +1,586 @@ +/* Disassembler interface for targets using CGEN. -*- C -*- + CGEN: Cpu tools GENerator + +This file is used to generate m32r-dis.c. + +Copyright (C) 1996, 1997 Free Software Foundation, Inc. + +This file is part of the GNU Binutils and GDB, the GNU debugger. + +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 2, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sysdep.h" +#include <stdio.h> +#include "ansidecl.h" +#include "dis-asm.h" +#include "m32r-opc.h" +#include "bfd.h" + +/* ??? The layout of this stuff is still work in progress. + For speed in assembly/disassembly, we use inline functions. That of course + will only work for GCC. When this stuff is finished, we can decide whether + to keep the inline functions (and only get the performance increase when + compiled with GCC), or switch to macros, or use something else. +*/ + +/* Default text to print if an instruction isn't recognized. */ +#define UNKNOWN_INSN_MSG "*unknown*" + +/* FIXME: Machine generate. */ +#ifndef CGEN_PCREL_OFFSET +#define CGEN_PCREL_OFFSET 0 +#endif + +static int print_insn PARAMS ((bfd_vma, disassemble_info *, char *, int)); + +static int extract_insn_normal + PARAMS ((const struct cgen_insn *, void *, cgen_insn_t, struct cgen_fields *)); +static void print_insn_normal + PARAMS ((void *, const struct cgen_insn *, struct cgen_fields *, bfd_vma, int)); + +/* Default extraction routine. + + ATTRS is a mask of the boolean attributes. We only need `unsigned', + but for generality we take a bitmask of all of them. */ + +static int +extract_normal (buf_ctrl, insn_value, attrs, start, length, shift, total_length, valuep) + void *buf_ctrl; + cgen_insn_t insn_value; + unsigned int attrs; + int start, length, shift, total_length; + long *valuep; +{ + long value; + +#ifdef CGEN_INT_INSN +#if 0 + value = ((insn_value >> (CGEN_BASE_INSN_BITSIZE - (start + length))) + & ((1 << length) - 1)); +#else + value = ((insn_value >> (total_length - (start + length))) + & ((1 << length) - 1)); +#endif + if (! (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED)) + && (value & (1 << (length - 1)))) + value -= 1 << length; +#else + /* FIXME: unfinished */ +#endif + + /* This is backwards as we undo the effects of insert_normal. */ + if (shift < 0) + value >>= -shift; + else + value <<= shift; + + *valuep = value; + return 1; +} + +/* Default print handler. */ + +static void +print_normal (dis_info, value, attrs, pc, length) + void *dis_info; + long value; + unsigned int attrs; + unsigned long pc; /* FIXME: should be bfd_vma */ + int length; +{ + disassemble_info *info = dis_info; + + /* Print the operand as directed by the attributes. */ + if (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_FAKE)) + ; /* nothing to do (??? at least not yet) */ + else if (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_PCREL_ADDR)) + (*info->print_address_func) (pc + CGEN_PCREL_OFFSET + value, info); + /* ??? Not all cases of this are currently caught. */ + else if (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_ABS_ADDR)) + /* FIXME: Why & 0xffffffff? */ + (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info); + else if (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED)) + (*info->fprintf_func) (info->stream, "0x%lx", value); + else + (*info->fprintf_func) (info->stream, "%ld", value); +} + +/* Keyword print handler. */ + +static void +print_keyword (dis_info, keyword_table, value, attrs) + void *dis_info; + struct cgen_keyword *keyword_table; + long value; + CGEN_ATTR *attrs; +{ + disassemble_info *info = dis_info; + const struct cgen_keyword_entry *ke; + + ke = cgen_keyword_lookup_value (keyword_table, value); + if (ke != NULL) + (*info->fprintf_func) (info->stream, "%s", ke->name); + else + (*info->fprintf_func) (info->stream, "???"); +} + +/* -- disassembler routines inserted here */ +/* -- dis.c */ + +#undef CGEN_PRINT_INSN +#define CGEN_PRINT_INSN my_print_insn + +static int +my_print_insn (pc, info, buf, buflen) + bfd_vma pc; + disassemble_info *info; + char *buf; + int buflen; +{ + unsigned long insn_value; + + /* 32 bit insn? */ + if ((pc & 3) == 0 && (buf[0] & 0x80) != 0) + return print_insn (pc, info, buf, buflen); + + /* Print the first insn. */ + if ((pc & 3) == 0) + { + if (print_insn (pc, info, buf, 16) == 0) + (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG); + buf += 2; + } + + if (buf[0] & 0x80) + { + /* Parallel. */ + (*info->fprintf_func) (info->stream, " || "); + buf[0] &= 0x7f; + } + else + (*info->fprintf_func) (info->stream, " -> "); + + /* The "& 3" is to ensure the branch address is computed correctly + [if it is a branch]. */ + if (print_insn (pc & ~ (bfd_vma) 3, info, buf, 16) == 0) + (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG); + + return (pc & 3) ? 2 : 4; +} + +/* -- */ + +/* Main entry point for operand extraction. + + This function is basically just a big switch statement. Earlier versions + used tables to look up the function to use, but + - if the table contains both assembler and disassembler functions then + the disassembler contains much of the assembler and vice-versa, + - there's a lot of inlining possibilities as things grow, + - using a switch statement avoids the function call overhead. + + This function could be moved into `print_insn_normal', but keeping it + separate makes clear the interface between `print_insn_normal' and each of + the handlers. +*/ + +CGEN_INLINE int +m32r_cgen_extract_operand (opindex, buf_ctrl, insn_value, fields) + int opindex; + void *buf_ctrl; + cgen_insn_t insn_value; + struct cgen_fields *fields; +{ + int length; + + switch (opindex) + { + case 0 : + length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_r2); + break; + case 1 : + length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_r1); + break; + case 2 : + length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_r1); + break; + case 3 : + length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_r2); + break; + case 4 : + length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_r2); + break; + case 5 : + length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_r1); + break; + case 6 : + length = extract_normal (NULL /*FIXME*/, insn_value, 0, 8, 8, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_simm8); + break; + case 7 : + length = extract_normal (NULL /*FIXME*/, insn_value, 0, 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_simm16); + break; + case 8 : + length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_uimm4); + break; + case 9 : + length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 11, 5, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_uimm5); + break; + case 10 : + length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_uimm16); + break; + case 11 : + length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_hi16); + break; + case 12 : + length = extract_normal (NULL /*FIXME*/, insn_value, 0, 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_simm16); + break; + case 13 : + length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_uimm16); + break; + case 14 : + length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_UNSIGNED), 8, 24, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_uimm24); + break; + case 15 : + length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 8, 8, 2, CGEN_FIELDS_BITSIZE (fields), &fields->f_disp8); + break; + case 16 : + length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 16, 16, 2, CGEN_FIELDS_BITSIZE (fields), &fields->f_disp16); + break; + case 17 : + length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 8, 24, 2, CGEN_FIELDS_BITSIZE (fields), &fields->f_disp24); + break; + + default : + fprintf (stderr, "Unrecognized field %d while decoding insn.\n", + opindex); + abort (); + } + + return length; +} + +/* Main entry point for printing operands. + + This function is basically just a big switch statement. Earlier versions + used tables to look up the function to use, but + - if the table contains both assembler and disassembler functions then + the disassembler contains much of the assembler and vice-versa, + - there's a lot of inlining possibilities as things grow, + - using a switch statement avoids the function call overhead. + + This function could be moved into `print_insn_normal', but keeping it + separate makes clear the interface between `print_insn_normal' and each of + the handlers. +*/ + +CGEN_INLINE void +m32r_cgen_print_operand (opindex, info, fields, attrs, pc, length) + int opindex; + disassemble_info *info; + struct cgen_fields *fields; + int attrs; + bfd_vma pc; + int length; +{ + switch (opindex) + { + case 0 : + print_keyword (info, & m32r_cgen_opval_h_gr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED)); + break; + case 1 : + print_keyword (info, & m32r_cgen_opval_h_gr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED)); + break; + case 2 : + print_keyword (info, & m32r_cgen_opval_h_gr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED)); + break; + case 3 : + print_keyword (info, & m32r_cgen_opval_h_gr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED)); + break; + case 4 : + print_keyword (info, & m32r_cgen_opval_h_cr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED)); + break; + case 5 : + print_keyword (info, & m32r_cgen_opval_h_cr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED)); + break; + case 6 : + print_normal (info, fields->f_simm8, 0, pc, length); + break; + case 7 : + print_normal (info, fields->f_simm16, 0, pc, length); + break; + case 8 : + print_normal (info, fields->f_uimm4, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length); + break; + case 9 : + print_normal (info, fields->f_uimm5, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length); + break; + case 10 : + print_normal (info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length); + break; + case 11 : + print_normal (info, fields->f_hi16, 0|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), pc, length); + break; + case 12 : + print_normal (info, fields->f_simm16, 0, pc, length); + break; + case 13 : + print_normal (info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length); + break; + case 14 : + print_normal (info, fields->f_uimm24, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_UNSIGNED), pc, length); + break; + case 15 : + print_normal (info, fields->f_disp8, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length); + break; + case 16 : + print_normal (info, fields->f_disp16, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length); + break; + case 17 : + print_normal (info, fields->f_disp24, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length); + break; + + default : + fprintf (stderr, "Unrecognized field %d while printing insn.\n", + opindex); + abort (); + } +} + +cgen_extract_fn *m32r_cgen_extract_handlers[] = { + 0, /* default */ + extract_insn_normal, +}; + +cgen_print_fn *m32r_cgen_print_handlers[] = { + 0, /* default */ + print_insn_normal, +}; + + +void +m32r_cgen_init_dis (mach, endian) + int mach; + enum cgen_endian endian; +{ + m32r_cgen_init_tables (mach); + cgen_set_cpu (& m32r_cgen_opcode_data, mach, endian); + cgen_dis_init (); +} + + +/* Default insn extractor. + + The extracted fields are stored in DIS_FLDS. + BUF_CTRL is used to handle reading variable length insns (FIXME: not done). + Return the length of the insn in bits, or 0 if no match. */ + +static int +extract_insn_normal (insn, buf_ctrl, insn_value, fields) + const struct cgen_insn *insn; + void *buf_ctrl; + cgen_insn_t insn_value; + struct cgen_fields *fields; +{ + const struct cgen_syntax *syntax = CGEN_INSN_SYNTAX (insn); + const unsigned char *syn; + + /* ??? Some of the operand extract routines need to know the insn length, + which might be computed as we go. Set a default value and it'll be + modified as necessary. */ + CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn); + + CGEN_INIT_EXTRACT (); + + for (syn = syntax->syntax; *syn; ++syn) + { + int length; + + if (CGEN_SYNTAX_CHAR_P (*syn)) + continue; + + length = m32r_cgen_extract_operand (CGEN_SYNTAX_FIELD (*syn), + buf_ctrl, insn_value, fields); + if (length == 0) + return 0; + } + + /* We recognized and successfully extracted this insn. + If a length is recorded with this insn, it has a fixed length. + Otherwise we require the syntax string to have a fake operand which + sets the `length' field in `flds'. */ + /* FIXME: wip */ + if (syntax->length > 0) + return syntax->length; + return fields->length; +} + +/* Default insn printer. + + DIS_INFO is defined as `void *' so the disassembler needn't know anything + about disassemble_info. +*/ + +static void +print_insn_normal (dis_info, insn, fields, pc, length) + void *dis_info; + const struct cgen_insn *insn; + struct cgen_fields *fields; + bfd_vma pc; + int length; +{ + const struct cgen_syntax *syntax = CGEN_INSN_SYNTAX (insn); + disassemble_info *info = dis_info; + const unsigned char *syn; + + CGEN_INIT_PRINT (); + + for (syn = syntax->syntax; *syn; ++syn) + { + if (CGEN_SYNTAX_CHAR_P (*syn)) + { + (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn)); + continue; + } + + /* We have an operand. */ + m32r_cgen_print_operand (CGEN_SYNTAX_FIELD (*syn), info, + fields, CGEN_INSN_ATTRS (insn), pc, length); + } +} + +/* Default value for CGEN_PRINT_INSN. + Given BUFLEN bytes (target byte order) read into BUF, look up the + insn in the instruction table and disassemble it. + + The result is the size of the insn in bytes. */ + +#ifndef CGEN_PRINT_INSN +#define CGEN_PRINT_INSN print_insn +#endif + +static int +print_insn (pc, info, buf, buflen) + bfd_vma pc; + disassemble_info *info; + char *buf; + int buflen; +{ + int i; + unsigned long insn_value; + const CGEN_INSN_LIST *insn_list; + + switch (buflen) + { + case 8: + insn_value = buf[0]; + break; + case 16: + insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb16 (buf) : bfd_getl16 (buf); + break; + case 32: + insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb32 (buf) : bfd_getl32 (buf); + break; + default: + abort (); + } + + /* The instructions are stored in hash lists. + Pick the first one and keep trying until we find the right one. */ + + insn_list = CGEN_DIS_LOOKUP_INSN (buf, insn_value); + while (insn_list != NULL) + { + const CGEN_INSN *insn = insn_list->insn; + const struct cgen_syntax *syntax = CGEN_INSN_SYNTAX (insn); + struct cgen_fields fields; + int length; + +#if 0 /* not needed as insn shouldn't be in hash lists if not supported */ + /* Supported by this cpu? */ + if (! m32r_cgen_insn_supported (insn)) + continue; +#endif + + /* Basic bit mask must be correct. */ + /* ??? May wish to allow target to defer this check until the extract + handler. */ + if ((insn_value & syntax->mask) == syntax->value) + { + /* Printing is handled in two passes. The first pass parses the + machine insn and extracts the fields. The second pass prints + them. */ + + length = (*CGEN_EXTRACT_FN (insn)) (insn, NULL, insn_value, &fields); + if (length > 0) + { + (*CGEN_PRINT_FN (insn)) (info, insn, &fields, pc, length); + /* length is in bits, result is in bytes */ + return length / 8; + } + } + + insn_list = CGEN_DIS_NEXT_INSN (insn_list); + } + + return 0; +} + +/* Main entry point. + Print one instruction from PC on INFO->STREAM. + Return the size of the instruction (in bytes). */ + +int +print_insn_m32r (pc, info) + bfd_vma pc; + disassemble_info *info; +{ + char buffer[CGEN_MAX_INSN_SIZE]; + int status, length; + static int initialized = 0; + static int current_mach = 0; + static int current_big_p = 0; + int mach = info->mach; + int big_p = info->endian == BFD_ENDIAN_BIG; + + /* If we haven't initialized yet, or if we've switched cpu's, initialize. */ + if (!initialized || mach != current_mach || big_p != current_big_p) + { + initialized = 1; + current_mach = mach; + current_big_p = big_p; + m32r_cgen_init_dis (mach, big_p ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE); + } + + /* Read enough of the insn so we can look it up in the hash lists. */ + + status = (*info->read_memory_func) (pc, buffer, CGEN_BASE_INSN_SIZE, info); + if (status != 0) + { + (*info->memory_error_func) (status, pc, info); + return -1; + } + + /* We try to have as much common code as possible. + But at this point some targets need to take over. */ + /* ??? Some targets may need a hook elsewhere. Try to avoid this, + but if not possible, try to move this hook elsewhere rather than + have two hooks. */ + length = CGEN_PRINT_INSN (pc, info, buffer, CGEN_BASE_INSN_BITSIZE); + if (length) + return length; + + (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG); + return CGEN_DEFAULT_INSN_SIZE; +} diff --git a/gnu/usr.bin/binutils/opcodes/m32r-opc.c b/gnu/usr.bin/binutils/opcodes/m32r-opc.c new file mode 100644 index 00000000000..fe6890b3d3c --- /dev/null +++ b/gnu/usr.bin/binutils/opcodes/m32r-opc.c @@ -0,0 +1,977 @@ +/* CGEN support code for m32r. + +This file is machine generated. + +Copyright (C) 1996, 1997 Free Software Foundation, Inc. + +This file is part of the GNU Binutils and/or GDB, the GNU debugger. + +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 2, 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., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + + +#include "sysdep.h" +#include <stdio.h> +#include "ansidecl.h" +#include "libiberty.h" +#include "bfd.h" +#include "m32r-opc.h" + +struct cgen_keyword_entry m32r_cgen_opval_mach_entries[] = { + { "m32r", 0 }, + { "test", 1 } +}; + +struct cgen_keyword m32r_cgen_opval_mach = { + & m32r_cgen_opval_mach_entries[0], + 2 +}; + +struct cgen_keyword_entry m32r_cgen_opval_h_gr_entries[] = { + { "fp", 13 }, + { "lr", 14 }, + { "sp", 15 }, + { "r0", 0 }, + { "r1", 1 }, + { "r2", 2 }, + { "r3", 3 }, + { "r4", 4 }, + { "r5", 5 }, + { "r6", 6 }, + { "r7", 7 }, + { "r8", 8 }, + { "r9", 9 }, + { "r10", 10 }, + { "r11", 11 }, + { "r12", 12 }, + { "r13", 13 }, + { "r14", 14 }, + { "r15", 15 } +}; + +struct cgen_keyword m32r_cgen_opval_h_gr = { + & m32r_cgen_opval_h_gr_entries[0], + 19 +}; + +struct cgen_keyword_entry m32r_cgen_opval_h_cr_entries[] = { + { "psw", 0 }, + { "cbr", 1 }, + { "spi", 2 }, + { "spu", 3 }, + { "bpc", 6 }, + { "cr0", 0 }, + { "cr1", 1 }, + { "cr2", 2 }, + { "cr3", 3 }, + { "cr4", 4 }, + { "cr5", 5 }, + { "cr6", 6 } +}; + +struct cgen_keyword m32r_cgen_opval_h_cr = { + & m32r_cgen_opval_h_cr_entries[0], + 12 +}; + + +static CGEN_HW_ENTRY m32r_cgen_hw_entries[] = { + { & m32r_cgen_hw_entries[1], "pc", CGEN_ASM_KEYWORD /*FIXME*/, 0 }, + { & m32r_cgen_hw_entries[2], "h-memory", CGEN_ASM_KEYWORD /*FIXME*/, 0 }, + { & m32r_cgen_hw_entries[3], "h-sint", CGEN_ASM_KEYWORD /*FIXME*/, 0 }, + { & m32r_cgen_hw_entries[4], "h-uint", CGEN_ASM_KEYWORD /*FIXME*/, 0 }, + { & m32r_cgen_hw_entries[5], "h-addr", CGEN_ASM_KEYWORD /*FIXME*/, 0 }, + { & m32r_cgen_hw_entries[6], "h-iaddr", CGEN_ASM_KEYWORD /*FIXME*/, 0 }, + { & m32r_cgen_hw_entries[7], "h-hi16", CGEN_ASM_KEYWORD /*FIXME*/, 0 }, + { & m32r_cgen_hw_entries[8], "h-slo16", CGEN_ASM_KEYWORD /*FIXME*/, 0 }, + { & m32r_cgen_hw_entries[9], "h-ulo16", CGEN_ASM_KEYWORD /*FIXME*/, 0 }, + { & m32r_cgen_hw_entries[10], "h-gr", CGEN_ASM_KEYWORD /*FIXME*/, & m32r_cgen_opval_h_gr }, + { & m32r_cgen_hw_entries[11], "h-cr", CGEN_ASM_KEYWORD /*FIXME*/, & m32r_cgen_opval_h_cr }, + { & m32r_cgen_hw_entries[12], "h-accum", CGEN_ASM_KEYWORD /*FIXME*/, 0 }, + { & m32r_cgen_hw_entries[13], "h-cond", CGEN_ASM_KEYWORD /*FIXME*/, 0 }, + { & m32r_cgen_hw_entries[14], "h-sm", CGEN_ASM_KEYWORD /*FIXME*/, 0 }, + { & m32r_cgen_hw_entries[15], "h-bsm", CGEN_ASM_KEYWORD /*FIXME*/, 0 }, + { & m32r_cgen_hw_entries[16], "h-ie", CGEN_ASM_KEYWORD /*FIXME*/, 0 }, + { & m32r_cgen_hw_entries[17], "h-bie", CGEN_ASM_KEYWORD /*FIXME*/, 0 }, + { & m32r_cgen_hw_entries[18], "h-bcond", CGEN_ASM_KEYWORD /*FIXME*/, 0 }, + { NULL, "h-bpc", CGEN_ASM_KEYWORD /*FIXME*/, 0 } +}; + + +const struct cgen_operand m32r_cgen_operand_table[CGEN_NUM_OPERANDS] = +{ +/* sr: source register */ + { "sr", 12, 4, { 0, 0|(1<<CGEN_OPERAND_UNSIGNED), { 0 } } }, +/* dr: destination register */ + { "dr", 4, 4, { 0, 0|(1<<CGEN_OPERAND_UNSIGNED), { 0 } } }, +/* src1: source register 1 */ + { "src1", 4, 4, { 0, 0|(1<<CGEN_OPERAND_UNSIGNED), { 0 } } }, +/* src2: source register 2 */ + { "src2", 12, 4, { 0, 0|(1<<CGEN_OPERAND_UNSIGNED), { 0 } } }, +/* scr: source control register */ + { "scr", 12, 4, { 0, 0|(1<<CGEN_OPERAND_UNSIGNED), { 0 } } }, +/* dcr: destination control register */ + { "dcr", 4, 4, { 0, 0|(1<<CGEN_OPERAND_UNSIGNED), { 0 } } }, +/* simm8: 8 bit signed immediate */ + { "simm8", 8, 8, { 0, 0, { 0 } } }, +/* simm16: 16 bit signed immediate */ + { "simm16", 16, 16, { 0, 0, { 0 } } }, +/* uimm4: 4 bit trap number */ + { "uimm4", 12, 4, { 0, 0|(1<<CGEN_OPERAND_UNSIGNED), { 0 } } }, +/* uimm5: 5 bit shift count */ + { "uimm5", 11, 5, { 0, 0|(1<<CGEN_OPERAND_UNSIGNED), { 0 } } }, +/* uimm16: 16 bit unsigned immediate */ + { "uimm16", 16, 16, { 0, 0|(1<<CGEN_OPERAND_UNSIGNED), { 0 } } }, +/* hi16: high 16 bit immediate, sign optional */ + { "hi16", 16, 16, { 0, 0|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), { 0 } } }, +/* slo16: 16 bit signed immediate, for low() */ + { "slo16", 16, 16, { 0, 0, { 0 } } }, +/* ulo16: 16 bit unsigned immediate, for low() */ + { "ulo16", 16, 16, { 0, 0|(1<<CGEN_OPERAND_UNSIGNED), { 0 } } }, +/* uimm24: 24 bit address */ + { "uimm24", 8, 24, { 0, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_UNSIGNED), { 0 } } }, +/* disp8: 8 bit displacement */ + { "disp8", 8, 8, { 0, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), { 0 } } }, +/* disp16: 16 bit displacement */ + { "disp16", 16, 16, { 0, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), { 0 } } }, +/* disp24: 24 bit displacement */ + { "disp24", 8, 24, { 0, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), { 0 } } }, +}; + +const struct cgen_insn m32r_cgen_insn_table_entries[CGEN_NUM_INSNS] = { +/* null first entry, end of all hash chains */ + { { 0 }, { 0 } }, +/* add $dr,$sr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "add $dr,$sr", "add", "add", {'a', 'd', 'd', ' ', 129, ',', 128, }, 0xf0f0, 0xa0, 16 } + }, +/* add3 $dr,$sr,$slo16 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "add3 $dr,$sr,$slo16", "add3", "add3", {'a', 'd', 'd', '3', ' ', 129, ',', 128, ',', 140, }, 0xf0f00000, 0x80a00000, 32 } + }, +/* and $dr,$sr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "and $dr,$sr", "and", "and", {'a', 'n', 'd', ' ', 129, ',', 128, }, 0xf0f0, 0xc0, 16 } + }, +/* and3 $dr,$sr,$uimm16 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "and3 $dr,$sr,$uimm16", "and3", "and3", {'a', 'n', 'd', '3', ' ', 129, ',', 128, ',', 138, }, 0xf0f00000, 0x80c00000, 32 } + }, +/* or $dr,$sr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "or $dr,$sr", "or", "or", {'o', 'r', ' ', 129, ',', 128, }, 0xf0f0, 0xe0, 16 } + }, +/* or3 $dr,$sr,$ulo16 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "or3 $dr,$sr,$ulo16", "or3", "or3", {'o', 'r', '3', ' ', 129, ',', 128, ',', 141, }, 0xf0f00000, 0x80e00000, 32 } + }, +/* xor $dr,$sr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "xor $dr,$sr", "xor", "xor", {'x', 'o', 'r', ' ', 129, ',', 128, }, 0xf0f0, 0xd0, 16 } + }, +/* xor3 $dr,$sr,$uimm16 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "xor3 $dr,$sr,$uimm16", "xor3", "xor3", {'x', 'o', 'r', '3', ' ', 129, ',', 128, ',', 138, }, 0xf0f00000, 0x80d00000, 32 } + }, +/* addi $dr,$simm8 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "addi $dr,$simm8", "addi", "addi", {'a', 'd', 'd', 'i', ' ', 129, ',', 134, }, 0xf000, 0x4000, 16 } + }, +/* addv $dr,$sr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "addv $dr,$sr", "addv", "addv", {'a', 'd', 'd', 'v', ' ', 129, ',', 128, }, 0xf0f0, 0x80, 16 } + }, +/* addv3 $dr,$sr,$simm16 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "addv3 $dr,$sr,$simm16", "addv3", "addv3", {'a', 'd', 'd', 'v', '3', ' ', 129, ',', 128, ',', 135, }, 0xf0f00000, 0x80800000, 32 } + }, +/* addx $dr,$sr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "addx $dr,$sr", "addx", "addx", {'a', 'd', 'd', 'x', ' ', 129, ',', 128, }, 0xf0f0, 0x90, 16 } + }, +/* bc $disp8 */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_RELAX_BC)|(1<<CGEN_INSN_RELAXABLE)|(1<<CGEN_INSN_COND_CTI), { 0 } } }, + { "bc $disp8", "bc8", "bc", {'b', 'c', ' ', 143, }, 0xff00, 0x7c00, 16 } + }, +/* bc.s $disp8 */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_ALIAS)|(1<<CGEN_INSN_COND_CTI), { 0 } } }, + { "bc.s $disp8", "bc8.s", "bc", {'b', 'c', '.', 's', ' ', 143, }, 0xff00, 0x7c00, 16 } + }, +/* bc $disp24 */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_RELAX_BC)|(1<<CGEN_INSN_RELAX)|(1<<CGEN_INSN_COND_CTI), { 0 } } }, + { "bc $disp24", "bc24", "bc", {'b', 'c', ' ', 145, }, 0xff000000, 0xfc000000, 32 } + }, +/* bc.l $disp24 */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_ALIAS)|(1<<CGEN_INSN_COND_CTI), { 0 } } }, + { "bc.l $disp24", "bc24.l", "bc", {'b', 'c', '.', 'l', ' ', 145, }, 0xff000000, 0xfc000000, 32 } + }, +/* beq $src1,$src2,$disp16 */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_COND_CTI), { 0 } } }, + { "beq $src1,$src2,$disp16", "beq", "beq", {'b', 'e', 'q', ' ', 130, ',', 131, ',', 144, }, 0xf0f00000, 0xb0000000, 32 } + }, +/* beqz $src2,$disp16 */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_COND_CTI), { 0 } } }, + { "beqz $src2,$disp16", "beqz", "beqz", {'b', 'e', 'q', 'z', ' ', 131, ',', 144, }, 0xfff00000, 0xb0800000, 32 } + }, +/* bgez $src2,$disp16 */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_COND_CTI), { 0 } } }, + { "bgez $src2,$disp16", "bgez", "bgez", {'b', 'g', 'e', 'z', ' ', 131, ',', 144, }, 0xfff00000, 0xb0b00000, 32 } + }, +/* bgtz $src2,$disp16 */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_COND_CTI), { 0 } } }, + { "bgtz $src2,$disp16", "bgtz", "bgtz", {'b', 'g', 't', 'z', ' ', 131, ',', 144, }, 0xfff00000, 0xb0d00000, 32 } + }, +/* blez $src2,$disp16 */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_COND_CTI), { 0 } } }, + { "blez $src2,$disp16", "blez", "blez", {'b', 'l', 'e', 'z', ' ', 131, ',', 144, }, 0xfff00000, 0xb0c00000, 32 } + }, +/* bltz $src2,$disp16 */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_COND_CTI), { 0 } } }, + { "bltz $src2,$disp16", "bltz", "bltz", {'b', 'l', 't', 'z', ' ', 131, ',', 144, }, 0xfff00000, 0xb0a00000, 32 } + }, +/* bnez $src2,$disp16 */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_COND_CTI), { 0 } } }, + { "bnez $src2,$disp16", "bnez", "bnez", {'b', 'n', 'e', 'z', ' ', 131, ',', 144, }, 0xfff00000, 0xb0900000, 32 } + }, +/* bl $disp8 */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_FILL_SLOT)|(1<<CGEN_INSN_RELAX_BL)|(1<<CGEN_INSN_RELAXABLE)|(1<<CGEN_INSN_UNCOND_CTI), { 0 } } }, + { "bl $disp8", "bl8", "bl", {'b', 'l', ' ', 143, }, 0xff00, 0x7e00, 16 } + }, +/* bl.s $disp8 */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_FILL_SLOT)|(1<<CGEN_INSN_ALIAS)|(1<<CGEN_INSN_UNCOND_CTI), { 0 } } }, + { "bl.s $disp8", "bl8.s", "bl", {'b', 'l', '.', 's', ' ', 143, }, 0xff00, 0x7e00, 16 } + }, +/* bl $disp24 */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_RELAX_BL)|(1<<CGEN_INSN_RELAX)|(1<<CGEN_INSN_UNCOND_CTI), { 0 } } }, + { "bl $disp24", "bl24", "bl", {'b', 'l', ' ', 145, }, 0xff000000, 0xfe000000, 32 } + }, +/* bl.l $disp24 */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_ALIAS)|(1<<CGEN_INSN_UNCOND_CTI), { 0 } } }, + { "bl.l $disp24", "bl24.l", "bl", {'b', 'l', '.', 'l', ' ', 145, }, 0xff000000, 0xfe000000, 32 } + }, +/* bnc $disp8 */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_RELAX_BNC)|(1<<CGEN_INSN_RELAXABLE)|(1<<CGEN_INSN_COND_CTI), { 0 } } }, + { "bnc $disp8", "bnc8", "bnc", {'b', 'n', 'c', ' ', 143, }, 0xff00, 0x7d00, 16 } + }, +/* bnc.s $disp8 */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_ALIAS)|(1<<CGEN_INSN_COND_CTI), { 0 } } }, + { "bnc.s $disp8", "bnc8.s", "bnc", {'b', 'n', 'c', '.', 's', ' ', 143, }, 0xff00, 0x7d00, 16 } + }, +/* bnc $disp24 */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_RELAX_BNC)|(1<<CGEN_INSN_RELAX)|(1<<CGEN_INSN_COND_CTI), { 0 } } }, + { "bnc $disp24", "bnc24", "bnc", {'b', 'n', 'c', ' ', 145, }, 0xff000000, 0xfd000000, 32 } + }, +/* bnc.l $disp24 */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_ALIAS)|(1<<CGEN_INSN_COND_CTI), { 0 } } }, + { "bnc.l $disp24", "bnc24.l", "bnc", {'b', 'n', 'c', '.', 'l', ' ', 145, }, 0xff000000, 0xfd000000, 32 } + }, +/* bne $src1,$src2,$disp16 */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_COND_CTI), { 0 } } }, + { "bne $src1,$src2,$disp16", "bne", "bne", {'b', 'n', 'e', ' ', 130, ',', 131, ',', 144, }, 0xf0f00000, 0xb0100000, 32 } + }, +/* bra $disp8 */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_RELAX_BRA)|(1<<CGEN_INSN_RELAXABLE)|(1<<CGEN_INSN_UNCOND_CTI), { 0 } } }, + { "bra $disp8", "bra8", "bra", {'b', 'r', 'a', ' ', 143, }, 0xff00, 0x7f00, 16 } + }, +/* bra.s $disp8 */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_ALIAS)|(1<<CGEN_INSN_UNCOND_CTI), { 0 } } }, + { "bra.s $disp8", "bra8.s", "bra", {'b', 'r', 'a', '.', 's', ' ', 143, }, 0xff00, 0x7f00, 16 } + }, +/* bra $disp24 */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_RELAX_BRA)|(1<<CGEN_INSN_RELAX)|(1<<CGEN_INSN_UNCOND_CTI), { 0 } } }, + { "bra $disp24", "bra24", "bra", {'b', 'r', 'a', ' ', 145, }, 0xff000000, 0xff000000, 32 } + }, +/* bra.l $disp24 */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_ALIAS)|(1<<CGEN_INSN_UNCOND_CTI), { 0 } } }, + { "bra.l $disp24", "bra24.l", "bra", {'b', 'r', 'a', '.', 'l', ' ', 145, }, 0xff000000, 0xff000000, 32 } + }, +/* cmp $src1,$src2 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "cmp $src1,$src2", "cmp", "cmp", {'c', 'm', 'p', ' ', 130, ',', 131, }, 0xf0f0, 0x40, 16 } + }, +/* cmpi $src2,$simm16 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "cmpi $src2,$simm16", "cmpi", "cmpi", {'c', 'm', 'p', 'i', ' ', 131, ',', 135, }, 0xfff00000, 0x80400000, 32 } + }, +/* cmpu $src1,$src2 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "cmpu $src1,$src2", "cmpu", "cmpu", {'c', 'm', 'p', 'u', ' ', 130, ',', 131, }, 0xf0f0, 0x50, 16 } + }, +/* cmpui $src2,$simm16 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "cmpui $src2,$simm16", "cmpui", "cmpui", {'c', 'm', 'p', 'u', 'i', ' ', 131, ',', 135, }, 0xfff00000, 0x80500000, 32 } + }, +/* div $dr,$sr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "div $dr,$sr", "div", "div", {'d', 'i', 'v', ' ', 129, ',', 128, }, 0xf0f0ffff, 0x90000000, 32 } + }, +/* divu $dr,$sr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "divu $dr,$sr", "divu", "divu", {'d', 'i', 'v', 'u', ' ', 129, ',', 128, }, 0xf0f0ffff, 0x90100000, 32 } + }, +/* rem $dr,$sr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "rem $dr,$sr", "rem", "rem", {'r', 'e', 'm', ' ', 129, ',', 128, }, 0xf0f0ffff, 0x90200000, 32 } + }, +/* remu $dr,$sr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "remu $dr,$sr", "remu", "remu", {'r', 'e', 'm', 'u', ' ', 129, ',', 128, }, 0xf0f0ffff, 0x90300000, 32 } + }, +/* jl $sr */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_FILL_SLOT)|(1<<CGEN_INSN_UNCOND_CTI), { 0 } } }, + { "jl $sr", "jl", "jl", {'j', 'l', ' ', 128, }, 0xfff0, 0x1ec0, 16 } + }, +/* jmp $sr */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_UNCOND_CTI), { 0 } } }, + { "jmp $sr", "jmp", "jmp", {'j', 'm', 'p', ' ', 128, }, 0xfff0, 0x1fc0, 16 } + }, +/* ld $dr,@$sr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "ld $dr,@$sr", "ld", "ld", {'l', 'd', ' ', 129, ',', '@', 128, }, 0xf0f0, 0x20c0, 16 } + }, +/* ld $dr,@($sr) */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_ALIAS), { 0 } } }, + { "ld $dr,@($sr)", "ld-2", "ld", {'l', 'd', ' ', 129, ',', '@', '(', 128, ')', }, 0xf0f0, 0x20c0, 16 } + }, +/* ld $dr,@($slo16,$sr) */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "ld $dr,@($slo16,$sr)", "ld-d", "ld", {'l', 'd', ' ', 129, ',', '@', '(', 140, ',', 128, ')', }, 0xf0f00000, 0xa0c00000, 32 } + }, +/* ld $dr,@($sr,$slo16) */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_ALIAS), { 0 } } }, + { "ld $dr,@($sr,$slo16)", "ld-d2", "ld", {'l', 'd', ' ', 129, ',', '@', '(', 128, ',', 140, ')', }, 0xf0f00000, 0xa0c00000, 32 } + }, +/* ldb $dr,@$sr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "ldb $dr,@$sr", "ldb", "ldb", {'l', 'd', 'b', ' ', 129, ',', '@', 128, }, 0xf0f0, 0x2080, 16 } + }, +/* ldb $dr,@($sr) */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_ALIAS), { 0 } } }, + { "ldb $dr,@($sr)", "ldb-2", "ldb", {'l', 'd', 'b', ' ', 129, ',', '@', '(', 128, ')', }, 0xf0f0, 0x2080, 16 } + }, +/* ldb $dr,@($slo16,$sr) */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "ldb $dr,@($slo16,$sr)", "ldb-d", "ldb", {'l', 'd', 'b', ' ', 129, ',', '@', '(', 140, ',', 128, ')', }, 0xf0f00000, 0xa0800000, 32 } + }, +/* ldb $dr,@($sr,$slo16) */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_ALIAS), { 0 } } }, + { "ldb $dr,@($sr,$slo16)", "ldb-d2", "ldb", {'l', 'd', 'b', ' ', 129, ',', '@', '(', 128, ',', 140, ')', }, 0xf0f00000, 0xa0800000, 32 } + }, +/* ldh $dr,@$sr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "ldh $dr,@$sr", "ldh", "ldh", {'l', 'd', 'h', ' ', 129, ',', '@', 128, }, 0xf0f0, 0x20a0, 16 } + }, +/* ldh $dr,@($sr) */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_ALIAS), { 0 } } }, + { "ldh $dr,@($sr)", "ldh-2", "ldh", {'l', 'd', 'h', ' ', 129, ',', '@', '(', 128, ')', }, 0xf0f0, 0x20a0, 16 } + }, +/* ldh $dr,@($slo16,$sr) */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "ldh $dr,@($slo16,$sr)", "ldh-d", "ldh", {'l', 'd', 'h', ' ', 129, ',', '@', '(', 140, ',', 128, ')', }, 0xf0f00000, 0xa0a00000, 32 } + }, +/* ldh $dr,@($sr,$slo16) */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_ALIAS), { 0 } } }, + { "ldh $dr,@($sr,$slo16)", "ldh-d2", "ldh", {'l', 'd', 'h', ' ', 129, ',', '@', '(', 128, ',', 140, ')', }, 0xf0f00000, 0xa0a00000, 32 } + }, +/* ldub $dr,@$sr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "ldub $dr,@$sr", "ldub", "ldub", {'l', 'd', 'u', 'b', ' ', 129, ',', '@', 128, }, 0xf0f0, 0x2090, 16 } + }, +/* ldub $dr,@($sr) */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_ALIAS), { 0 } } }, + { "ldub $dr,@($sr)", "ldub-2", "ldub", {'l', 'd', 'u', 'b', ' ', 129, ',', '@', '(', 128, ')', }, 0xf0f0, 0x2090, 16 } + }, +/* ldub $dr,@($slo16,$sr) */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "ldub $dr,@($slo16,$sr)", "ldub-d", "ldub", {'l', 'd', 'u', 'b', ' ', 129, ',', '@', '(', 140, ',', 128, ')', }, 0xf0f00000, 0xa0900000, 32 } + }, +/* ldub $dr,@($sr,$slo16) */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_ALIAS), { 0 } } }, + { "ldub $dr,@($sr,$slo16)", "ldub-d2", "ldub", {'l', 'd', 'u', 'b', ' ', 129, ',', '@', '(', 128, ',', 140, ')', }, 0xf0f00000, 0xa0900000, 32 } + }, +/* lduh $dr,@$sr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "lduh $dr,@$sr", "lduh", "lduh", {'l', 'd', 'u', 'h', ' ', 129, ',', '@', 128, }, 0xf0f0, 0x20b0, 16 } + }, +/* lduh $dr,@($sr) */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_ALIAS), { 0 } } }, + { "lduh $dr,@($sr)", "lduh-2", "lduh", {'l', 'd', 'u', 'h', ' ', 129, ',', '@', '(', 128, ')', }, 0xf0f0, 0x20b0, 16 } + }, +/* lduh $dr,@($slo16,$sr) */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "lduh $dr,@($slo16,$sr)", "lduh-d", "lduh", {'l', 'd', 'u', 'h', ' ', 129, ',', '@', '(', 140, ',', 128, ')', }, 0xf0f00000, 0xa0b00000, 32 } + }, +/* lduh $dr,@($sr,$slo16) */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_ALIAS), { 0 } } }, + { "lduh $dr,@($sr,$slo16)", "lduh-d2", "lduh", {'l', 'd', 'u', 'h', ' ', 129, ',', '@', '(', 128, ',', 140, ')', }, 0xf0f00000, 0xa0b00000, 32 } + }, +/* ld $dr,@$sr+ */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "ld $dr,@$sr+", "ld-plus", "ld", {'l', 'd', ' ', 129, ',', '@', 128, '+', }, 0xf0f0, 0x20e0, 16 } + }, +/* ld24 $dr,$uimm24 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "ld24 $dr,$uimm24", "ld24", "ld24", {'l', 'd', '2', '4', ' ', 129, ',', 142, }, 0xf0000000, 0xe0000000, 32 } + }, +/* ldi $dr,$simm8 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "ldi $dr,$simm8", "ldi8", "ldi", {'l', 'd', 'i', ' ', 129, ',', 134, }, 0xf000, 0x6000, 16 } + }, +/* ldi8 $dr,$simm8 */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_ALIAS), { 0 } } }, + { "ldi8 $dr,$simm8", "ldi8a", "ldi8", {'l', 'd', 'i', '8', ' ', 129, ',', 134, }, 0xf000, 0x6000, 16 } + }, +/* ldi $dr,$slo16 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "ldi $dr,$slo16", "ldi16", "ldi", {'l', 'd', 'i', ' ', 129, ',', 140, }, 0xf0ff0000, 0x90f00000, 32 } + }, +/* ldi16 $dr,$slo16 */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_ALIAS), { 0 } } }, + { "ldi16 $dr,$slo16", "ldi16a", "ldi16", {'l', 'd', 'i', '1', '6', ' ', 129, ',', 140, }, 0xf0ff0000, 0x90f00000, 32 } + }, +/* lock $dr,@$sr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "lock $dr,@$sr", "lock", "lock", {'l', 'o', 'c', 'k', ' ', 129, ',', '@', 128, }, 0xf0f0, 0x20d0, 16 } + }, +/* machi $src1,$src2 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "machi $src1,$src2", "machi", "machi", {'m', 'a', 'c', 'h', 'i', ' ', 130, ',', 131, }, 0xf0f0, 0x3040, 16 } + }, +/* maclo $src1,$src2 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "maclo $src1,$src2", "maclo", "maclo", {'m', 'a', 'c', 'l', 'o', ' ', 130, ',', 131, }, 0xf0f0, 0x3050, 16 } + }, +/* macwhi $src1,$src2 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "macwhi $src1,$src2", "macwhi", "macwhi", {'m', 'a', 'c', 'w', 'h', 'i', ' ', 130, ',', 131, }, 0xf0f0, 0x3060, 16 } + }, +/* macwlo $src1,$src2 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "macwlo $src1,$src2", "macwlo", "macwlo", {'m', 'a', 'c', 'w', 'l', 'o', ' ', 130, ',', 131, }, 0xf0f0, 0x3070, 16 } + }, +/* mul $dr,$sr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "mul $dr,$sr", "mul", "mul", {'m', 'u', 'l', ' ', 129, ',', 128, }, 0xf0f0, 0x1060, 16 } + }, +/* mulhi $src1,$src2 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "mulhi $src1,$src2", "mulhi", "mulhi", {'m', 'u', 'l', 'h', 'i', ' ', 130, ',', 131, }, 0xf0f0, 0x3000, 16 } + }, +/* mullo $src1,$src2 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "mullo $src1,$src2", "mullo", "mullo", {'m', 'u', 'l', 'l', 'o', ' ', 130, ',', 131, }, 0xf0f0, 0x3010, 16 } + }, +/* mulwhi $src1,$src2 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "mulwhi $src1,$src2", "mulwhi", "mulwhi", {'m', 'u', 'l', 'w', 'h', 'i', ' ', 130, ',', 131, }, 0xf0f0, 0x3020, 16 } + }, +/* mulwlo $src1,$src2 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "mulwlo $src1,$src2", "mulwlo", "mulwlo", {'m', 'u', 'l', 'w', 'l', 'o', ' ', 130, ',', 131, }, 0xf0f0, 0x3030, 16 } + }, +/* mv $dr,$sr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "mv $dr,$sr", "mv", "mv", {'m', 'v', ' ', 129, ',', 128, }, 0xf0f0, 0x1080, 16 } + }, +/* mvfachi $dr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "mvfachi $dr", "mvfachi", "mvfachi", {'m', 'v', 'f', 'a', 'c', 'h', 'i', ' ', 129, }, 0xf0ff, 0x50f0, 16 } + }, +/* mvfaclo $dr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "mvfaclo $dr", "mvfaclo", "mvfaclo", {'m', 'v', 'f', 'a', 'c', 'l', 'o', ' ', 129, }, 0xf0ff, 0x50f1, 16 } + }, +/* mvfacmi $dr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "mvfacmi $dr", "mvfacmi", "mvfacmi", {'m', 'v', 'f', 'a', 'c', 'm', 'i', ' ', 129, }, 0xf0ff, 0x50f2, 16 } + }, +/* mvfc $dr,$scr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "mvfc $dr,$scr", "mvfc", "mvfc", {'m', 'v', 'f', 'c', ' ', 129, ',', 132, }, 0xf0f0, 0x1090, 16 } + }, +/* mvtachi $src1 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "mvtachi $src1", "mvtachi", "mvtachi", {'m', 'v', 't', 'a', 'c', 'h', 'i', ' ', 130, }, 0xf0ff, 0x5070, 16 } + }, +/* mvtaclo $src1 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "mvtaclo $src1", "mvtaclo", "mvtaclo", {'m', 'v', 't', 'a', 'c', 'l', 'o', ' ', 130, }, 0xf0ff, 0x5071, 16 } + }, +/* mvtc $sr,$dcr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "mvtc $sr,$dcr", "mvtc", "mvtc", {'m', 'v', 't', 'c', ' ', 128, ',', 133, }, 0xf0f0, 0x10a0, 16 } + }, +/* neg $dr,$sr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "neg $dr,$sr", "neg", "neg", {'n', 'e', 'g', ' ', 129, ',', 128, }, 0xf0f0, 0x30, 16 } + }, +/* nop */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "nop", "nop", "nop", {'n', 'o', 'p', }, 0xffff, 0x7000, 16 } + }, +/* not $dr,$sr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "not $dr,$sr", "not", "not", {'n', 'o', 't', ' ', 129, ',', 128, }, 0xf0f0, 0xb0, 16 } + }, +/* rac */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "rac", "rac", "rac", {'r', 'a', 'c', }, 0xffff, 0x5090, 16 } + }, +/* rach */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "rach", "rach", "rach", {'r', 'a', 'c', 'h', }, 0xffff, 0x5080, 16 } + }, +/* rte */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_UNCOND_CTI), { 0 } } }, + { "rte", "rte", "rte", {'r', 't', 'e', }, 0xffff, 0x10d6, 16 } + }, +/* seth $dr,$hi16 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "seth $dr,$hi16", "seth", "seth", {'s', 'e', 't', 'h', ' ', 129, ',', 139, }, 0xf0ff0000, 0xd0c00000, 32 } + }, +/* sll $dr,$sr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "sll $dr,$sr", "sll", "sll", {'s', 'l', 'l', ' ', 129, ',', 128, }, 0xf0f0, 0x1040, 16 } + }, +/* sll3 $dr,$sr,$simm16 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "sll3 $dr,$sr,$simm16", "sll3", "sll3", {'s', 'l', 'l', '3', ' ', 129, ',', 128, ',', 135, }, 0xf0f00000, 0x90c00000, 32 } + }, +/* slli $dr,$uimm5 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "slli $dr,$uimm5", "slli", "slli", {'s', 'l', 'l', 'i', ' ', 129, ',', 137, }, 0xf0e0, 0x5040, 16 } + }, +/* sra $dr,$sr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "sra $dr,$sr", "sra", "sra", {'s', 'r', 'a', ' ', 129, ',', 128, }, 0xf0f0, 0x1020, 16 } + }, +/* sra3 $dr,$sr,$simm16 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "sra3 $dr,$sr,$simm16", "sra3", "sra3", {'s', 'r', 'a', '3', ' ', 129, ',', 128, ',', 135, }, 0xf0f00000, 0x90a00000, 32 } + }, +/* srai $dr,$uimm5 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "srai $dr,$uimm5", "srai", "srai", {'s', 'r', 'a', 'i', ' ', 129, ',', 137, }, 0xf0e0, 0x5020, 16 } + }, +/* srl $dr,$sr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "srl $dr,$sr", "srl", "srl", {'s', 'r', 'l', ' ', 129, ',', 128, }, 0xf0f0, 0x1000, 16 } + }, +/* srl3 $dr,$sr,$simm16 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "srl3 $dr,$sr,$simm16", "srl3", "srl3", {'s', 'r', 'l', '3', ' ', 129, ',', 128, ',', 135, }, 0xf0f00000, 0x90800000, 32 } + }, +/* srli $dr,$uimm5 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "srli $dr,$uimm5", "srli", "srli", {'s', 'r', 'l', 'i', ' ', 129, ',', 137, }, 0xf0e0, 0x5000, 16 } + }, +/* st $src1,@$src2 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "st $src1,@$src2", "st", "st", {'s', 't', ' ', 130, ',', '@', 131, }, 0xf0f0, 0x2040, 16 } + }, +/* st $src1,@($src2) */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_ALIAS), { 0 } } }, + { "st $src1,@($src2)", "st-2", "st", {'s', 't', ' ', 130, ',', '@', '(', 131, ')', }, 0xf0f0, 0x2040, 16 } + }, +/* st $src1,@($slo16,$src2) */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "st $src1,@($slo16,$src2)", "st-d", "st", {'s', 't', ' ', 130, ',', '@', '(', 140, ',', 131, ')', }, 0xf0f00000, 0xa0400000, 32 } + }, +/* st $src1,@($src2,$slo16) */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_ALIAS), { 0 } } }, + { "st $src1,@($src2,$slo16)", "st-d2", "st", {'s', 't', ' ', 130, ',', '@', '(', 131, ',', 140, ')', }, 0xf0f00000, 0xa0400000, 32 } + }, +/* stb $src1,@$src2 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "stb $src1,@$src2", "stb", "stb", {'s', 't', 'b', ' ', 130, ',', '@', 131, }, 0xf0f0, 0x2000, 16 } + }, +/* stb $src1,@($src2) */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_ALIAS), { 0 } } }, + { "stb $src1,@($src2)", "stb-2", "stb", {'s', 't', 'b', ' ', 130, ',', '@', '(', 131, ')', }, 0xf0f0, 0x2000, 16 } + }, +/* stb $src1,@($slo16,$src2) */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "stb $src1,@($slo16,$src2)", "stb-d", "stb", {'s', 't', 'b', ' ', 130, ',', '@', '(', 140, ',', 131, ')', }, 0xf0f00000, 0xa0000000, 32 } + }, +/* stb $src1,@($src2,$slo16) */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_ALIAS), { 0 } } }, + { "stb $src1,@($src2,$slo16)", "stb-d2", "stb", {'s', 't', 'b', ' ', 130, ',', '@', '(', 131, ',', 140, ')', }, 0xf0f00000, 0xa0000000, 32 } + }, +/* sth $src1,@$src2 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "sth $src1,@$src2", "sth", "sth", {'s', 't', 'h', ' ', 130, ',', '@', 131, }, 0xf0f0, 0x2020, 16 } + }, +/* sth $src1,@($src2) */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_ALIAS), { 0 } } }, + { "sth $src1,@($src2)", "sth-2", "sth", {'s', 't', 'h', ' ', 130, ',', '@', '(', 131, ')', }, 0xf0f0, 0x2020, 16 } + }, +/* sth $src1,@($slo16,$src2) */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "sth $src1,@($slo16,$src2)", "sth-d", "sth", {'s', 't', 'h', ' ', 130, ',', '@', '(', 140, ',', 131, ')', }, 0xf0f00000, 0xa0200000, 32 } + }, +/* sth $src1,@($src2,$slo16) */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_ALIAS), { 0 } } }, + { "sth $src1,@($src2,$slo16)", "sth-d2", "sth", {'s', 't', 'h', ' ', 130, ',', '@', '(', 131, ',', 140, ')', }, 0xf0f00000, 0xa0200000, 32 } + }, +/* st $src1,@+$src2 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "st $src1,@+$src2", "st-plus", "st", {'s', 't', ' ', 130, ',', '@', '+', 131, }, 0xf0f0, 0x2060, 16 } + }, +/* st $src1,@-$src2 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "st $src1,@-$src2", "st-minus", "st", {'s', 't', ' ', 130, ',', '@', '-', 131, }, 0xf0f0, 0x2070, 16 } + }, +/* sub $dr,$sr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "sub $dr,$sr", "sub", "sub", {'s', 'u', 'b', ' ', 129, ',', 128, }, 0xf0f0, 0x20, 16 } + }, +/* subv $dr,$sr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "subv $dr,$sr", "subv", "subv", {'s', 'u', 'b', 'v', ' ', 129, ',', 128, }, 0xf0f0, 0x0, 16 } + }, +/* subx $dr,$sr */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "subx $dr,$sr", "subx", "subx", {'s', 'u', 'b', 'x', ' ', 129, ',', 128, }, 0xf0f0, 0x10, 16 } + }, +/* trap $uimm4 */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_FILL_SLOT)|(1<<CGEN_INSN_UNCOND_CTI), { 0 } } }, + { "trap $uimm4", "trap", "trap", {'t', 'r', 'a', 'p', ' ', 136, }, 0xfff0, 0x10f0, 16 } + }, +/* unlock $src1,@$src2 */ + { + { 1, 1, 1, 1, { 0, 0, { 0 } } }, + { "unlock $src1,@$src2", "unlock", "unlock", {'u', 'n', 'l', 'o', 'c', 'k', ' ', 130, ',', '@', 131, }, 0xf0f0, 0x2050, 16 } + }, +/* push $src1 */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_ALIAS), { 0 } } }, + { "push $src1", "push", "push", {'p', 'u', 's', 'h', ' ', 130, }, 0xf0ff, 0x207f, 16 } + }, +/* pop $dr */ + { + { 1, 1, 1, 1, { 0, 0|(1<<CGEN_INSN_ALIAS), { 0 } } }, + { "pop $dr", "pop", "pop", {'p', 'o', 'p', ' ', 129, }, 0xf0ff, 0x20ef, 16 } + }, +}; + +CGEN_INSN_TABLE m32r_cgen_insn_table = { + & m32r_cgen_insn_table_entries[0], + CGEN_NUM_INSNS, + NULL, + m32r_cgen_asm_hash_insn, CGEN_ASM_HASH_SIZE, + m32r_cgen_dis_hash_insn, CGEN_DIS_HASH_SIZE +}; + +/* The hash functions are recorded here to help keep assembler code out of + the disassembler and vice versa. */ + +unsigned int +m32r_cgen_asm_hash_insn (insn) + const char *insn; +{ + return CGEN_ASM_HASH (insn); +} + +unsigned int +m32r_cgen_dis_hash_insn (buf, value) + const char *buf; + unsigned long value; +{ + return CGEN_DIS_HASH (buf, value); +} + +CGEN_OPCODE_DATA m32r_cgen_opcode_data = { + & m32r_cgen_hw_entries[0], + & m32r_cgen_insn_table, +}; + +void +m32r_cgen_init_tables (mach) + int mach; +{ +} + +/* Main entry point for stuffing values in cgen_fields. */ + +CGEN_INLINE void +m32r_cgen_set_operand (opindex, valuep, fields) + int opindex; + const long *valuep; + struct cgen_fields *fields; +{ + switch (opindex) + { + case 0 : + fields->f_r2 = *valuep; + break; + case 1 : + fields->f_r1 = *valuep; + break; + case 2 : + fields->f_r1 = *valuep; + break; + case 3 : + fields->f_r2 = *valuep; + break; + case 4 : + fields->f_r2 = *valuep; + break; + case 5 : + fields->f_r1 = *valuep; + break; + case 6 : + fields->f_simm8 = *valuep; + break; + case 7 : + fields->f_simm16 = *valuep; + break; + case 8 : + fields->f_uimm4 = *valuep; + break; + case 9 : + fields->f_uimm5 = *valuep; + break; + case 10 : + fields->f_uimm16 = *valuep; + break; + case 11 : + fields->f_hi16 = *valuep; + break; + case 12 : + fields->f_simm16 = *valuep; + break; + case 13 : + fields->f_uimm16 = *valuep; + break; + case 14 : + fields->f_uimm24 = *valuep; + break; + case 15 : + fields->f_disp8 = *valuep; + break; + case 16 : + fields->f_disp16 = *valuep; + break; + case 17 : + fields->f_disp24 = *valuep; + break; + + default : + fprintf (stderr, "Unrecognized field %d while setting operand.\n", + opindex); + abort (); + } +} + +/* Main entry point for getting values from cgen_fields. */ + +CGEN_INLINE long +m32r_cgen_get_operand (opindex, fields) + int opindex; + const struct cgen_fields *fields; +{ + long value; + + switch (opindex) + { + case 0 : + value = fields->f_r2; + break; + case 1 : + value = fields->f_r1; + break; + case 2 : + value = fields->f_r1; + break; + case 3 : + value = fields->f_r2; + break; + case 4 : + value = fields->f_r2; + break; + case 5 : + value = fields->f_r1; + break; + case 6 : + value = fields->f_simm8; + break; + case 7 : + value = fields->f_simm16; + break; + case 8 : + value = fields->f_uimm4; + break; + case 9 : + value = fields->f_uimm5; + break; + case 10 : + value = fields->f_uimm16; + break; + case 11 : + value = fields->f_hi16; + break; + case 12 : + value = fields->f_simm16; + break; + case 13 : + value = fields->f_uimm16; + break; + case 14 : + value = fields->f_uimm24; + break; + case 15 : + value = fields->f_disp8; + break; + case 16 : + value = fields->f_disp16; + break; + case 17 : + value = fields->f_disp24; + break; + + default : + fprintf (stderr, "Unrecognized field %d while getting operand.\n", + opindex); + abort (); + } + + return value; +} + diff --git a/gnu/usr.bin/binutils/opcodes/m32r-opc.h b/gnu/usr.bin/binutils/opcodes/m32r-opc.h new file mode 100644 index 00000000000..5843ec2922d --- /dev/null +++ b/gnu/usr.bin/binutils/opcodes/m32r-opc.h @@ -0,0 +1,198 @@ +/* Instruction description for m32r. + +This file is machine generated. + +Copyright (C) 1996, 1997 Free Software Foundation, Inc. + +This file is part of the GNU Binutils and/or GDB, the GNU debugger. + +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 2, 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., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifndef m32r_OPC_H +#define m32r_OPC_H + +#define CGEN_CPU m32r +/* Given symbol S, return m32r_cgen_<s>. */ +#define CGEN_SYM(s) CGEN_CAT3 (m32r,_cgen_,s) + +#define CGEN_WORD_BITSIZE 32 +#define CGEN_DEFAULT_INSN_BITSIZE 32 +#define CGEN_BASE_INSN_BITSIZE 32 +#define CGEN_MAX_INSN_BITSIZE 32 +#define CGEN_DEFAULT_INSN_SIZE (CGEN_DEFAULT_INSN_BITSIZE / 8) +#define CGEN_BASE_INSN_SIZE (CGEN_BASE_INSN_BITSIZE / 8) +#define CGEN_MAX_INSN_SIZE (CGEN_MAX_INSN_BITSIZE / 8) +#define CGEN_INT_INSN + +/* +1 because the first entry is reserved (null) */ +#define CGEN_NUM_INSNS (127 + 1) +#define CGEN_NUM_OPERANDS (18) + +/* Number of non-boolean attributes. */ +#define CGEN_MAX_INSN_ATTRS 0 +#define CGEN_MAX_OPERAND_ATTRS 0 + +/* FIXME: Need to compute CGEN_MAX_SYNTAX_BYTES. */ + +/* CGEN_MNEMONIC_OPERANDS is defined if mnemonics have operands. */ +#define CGEN_MNEMONIC_OPERANDS + +/* Enum declaration for machine types. */ +typedef enum mach_type { + MACH_M32R, MACH_TEST, MACH_MAX +} MACH_TYPE; + +#define MAX_MACHS ((int) MACH_MAX) + +/* Enum declaration for insn format enums. */ +typedef enum insn_op1 { + INSN_OP1_OP1_0 = 0, INSN_OP1_OP1_1 = 1, INSN_OP1_OP1_2 = 2, INSN_OP1_OP1_3 = 3, + INSN_OP1_OP1_4 = 4, INSN_OP1_OP1_5 = 5, INSN_OP1_OP1_6 = 6, INSN_OP1_OP1_7 = 7, + INSN_OP1_OP1_8 = 8, INSN_OP1_OP1_9 = 9, INSN_OP1_OP1_10 = 10, INSN_OP1_OP1_11 = 11, + INSN_OP1_OP1_12 = 12, INSN_OP1_OP1_13 = 13, INSN_OP1_OP1_14 = 14, INSN_OP1_OP1_15 = 15 +} INSN_OP1; + +/* Enum declaration for op2 enums. */ +typedef enum insn_op2 { + INSN_OP2_OP2_0 = 0, INSN_OP2_OP2_1 = 1, INSN_OP2_OP2_2 = 2, INSN_OP2_OP2_3 = 3, + INSN_OP2_OP2_4 = 4, INSN_OP2_OP2_5 = 5, INSN_OP2_OP2_6 = 6, INSN_OP2_OP2_7 = 7, + INSN_OP2_OP2_8 = 8, INSN_OP2_OP2_9 = 9, INSN_OP2_OP2_10 = 10, INSN_OP2_OP2_11 = 11, + INSN_OP2_OP2_12 = 12, INSN_OP2_OP2_13 = 13, INSN_OP2_OP2_14 = 14, INSN_OP2_OP2_15 = 15 +} INSN_OP2; + +/* Enum declaration for cgen_operand attrs. */ +typedef enum cgen_operand_attr { + CGEN_OPERAND_ABS_ADDR, CGEN_OPERAND_FAKE, CGEN_OPERAND_NEGATIVE, CGEN_OPERAND_PCREL_ADDR, + CGEN_OPERAND_RELAX, CGEN_OPERAND_RELOC, CGEN_OPERAND_SIGN_OPT, CGEN_OPERAND_UNSIGNED +} CGEN_OPERAND_ATTR; + +/* Enum declaration for cgen_insn attrs. */ +typedef enum cgen_insn_attr { + CGEN_INSN_ALIAS, CGEN_INSN_COND_CTI, CGEN_INSN_FILL_SLOT, CGEN_INSN_RELAX, + CGEN_INSN_RELAX_BC, CGEN_INSN_RELAX_BL, CGEN_INSN_RELAX_BNC, CGEN_INSN_RELAX_BRA, + CGEN_INSN_RELAXABLE, CGEN_INSN_UNCOND_CTI +} CGEN_INSN_ATTR; + +/* Enum declaration for m32r operand types. */ +typedef enum cgen_operand_type { + M32R_OPERAND_SR, M32R_OPERAND_DR, M32R_OPERAND_SRC1, M32R_OPERAND_SRC2, + M32R_OPERAND_SCR, M32R_OPERAND_DCR, M32R_OPERAND_SIMM8, M32R_OPERAND_SIMM16, + M32R_OPERAND_UIMM4, M32R_OPERAND_UIMM5, M32R_OPERAND_UIMM16, M32R_OPERAND_HI16, + M32R_OPERAND_SLO16, M32R_OPERAND_ULO16, M32R_OPERAND_UIMM24, M32R_OPERAND_DISP8, + M32R_OPERAND_DISP16, M32R_OPERAND_DISP24 +} CGEN_OPERAND_TYPE; + +/* Insn types are used by the simulator. */ +/* Enum declaration for m32r instruction types. */ +typedef enum cgen_insn_type { + M32R_INSN_ILLEGAL, M32R_INSN_ADD, M32R_INSN_ADD3, M32R_INSN_AND, + M32R_INSN_AND3, M32R_INSN_OR, M32R_INSN_OR3, M32R_INSN_XOR, + M32R_INSN_XOR3, M32R_INSN_ADDI, M32R_INSN_ADDV, M32R_INSN_ADDV3, + M32R_INSN_ADDX, M32R_INSN_BC8, M32R_INSN_BC8_S, M32R_INSN_BC24, + M32R_INSN_BC24_L, M32R_INSN_BEQ, M32R_INSN_BEQZ, M32R_INSN_BGEZ, + M32R_INSN_BGTZ, M32R_INSN_BLEZ, M32R_INSN_BLTZ, M32R_INSN_BNEZ, + M32R_INSN_BL8, M32R_INSN_BL8_S, M32R_INSN_BL24, M32R_INSN_BL24_L, + M32R_INSN_BNC8, M32R_INSN_BNC8_S, M32R_INSN_BNC24, M32R_INSN_BNC24_L, + M32R_INSN_BNE, M32R_INSN_BRA8, M32R_INSN_BRA8_S, M32R_INSN_BRA24, + M32R_INSN_BRA24_L, M32R_INSN_CMP, M32R_INSN_CMPI, M32R_INSN_CMPU, + M32R_INSN_CMPUI, M32R_INSN_DIV, M32R_INSN_DIVU, M32R_INSN_REM, + M32R_INSN_REMU, M32R_INSN_JL, M32R_INSN_JMP, M32R_INSN_LD, + M32R_INSN_LD_2, M32R_INSN_LD_D, M32R_INSN_LD_D2, M32R_INSN_LDB, + M32R_INSN_LDB_2, M32R_INSN_LDB_D, M32R_INSN_LDB_D2, M32R_INSN_LDH, + M32R_INSN_LDH_2, M32R_INSN_LDH_D, M32R_INSN_LDH_D2, M32R_INSN_LDUB, + M32R_INSN_LDUB_2, M32R_INSN_LDUB_D, M32R_INSN_LDUB_D2, M32R_INSN_LDUH, + M32R_INSN_LDUH_2, M32R_INSN_LDUH_D, M32R_INSN_LDUH_D2, M32R_INSN_LD_PLUS, + M32R_INSN_LD24, M32R_INSN_LDI8, M32R_INSN_LDI8A, M32R_INSN_LDI16, + M32R_INSN_LDI16A, M32R_INSN_LOCK, M32R_INSN_MACHI, M32R_INSN_MACLO, + M32R_INSN_MACWHI, M32R_INSN_MACWLO, M32R_INSN_MUL, M32R_INSN_MULHI, + M32R_INSN_MULLO, M32R_INSN_MULWHI, M32R_INSN_MULWLO, M32R_INSN_MV, + M32R_INSN_MVFACHI, M32R_INSN_MVFACLO, M32R_INSN_MVFACMI, M32R_INSN_MVFC, + M32R_INSN_MVTACHI, M32R_INSN_MVTACLO, M32R_INSN_MVTC, M32R_INSN_NEG, + M32R_INSN_NOP, M32R_INSN_NOT, M32R_INSN_RAC, M32R_INSN_RACH, + M32R_INSN_RTE, M32R_INSN_SETH, M32R_INSN_SLL, M32R_INSN_SLL3, + M32R_INSN_SLLI, M32R_INSN_SRA, M32R_INSN_SRA3, M32R_INSN_SRAI, + M32R_INSN_SRL, M32R_INSN_SRL3, M32R_INSN_SRLI, M32R_INSN_ST, + M32R_INSN_ST_2, M32R_INSN_ST_D, M32R_INSN_ST_D2, M32R_INSN_STB, + M32R_INSN_STB_2, M32R_INSN_STB_D, M32R_INSN_STB_D2, M32R_INSN_STH, + M32R_INSN_STH_2, M32R_INSN_STH_D, M32R_INSN_STH_D2, M32R_INSN_ST_PLUS, + M32R_INSN_ST_MINUS, M32R_INSN_SUB, M32R_INSN_SUBV, M32R_INSN_SUBX, + M32R_INSN_TRAP, M32R_INSN_UNLOCK, M32R_INSN_PUSH, M32R_INSN_POP, + M32R_INSN_MAX +} CGEN_INSN_TYPE; + +/* Index of `illegal' insn place holder. */ +#define CGEN_INSN_ILLEGAL M32R_INSN_ILLEGAL +/* Total number of insns in table. */ +#define CGEN_MAX_INSNS ((int) M32R_INSN_MAX) + +/* cgen.h uses things we just defined. */ +#include "opcode/cgen.h" + +/* This struct records data prior to insertion or after extraction. */ +struct cgen_fields { + long f_op1; + long f_op2; + long f_cond; + long f_r1; + long f_r2; + long f_simm8; + long f_simm16; + long f_shift_op2; + long f_uimm4; + long f_uimm5; + long f_uimm16; + long f_uimm24; + long f_hi16; + long f_disp8; + long f_disp16; + long f_disp24; + int length; +}; + +extern struct cgen_keyword m32r_cgen_opval_mach; +extern struct cgen_keyword m32r_cgen_opval_h_gr; +extern struct cgen_keyword m32r_cgen_opval_h_cr; + +#define CGEN_INIT_PARSE() \ +{\ +} +#define CGEN_INIT_INSERT() \ +{\ +} +#define CGEN_INIT_EXTRACT() \ +{\ +} +#define CGEN_INIT_PRINT() \ +{\ +} + +/* -- opc.h */ + +#undef CGEN_DIS_HASH_SIZE +#define CGEN_DIS_HASH_SIZE 256 +#undef CGEN_DIS_HASH +#define X(b) (((unsigned char *) (b))[0] & 0xf0) +#define CGEN_DIS_HASH(buffer, insn) \ +(X (buffer) | \ + (X (buffer) == 0x40 || X (buffer) == 0xe0 || X (buffer) == 0x60 || X (buffer) == 0x50 ? 0 \ + : X (buffer) == 0x70 || X (buffer) == 0xf0 ? (((unsigned char *) (buffer))[0] & 0xf) \ + : ((((unsigned char *) (buffer))[1] & 0xf0) >> 4))) + +/* -- */ + + +#endif /* m32r_OPC_H */ diff --git a/gnu/usr.bin/binutils/opcodes/makefile.vms b/gnu/usr.bin/binutils/opcodes/makefile.vms index 160319d5ce8..dbf8e0b9f76 100644 --- a/gnu/usr.bin/binutils/opcodes/makefile.vms +++ b/gnu/usr.bin/binutils/opcodes/makefile.vms @@ -1,13 +1,11 @@ # -# Makefile for libopcodes under openVMS/AXP +# Makefile for libopcodes under openVMS/Alpha # # For use with gnu-make for vms # -# Created by Klaus Kaempf, kkaempf@progis.de +# Created by Klaus K"ampf, kkaempf@progis.de # # -CC=gcc - OBJS=alpha-dis.obj,alpha-opc.obj,dis-buf.obj,disassemble.obj ifeq ($(CC),gcc) @@ -29,3 +27,9 @@ alpha-dis.obj: alpha-dis.c sysdep.h: [-.bfd.hosts]alphavms.h $(CP) $< $@ + +clean: + $$ purge + $(RM) *.obj; + $(RM) sysdep.h; + $(RM) libopcodes.olb; diff --git a/gnu/usr.bin/binutils/opcodes/mips16-opc.c b/gnu/usr.bin/binutils/opcodes/mips16-opc.c new file mode 100644 index 00000000000..dc7a9c3094a --- /dev/null +++ b/gnu/usr.bin/binutils/opcodes/mips16-opc.c @@ -0,0 +1,223 @@ +/* mips16-opc.c. Mips16 opcode table. + Copyright 1996, 1997 Free Software Foundation, Inc. + Contributed by Ian Lance Taylor, Cygnus Support + +This file is part of GDB, GAS, and the GNU binutils. + +GDB, GAS, and the GNU binutils are free software; you can redistribute +them and/or modify them under the terms of the GNU General Public +License as published by the Free Software Foundation; either version +1, or (at your option) any later version. + +GDB, GAS, and the GNU binutils are distributed in the hope that they +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 file; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. */ + +#include <stdio.h> +#include "ansidecl.h" +#include "opcode/mips.h" + +/* This is the opcodes table for the mips16 processor. The format of + this table is intentionally identical to the one in mips-opc.c. + However, the special letters that appear in the argument string are + different, and the table uses some different flags. */ + +/* Use some short hand macros to keep down the length of the lines in + the opcodes table. */ + +#define UBD INSN_UNCOND_BRANCH_DELAY + +#define WR_x MIPS16_INSN_WRITE_X +#define WR_y MIPS16_INSN_WRITE_Y +#define WR_z MIPS16_INSN_WRITE_Z +#define WR_T MIPS16_INSN_WRITE_T +#define WR_SP MIPS16_INSN_WRITE_SP +#define WR_31 MIPS16_INSN_WRITE_31 +#define WR_Y MIPS16_INSN_WRITE_GPR_Y + +#define RD_x MIPS16_INSN_READ_X +#define RD_y MIPS16_INSN_READ_Y +#define RD_Z MIPS16_INSN_READ_Z +#define RD_T MIPS16_INSN_READ_T +#define RD_SP MIPS16_INSN_READ_SP +#define RD_31 MIPS16_INSN_READ_31 +#define RD_PC MIPS16_INSN_READ_PC +#define RD_X MIPS16_INSN_READ_GPR_X + +#define WR_HI INSN_WRITE_HI +#define WR_LO INSN_WRITE_LO +#define RD_HI INSN_READ_HI +#define RD_LO INSN_READ_LO + +#define TRAP INSN_TRAP + +#define I3 INSN_ISA3 + +const struct mips_opcode mips16_opcodes[] = { +{"nop", "", 0x6500, 0xffff, RD_Z }, /* move $0,$Z */ +{"la", "x,A", 0x0800, 0xf800, WR_x|RD_PC }, +{"abs", "x,w", 0, (int) M_ABS, INSN_MACRO }, +{"addiu", "y,x,4", 0x4000, 0xf810, WR_y|RD_x }, +{"addiu", "x,k", 0x4800, 0xf800, WR_x|RD_x }, +{"addiu", "S,K", 0x6300, 0xff00, WR_SP|RD_SP }, +{"addiu", "S,S,K", 0x6300, 0xff00, WR_SP|RD_SP }, +{"addiu", "x,P,V", 0x0800, 0xf800, WR_x|RD_PC }, +{"addiu", "x,S,V", 0x0000, 0xf800, WR_x|RD_SP }, +{"addu", "z,v,y", 0xe001, 0xf803, WR_z|RD_x|RD_y }, +{"addu", "y,x,4", 0x4000, 0xf810, WR_y|RD_x }, +{"addu", "x,k", 0x4800, 0xf800, WR_x|RD_x }, +{"addu", "S,K", 0x6300, 0xff00, WR_SP|RD_SP }, +{"addu", "S,S,K", 0x6300, 0xff00, WR_SP|RD_SP }, +{"addu", "x,P,V", 0x0800, 0xf800, WR_x|RD_PC }, +{"addu", "x,S,V", 0x0000, 0xf800, WR_x|RD_SP }, +{"and", "x,y", 0xe80c, 0xf81f, WR_x|RD_x|RD_y }, +{"b", "q", 0x1000, 0xf800, 0 }, +{"beq", "x,y,p", 0, (int) M_BEQ, INSN_MACRO }, +{"beq", "x,U,p", 0, (int) M_BEQ_I, INSN_MACRO }, +{"beqz", "x,p", 0x2000, 0xf800, RD_x }, +{"bge", "x,y,p", 0, (int) M_BGE, INSN_MACRO }, +{"bge", "x,8,p", 0, (int) M_BGE_I, INSN_MACRO }, +{"bgeu", "x,y,p", 0, (int) M_BGEU, INSN_MACRO }, +{"bgeu", "x,8,p", 0, (int) M_BGEU_I, INSN_MACRO }, +{"bgt", "x,y,p", 0, (int) M_BGT, INSN_MACRO }, +{"bgt", "x,8,p", 0, (int) M_BGT_I, INSN_MACRO }, +{"bgtu", "x,y,p", 0, (int) M_BGTU, INSN_MACRO }, +{"bgtu", "x,8,p", 0, (int) M_BGTU_I, INSN_MACRO }, +{"ble", "x,y,p", 0, (int) M_BLE, INSN_MACRO }, +{"ble", "x,8,p", 0, (int) M_BLE_I, INSN_MACRO }, +{"bleu", "x,y,p", 0, (int) M_BLEU, INSN_MACRO }, +{"bleu", "x,8,p", 0, (int) M_BLEU_I, INSN_MACRO }, +{"blt", "x,y,p", 0, (int) M_BLT, INSN_MACRO }, +{"blt", "x,8,p", 0, (int) M_BLT_I, INSN_MACRO }, +{"bltu", "x,y,p", 0, (int) M_BLTU, INSN_MACRO }, +{"bltu", "x,8,p", 0, (int) M_BLTU_I, INSN_MACRO }, +{"bne", "x,y,p", 0, (int) M_BNE, INSN_MACRO }, +{"bne", "x,U,p", 0, (int) M_BNE_I, INSN_MACRO }, +{"bnez", "x,p", 0x2800, 0xf800, RD_x }, +{"break", "6", 0xe805, 0xf81f, TRAP }, +{"bteqz", "p", 0x6000, 0xff00, RD_T }, +{"btnez", "p", 0x6100, 0xff00, RD_T }, +{"cmpi", "x,U", 0x7000, 0xf800, WR_T|RD_x }, +{"cmp", "x,y", 0xe80a, 0xf81f, WR_T|RD_x|RD_y }, +{"cmp", "x,U", 0x7000, 0xf800, WR_T|RD_x }, +{"dla", "y,E", 0xfe00, 0xff00, WR_y|RD_PC|I3 }, +{"daddiu", "y,x,4", 0x4010, 0xf810, WR_y|RD_x|I3 }, +{"daddiu", "y,j", 0xfd00, 0xff00, WR_y|RD_y|I3 }, +{"daddiu", "S,K", 0xfb00, 0xff00, WR_SP|RD_SP|I3 }, +{"daddiu", "S,S,K", 0xfb00, 0xff00, WR_SP|RD_SP|I3 }, +{"daddiu", "y,P,W", 0xfe00, 0xff00, WR_y|RD_PC|I3 }, +{"daddiu", "y,S,W", 0xff00, 0xff00, WR_y|RD_SP|I3 }, +{"daddu", "z,v,y", 0xe000, 0xf803, WR_z|RD_x|RD_y|I3 }, +{"daddu", "y,x,4", 0x4010, 0xf810, WR_y|RD_x|I3 }, +{"daddu", "y,j", 0xfd00, 0xff00, WR_y|RD_y|I3 }, +{"daddu", "S,K", 0xfb00, 0xff00, WR_SP|RD_SP|I3 }, +{"daddu", "S,S,K", 0xfb00, 0xff00, WR_SP|RD_SP|I3 }, +{"daddu", "y,P,W", 0xfe00, 0xff00, WR_y|RD_PC|I3 }, +{"daddu", "y,S,W", 0xff00, 0xff00, WR_y|RD_SP|I3 }, +{"ddiv", "0,x,y", 0xe81e, 0xf81f, RD_x|RD_y|WR_HI|WR_LO|I3 }, +{"ddiv", "z,v,y", 0, (int) M_DDIV_3, INSN_MACRO }, +{"ddivu", "0,x,y", 0xe81f, 0xf81f, RD_x|RD_y|WR_HI|WR_LO|I3 }, +{"ddivu", "z,v,y", 0, (int) M_DDIVU_3, INSN_MACRO }, +{"div", "0,x,y", 0xe81a, 0xf81f, RD_x|RD_y|WR_HI|WR_LO }, +{"div", "z,v,y", 0, (int) M_DIV_3, INSN_MACRO }, +{"divu", "0,x,y", 0xe81b, 0xf81f, RD_x|RD_y|WR_HI|WR_LO }, +{"divu", "z,v,y", 0, (int) M_DIVU_3, INSN_MACRO }, +{"dmul", "z,v,y", 3, (int) M_DMUL, INSN_MACRO }, +{"dmult", "x,y", 0xe81c, 0xf81f, RD_x|RD_y|WR_HI|WR_LO|I3 }, +{"dmultu", "x,y", 0xe81d, 0xf81f, RD_x|RD_y|WR_HI|WR_LO|I3 }, +{"drem", "0,x,y", 0xe81e, 0xf81f, RD_x|RD_y|WR_HI|WR_LO|I3 }, +{"drem", "z,v,y", 0, (int) M_DREM_3, INSN_MACRO }, +{"dremu", "0,x,y", 0xe81f, 0xf81f, RD_x|RD_y|WR_HI|WR_LO|I3 }, +{"dremu", "z,v,y", 0, (int) M_DREMU_3, INSN_MACRO }, +{"dsllv", "y,x", 0xe814, 0xf81f, WR_y|RD_y|RD_x|I3 }, +{"dsll", "x,w,[", 0x3001, 0xf803, WR_x|RD_y|I3 }, +{"dsll", "y,x", 0xe814, 0xf81f, WR_y|RD_y|RD_x|I3 }, +{"dsrav", "y,x", 0xe817, 0xf81f, WR_y|RD_y|RD_x|I3 }, +{"dsra", "y,]", 0xe813, 0xf81f, WR_y|RD_y|I3 }, +{"dsra", "y,x", 0xe817, 0xf81f, WR_y|RD_y|RD_x|I3 }, +{"dsrlv", "y,x", 0xe816, 0xf81f, WR_y|RD_y|RD_x|I3 }, +{"dsrl", "y,]", 0xe808, 0xf81f, WR_y|RD_y|I3 }, +{"dsrl", "y,x", 0xe816, 0xf81f, WR_y|RD_y|RD_x|I3 }, +{"dsubu", "z,v,y", 0xe002, 0xf803, WR_z|RD_x|RD_y|I3 }, +{"dsubu", "y,x,4", 0, (int) M_DSUBU_I, INSN_MACRO }, +{"dsubu", "y,j", 0, (int) M_DSUBU_I_2, INSN_MACRO }, +{"exit", "L", 0xed09, 0xff1f, TRAP }, +{"exit", "L", 0xee09, 0xff1f, TRAP }, +{"exit", "L", 0xef09, 0xff1f, TRAP }, +{"entry", "l", 0xe809, 0xf81f, TRAP }, +{"extend", "e", 0xf000, 0xf800, 0 }, +{"jalr", "x", 0xe840, 0xf8ff, UBD|WR_31|RD_x }, +{"jalr", "R,x", 0xe840, 0xf8ff, UBD|WR_31|RD_x }, +{"jal", "x", 0xe840, 0xf8ff, UBD|WR_31|RD_x }, +{"jal", "R,x", 0xe840, 0xf8ff, UBD|WR_31|RD_x }, +{"jal", "a", 0x1800, 0xfc00, UBD|WR_31 }, +{"jalx", "a", 0x1c00, 0xfc00, UBD|WR_31 }, +{"jr", "x", 0xe800, 0xf8ff, UBD|RD_x }, +{"jr", "R", 0xe820, 0xffff, UBD|RD_31 }, +{"j", "x", 0xe800, 0xf8ff, UBD|RD_x }, +{"j", "R", 0xe820, 0xffff, UBD|RD_31 }, +{"lb", "y,5(x)", 0x8000, 0xf800, WR_y|RD_x }, +{"lbu", "y,5(x)", 0xa000, 0xf800, WR_y|RD_x }, +{"ld", "y,D(x)", 0x3800, 0xf800, WR_y|RD_x|I3 }, +{"ld", "y,B", 0xfc00, 0xff00, WR_y|RD_PC|I3 }, +{"ld", "y,D(P)", 0xfc00, 0xff00, WR_y|RD_PC|I3 }, +{"ld", "y,D(S)", 0xf800, 0xff00, WR_y|RD_SP|I3 }, +{"lh", "y,H(x)", 0x8800, 0xf800, WR_y|RD_x }, +{"lhu", "y,H(x)", 0xa800, 0xf800, WR_y|RD_x }, +{"li", "x,U", 0x6800, 0xf800, WR_x }, +{"lw", "y,W(x)", 0x9800, 0xf800, WR_y|RD_x }, +{"lw", "x,A", 0xb000, 0xf800, WR_x|RD_PC }, +{"lw", "x,V(P)", 0xb000, 0xf800, WR_x|RD_PC }, +{"lw", "x,V(S)", 0x9000, 0xf800, WR_x|RD_SP }, +{"lwu", "y,W(x)", 0xb800, 0xf800, WR_y|RD_x|I3 }, +{"mfhi", "x", 0xe810, 0xf8ff, WR_x|RD_HI }, +{"mflo", "x", 0xe812, 0xf8ff, WR_x|RD_LO }, +{"move", "y,X", 0x6700, 0xff00, WR_y|RD_X }, +{"move", "Y,Z", 0x6500, 0xff00, WR_Y|RD_Z }, +{"mul", "z,v,y", 0, (int) M_MUL, INSN_MACRO }, +{"mult", "x,y", 0xe818, 0xf81f, RD_x|RD_y|WR_HI|WR_LO }, +{"multu", "x,y", 0xe819, 0xf81f, RD_x|RD_y|WR_HI|WR_LO }, +{"neg", "x,w", 0xe80b, 0xf81f, WR_x|RD_y }, +{"not", "x,w", 0xe80f, 0xf81f, WR_x|RD_y }, +{"or", "x,y", 0xe80d, 0xf81f, WR_x|RD_x|RD_y }, +{"rem", "0,x,y", 0xe81a, 0xf81f, RD_x|RD_y|WR_HI|WR_LO }, +{"rem", "z,v,y", 0, (int) M_REM_3, INSN_MACRO }, +{"remu", "0,x,y", 0xe81b, 0xf81f, RD_x|RD_y|WR_HI|WR_LO }, +{"remu", "z,v,y", 0, (int) M_REMU_3, INSN_MACRO }, +{"sb", "y,5(x)", 0xc000, 0xf800, RD_y|RD_x }, +{"sd", "y,D(x)", 0x7800, 0xf800, RD_y|RD_x|I3 }, +{"sd", "y,D(S)", 0xf900, 0xff00, RD_y|RD_PC|I3 }, +{"sd", "R,C(S)", 0xfa00, 0xff00, RD_31|RD_PC }, +{"sh", "y,H(x)", 0xc800, 0xf800, RD_y|RD_x }, +{"sllv", "y,x", 0xe804, 0xf81f, WR_y|RD_y|RD_x }, +{"sll", "x,w,<", 0x3000, 0xf803, WR_x|RD_y }, +{"sll", "y,x", 0xe804, 0xf81f, WR_y|RD_y|RD_x }, +{"slti", "x,8", 0x5000, 0xf800, WR_T|RD_x }, +{"slt", "x,y", 0xe802, 0xf81f, WR_T|RD_x|RD_y }, +{"slt", "x,8", 0x5000, 0xf800, WR_T|RD_x }, +{"sltiu", "x,8", 0x5800, 0xf800, WR_T|RD_x }, +{"sltu", "x,y", 0xe803, 0xf81f, WR_T|RD_x|RD_y }, +{"sltu", "x,8", 0x5800, 0xf800, WR_T|RD_x }, +{"srav", "y,x", 0xe807, 0xf81f, WR_y|RD_y|RD_x }, +{"sra", "x,w,<", 0x3003, 0xf803, WR_x|RD_y }, +{"sra", "y,x", 0xe807, 0xf81f, WR_y|RD_y|RD_x }, +{"srlv", "y,x", 0xe806, 0xf81f, WR_y|RD_y|RD_x }, +{"srl", "x,w,<", 0x3002, 0xf803, WR_x|RD_y }, +{"srl", "y,x", 0xe806, 0xf81f, WR_y|RD_y|RD_x }, +{"subu", "z,v,y", 0xe003, 0xf803, WR_z|RD_x|RD_y }, +{"subu", "y,x,4", 0, (int) M_SUBU_I, INSN_MACRO }, +{"subu", "x,k", 0, (int) M_SUBU_I_2, INSN_MACRO }, +{"sw", "y,W(x)", 0xd800, 0xf800, RD_y|RD_x }, +{"sw", "x,V(S)", 0xd000, 0xf800, RD_x|RD_SP }, +{"sw", "R,V(S)", 0x6200, 0xff00, RD_31|RD_SP }, +{"xor", "x,y", 0xe80e, 0xf81f, WR_x|RD_x|RD_y }, +}; + +const int bfd_mips16_num_opcodes = + ((sizeof mips16_opcodes) / (sizeof (mips16_opcodes[0]))); |