diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 28f8bdc65f..1fd14c41d8 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,37 @@ +Fri May 9 10:15:27 1997 Nick Clifton + + * archures.c (constants): Added new constants to identify the + type of the ARM architecture: bfd_mach_arm_2, bfd_mach_arm_2a, + bfd_mach_arm_3, bfd_mach_arm_3M, bfd_mach_arm_4 and bfd_mach_arm_4T. + + * bfd-in2.h (constants): Added new constants to identify + the type of the ARM architecture: bfd_mach_arm_2, bfd_mach_arm_2a, + bfd_mach_arm_3, bfd_mach_arm_3M, bfd_mach_arm_4 and + bfd_mach_arm_4T. This file is auto-magically generated from the + archures.c file. This update is just to save work. + + * coff-arm.c (coff_arm_bfd_merge_private_bfd_data, + coff_arm_bfd_print_private_bfd_data, + coff_arm_bfd_set_private_flags, + coff_arm_bfd_copy_private_bfd_data): Added these new functions. + (global): Macro redefinitions set up to use these new functions. + + * coffcode.h (coff_mkobject_hook): Added call to + coff_arm_bfd_set_private_flags(). (coff_set_arch_mach_hook): + Added code to set machine type based on bits stored in internal + flags. (coff_set_flags): Added code to set the new bits in the + flags field based on the machine number. + + (function definition macros): Made all function definition macros + conditional so that they can be overridden by target specific + files. + + * cpu-arm.c (compatible): Added this function. (arch_info_struct): + Structure extended to include new types, one each for ARMv2, + ARMv2a, ARMv3, ARMv3M, ARMv4 and ARMv4T. + + * libcoff-in.h (struct coff_tdata): Added flags field. + Fri May 9 17:40:02 1997 Ian Lance Taylor * config.bfd (i[3456]86-*-gnu*): Don't include Mach support. diff --git a/bfd/coff-arm.c b/bfd/coff-arm.c index a33bbb229b..1f0e348c00 100644 --- a/bfd/coff-arm.c +++ b/bfd/coff-arm.c @@ -1,5 +1,5 @@ /* BFD back-end for ARM COFF files. - Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + Copyright 1990, 91, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -21,7 +21,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "bfd.h" #include "sysdep.h" #include "libbfd.h" -#include "obstack.h" #include "coff/arm.h" @@ -44,7 +43,9 @@ aoutarm_fix_pcrel_26 PARAMS ((bfd *, arelent *, asymbol *, PTR, static bfd_reloc_status_type coff_arm_reloc PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); - +static boolean coff_arm_adjust_symndx + PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, + struct internal_reloc *, boolean *)); /* Used by the assembler. */ static bfd_reloc_status_type @@ -216,7 +217,7 @@ static reloc_howto_type aoutarm_std_reloc_howto[] = "ARM26D", true, 0x00ffffff, - 0x00ffffff, + 0x0, false), {-1}, HOWTO( 9, @@ -294,6 +295,37 @@ coff_arm_rtype_to_howto (abfd, sec, rel, h, sym, addendp) { *addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase; } + + /* The relocation_section function will skip pcrel_offset relocs + when doing a relocateable link. However, we want to convert + ARM26 to ARM26D relocs if possible. We return a fake howto in + this case without pcrel_offset set, and adjust the addend to + compensate. */ + if (rel->r_type == 3 + && h != NULL + && (h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + && h->root.u.def.section->output_section == sec->output_section) + { + static reloc_howto_type fake_arm26_reloc = + HOWTO (3, + 2, + 2, + 26, + true, + 0, + complain_overflow_signed, + aoutarm_fix_pcrel_26 , + "ARM26", + false, + 0x00ffffff, + 0x00ffffff, + false); + + *addendp -= rel->r_vaddr - sec->vma; + return &fake_arm26_reloc; + } + return howto; } @@ -419,6 +451,170 @@ arm_reloc_type_lookup(abfd,code) /* We use the special COFF backend linker. */ #define coff_relocate_section _bfd_coff_generic_relocate_section +/* When doing a relocateable link, we want to convert ARM26 relocs + into ARM26D relocs. */ + +static boolean +coff_arm_adjust_symndx (obfd, info, ibfd, sec, irel, adjustedp) + bfd *obfd; + struct bfd_link_info *info; + bfd *ibfd; + asection *sec; + struct internal_reloc *irel; + boolean *adjustedp; +{ + if (irel->r_type == 3) + { + struct coff_link_hash_entry *h; + + h = obj_coff_sym_hashes (ibfd)[irel->r_symndx]; + if (h != NULL + && (h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + && h->root.u.def.section->output_section == sec->output_section) + irel->r_type = 7; + } + *adjustedp = false; + return true; +} + + +#define APCS_FLAG( abfd ) (coff_data (abfd)->flags & F_APCS_26) +#define APCS_SET( abfd ) (coff_data (abfd)->flags & F_APCS_SET) +#define SET_APCS_FLAG( abfd, flg ) (coff_data (abfd)->flags = (coff_data (abfd)->flags & ~ F_APCS_26) | (flg | F_APCS_SET)) + +/* Called when merging the private data areas of two BFDs. + This is important as it allows us to detect if we are + attempting to merge binaries compiled for different ARM + targets, eg different CPUs or differents APCS's. */ + +boolean +coff_arm_bfd_merge_private_bfd_data (ibfd, obfd) + bfd * ibfd; + bfd * obfd; +{ + BFD_ASSERT (ibfd != NULL && obfd != NULL) + + if (ibfd == obfd) + return true; + + /* If the two formats are different we cannot check anything */ + if (ibfd->xvec != obfd->xvec) + return true; + + /* Verify that the APCS is the same for the two BFDs */ + if (APCS_SET (ibfd)) + { + if (APCS_SET (obfd)) + { + /* If the src and dest have different APCS flag bits set, fail */ + if (APCS_FLAG (obfd) != APCS_FLAG (ibfd)) + { + _bfd_error_handler + ("%s: ERROR: compiled for APCS-%d whereas target %s uses APCS-%d", + bfd_get_filename (ibfd), APCS_FLAG (ibfd) ? 26 : 32, + bfd_get_filename (obfd), APCS_FLAG (obfd) ? 26 : 32 + ); + + bfd_set_error (bfd_error_wrong_format); + return false; + } + } + else + SET_APCS_FLAG (obfd, APCS_FLAG (ibfd)); + } + + return true; +} + + +/* Display the flags field */ + +boolean +coff_arm_bfd_print_private_bfd_data (abfd, ptr) + bfd * abfd; + PTR ptr; +{ + FILE * file = (FILE *) ptr; + + BFD_ASSERT (abfd != NULL && ptr != NULL) + + fprintf (file, "private flags = %x", coff_data( abfd )->flags); + + if (APCS_SET (abfd)) + fprintf (file, ": [APCS-%d]", APCS_FLAG( abfd ) ? 26 : 32); + + fputc ('\n', file); + + return true; +} + + +/* Copies the given flags into the coff_tdata.flags field. + Typically these flags come from the f_flags[] field of + the COFF filehdr structure, which contains important, + target specific information. */ + +boolean +coff_arm_bfd_set_private_flags (abfd, flags) + bfd * abfd; + flagword flags; +{ + int flag; + + BFD_ASSERT (abfd != NULL); + + flag = (flags & F_APCS26) ? F_APCS_26 : 0; + + /* Make sure that the APCS field has not been initialised to the opposite value */ + if (APCS_SET (abfd) && (APCS_FLAG (abfd) != flag)) + return false; + + SET_APCS_FLAG (abfd, flag); + + return true; +} + + +/* Copy the important parts of the target specific data + from one instance of a BFD to another. */ + +boolean +coff_arm_bfd_copy_private_bfd_data (src, dest) + bfd * src; + bfd * dest; +{ + BFD_ASSERT (src != NULL && dest != NULL) + + if (src == dest) + return true; + + /* If the destination is not in the same format as the source, do not do the copy */ + if (src->xvec != dest->xvec) + return true; + + /* copy the flags field */ + if (APCS_SET (src)) + { + if (APCS_SET (dest)) + { + /* If the src and dest have different APCS flag bits set, fail */ + if (APCS_FLAG (dest) != APCS_FLAG (src)) + return false; + } + else + SET_APCS_FLAG (dest, APCS_FLAG (src)); + } + + return true; +} + + +#define coff_adjust_symndx coff_arm_adjust_symndx +#define coff_bfd_merge_private_bfd_data coff_arm_bfd_merge_private_bfd_data +#define coff_bfd_print_private_bfd_data coff_arm_bfd_print_private_bfd_data +#define coff_bfd_set_private_flags coff_arm_bfd_set_private_flags +#define coff_bfd_copy_private_bfd_data coff_arm_bfd_copy_private_bfd_data #include "coffcode.h" @@ -435,14 +631,20 @@ armcoff_little_vec = "coff-arm-little", #endif bfd_target_coff_flavour, - false, /* data byte order is little */ - false, /* header byte order is little */ + BFD_ENDIAN_LITTLE, /* data byte order is little */ + BFD_ENDIAN_LITTLE, /* header byte order is little */ (HAS_RELOC | EXEC_P | /* object flags */ HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), +#ifndef COFF_WITH_PE (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ +#else + (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */ + | SEC_LINK_ONCE | SEC_LINK_DUPLICATES), +#endif + #ifdef TARGET_UNDERSCORE TARGET_UNDERSCORE, /* leading underscore */ #else @@ -492,14 +694,20 @@ armcoff_big_vec = "coff-arm-big", #endif bfd_target_coff_flavour, - true, /* data byte order is big */ - true, /* header byte order is big */ + BFD_ENDIAN_BIG, /* data byte order is big */ + BFD_ENDIAN_BIG, /* header byte order is big */ (HAS_RELOC | EXEC_P | /* object flags */ HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), +#ifndef COFF_WITH_PE (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ +#else + (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */ + | SEC_LINK_ONCE | SEC_LINK_DUPLICATES), +#endif + #ifdef TARGET_UNDERSCORE TARGET_UNDERSCORE, /* leading underscore */ #else diff --git a/bfd/coffcode.h b/bfd/coffcode.h index 7679a44712..c46c03ae52 100644 --- a/bfd/coffcode.h +++ b/bfd/coffcode.h @@ -310,6 +310,30 @@ CODE_FRAGMENT #endif #define STRING_SIZE_SIZE (4) + +static long sec_to_styp_flags PARAMS ((const char *, flagword)); +static flagword styp_to_sec_flags PARAMS ((bfd *, PTR, const char *)); +static boolean coff_bad_format_hook PARAMS ((bfd *, PTR)); +static boolean coff_new_section_hook PARAMS ((bfd *, asection *)); +static boolean coff_set_arch_mach_hook PARAMS ((bfd *, PTR)); +static boolean coff_write_relocs PARAMS ((bfd *, int)); +static boolean coff_set_flags + PARAMS ((bfd *, unsigned int *, unsigned short *)); +static boolean coff_set_arch_mach + PARAMS ((bfd *, enum bfd_architecture, unsigned long)); +static boolean coff_compute_section_file_positions PARAMS ((bfd *)); +static boolean coff_write_object_contents PARAMS ((bfd *)); +static boolean coff_set_section_contents + PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type)); +static PTR buy_and_read PARAMS ((bfd *, file_ptr, int, size_t)); +static boolean coff_slurp_line_table PARAMS ((bfd *, asection *)); +static boolean coff_slurp_symbol_table PARAMS ((bfd *)); +static boolean coff_slurp_reloc_table PARAMS ((bfd *, asection *, asymbol **)); +static long coff_canonicalize_reloc + PARAMS ((bfd *, asection *, arelent **, asymbol **)); +#ifndef coff_mkobject_hook +static PTR coff_mkobject_hook PARAMS ((bfd *, PTR, PTR)); +#endif /* void warning(); */ @@ -727,6 +751,7 @@ dependent COFF routines: . 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, @@ -880,6 +905,8 @@ dependent COFF routines: .#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)) . @@ -1033,6 +1060,8 @@ coff_new_section_hook (abfd, section) /* Set the alignment of a BFD section. */ +static void coff_set_alignment_hook PARAMS ((bfd *, asection *, PTR)); + static void coff_set_alignment_hook (abfd, section, scnhdr) bfd * abfd; @@ -1064,6 +1093,8 @@ coff_set_alignment_hook (abfd, section, scnhdr) section->alignment_power = y;\ } +static void coff_set_alignment_hook PARAMS ((bfd *, asection *, PTR)); + static void coff_set_alignment_hook (abfd, section, scnhdr) bfd * abfd; @@ -1151,6 +1182,8 @@ coff_set_alignment_hook (abfd, section, scnhdr) When we see one, we correct the reloc and line number counts in the real header, and remove the section we just created. */ +static void coff_set_alignment_hook PARAMS ((bfd *, asection *, PTR)); + static void coff_set_alignment_hook (abfd, section, scnhdr) bfd *abfd; @@ -1192,6 +1225,9 @@ coff_set_alignment_hook (abfd, section, scnhdr) #endif /* ! I960 */ #ifndef coff_mkobject + +static boolean coff_mkobject PARAMS ((bfd *)); + static boolean coff_mkobject (abfd) bfd * abfd; @@ -1270,6 +1306,12 @@ coff_mkobject_hook (abfd, filehdr, aouthdr) } #endif +#ifdef ARM + /* Set the flags field from the COFF header read in */ + if (! coff_arm_bfd_set_private_flags (abfd, internal_f->f_flags)) + coff->flags = 0; +#endif + return (PTR) coff; } #endif @@ -1318,7 +1360,16 @@ coff_set_arch_mach_hook (abfd, filehdr) #ifdef ARMMAGIC case ARMMAGIC: arch = bfd_arch_arm; - machine =0; + switch (internal_f->f_flags & F_ARM_ARCHITECTURE_MASK) + { + case F_ARM_2: machine = bfd_mach_arm_2; break; + case F_ARM_2a: machine = bfd_mach_arm_2a; break; + case F_ARM_3: machine = bfd_mach_arm_3; break; + default: + case F_ARM_3M: machine = bfd_mach_arm_3M; break; + case F_ARM_4: machine = bfd_mach_arm_4; break; + case F_ARM_4T: machine = bfd_mach_arm_4T; break; + } break; #endif #ifdef MC68MAGIC @@ -1550,6 +1601,9 @@ coff_set_arch_mach_hook (abfd, filehdr) #ifdef SYMNAME_IN_DEBUG +static boolean symname_in_debug_hook + PARAMS ((bfd *, struct internal_syment *)); + static boolean symname_in_debug_hook (abfd, sym) bfd * abfd; @@ -1840,7 +1894,7 @@ coff_write_relocs (abfd, first_undef) static boolean coff_set_flags (abfd, magicp, flagsp) bfd * abfd; - unsigned *magicp; + unsigned int *magicp; unsigned short *flagsp; { switch (bfd_get_arch (abfd)) @@ -1915,7 +1969,18 @@ coff_set_flags (abfd, magicp, flagsp) /* end-sanitize-tic80 */ #ifdef ARMMAGIC case bfd_arch_arm: - *magicp = ARMMAGIC; + * magicp = ARMMAGIC; + if (coff_data (abfd)->flags & F_APCS_26) + * flagsp = F_APCS26; + switch (bfd_get_mach (abfd)) + { + case bfd_mach_arm_2: * flagsp |= F_ARM_2; break; + case bfd_mach_arm_2a: * flagsp |= F_ARM_2a; break; + case bfd_mach_arm_3: * flagsp |= F_ARM_3; break; + case bfd_mach_arm_3M: * flagsp |= F_ARM_3M; break; + case bfd_mach_arm_4: * flagsp |= F_ARM_4; break; + case bfd_mach_arm_4T: * flagsp |= F_ARM_4T; break; + } return true; #endif #ifdef PPCMAGIC @@ -2249,6 +2314,14 @@ coff_compute_section_file_positions (abfd) } #endif +#ifdef COFF_IMAGE_WITH_PE + /* For PE we need to make sure we pad out to the aligned + _raw_size, in case the caller only writes out data to the + unaligned _raw_size. */ + if (pei_section_data (abfd, current)->virt_size < current->_raw_size) + align_adjust = true; +#endif + #ifdef _LIB /* Force .lib sections to start at zero. The vma is then incremented in coff_set_section_contents. This is right for @@ -2800,10 +2873,12 @@ coff_write_object_contents (abfd) #define __A_MAGIC_SET__ internal_a.magic = ZMAGIC; #endif + #if defined(PPC_PE) #define __A_MAGIC_SET__ internal_a.magic = IMAGE_NT_OPTIONAL_HDR_MAGIC; #endif + #if defined(I386) #define __A_MAGIC_SET__ #if defined(LYNXOS) @@ -3544,6 +3619,8 @@ coff_slurp_symbol_table (abfd) #ifdef OTHER_GLOBAL_CLASS +static boolean coff_sym_is_global PARAMS ((bfd *, struct internal_syment *)); + static boolean coff_sym_is_global (abfd, syment) bfd *abfd; @@ -3808,6 +3885,10 @@ coff_sym_filepos (abfd) #ifndef coff_reloc16_estimate #define coff_reloc16_estimate dummy_reloc16_estimate +static int dummy_reloc16_estimate + PARAMS ((bfd *, asection *, arelent *, unsigned int, + struct bfd_link_info *)); + static int dummy_reloc16_estimate (abfd, input_section, reloc, shrink, link_info) bfd *abfd; @@ -3822,8 +3903,15 @@ dummy_reloc16_estimate (abfd, input_section, reloc, shrink, link_info) #endif #ifndef coff_reloc16_extra_cases + #define coff_reloc16_extra_cases dummy_reloc16_extra_cases + /* This works even if abort is not declared in any header file. */ + +static void dummy_reloc16_extra_cases + PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *, arelent *, + bfd_byte *, unsigned int *, unsigned int *)); + static void dummy_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr, dst_ptr) @@ -3861,6 +3949,7 @@ dummy_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr, #endif #define coff_bfd_final_link _bfd_generic_final_link #endif /* ! defined (coff_relocate_section) */ + #define coff_bfd_link_split_section _bfd_generic_link_split_section #ifndef coff_start_final_link @@ -3893,6 +3982,7 @@ static CONST bfd_coff_backend_data bfd_coff_std_swap_table = #else false, #endif + COFF_DEFAULT_SECTION_ALIGNMENT_POWER, coff_swap_filehdr_in, coff_swap_aouthdr_in, coff_swap_scnhdr_in, coff_swap_reloc_in, coff_bad_format_hook, coff_set_arch_mach_hook, coff_mkobject_hook, styp_to_sec_flags, coff_set_alignment_hook, @@ -3903,12 +3993,20 @@ static CONST bfd_coff_backend_data bfd_coff_std_swap_table = coff_adjust_symndx, coff_link_add_one_symbol }; -#define coff_close_and_cleanup _bfd_generic_close_and_cleanup -#define coff_bfd_free_cached_info _bfd_generic_bfd_free_cached_info -#define coff_get_section_contents _bfd_generic_get_section_contents +#ifndef coff_close_and_cleanup +#define coff_close_and_cleanup _bfd_generic_close_and_cleanup +#endif + +#ifndef coff_bfd_free_cached_info +#define coff_bfd_free_cached_info _bfd_generic_bfd_free_cached_info +#endif + +#ifndef coff_get_section_contents +#define coff_get_section_contents _bfd_generic_get_section_contents +#endif #ifndef coff_bfd_copy_private_symbol_data -#define coff_bfd_copy_private_symbol_data _bfd_generic_bfd_copy_private_symbol_data +#define coff_bfd_copy_private_symbol_data _bfd_generic_bfd_copy_private_symbol_data #endif #ifndef coff_bfd_copy_private_section_data @@ -3916,36 +4014,44 @@ static CONST bfd_coff_backend_data bfd_coff_std_swap_table = #endif #ifndef coff_bfd_copy_private_bfd_data -#define coff_bfd_copy_private_bfd_data _bfd_generic_bfd_copy_private_bfd_data +#define coff_bfd_copy_private_bfd_data _bfd_generic_bfd_copy_private_bfd_data #endif -#define coff_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data -#define coff_bfd_set_private_flags _bfd_generic_bfd_set_private_flags +#ifndef coff_bfd_merge_private_bfd_data +#define coff_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data +#endif + +#ifndef coff_bfd_set_private_flags +#define coff_bfd_set_private_flags _bfd_generic_bfd_set_private_flags +#endif #ifndef coff_bfd_print_private_bfd_data -#define coff_bfd_print_private_bfd_data _bfd_generic_bfd_print_private_bfd_data +#define coff_bfd_print_private_bfd_data _bfd_generic_bfd_print_private_bfd_data #endif #ifndef coff_bfd_is_local_label_name -#define coff_bfd_is_local_label_name _bfd_coff_is_local_label_name +#define coff_bfd_is_local_label_name _bfd_coff_is_local_label_name #endif + #ifndef coff_read_minisymbols -#define coff_read_minisymbols _bfd_generic_read_minisymbols +#define coff_read_minisymbols _bfd_generic_read_minisymbols #endif + #ifndef coff_minisymbol_to_symbol -#define coff_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol +#define coff_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol #endif /* The reloc lookup routine must be supplied by each individual COFF backend. */ #ifndef coff_bfd_reloc_type_lookup -#define coff_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup +#define coff_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup #endif #ifndef coff_bfd_get_relocated_section_contents #define coff_bfd_get_relocated_section_contents \ bfd_generic_get_relocated_section_contents #endif + #ifndef coff_bfd_relax_section -#define coff_bfd_relax_section bfd_generic_relax_section +#define coff_bfd_relax_section bfd_generic_relax_section #endif diff --git a/bfd/cpu-arm.c b/bfd/cpu-arm.c new file mode 100644 index 0000000000..db8282e31f --- /dev/null +++ b/bfd/cpu-arm.c @@ -0,0 +1,108 @@ +/* BFD support for the ARM processor + Copyright 1994 Free Software Foundation, Inc. + Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org) + +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. */ + +#include "bfd.h" +#include "sysdep.h" +#include "libbfd.h" + +/* This routine is provided two arch_infos and works out which ARM + machine which would be compatible with both and returns a pointer + to its info structure */ + +static const bfd_arch_info_type * +compatible (a,b) + const bfd_arch_info_type * a; + const bfd_arch_info_type * b; +{ + /* For now keep things real simple - insist on matching architecture types */ + + return (a->arch != b->arch || a->mach != b->mach ) ? NULL : a ; +} + +static struct +{ + enum bfd_architecture arch; + char * name; +} +processors[] = +{ + { bfd_mach_arm_2, "arm2" }, + { bfd_mach_arm_2a, "arm250" }, + { bfd_mach_arm_2a, "arm3" }, + { bfd_mach_arm_3, "arm6" }, + { bfd_mach_arm_3, "arm60" }, + { bfd_mach_arm_3, "arm600" }, + { bfd_mach_arm_3, "arm610" }, + { bfd_mach_arm_3, "arm7" }, + { bfd_mach_arm_3, "arm710" }, + { bfd_mach_arm_3, "arm7500" }, + { bfd_mach_arm_3, "arm7d" }, + { bfd_mach_arm_3, "arm7di" }, + { bfd_mach_arm_3M, "arm7dm" }, + { bfd_mach_arm_3M, "arm7dmi" }, + { bfd_mach_arm_4, "arm8" }, + { bfd_mach_arm_4, "arm810" }, + { bfd_mach_arm_4, "sa1" }, + { bfd_mach_arm_4T, "arm7tdmi" } +}; + +static boolean +scan (info, string) + const struct bfd_arch_info * info; + const char * string; +{ + int i; + + /* First test for an exact match */ + if (strcasecmp (string, info->printable_name) == 0) + return true; + + /* Next check for a processor name instead of an Architecture name */ + for (i = sizeof (processors) / sizeof (processors[0]); i--;) + { + if (strcasecmp (string, processors[ i ].name) == 0) + break; + } + + if (i != -1 && info->arch == processors[ i ].arch) + return true; + + /* Finally check for the default architecture */ + if (strcasecmp (string, "arm") == 0) + return info->the_default; + + return false; +} + + +#define N(number, print, default, next) \ +{ 32, 32, 8, bfd_arch_arm, number, "arm", print, 4, default, compatible, scan, next } + +static const bfd_arch_info_type arch_info_struct[] = +{ + N( bfd_mach_arm_2, "ARMv2", false, & arch_info_struct[1] ), + N( bfd_mach_arm_2a, "ARMv2a", false, & arch_info_struct[2] ), + N( bfd_mach_arm_3, "ARMv3", false, & arch_info_struct[3] ), + N( bfd_mach_arm_4, "ARMv4", false, & arch_info_struct[4] ), + N( bfd_mach_arm_4T, "ARMv4T", false, NULL ) +}; + +const bfd_arch_info_type bfd_arm_arch = + N( bfd_mach_arm_3M, "ARMv3M", true, & arch_info_struct[0] ); diff --git a/gas/ChangeLog b/gas/ChangeLog index 83efb5f885..7ab2f13a4a 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,15 @@ +Wed May 14 09:54:53 1997 Nick Clifton + + * config/tc-arm.c (global variables): Added 'uses_apcs_26' flag to + hold APCS selection. (md_begin): Added code to generate flags to + be set into the COFF header and the calls to the BFD functions to + do this. (md_parse_option, md_show_usage): Added new command line + options -mapcs-32, -mapcs-26, -marmv2, -marmv2a, -marmv3, + -marmv3m, -marmv4, -marmv4t. + + * tc-arm.h (LOCAL_LABEL): Removed the definition of this macro + as it is never used. + Tue May 13 22:26:14 1997 Jeffrey A Law (law@cygnus.com) * config/tc-mn10200.c (md_convert_frag): Prefix temporary diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 644d89b2ce..667fbc7a9f 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -47,6 +47,7 @@ #define ARM_250 ARM_3 #define ARM_6 0x00000008 #define ARM_7 ARM_6 /* same core instruction set */ +#define ARM_CPU_MASK 0x0000000f /* The following bitmasks control CPU extensions (ARM7 onwards): */ #define ARM_LONGMUL 0x00000010 /* allow long multiplies */ @@ -77,7 +78,10 @@ #define FPU_DEFAULT FPU_ALL #endif -unsigned long cpu_variant = CPU_DEFAULT | FPU_DEFAULT; +static unsigned long cpu_variant = CPU_DEFAULT | FPU_DEFAULT; + +/* Flags stored in private area of BFD COFF structure */ +static boolean uses_apcs_26 = false; /* This array holds the chars that always start a comment. If the pre-processor is disabled, these aren't very useful */ @@ -958,11 +962,9 @@ symbol_make_empty () /* symbol must be born in some fixed state. This seems as good as any. */ memset (symbolP, 0, sizeof (symbolS)); -#ifdef BFD_ASSEMBLER symbolP->bsym = bfd_make_empty_symbol (stdoutput); assert (symbolP->bsym != 0); symbolP->bsym->udata.p = (PTR) symbolP; -#endif return symbolP; } @@ -4580,6 +4582,43 @@ md_begin () insert_reg (i); set_constant_flonums (); + +#ifdef OBJ_COFF + /* Set the flags in the private structure */ + coff_arm_bfd_set_private_flags (stdoutput, uses_apcs_26 ? F_APCS26 : 0); +#endif + + { + unsigned mach; + + /* Record the CPU type as well */ + switch (cpu_variant & ARM_CPU_MASK) + { + case ARM_2: + mach = bfd_mach_arm_2; + break; + + case ARM_3: /* also ARM_250 */ + mach = bfd_mach_arm_2a; + break; + + default: + case ARM_6 | ARM_3 | ARM_2: /* Actually no CPU type defined */ + case ARM_7: /* also ARM_6 */ + mach = bfd_mach_arm_3; + break; + } + + /* Catch special cases */ + if (cpu_variant & ARM_THUMB) + mach = bfd_mach_arm_4T; + else if (cpu_variant & ARM_LONGMUL) + mach = bfd_mach_arm_3M; + else if (cpu_variant & ARM_ARCH4) + mach = bfd_mach_arm_4; + + bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach); + } } /* Turn an integer of n bytes (in val) into a stream of bytes appropriate @@ -5635,10 +5674,14 @@ md_assemble (str) * Run-time endian selection: * -EB big endian cpu * -EL little endian cpu + * ARM Procedure Calling Standard: + * -mapcs-32 32 bit APCS + * -mapcs-26 26 bit APCS */ CONST char *md_shortopts = "m:"; -struct option md_longopts[] = { +struct option md_longopts[] = +{ #ifdef ARM_BI_ENDIAN #define OPTION_EB (OPTION_MD_BASE + 0) {"EB", no_argument, NULL, OPTION_EB}, @@ -5704,7 +5747,17 @@ md_parse_option (c, arg) cpu_variant = ARM_ALL | FPU_ALL; return 1; } - + else if (! strcmp( str, "apcs-32" )) + { + uses_apcs_26 = false; + return 1; + } + else if (! strcmp( str, "apcs-26" )) + { + uses_apcs_26 = true; + return 1; + } + /* Strip off optional "arm" */ if (! strncmp (str, "arm", 3)) str += 3; @@ -5768,9 +5821,50 @@ md_parse_option (c, arg) } break; + case 'v': + /* Select variant based on architecture rather than processor */ + switch (*++str) + { + case '2': + switch (*++str) + { + case 'a': cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_3; break; + case 0: cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_2; break; + default: as_bad( "Invalid architecture variant -m%s", arg ); break; + } + break; + + case '3': + cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7; + + switch (*++str) + { + case 'm': cpu_variant |= ARM_LONGMUL; break; + case 0: break; + default: as_bad( "Invalid architecture variant -m%s", arg ); break; + } + break; + + case '4': + cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7; + + switch (*++str) + { + case 't': cpu_variant |= ARM_THUMB; break; + case 0: break; + default: as_bad( "Invalid architecture variant -m%s", arg ); break; + } + break; + + default: + as_bad( "Invalid architecture variant -m%s", arg ); + break; + } + break; + default: bad: - as_bad ("Invalid architecture -m%s", arg); + as_bad ("Invalid processor variant -m%s", arg); return 0; } } @@ -5788,12 +5882,14 @@ md_show_usage (fp) FILE *fp; { fprintf (fp, -"-m[arm]1, -m[arm]2, -m[arm]250,\n-m[arm]3, -m[arm]6, -m[arm]7[t][[d]m]\n\ --mthumb\t\t\tselect processor architecture\n\ +"-m[arm][1|2|250|3|6|7[t][d][m][i]] select processor variant\n\ +-m[arm]v[2|2a|3|3m|4|4t] select architecture variant\n\ +-mthumb\t\t\tonly allow Thumb instructions\n\ -mall\t\t\tallow any instruction\n\ -mfpa10, -mfpa11\tselect floating point architecture\n\ -mfpe-old\t\tdon't allow floating-point multiple instructions\n\ --mno-fpu\t\tdon't allow any floating-point instructions.\n"); +-mno-fpu\t\tdon't allow any floating-point instructions.\n\ +-mapcs-32, -mapcs-26\tspecify which ARM Procedure Calling Standard is in use\n"); #ifdef ARM_BI_ENDIAN fprintf (fp, "-EB\t\t\tassemble code for a big endian cpu\n\ diff --git a/include/ChangeLog b/include/ChangeLog index 22f2fe7e55..7a2403c76c 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,17 @@ +Tue May 13 10:21:14 1997 Nick Clifton + + * coff/arm.h (constants): Added new flag bits F_APCS_26 and + F_APCS_SET for the f_flags field of the filehdr structure. Added new + flags: F_APCS26, F_ARM_2, F_ARM_3, F_ARM_7, F_ARM_7T to store + information in the flags field of the internal_f structure used by BFD + routines. + +Tue Apr 22 10:24:34 1997 Fred Fish + + * floatformat.h (floatformat_byteorders): Add comments for previous + formats and add floatformat_littlebyte_bigword, primarily for ARM. + Add declaration for floatformat_ieee_double_littlebyte_bigword. + Fri Apr 18 13:04:49 1997 Andrew Cagney * remote-sim.h (sim_stop): New interface - asynchronous