summaryrefslogtreecommitdiffstats
path: root/contrib/binutils/gas
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>2002-07-05 20:16:34 +0000
committerobrien <obrien@FreeBSD.org>2002-07-05 20:16:34 +0000
commitf3c54bd2c1850601b80aa0558b8843517125f50f (patch)
tree30918b465d458ef1aca113937ad46b1e912ce044 /contrib/binutils/gas
parent18ff9f4f1bddd11c341a37177885ac89fcccedd9 (diff)
downloadFreeBSD-src-f3c54bd2c1850601b80aa0558b8843517125f50f.zip
FreeBSD-src-f3c54bd2c1850601b80aa0558b8843517125f50f.tar.gz
Import of Binutils from the FSF 2.12 branch (just post-.1 release).
These bits are taken from the FSF anoncvs repo on 22-June-2002 23:28:00 EDT.
Diffstat (limited to 'contrib/binutils/gas')
-rw-r--r--contrib/binutils/gas/ChangeLog91
-rw-r--r--contrib/binutils/gas/config/obj-coff.c569
-rw-r--r--contrib/binutils/gas/config/tc-arm.c14
-rw-r--r--contrib/binutils/gas/config/tc-i386.c114
-rw-r--r--contrib/binutils/gas/config/tc-ppc.c8
-rw-r--r--contrib/binutils/gas/config/tc-s390.c1977
-rw-r--r--contrib/binutils/gas/config/tc-s390.h115
-rw-r--r--contrib/binutils/gas/doc/as.12
-rw-r--r--contrib/binutils/gas/stabs.c8
-rw-r--r--contrib/binutils/gas/symbols.c38
10 files changed, 2549 insertions, 387 deletions
diff --git a/contrib/binutils/gas/ChangeLog b/contrib/binutils/gas/ChangeLog
index fdba914..d5c95ae 100644
--- a/contrib/binutils/gas/ChangeLog
+++ b/contrib/binutils/gas/ChangeLog
@@ -1,3 +1,94 @@
+2002-05-13 Nick Clifton <nickc@cambridge.redhat.com>
+
+ * stabs.c (s_stab_generic): Fix grammatical error in warning
+ message.
+
+2002-05-11 Nick Clifton <nickc@cambridge.redhat.com>
+
+ * stabs.c (s_stab_generic): Warn about a description field that is
+ too big.
+
+2002-05-11 Daniel Jacobowitz <drow@mvista.com>
+
+ Merge from mainline:
+ 2002-05-11 Nick Clifton <nickc@cambridge.redhat.com>
+ * config/obj-coff.c: Fix compile time warnings when compiling
+ without BFD_ASSEMBLER defined.
+ Fix formatting.
+
+ * config/tc-sh.c (md_pcrel_from): Define for use with sh-hms
+ target.
+ (md_pcrel_from_section): Use md_pcrel_from().
+
+2002-05-09 Alan Modra <amodra@bigpond.net.au>
+
+ * config/tc-i386.c (md_estimate_size_before_relax) Don't lose
+ reloc when no_cond_jump_promotion.
+
+ Merge from mainline
+ 2002-05-08 Jim Wilson <wilson@redhat.com>
+ * config/tc-i960.c (md_estimate_size_before_relax): Return size of
+ current variable part of frag.
+
+ 2002-05-02 Alan Modra <amodra@bigpond.net.au>
+ * config/tc-ppc.c (mapping): Map sectoff to BFD_RELOC_16_BASEREL.
+ (ppc_elf_validate_fix): Replace BFD_RELOC_32_BASEREL with
+ BFD_RELOC_16_BASEREL.
+ (md_assemble): Likewise.
+ (md_apply_fix3): Likewise.
+
+ 2002-05-01 Andrew Macleod <amacleod@cygnus.com>
+ * config/tc-i386.c (extra_symbol_chars): Add '[' to the list.
+
+ 2002-04-28 Alan Modra <amodra@bigpond.net.au>
+ * config/tc-i386.c: Formatting fixes, add missing space in error
+ message.
+
+2002-05-03 Alexandre Oliva <aoliva@redhat.com>
+
+ * config/tc-s390.c (md_gather_operands): Emit dwarf2 line-number
+ information for instructions.
+
+2002-05-02 Nick Clifton <nickc@cambridge.redhat.com>
+
+ * config/tc-arm.c (thumb_add_sub): Do not convert a subtract of
+ zero into an add of zero - it is not the same.
+
+2002-04-27 Alan Modra <amodra@bigpond.net.au>
+
+ Merge from mainline.
+ 2002-04-17 Martin Schwidefsky <schwidefsky@de.ibm.com>
+ * config/tc-s390.c (tc_s390_fix_adjustable): Prevent adjustments to
+ symbols in merge sections.
+
+ 2002-02-19 Martin Schwidefsky <schwidefsky@de.ibm.com>
+ * config/tc-s390.c (md_parse_option): Add switches -m31 and -m64.
+ Make bit size independent of architecture switch.
+ (md_begin): Add warning for -m64 with -Aesa.
+ (s390_md_end): Use renamed architecture defines.
+
+ 2002-02-19 Tom Tromey <tromey@redhat.com>
+ * config/tc-xstormy16.h (DWARF2_LINE_MIN_INSN_LENGTH): Define.
+
+ Tue Apr 9 16:45:48 2002 J"orn Rennecke <joern.rennecke@superh.com>
+ * config/tc-sh.h (TC_FIX_ADJUSTABLE): Disable adjusting if
+ symbol_used_in_reloc_p is true.
+ * config/tc-sh.c (md_apply_fix3): Don't zero relocations on big
+ endian hosts.
+
+ 2002-04-03 Alan Modra <amodra@bigpond.net.au>
+ * symbols.c (resolve_symbol_value <O_uminus, O_bit_not,
+ O_logical_not>): Derive final_seg from add_symbol.
+ <O_multiply..O_logical_or>: More final_seg twiddles.
+
+2002-04-24 Andreas Schwab <schwab@suse.de>
+
+ * config/tc-i386.c (output_jump, output_disp)
+ (md_estimate_size_before_relax): Don't set fx_pcrel_adjust any
+ more.
+ (md_apply_fix3): Remember addend value for rela relocations.
+ (tc_gen_reloc): Correctly compute pc-relative relocation addend.
+
2002-04-10 Alan Modra <amodra@bigpond.net.au>
* as.c (parse_args <OPTION_VERSION>): Use VERSION is
diff --git a/contrib/binutils/gas/config/obj-coff.c b/contrib/binutils/gas/config/obj-coff.c
index c956d62..9eb4bdd 100644
--- a/contrib/binutils/gas/config/obj-coff.c
+++ b/contrib/binutils/gas/config/obj-coff.c
@@ -1713,9 +1713,9 @@ const short seg_N_TYPE[] =
int function_lineoff = -1; /* Offset in line#s where the last function
started (the odd entry for line #0) */
-/* structure used to keep the filenames which
+/* Structure used to keep the filenames which
are too long around so that we can stick them
- into the string table */
+ into the string table. */
struct filename_list
{
char *filename;
@@ -1729,39 +1729,38 @@ static symbolS *last_line_symbol;
/* Add 4 to the real value to get the index and compensate the
negatives. This vector is used by S_GET_SEGMENT to turn a coff
- section number into a segment number
-*/
-static symbolS *previous_file_symbol;
-void c_symbol_merge ();
-static int line_base;
+ section number into a segment number. */
-symbolS *c_section_symbol ();
bfd *abfd;
+static symbolS *previous_file_symbol;
+static int line_base;
-static void fixup_segment PARAMS ((segment_info_type *segP,
- segT this_segment_type));
-
-static void fixup_mdeps PARAMS ((fragS *,
- object_headers *,
- segT));
-
-static void fill_section PARAMS ((bfd * abfd,
- object_headers *,
- unsigned long *));
-
-static int c_line_new PARAMS ((symbolS * symbol, long paddr,
- int line_number,
- fragS * frag));
-
-static void w_symbols PARAMS ((bfd * abfd, char *where,
- symbolS * symbol_rootP));
-
-static void adjust_stab_section PARAMS ((bfd *abfd, segT seg));
-
+void c_symbol_merge PARAMS ((symbolS *, symbolS *));
+symbolS *c_section_symbol PARAMS ((char *, int));
+void obj_coff_section PARAMS ((int));
+void do_relocs_for PARAMS ((bfd *, object_headers *, unsigned long *));
+char * symbol_to_chars PARAMS ((bfd *, char *, symbolS *));
+void w_strings PARAMS ((char *));
+
+static void fixup_segment PARAMS ((segment_info_type *, segT));
+static void fixup_mdeps PARAMS ((fragS *, object_headers *, segT));
+static void fill_section PARAMS ((bfd *, object_headers *, unsigned long *));
+static int c_line_new PARAMS ((symbolS *, long, int, fragS *));
+static void w_symbols PARAMS ((bfd *, char *, symbolS *));
+static void adjust_stab_section PARAMS ((bfd *, segT));
static void obj_coff_lcomm PARAMS ((int));
static void obj_coff_text PARAMS ((int));
static void obj_coff_data PARAMS ((int));
-void obj_coff_section PARAMS ((int));
+static unsigned int count_entries_in_chain PARAMS ((unsigned int));
+static void coff_header_append PARAMS ((bfd *, object_headers *));
+static unsigned int yank_symbols PARAMS ((void));
+static unsigned int glue_symbols PARAMS ((symbolS **, symbolS **));
+static unsigned int tie_tags PARAMS ((void));
+static void crawl_symbols PARAMS ((object_headers *, bfd *));
+static void do_linenos_for PARAMS ((bfd *, object_headers *, unsigned long *));
+static void remove_subsegs PARAMS ((void));
+
+
/* When not using BFD_ASSEMBLER, we permit up to 40 sections.
@@ -1800,6 +1799,8 @@ static const segT seg_info_off_by_4[] =
#define SEG_INFO_FROM_SECTION_NUMBER(x) (seg_info_off_by_4[(x)+4])
+static relax_addressT relax_align PARAMS ((relax_addressT, long));
+
static relax_addressT
relax_align (address, alignment)
relax_addressT address;
@@ -1820,8 +1821,11 @@ s_get_segment (x)
return SEG_INFO_FROM_SECTION_NUMBER (x->sy_symbol.ost_entry.n_scnum);
}
-/* calculate the size of the frag chain and fill in the section header
- to contain all of it, also fill in the addr of the sections */
+static unsigned int size_section PARAMS ((bfd *, unsigned int));
+
+/* Calculate the size of the frag chain and fill in the section header
+ to contain all of it, also fill in the addr of the sections. */
+
static unsigned int
size_section (abfd, idx)
bfd *abfd ATTRIBUTE_UNUSED;
@@ -1830,6 +1834,7 @@ size_section (abfd, idx)
unsigned int size = 0;
fragS *frag = segment_info[idx].frchainP->frch_root;
+
while (frag)
{
size = frag->fr_address;
@@ -1882,7 +1887,7 @@ count_entries_in_chain (idx)
unsigned int nrelocs;
fixS *fixup_ptr;
- /* Count the relocations */
+ /* Count the relocations. */
fixup_ptr = segment_info[idx].fix_root;
nrelocs = 0;
while (fixup_ptr != (fixS *) NULL)
@@ -1908,7 +1913,8 @@ count_entries_in_chain (idx)
static int compare_external_relocs PARAMS ((const PTR, const PTR));
-/* AUX's ld expects relocations to be sorted */
+/* AUX's ld expects relocations to be sorted. */
+
static int
compare_external_relocs (x, y)
const PTR x;
@@ -1923,7 +1929,8 @@ compare_external_relocs (x, y)
#endif
-/* output all the relocations for a section */
+/* Output all the relocations for a section. */
+
void
do_relocs_for (abfd, h, file_cursor)
bfd * abfd;
@@ -1961,13 +1968,12 @@ do_relocs_for (abfd, h, file_cursor)
{
struct internal_reloc intr;
- /* Only output some of the relocations */
+ /* Only output some of the relocations. */
if (fix_ptr->fx_done == 0 && TC_COUNT_RELOC (fix_ptr))
{
#ifdef TC_RELOC_MANGLE
TC_RELOC_MANGLE (&segment_info[idx], fix_ptr, &intr,
base);
-
#else
symbolS *dot;
symbolS *symbol_ptr = fix_ptr->fx_addsy;
@@ -2012,36 +2018,26 @@ do_relocs_for (abfd, h, file_cursor)
as_bad (_("bad relocation: symbol `%s' not in symbol table"),
S_GET_NAME (symbol_ptr));
}
+
dot = segment_info[S_GET_SEGMENT (symbol_ptr)].dot;
if (dot)
- {
- intr.r_symndx = dot->sy_number;
- }
+ intr.r_symndx = dot->sy_number;
else
- {
- intr.r_symndx = symbol_ptr->sy_number;
- }
-
+ intr.r_symndx = symbol_ptr->sy_number;
}
else
- {
- intr.r_symndx = -1;
- }
+ intr.r_symndx = -1;
#endif
-
(void) bfd_coff_swap_reloc_out (abfd, &intr, ext_ptr);
ext_ptr++;
-
#if defined(TC_A29K)
-
/* The 29k has a special kludge for the high 16 bit
reloc. Two relocations are emited, R_IHIHALF,
and R_IHCONST. The second one doesn't contain a
symbol, but uses the value for offset. */
-
if (intr.r_type == R_IHIHALF)
{
- /* now emit the second bit */
+ /* Now emit the second bit. */
intr.r_type = R_IHCONST;
intr.r_symndx = fix_ptr->fx_addnumber;
(void) bfd_coff_swap_reloc_out (abfd, &intr, ext_ptr);
@@ -2066,14 +2062,12 @@ do_relocs_for (abfd, h, file_cursor)
fix_ptr = fix_ptr->fx_next;
}
-
#ifdef TE_AUX
- /* Sort the reloc table */
+ /* Sort the reloc table. */
qsort ((PTR) external_reloc_vec, nrelocs,
sizeof (struct external_reloc), compare_external_relocs);
#endif
-
- /* Write out the reloc table */
+ /* Write out the reloc table. */
bfd_bwrite ((PTR) external_reloc_vec,
(bfd_size_type) external_reloc_size, abfd);
free (external_reloc_vec);
@@ -2085,25 +2079,25 @@ do_relocs_for (abfd, h, file_cursor)
}
else
{
- /* No relocs */
+ /* No relocs. */
segment_info[idx].scnhdr.s_relptr = 0;
}
}
}
- /* Set relocation_size field in file headers */
+
+ /* Set relocation_size field in file headers. */
H_SET_RELOCATION_SIZE (h, *file_cursor - reloc_start, 0);
}
-/* run through a frag chain and write out the data to go with it, fill
- in the scnhdrs with the info on the file postions
-*/
+/* Run through a frag chain and write out the data to go with it, fill
+ in the scnhdrs with the info on the file postions. */
+
static void
fill_section (abfd, h, file_cursor)
bfd * abfd;
object_headers *h ATTRIBUTE_UNUSED;
unsigned long *file_cursor;
{
-
unsigned int i;
unsigned int paddr = 0;
@@ -2229,7 +2223,7 @@ fill_section (abfd, h, file_cursor)
}
}
-/* Coff file generation & utilities */
+/* Coff file generation & utilities. */
static void
coff_header_append (abfd, h)
@@ -2279,7 +2273,6 @@ coff_header_append (abfd, h)
string_size += strlen (segment_info[i].name) + 1;
}
#endif
-
size = bfd_coff_swap_scnhdr_out (abfd,
&(segment_info[i].scnhdr),
buffer);
@@ -2300,13 +2293,11 @@ symbol_to_chars (abfd, where, symbolP)
unsigned int i;
valueT val;
- /* Turn any symbols with register attributes into abs symbols */
+ /* Turn any symbols with register attributes into abs symbols. */
if (S_GET_SEGMENT (symbolP) == reg_section)
- {
- S_SET_SEGMENT (symbolP, absolute_section);
- }
- /* At the same time, relocate all symbols to their output value */
+ S_SET_SEGMENT (symbolP, absolute_section);
+ /* At the same time, relocate all symbols to their output value. */
#ifndef TE_PE
val = (segment_info[S_GET_SEGMENT (symbolP)].scnhdr.s_paddr
+ S_GET_VALUE (symbolP));
@@ -2329,25 +2320,25 @@ symbol_to_chars (abfd, where, symbolP)
S_GET_STORAGE_CLASS (symbolP),
i, numaux, where);
}
- return where;
+ return where;
}
void
coff_obj_symbol_new_hook (symbolP)
symbolS *symbolP;
{
- char underscore = 0; /* Symbol has leading _ */
+ char underscore = 0; /* Symbol has leading _ */
- /* Effective symbol */
+ /* Effective symbol. */
/* Store the pointer in the offset. */
S_SET_ZEROES (symbolP, 0L);
S_SET_DATA_TYPE (symbolP, T_NULL);
S_SET_STORAGE_CLASS (symbolP, 0);
S_SET_NUMBER_AUXILIARY (symbolP, 0);
- /* Additional information */
+ /* Additional information. */
symbolP->sy_symbol.ost_flags = 0;
- /* Auxiliary entries */
+ /* Auxiliary entries. */
memset ((char *) &symbolP->sy_symbol.ost_auxent[0], 0, AUXESZ);
if (S_IS_STRING (symbolP))
@@ -2356,9 +2347,7 @@ coff_obj_symbol_new_hook (symbolP)
SF_SET_LOCAL (symbolP);
}
-/*
- * Handle .ln directives.
- */
+/* Handle .ln directives. */
static void
obj_coff_ln (appline)
@@ -2368,10 +2357,11 @@ obj_coff_ln (appline)
if (! appline && def_symbol_in_progress != NULL)
{
+ /* Wrong context. */
as_warn (_(".ln pseudo-op inside .def/.endef: ignored."));
demand_empty_rest_of_line ();
return;
- } /* wrong context */
+ }
l = get_absolute_expression ();
c_line_new (0, frag_now_fix (), l, frag_now);
@@ -2395,19 +2385,14 @@ obj_coff_ln (appline)
demand_empty_rest_of_line ();
}
-/*
- * def()
- *
- * Handle .def directives.
- *
- * One might ask : why can't we symbol_new if the symbol does not
- * already exist and fill it with debug information. Because of
- * the C_EFCN special symbol. It would clobber the value of the
- * function symbol before we have a chance to notice that it is
- * a C_EFCN. And a second reason is that the code is more clear this
- * way. (at least I think it is :-).
- *
- */
+/* Handle .def directives.
+
+ One might ask : why can't we symbol_new if the symbol does not
+ already exist and fill it with debug information. Because of
+ the C_EFCN special symbol. It would clobber the value of the
+ function symbol before we have a chance to notice that it is
+ a C_EFCN. And a second reason is that the code is more clear this
+ way. (at least I think it is :-). */
#define SKIP_SEMI_COLON() while (*input_line_pointer++ != ';')
#define SKIP_WHITESPACES() while (*input_line_pointer == ' ' || \
@@ -2418,9 +2403,9 @@ static void
obj_coff_def (what)
int what ATTRIBUTE_UNUSED;
{
- char name_end; /* Char after the end of name */
- char *symbol_name; /* Name of the debug symbol */
- char *symbol_name_copy; /* Temporary copy of the name */
+ char name_end; /* Char after the end of name. */
+ char *symbol_name; /* Name of the debug symbol. */
+ char *symbol_name_copy; /* Temporary copy of the name. */
unsigned int symbol_name_length;
if (def_symbol_in_progress != NULL)
@@ -2428,7 +2413,7 @@ obj_coff_def (what)
as_warn (_(".def pseudo-op used inside of .def/.endef: ignored."));
demand_empty_rest_of_line ();
return;
- } /* if not inside .def/.endef */
+ }
SKIP_WHITESPACES ();
@@ -2444,7 +2429,7 @@ obj_coff_def (what)
symbol_name_copy = tc_canonicalize_symbol_name (symbol_name_copy);
#endif
- /* Initialize the new symbol */
+ /* Initialize the new symbol. */
#ifdef STRIP_UNDERSCORE
S_SET_NAME (def_symbol_in_progress, (*symbol_name_copy == '_'
? symbol_name_copy + 1
@@ -2480,7 +2465,7 @@ obj_coff_endef (ignore)
as_warn (_(".endef pseudo-op used outside of .def/.endef: ignored."));
demand_empty_rest_of_line ();
return;
- } /* if not inside .def/.endef */
+ }
/* Set the section number according to storage class. */
switch (S_GET_STORAGE_CLASS (def_symbol_in_progress))
@@ -2489,7 +2474,8 @@ obj_coff_endef (ignore)
case C_ENTAG:
case C_UNTAG:
SF_SET_TAG (def_symbol_in_progress);
- /* intentional fallthrough */
+ /* Intentional fallthrough. */
+
case C_FILE:
case C_TPDEF:
SF_SET_DEBUG (def_symbol_in_progress);
@@ -2497,20 +2483,23 @@ obj_coff_endef (ignore)
break;
case C_EFCN:
- SF_SET_LOCAL (def_symbol_in_progress); /* Do not emit this symbol. */
- /* intentional fallthrough */
+ /* Do not emit this symbol. */
+ SF_SET_LOCAL (def_symbol_in_progress);
+ /* Intentional fallthrough. */
+
case C_BLOCK:
- SF_SET_PROCESS (def_symbol_in_progress); /* Will need processing before writing */
- /* intentional fallthrough */
+ /* Will need processing before writing. */
+ SF_SET_PROCESS (def_symbol_in_progress);
+ /* Intentional fallthrough. */
+
case C_FCN:
S_SET_SEGMENT (def_symbol_in_progress, SEG_E0);
if (strcmp (S_GET_NAME (def_symbol_in_progress), ".bf") == 0)
{ /* .bf */
if (function_lineoff < 0)
- {
- fprintf (stderr, _("`.bf' symbol without preceding function\n"));
- } /* missing function symbol */
+ fprintf (stderr, _("`.bf' symbol without preceding function\n"));
+
SA_GET_SYM_LNNOPTR (last_line_symbol) = function_lineoff;
SF_SET_PROCESS (last_line_symbol);
@@ -2518,6 +2507,7 @@ obj_coff_endef (ignore)
SF_SET_PROCESS (def_symbol_in_progress);
function_lineoff = -1;
}
+
/* Value is always set to . */
def_symbol_in_progress->sy_frag = frag_now;
S_SET_VALUE (def_symbol_in_progress, (valueT) frag_now_fix ());
@@ -2546,7 +2536,7 @@ obj_coff_endef (ignore)
#endif
case C_STAT:
case C_LABEL:
- /* Valid but set somewhere else (s_comm, s_lcomm, colon) */
+ /* Valid but set somewhere else (s_comm, s_lcomm, colon). */
break;
case C_USTATIC:
@@ -2554,7 +2544,7 @@ obj_coff_endef (ignore)
case C_ULABEL:
as_warn (_("unexpected storage class %d"), S_GET_STORAGE_CLASS (def_symbol_in_progress));
break;
- } /* switch on storage class */
+ }
/* Now that we have built a debug symbol, try to find if we should
merge with an existing symbol or not. If a symbol is C_EFCN or
@@ -2609,16 +2599,16 @@ obj_coff_endef (ignore)
/* For functions, and tags, and static symbols, the symbol
*must* be where the debug symbol appears. Move the
existing symbol to the current place. */
- /* If it already is at the end of the symbol list, do nothing */
+ /* If it already is at the end of the symbol list, do nothing. */
if (def_symbol_in_progress != symbol_lastP)
{
symbol_remove (def_symbol_in_progress, &symbol_rootP,
&symbol_lastP);
symbol_append (def_symbol_in_progress, symbol_lastP,
&symbol_rootP, &symbol_lastP);
- } /* if not already in place */
- } /* if function */
- } /* normal or mergable */
+ }
+ }
+ }
if (SF_GET_TAG (def_symbol_in_progress))
{
@@ -2644,8 +2634,8 @@ obj_coff_endef (ignore)
/* That is, if this is the first time we've seen the
function... */
symbol_table_insert (def_symbol_in_progress);
- } /* definition follows debug */
- } /* Create the line number entry pointing to the function being defined */
+ }
+ }
def_symbol_in_progress = NULL;
demand_empty_rest_of_line ();
@@ -2662,7 +2652,7 @@ obj_coff_dim (ignore)
as_warn (_(".dim pseudo-op used outside of .def/.endef: ignored."));
demand_empty_rest_of_line ();
return;
- } /* if not inside .def/.endef */
+ }
S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
@@ -2680,7 +2670,8 @@ obj_coff_dim (ignore)
default:
as_warn (_("badly formed .dim directive ignored"));
- /* intentional fallthrough */
+ /* Intentional fallthrough. */
+
case '\n':
case ';':
dim_index = DIMNUM;
@@ -2715,17 +2706,13 @@ obj_coff_line (ignore)
#if 0 /* XXX Can we ever have line numbers going backwards? */
if (this_base > line_base)
#endif
- {
- line_base = this_base;
- }
+ line_base = this_base;
#ifndef NO_LISTING
{
extern int listing;
if (listing)
- {
- listing_source_line ((unsigned int) line_base);
- }
+ listing_source_line ((unsigned int) line_base);
}
#endif
}
@@ -2745,7 +2732,7 @@ obj_coff_size (ignore)
as_warn (_(".size pseudo-op used outside of .def/.endef ignored."));
demand_empty_rest_of_line ();
return;
- } /* if not inside .def/.endef */
+ }
S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
SA_SET_SYM_SIZE (def_symbol_in_progress, get_absolute_expression ());
@@ -2761,7 +2748,7 @@ obj_coff_scl (ignore)
as_warn (_(".scl pseudo-op used outside of .def/.endef ignored."));
demand_empty_rest_of_line ();
return;
- } /* if not inside .def/.endef */
+ }
S_SET_STORAGE_CLASS (def_symbol_in_progress, get_absolute_expression ());
demand_empty_rest_of_line ();
@@ -2793,9 +2780,7 @@ obj_coff_tag (ignore)
SA_SET_SYM_TAGNDX (def_symbol_in_progress,
(long) tag_find_or_make (symbol_name));
if (SA_GET_SYM_TAGNDX (def_symbol_in_progress) == 0L)
- {
- as_warn (_("tag not found for .tag %s"), symbol_name);
- } /* not defined */
+ as_warn (_("tag not found for .tag %s"), symbol_name);
SF_SET_TAGGED (def_symbol_in_progress);
*input_line_pointer = name_end;
@@ -2812,15 +2797,13 @@ obj_coff_type (ignore)
as_warn (_(".type pseudo-op used outside of .def/.endef ignored."));
demand_empty_rest_of_line ();
return;
- } /* if not inside .def/.endef */
+ }
S_SET_DATA_TYPE (def_symbol_in_progress, get_absolute_expression ());
if (ISFCN (S_GET_DATA_TYPE (def_symbol_in_progress)) &&
S_GET_STORAGE_CLASS (def_symbol_in_progress) != C_TPDEF)
- {
- SF_SET_FUNCTION (def_symbol_in_progress);
- } /* is a function */
+ SF_SET_FUNCTION (def_symbol_in_progress);
demand_empty_rest_of_line ();
}
@@ -2834,7 +2817,7 @@ obj_coff_val (ignore)
as_warn (_(".val pseudo-op used outside of .def/.endef ignored."));
demand_empty_rest_of_line ();
return;
- } /* if not inside .def/.endef */
+ }
if (is_name_beginner (*input_line_pointer))
{
@@ -2849,7 +2832,7 @@ obj_coff_val (ignore)
{
def_symbol_in_progress->sy_frag = frag_now;
S_SET_VALUE (def_symbol_in_progress, (valueT) frag_now_fix ());
- /* If the .val is != from the .def (e.g. statics) */
+ /* If the .val is != from the .def (e.g. statics). */
}
else if (strcmp (S_GET_NAME (def_symbol_in_progress), symbol_name))
{
@@ -2918,13 +2901,13 @@ coff_obj_read_begin_hook ()
}
/* This function runs through the symbol table and puts all the
- externals onto another chain */
+ externals onto another chain. */
/* The chain of globals. */
symbolS *symbol_globalP;
symbolS *symbol_global_lastP;
-/* The chain of externals */
+/* The chain of externals. */
symbolS *symbol_externP;
symbolS *symbol_extern_lastP;
@@ -2961,7 +2944,7 @@ yank_symbols ()
if (!SF_GET_DEBUG (symbolP))
{
- /* Debug symbols do not need all this rubbish */
+ /* Debug symbols do not need all this rubbish. */
symbolS *real_symbolP;
/* L* and C_EFCN symbols never merge. */
@@ -2980,20 +2963,18 @@ yank_symbols ()
list.) Because some pointers refer to the real symbol
whereas no pointers refer to the debug symbol. */
c_symbol_merge (symbolP, real_symbolP);
- /* Replace the current symbol by the real one */
+ /* Replace the current symbol by the real one. */
/* The symbols will never be the last or the first
because : 1st symbol is .file and 3 last symbols are
- .text, .data, .bss */
+ .text, .data, .bss. */
symbol_remove (real_symbolP, &symbol_rootP, &symbol_lastP);
symbol_insert (real_symbolP, symbolP, &symbol_rootP, &symbol_lastP);
symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
symbolP = real_symbolP;
- } /* if not local but dup'd */
+ }
if (flag_readonly_data_in_text && (S_GET_SEGMENT (symbolP) == SEG_E1))
- {
- S_SET_SEGMENT (symbolP, SEG_E0);
- } /* push data into text */
+ S_SET_SEGMENT (symbolP, SEG_E0);
resolve_symbol_value (symbolP);
@@ -3003,17 +2984,15 @@ yank_symbols ()
{
S_SET_EXTERNAL (symbolP);
}
+
else if (S_GET_SEGMENT (symbolP) == SEG_E0)
- {
- S_SET_STORAGE_CLASS (symbolP, C_LABEL);
- }
+ S_SET_STORAGE_CLASS (symbolP, C_LABEL);
+
else
- {
- S_SET_STORAGE_CLASS (symbolP, C_STAT);
- }
+ S_SET_STORAGE_CLASS (symbolP, C_STAT);
}
- /* Mainly to speed up if not -g */
+ /* Mainly to speed up if not -g. */
if (SF_GET_PROCESS (symbolP))
{
/* Handle the nested blocks auxiliary info. */
@@ -3022,8 +3001,10 @@ yank_symbols ()
if (!strcmp (S_GET_NAME (symbolP), ".bb"))
stack_push (block_stack, (char *) &symbolP);
else
- { /* .eb */
- register symbolS *begin_symbolP;
+ {
+ /* .eb */
+ symbolS *begin_symbolP;
+
begin_symbolP = *(symbolS **) stack_pop (block_stack);
if (begin_symbolP == (symbolS *) 0)
as_warn (_("mismatched .eb"));
@@ -3041,13 +3022,11 @@ yank_symbols ()
last_functionP = symbolP;
if (S_GET_NUMBER_AUXILIARY (symbolP) < 1)
- {
- S_SET_NUMBER_AUXILIARY (symbolP, 1);
- } /* make it at least 1 */
+ S_SET_NUMBER_AUXILIARY (symbolP, 1);
/* Clobber possible stale .dim information. */
#if 0
- /* Iffed out by steve - this fries the lnnoptr info too */
+ /* Iffed out by steve - this fries the lnnoptr info too. */
bzero (symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen,
sizeof (symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen));
#endif
@@ -3078,19 +3057,19 @@ yank_symbols ()
else if (SF_GET_TAG (symbolP))
{
/* First descriptor of a structure must point to
- the first slot after the structure description. */
+ the first slot after the structure description. */
last_tagP = symbolP;
}
else if (S_GET_STORAGE_CLASS (symbolP) == C_EOS)
{
- /* +2 take in account the current symbol */
+ /* +2 take in account the current symbol. */
SA_SET_SYM_ENDNDX (last_tagP, symbol_number + 2);
}
else if (S_GET_STORAGE_CLASS (symbolP) == C_FILE)
{
/* If the filename was too long to fit in the
- auxent, put it in the string table */
+ auxent, put it in the string table. */
if (SA_GET_FILE_FNAME_ZEROS (symbolP) == 0
&& SA_GET_FILE_FNAME_OFFSET (symbolP) != 0)
{
@@ -3102,8 +3081,8 @@ yank_symbols ()
{
S_SET_VALUE (symbolP, last_file_symno);
last_file_symno = symbol_number;
- } /* no one points at the first .file symbol */
- } /* if debug or tag or eos or file */
+ }
+ }
#ifdef tc_frob_coff_symbol
tc_frob_coff_symbol (symbolP);
@@ -3122,8 +3101,8 @@ yank_symbols ()
if (SF_GET_LOCAL (symbolP))
{
- /* remove C_EFCN and LOCAL (L...) symbols */
- /* next pointer remains valid */
+ /* Remove C_EFCN and LOCAL (L...) symbols. */
+ /* Next pointer remains valid. */
symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
}
@@ -3143,7 +3122,7 @@ yank_symbols ()
#endif
|| S_GET_STORAGE_CLASS (symbolP) == C_WEAKEXT))
{
- /* if external, Remove from the list */
+ /* If external, Remove from the list. */
symbolS *hold = symbol_previous (symbolP);
symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
@@ -3165,7 +3144,6 @@ yank_symbols ()
/* The O'Reilly COFF book says that defined global symbols
come at the end of the symbol table, just before
undefined global symbols. */
-
symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
symbol_clear_list_pointers (symbolP);
symbol_append (symbolP, symbol_global_lastP, &symbol_globalP,
@@ -3182,14 +3160,14 @@ yank_symbols ()
else
{
symbolP->sy_name_offset = 0;
- } /* fix "long" names */
+ }
symbolP->sy_number = symbol_number;
symbol_number += 1 + S_GET_NUMBER_AUXILIARY (symbolP);
- } /* if local symbol */
- } /* traverse the symbol list */
- return symbol_number;
+ }
+ }
+ return symbol_number;
}
static unsigned int
@@ -3203,11 +3181,11 @@ glue_symbols (head, tail)
{
symbolS *tmp = *head;
- /* append */
+ /* Append. */
symbol_remove (tmp, head, tail);
symbol_append (tmp, symbol_lastP, &symbol_rootP, &symbol_lastP);
- /* and process */
+ /* Process. */
if (SF_GET_STRING (tmp))
{
tmp->sy_name_offset = string_byte_count;
@@ -3215,12 +3193,13 @@ glue_symbols (head, tail)
}
else
{
+ /* Fix "long" names. */
tmp->sy_name_offset = 0;
- } /* fix "long" names */
+ }
tmp->sy_number = symbol_number;
symbol_number += 1 + S_GET_NUMBER_AUXILIARY (tmp);
- } /* append the entire extern chain */
+ }
return symbol_number;
}
@@ -3248,6 +3227,7 @@ tie_tags ()
return symbol_number;
}
+
static void
crawl_symbols (h, abfd)
object_headers *h;
@@ -3255,40 +3235,35 @@ crawl_symbols (h, abfd)
{
unsigned int i;
- /* Initialize the stack used to keep track of the matching .bb .be */
+ /* Initialize the stack used to keep track of the matching .bb .be. */
block_stack = stack_init (512, sizeof (symbolS *));
/* The symbol list should be ordered according to the following sequence
- * order :
- * . .file symbol
- * . debug entries for functions
- * . fake symbols for the sections, including .text .data and .bss
- * . defined symbols
- * . undefined symbols
- * But this is not mandatory. The only important point is to put the
- * undefined symbols at the end of the list.
- */
+ order :
+ . .file symbol
+ . debug entries for functions
+ . fake symbols for the sections, including .text .data and .bss
+ . defined symbols
+ . undefined symbols
+ But this is not mandatory. The only important point is to put the
+ undefined symbols at the end of the list. */
/* Is there a .file symbol ? If not insert one at the beginning. */
if (symbol_rootP == NULL
|| S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE)
- {
- c_dot_file_symbol ("fake");
- }
+ c_dot_file_symbol ("fake");
- /*
- * Build up static symbols for the sections, they are filled in later
- */
+ /* Build up static symbols for the sections, they are filled in later. */
for (i = SEG_E0; i < SEG_LAST; i++)
if (segment_info[i].scnhdr.s_name[0])
- segment_info[i].dot = c_section_symbol (segment_info[i].name,
+ segment_info[i].dot = c_section_symbol ((char *) segment_info[i].name,
i - SEG_E0 + 1);
- /* Take all the externals out and put them into another chain */
+ /* Take all the externals out and put them into another chain. */
H_SET_SYMBOL_TABLE_SIZE (h, yank_symbols ());
- /* Take the externals and glue them onto the end.*/
+ /* Take the externals and glue them onto the end. */
H_SET_SYMBOL_TABLE_SIZE (h,
(H_GET_SYMBOL_COUNT (h)
+ glue_symbols (&symbol_globalP,
@@ -3303,9 +3278,7 @@ crawl_symbols (h, abfd)
know (symbol_extern_lastP == NULL);
}
-/*
- * Find strings by crawling along symbol table chain.
- */
+/* Find strings by crawling along symbol table chain. */
void
w_strings (where)
@@ -3314,7 +3287,7 @@ w_strings (where)
symbolS *symbolP;
struct filename_list *filename_list_scan = filename_list_head;
- /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */
+ /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK. */
md_number_to_chars (where, (valueT) string_byte_count, 4);
where += 4;
@@ -3386,7 +3359,7 @@ do_linenos_for (abfd, h, file_cursor)
struct external_lineno *dst = buffer;
/* Run through the table we've built and turn it into its external
- form, take this chance to remove duplicates */
+ form, take this chance to remove duplicates. */
for (line_ptr = s->lineno_list_head;
line_ptr != (struct lineno_list *) NULL;
@@ -3401,13 +3374,10 @@ do_linenos_for (abfd, h, file_cursor)
((symbolS *) line_ptr->line.l_addr.l_symndx)->sy_number;
}
else
- {
- line_ptr->line.l_addr.l_paddr += ((struct frag *) (line_ptr->frag))->fr_address;
- }
+ line_ptr->line.l_addr.l_paddr += ((struct frag *) (line_ptr->frag))->fr_address;
(void) bfd_coff_swap_lineno_out (abfd, &(line_ptr->line), dst);
dst++;
-
}
s->scnhdr.s_lnnoptr = *file_cursor;
@@ -3418,12 +3388,13 @@ do_linenos_for (abfd, h, file_cursor)
*file_cursor += s->scnhdr.s_nlnno * LINESZ;
}
}
+
H_SET_LINENO_SIZE (h, *file_cursor - start);
}
/* Now we run through the list of frag chains in a segment and
make all the subsegment frags appear at the end of the
- list, as if the seg 0 was extra long */
+ list, as if the seg 0 was extra long. */
static void
remove_subsegs ()
@@ -3448,6 +3419,7 @@ remove_subsegs ()
unsigned long machine;
int coff_flags;
+
extern void
write_object_file ()
{
@@ -3506,9 +3478,7 @@ write_object_file ()
remove_subsegs ();
for (i = SEG_E0; i < SEG_UNKNOWN; i++)
- {
- relax_segment (segment_info[i].frchainP->frch_root, i);
- }
+ relax_segment (segment_info[i].frchainP->frch_root, i);
/* Relaxation has completed. Freeze all syms. */
finalize_syms = 1;
@@ -3562,7 +3532,7 @@ write_object_file ()
H_SET_BSS_SIZE (&headers, size);
}
- /* Turn the gas native symbol table shape into a coff symbol table */
+ /* Turn the gas native symbol table shape into a coff symbol table. */
crawl_symbols (&headers, abfd);
if (string_byte_count == 4)
@@ -3596,8 +3566,7 @@ write_object_file ()
bfd_seek (abfd, (file_ptr) file_cursor, 0);
- /* Plant the data */
-
+ /* Plant the data. */
fill_section (abfd, &headers, &file_cursor);
do_relocs_for (abfd, &headers, &file_cursor);
@@ -3692,28 +3661,26 @@ obj_coff_add_segment (name)
return (segT) i;
}
-/*
- * implement the .section pseudo op:
- * .section name {, "flags"}
- * ^ ^
- * | +--- optional flags: 'b' for bss
- * | 'i' for info
- * +-- section name 'l' for lib
- * 'n' for noload
- * 'o' for over
- * 'w' for data
- * 'd' (apparently m88k for data)
- * 'x' for text
- * 'r' for read-only data
- * But if the argument is not a quoted string, treat it as a
- * subsegment number.
- */
+/* Implement the .section pseudo op:
+ .section name {, "flags"}
+ ^ ^
+ | +--- optional flags: 'b' for bss
+ | 'i' for info
+ +-- section name 'l' for lib
+ 'n' for noload
+ 'o' for over
+ 'w' for data
+ 'd' (apparently m88k for data)
+ 'x' for text
+ 'r' for read-only data
+ But if the argument is not a quoted string, treat it as a
+ subsegment number. */
void
obj_coff_section (ignore)
int ignore ATTRIBUTE_UNUSED;
{
- /* Strip out the section name */
+ /* Strip out the section name. */
char *section_name, *name;
char c;
unsigned int exp;
@@ -3810,11 +3777,12 @@ static void
obj_coff_ident (ignore)
int ignore ATTRIBUTE_UNUSED;
{
- segT current_seg = now_seg; /* save current seg */
+ segT current_seg = now_seg; /* Save current seg. */
subsegT current_subseg = now_subseg;
- subseg_new (".comment", 0); /* .comment seg */
- stringer (1); /* read string */
- subseg_set (current_seg, current_subseg); /* restore current seg */
+
+ subseg_new (".comment", 0); /* .comment seg. */
+ stringer (1); /* Read string. */
+ subseg_set (current_seg, current_subseg); /* Restore current seg. */
}
void
@@ -3826,20 +3794,16 @@ c_symbol_merge (debug, normal)
S_SET_STORAGE_CLASS (normal, S_GET_STORAGE_CLASS (debug));
if (S_GET_NUMBER_AUXILIARY (debug) > S_GET_NUMBER_AUXILIARY (normal))
- {
- S_SET_NUMBER_AUXILIARY (normal, S_GET_NUMBER_AUXILIARY (debug));
- } /* take the most we have */
+ S_SET_NUMBER_AUXILIARY (normal, S_GET_NUMBER_AUXILIARY (debug));
if (S_GET_NUMBER_AUXILIARY (debug) > 0)
- {
- memcpy ((char *) &normal->sy_symbol.ost_auxent[0],
- (char *) &debug->sy_symbol.ost_auxent[0],
- (unsigned int) (S_GET_NUMBER_AUXILIARY (debug) * AUXESZ));
- } /* Move all the auxiliary information */
+ memcpy ((char *) &normal->sy_symbol.ost_auxent[0],
+ (char *) &debug->sy_symbol.ost_auxent[0],
+ (unsigned int) (S_GET_NUMBER_AUXILIARY (debug) * AUXESZ));
/* Move the debug flags. */
SF_SET_DEBUG_FIELD (normal, SF_GET_DEBUG_FIELD (debug));
-} /* c_symbol_merge() */
+}
static int
c_line_new (symbol, paddr, line_number, frag)
@@ -3868,13 +3832,10 @@ c_line_new (symbol, paddr, line_number, frag)
new_line->next = (struct lineno_list *) NULL;
if (s->lineno_list_head == (struct lineno_list *) NULL)
- {
- s->lineno_list_head = new_line;
- }
+ s->lineno_list_head = new_line;
else
- {
- s->lineno_list_tail->next = new_line;
- }
+ s->lineno_list_tail->next = new_line;
+
s->lineno_list_tail = new_line;
return LINESZ * s->scnhdr.s_nlnno++;
}
@@ -3898,7 +3859,7 @@ c_dot_file_symbol (filename)
/* Filename is too long to fit into an auxent,
we stick it into the string table instead. We keep
a linked list of the filenames we find so we can emit
- them later.*/
+ them later. */
struct filename_list *f = ((struct filename_list *)
xmalloc (sizeof (struct filename_list)));
@@ -3922,29 +3883,23 @@ c_dot_file_symbol (filename)
{
extern int listing;
if (listing)
- {
- listing_source_file (filename);
- }
-
+ listing_source_file (filename);
}
-
#endif
SF_SET_DEBUG (symbolP);
S_SET_VALUE (symbolP, (valueT) previous_file_symbol);
previous_file_symbol = symbolP;
- /* Make sure that the symbol is first on the symbol chain */
+ /* Make sure that the symbol is first on the symbol chain. */
if (symbol_rootP != symbolP)
{
symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
symbol_insert (symbolP, symbol_rootP, &symbol_rootP, &symbol_lastP);
}
-} /* c_dot_file_symbol() */
+}
-/*
- * Build a 'section static' symbol.
- */
+/* Build a 'section static' symbol. */
symbolS *
c_section_symbol (name, idx)
@@ -4004,7 +3959,7 @@ c_section_symbol (name, idx)
#endif /* TE_PE */
return symbolP;
-} /* c_section_symbol() */
+}
static void
w_symbols (abfd, where, symbol_rootP)
@@ -4015,7 +3970,7 @@ w_symbols (abfd, where, symbol_rootP)
symbolS *symbolP;
unsigned int i;
- /* First fill in those values we have only just worked out */
+ /* First fill in those values we have only just worked out. */
for (i = SEG_E0; i < SEG_LAST; i++)
{
symbolP = segment_info[i].dot;
@@ -4027,23 +3982,19 @@ w_symbols (abfd, where, symbol_rootP)
}
}
- /*
- * Emit all symbols left in the symbol chain.
- */
+ /* Emit all symbols left in the symbol chain. */
for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
{
/* Used to save the offset of the name. It is used to point
- to the string in memory but must be a file offset. */
- register char *temp;
+ to the string in memory but must be a file offset. */
+ char *temp;
/* We can't fix the lnnoptr field in yank_symbols with the other
adjustments, because we have to wait until we know where they
go in the file. */
if (SF_GET_ADJ_LNNOPTR (symbolP))
- {
- SA_GET_SYM_LNNOPTR (symbolP) +=
- segment_info[S_GET_SEGMENT (symbolP)].scnhdr.s_lnnoptr;
- }
+ SA_GET_SYM_LNNOPTR (symbolP) +=
+ segment_info[S_GET_SEGMENT (symbolP)].scnhdr.s_lnnoptr;
tc_coff_symbol_emit_hook (symbolP);
@@ -4061,8 +4012,7 @@ w_symbols (abfd, where, symbol_rootP)
where = symbol_to_chars (abfd, where, symbolP);
S_SET_NAME (symbolP, temp);
}
-
-} /* w_symbols() */
+}
static void
obj_coff_lcomm (ignore)
@@ -4112,7 +4062,7 @@ obj_coff_lcomm (ignore)
if (! need_pass_2)
{
char *p;
- segT current_seg = now_seg; /* save current seg */
+ segT current_seg = now_seg; /* Save current seg. */
subsegT current_subseg = now_subseg;
subseg_set (SEG_E2, 1);
@@ -4120,7 +4070,7 @@ obj_coff_lcomm (ignore)
p = frag_var(rs_org, 1, 1, (relax_substateT)0, symbolP,
(offsetT) temp, (char *) 0);
*p = 0;
- subseg_set (current_seg, current_subseg); /* restore current seg */
+ subseg_set (current_seg, current_subseg); /* Restore current seg. */
S_SET_SEGMENT (symbolP, SEG_E2);
S_SET_STORAGE_CLASS (symbolP, C_STAT);
}
@@ -4139,6 +4089,7 @@ fixup_mdeps (frags, h, this_segment)
segT this_segment;
{
subseg_change (this_segment, 0);
+
while (frags)
{
switch (frags->fr_type)
@@ -4177,16 +4128,16 @@ fixup_segment (segP, this_segment_type)
segment_info_type * segP;
segT this_segment_type;
{
- register fixS * fixP;
- register symbolS *add_symbolP;
- register symbolS *sub_symbolP;
+ fixS * fixP;
+ symbolS *add_symbolP;
+ symbolS *sub_symbolP;
long add_number;
- register int size;
- register char *place;
- register long where;
- register char pcrel;
- register fragS *fragP;
- register segT add_symbol_segment = absolute_section;
+ int size;
+ char *place;
+ long where;
+ char pcrel;
+ fragS *fragP;
+ segT add_symbol_segment = absolute_section;
for (fixP = segP->fix_root; fixP; fixP = fixP->fx_next)
{
@@ -4274,9 +4225,7 @@ fixup_segment (segP, this_segment_type)
}
if (add_symbolP)
- {
- add_symbol_segment = S_GET_SEGMENT (add_symbolP);
- } /* if there is an addend */
+ add_symbol_segment = S_GET_SEGMENT (add_symbolP);
if (sub_symbolP)
{
@@ -4307,7 +4256,7 @@ fixup_segment (segP, this_segment_type)
} /* not absolute */
/* if sub_symbol is in the same segment that add_symbol
- and add_symbol is either in DATA, TEXT, BSS or ABSOLUTE */
+ and add_symbol is either in DATA, TEXT, BSS or ABSOLUTE. */
}
else if (S_GET_SEGMENT (sub_symbolP) == add_symbol_segment
&& SEG_NORMAL (add_symbol_segment))
@@ -4319,10 +4268,8 @@ fixup_segment (segP, this_segment_type)
/* Makes no sense to use the difference of 2 arbitrary symbols
as the target of a call instruction. */
if (fixP->fx_tcbit)
- {
- as_bad_where (fixP->fx_file, fixP->fx_line,
- _("callj to difference of 2 symbols"));
- }
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("callj to difference of 2 symbols"));
#endif /* TC_I960 */
add_number += S_GET_VALUE (add_symbolP) -
S_GET_VALUE (sub_symbolP);
@@ -4345,9 +4292,8 @@ fixup_segment (segP, this_segment_type)
know (!(S_IS_EXTERNAL (sub_symbolP) && (S_GET_SEGMENT (sub_symbolP) == absolute_section)));
if ((S_GET_SEGMENT (sub_symbolP) == absolute_section))
- {
- add_number -= S_GET_VALUE (sub_symbolP);
- }
+ add_number -= S_GET_VALUE (sub_symbolP);
+
#ifdef DIFF_EXPR_OK
else if (S_GET_SEGMENT (sub_symbolP) == this_segment_type
#if 0 /* Okay for 68k, at least... */
@@ -4371,25 +4317,22 @@ fixup_segment (segP, this_segment_type)
segment_name (S_GET_SEGMENT (sub_symbolP)),
S_GET_NAME (sub_symbolP),
(long) (fragP->fr_address + where));
- } /* if absolute */
+ }
}
- } /* if sub_symbolP */
+ }
if (add_symbolP)
{
if (add_symbol_segment == this_segment_type && pcrel)
{
- /*
- * This fixup was made when the symbol's segment was
- * SEG_UNKNOWN, but it is now in the local segment.
- * So we know how to do the address without relocation.
- */
+ /* This fixup was made when the symbol's segment was
+ SEG_UNKNOWN, but it is now in the local segment.
+ So we know how to do the address without relocation. */
#ifdef TC_I960
/* reloc_callj() may replace a 'call' with a 'calls' or a 'bal',
- * in which cases it modifies *fixP as appropriate. In the case
- * of a 'calls', no further work is required, and *fixP has been
- * set up to make the rest of the code below a no-op.
- */
+ in which cases it modifies *fixP as appropriate. In the case
+ of a 'calls', no further work is required, and *fixP has been
+ set up to make the rest of the code below a no-op. */
reloc_callj (fixP);
#endif /* TC_I960 */
@@ -4423,7 +4366,8 @@ fixup_segment (segP, this_segment_type)
{
case absolute_section:
#ifdef TC_I960
- reloc_callj (fixP); /* See comment about reloc_callj() above*/
+ /* See comment about reloc_callj() above. */
+ reloc_callj (fixP);
#endif /* TC_I960 */
add_number += S_GET_VALUE (add_symbolP);
add_symbolP = NULL;
@@ -4451,16 +4395,15 @@ fixup_segment (segP, this_segment_type)
if ((int) fixP->fx_bit_fixP == 13)
{
/* This is a COBR instruction. They have only a
- * 13-bit displacement and are only to be used
- * for local branches: flag as error, don't generate
- * relocation.
- */
+ 13-bit displacement and are only to be used
+ for local branches: flag as error, don't generate
+ relocation. */
as_bad_where (fixP->fx_file, fixP->fx_line,
_("can't use COBR format with external label"));
fixP->fx_addsy = NULL;
fixP->fx_done = 1;
continue;
- } /* COBR */
+ }
#endif /* TC_I960 */
#if ((defined (TC_I386) || defined (TE_LYNX) || defined (TE_AUX)) && !defined(TE_PE)) || defined (COFF_COMMON_ADDEND)
/* 386 COFF uses a peculiar format in which the
@@ -4476,9 +4419,9 @@ fixup_segment (segP, this_segment_type)
#endif
break;
- } /* switch on symbol seg */
- } /* if not in local seg */
- } /* if there was a + symbol */
+ }
+ }
+ }
if (pcrel)
{
@@ -4488,9 +4431,7 @@ fixup_segment (segP, this_segment_type)
add_number -= md_pcrel_from (fixP);
#endif
if (add_symbolP == 0)
- {
- fixP->fx_addsy = &abs_symbol;
- } /* if there's an add_symbol */
+ fixP->fx_addsy = &abs_symbol;
#if defined (TC_I386) || defined (TE_LYNX) || defined (TC_I960) || defined (TC_M68K)
/* On the 386 we must adjust by the segment vaddr as well.
Ian Taylor.
@@ -4510,7 +4451,7 @@ fixup_segment (segP, this_segment_type)
add_number -= segP->scnhdr.s_vaddr;
#endif
- } /* if pcrel */
+ }
md_apply_fix3 (fixP, (valueT *) & add_number, this_segment_type);
@@ -4549,9 +4490,9 @@ fixup_segment (segP, this_segment_type)
(long) add_number,
(unsigned long) (fragP->fr_address + where));
#endif
- } /* not a bit fix */
- } /* For each fixS in this segment. */
-} /* fixup_segment() */
+ }
+ }
+}
#endif
diff --git a/contrib/binutils/gas/config/tc-arm.c b/contrib/binutils/gas/config/tc-arm.c
index 162553f..2d8cc7c 100644
--- a/contrib/binutils/gas/config/tc-arm.c
+++ b/contrib/binutils/gas/config/tc-arm.c
@@ -521,7 +521,7 @@ struct vfp_reg
unsigned long regno;
};
-static const struct vfp_reg vfp_regs[] =
+static const struct vfp_reg vfp_regs[] =
{
{"fpsid", 0x00000000},
{"FPSID", 0x00000000},
@@ -842,7 +842,7 @@ static void do_mav_binops_3a PARAMS ((char *));
static void do_mav_binops_3b PARAMS ((char *));
static void do_mav_binops_3c PARAMS ((char *));
static void do_mav_binops_3d PARAMS ((char *));
-static void do_mav_triple PARAMS ((char *, int, enum arm_reg_type,
+static void do_mav_triple PARAMS ((char *, int, enum arm_reg_type,
enum arm_reg_type,
enum arm_reg_type));
static void do_mav_triple_4a PARAMS ((char *));
@@ -855,7 +855,7 @@ static void do_mav_triple_5e PARAMS ((char *));
static void do_mav_triple_5f PARAMS ((char *));
static void do_mav_triple_5g PARAMS ((char *));
static void do_mav_triple_5h PARAMS ((char *));
-static void do_mav_quad PARAMS ((char *, int, enum arm_reg_type,
+static void do_mav_quad PARAMS ((char *, int, enum arm_reg_type,
enum arm_reg_type,
enum arm_reg_type,
enum arm_reg_type));
@@ -1106,7 +1106,7 @@ static const struct asm_opcode insns[] =
{"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
/* ARM Architecture 4T. */
- /* Note: bx (and blx) are required on V5, even if the processor does
+ /* Note: bx (and blx) are required on V5, even if the processor does
not support Thumb. */
{"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
@@ -7447,7 +7447,9 @@ thumb_add_sub (str, subtract)
return;
}
}
- else
+ /* Note - you cannot convert a subtract of 0 into an
+ add of 0 because the carry flag is set differently. */
+ else if (offset > 0)
subtract = 0;
if (Rd == REG_SP)
@@ -7927,7 +7929,7 @@ mav_reg_required_here (str, shift, regtype)
/* Restore the start point. */
*str = start;
-
+
/* In the few cases where we might be able to accept something else
this error can be overridden. */
inst.error = _(all_reg_maps[regtype].expected);
diff --git a/contrib/binutils/gas/config/tc-i386.c b/contrib/binutils/gas/config/tc-i386.c
index 1d874af..f681014 100644
--- a/contrib/binutils/gas/config/tc-i386.c
+++ b/contrib/binutils/gas/config/tc-i386.c
@@ -182,9 +182,9 @@ typedef struct _i386_insn i386_insn;
/* List of chars besides those in app.c:symbol_chars that can start an
operand. Used to prevent the scrubber eating vital white-space. */
#ifdef LEX_AT
-const char extra_symbol_chars[] = "*%-(@";
+const char extra_symbol_chars[] = "*%-(@[";
#else
-const char extra_symbol_chars[] = "*%-(";
+const char extra_symbol_chars[] = "*%-([";
#endif
#if (defined (TE_I386AIX) \
@@ -2208,15 +2208,15 @@ process_suffix ()
/* For movzx and movsx, need to check the register type. */
if (intel_syntax
- && (i.tm.base_opcode == 0xfb6 || i.tm.base_opcode == 0xfbe))
- if (i.suffix && i.suffix == BYTE_MNEM_SUFFIX)
- {
- unsigned int prefix = DATA_PREFIX_OPCODE;
+ && (i.tm.base_opcode == 0xfb6 || i.tm.base_opcode == 0xfbe)
+ && i.suffix == BYTE_MNEM_SUFFIX)
+ {
+ unsigned int prefix = DATA_PREFIX_OPCODE;
- if ((i.op[1].regs->reg_type & Reg16) != 0)
- if (!add_prefix (prefix))
- return 0;
- }
+ if ((i.op[1].regs->reg_type & Reg16) != 0)
+ if (!add_prefix (prefix))
+ return 0;
+ }
if (i.suffix && i.suffix != BYTE_MNEM_SUFFIX)
{
@@ -2228,6 +2228,7 @@ process_suffix ()
else
i.tm.base_opcode |= 1;
}
+
/* Now select between word & dword operations via the operand
size prefix, except for instructions that will ignore this
prefix anyway. */
@@ -2309,7 +2310,7 @@ check_byte_reg ()
if (flag_code == CODE_64BIT
&& (i.tm.operand_types[op] & InOutPortReg) == 0)
{
- as_bad (_("Incorrect register `%%%s' used with`%c' suffix"),
+ as_bad (_("Incorrect register `%%%s' used with `%c' suffix"),
i.op[op].regs->reg_name,
i.suffix);
return 0;
@@ -2368,7 +2369,7 @@ check_long_reg ()
lowering is more complicated. */
if (flag_code == CODE_64BIT)
{
- as_bad (_("Incorrect register `%%%s' used with`%c' suffix"),
+ as_bad (_("Incorrect register `%%%s' used with `%c' suffix"),
i.op[op].regs->reg_name,
i.suffix);
return 0;
@@ -2385,7 +2386,7 @@ check_long_reg ()
else if ((i.types[op] & Reg64) != 0
&& (i.tm.operand_types[op] & (Reg32 | Acc)) != 0)
{
- as_bad (_("Incorrect register `%%%s' used with`%c' suffix"),
+ as_bad (_("Incorrect register `%%%s' used with `%c' suffix"),
i.op[op].regs->reg_name,
i.suffix);
return 0;
@@ -2417,7 +2418,7 @@ check_qword_reg ()
{
/* Prohibit these changes in the 64bit mode, since the
lowering is more complicated. */
- as_bad (_("Incorrect register `%%%s' used with`%c' suffix"),
+ as_bad (_("Incorrect register `%%%s' used with `%c' suffix"),
i.op[op].regs->reg_name,
i.suffix);
return 0;
@@ -2450,7 +2451,7 @@ check_word_reg ()
lowering is more complicated. */
if (flag_code == CODE_64BIT)
{
- as_bad (_("Incorrect register `%%%s' used with`%c' suffix"),
+ as_bad (_("Incorrect register `%%%s' used with `%c' suffix"),
i.op[op].regs->reg_name,
i.suffix);
return 0;
@@ -2980,7 +2981,6 @@ output_jump ()
{
char *p;
int size;
- fixS *fixP;
if (i.tm.opcode_modifier & JumpByte)
{
@@ -3031,9 +3031,8 @@ output_jump ()
p = frag_more (1 + size);
*p++ = i.tm.base_opcode;
- fixP = fix_new_exp (frag_now, p - frag_now->fr_literal, size,
- i.op[0].disps, 1, reloc (size, 1, 1, i.reloc[0]));
- fixP->fx_pcrel_adjust = size;
+ fix_new_exp (frag_now, p - frag_now->fr_literal, size,
+ i.op[0].disps, 1, reloc (size, 1, 1, i.reloc[0]));
}
static void
@@ -3226,7 +3225,6 @@ output_disp ()
int size = 4;
int sign = 0;
int pcrel = (i.flags[n] & Operand_PCrel) != 0;
- fixS *fixP;
/* The PC relative address is computed relative
to the instruction boundary, so in case immediate
@@ -3266,11 +3264,9 @@ output_disp ()
}
p = frag_more (size);
- fixP = fix_new_exp (frag_now, p - frag_now->fr_literal, size,
- i.op[n].disps, pcrel,
- reloc (size, pcrel, sign, i.reloc[n]));
- if (pcrel)
- fixP->fx_pcrel_adjust = size;
+ fix_new_exp (frag_now, p - frag_now->fr_literal, size,
+ i.op[n].disps, pcrel,
+ reloc (size, pcrel, sign, i.reloc[n]));
}
}
}
@@ -4215,7 +4211,6 @@ md_estimate_size_before_relax (fragP, segment)
RELOC_ENUM reloc_type;
unsigned char *opcode;
int old_fr_fix;
- fixS *fixP;
if (fragP->fr_var != NO_RELOC)
reloc_type = fragP->fr_var;
@@ -4233,18 +4228,15 @@ md_estimate_size_before_relax (fragP, segment)
/* Make jmp (0xeb) a (d)word displacement jump. */
opcode[0] = 0xe9;
fragP->fr_fix += size;
- fixP = fix_new (fragP, old_fr_fix, size,
- fragP->fr_symbol,
- fragP->fr_offset, 1,
- reloc_type);
- fixP->fx_pcrel_adjust = size;
+ fix_new (fragP, old_fr_fix, size,
+ fragP->fr_symbol,
+ fragP->fr_offset, 1,
+ reloc_type);
break;
case COND_JUMP86:
- if (no_cond_jump_promotion)
- goto relax_guess;
-
- if (size == 2)
+ if (size == 2
+ && (!no_cond_jump_promotion || fragP->fr_var != NO_RELOC))
{
/* Negate the condition, and branch past an
unconditional jump. */
@@ -4255,18 +4247,24 @@ md_estimate_size_before_relax (fragP, segment)
/* We added two extra opcode bytes, and have a two byte
offset. */
fragP->fr_fix += 2 + 2;
- fixP = fix_new (fragP, old_fr_fix + 2, 2,
- fragP->fr_symbol,
- fragP->fr_offset, 1,
- reloc_type);
- fixP->fx_pcrel_adjust = size;
+ fix_new (fragP, old_fr_fix + 2, 2,
+ fragP->fr_symbol,
+ fragP->fr_offset, 1,
+ reloc_type);
break;
}
/* Fall through. */
case COND_JUMP:
- if (no_cond_jump_promotion)
- goto relax_guess;
+ if (no_cond_jump_promotion && fragP->fr_var == NO_RELOC)
+ {
+ fragP->fr_fix += 1;
+ fix_new (fragP, old_fr_fix, 1,
+ fragP->fr_symbol,
+ fragP->fr_offset, 1,
+ BFD_RELOC_8_PCREL);
+ break;
+ }
/* This changes the byte-displacement jump 0x7N
to the (d)word-displacement jump 0x0f,0x8N. */
@@ -4274,11 +4272,10 @@ md_estimate_size_before_relax (fragP, segment)
opcode[0] = TWO_BYTE_OPCODE_ESCAPE;
/* We've added an opcode byte. */
fragP->fr_fix += 1 + size;
- fixP = fix_new (fragP, old_fr_fix + 1, size,
- fragP->fr_symbol,
- fragP->fr_offset, 1,
- reloc_type);
- fixP->fx_pcrel_adjust = size;
+ fix_new (fragP, old_fr_fix + 1, size,
+ fragP->fr_symbol,
+ fragP->fr_offset, 1,
+ reloc_type);
break;
default:
@@ -4289,7 +4286,6 @@ md_estimate_size_before_relax (fragP, segment)
return fragP->fr_fix - old_fr_fix;
}
- relax_guess:
/* Guess size depending on current relax state. Initially the relax
state will correspond to a short jump and we return 1, because
the variable part of the frag (the branch offset) is one byte
@@ -4607,6 +4603,8 @@ md_apply_fix3 (fixP, valP, seg)
else if (use_rela_relocations)
{
fixP->fx_no_overflow = 1;
+ /* Remember value for tc_gen_reloc. */
+ fixP->fx_addnumber = value;
value = 0;
}
#endif
@@ -5120,9 +5118,23 @@ tc_gen_reloc (section, fixp)
/* Use the rela in 64bit mode. */
else
{
- rel->addend = fixp->fx_offset;
- if (fixp->fx_pcrel)
- rel->addend -= fixp->fx_pcrel_adjust;
+ if (!fixp->fx_pcrel)
+ rel->addend = fixp->fx_offset;
+ else
+ switch (code)
+ {
+ case BFD_RELOC_X86_64_PLT32:
+ case BFD_RELOC_X86_64_GOT32:
+ case BFD_RELOC_X86_64_GOTPCREL:
+ rel->addend = fixp->fx_offset - fixp->fx_size;
+ break;
+ default:
+ rel->addend = (section->vma
+ - fixp->fx_size
+ + fixp->fx_addnumber
+ + md_pcrel_from (fixp));
+ break;
+ }
}
rel->howto = bfd_reloc_type_lookup (stdoutput, code);
diff --git a/contrib/binutils/gas/config/tc-ppc.c b/contrib/binutils/gas/config/tc-ppc.c
index 560622b..f7872a0 100644
--- a/contrib/binutils/gas/config/tc-ppc.c
+++ b/contrib/binutils/gas/config/tc-ppc.c
@@ -1374,7 +1374,7 @@ ppc_elf_suffix (str_p, exp_p)
MAP ("plt@h", (int) BFD_RELOC_HI16_PLTOFF),
MAP ("plt@ha", (int) BFD_RELOC_HI16_S_PLTOFF),
MAP ("sdarel", (int) BFD_RELOC_GPREL16),
- MAP ("sectoff", (int) BFD_RELOC_32_BASEREL),
+ MAP ("sectoff", (int) BFD_RELOC_16_BASEREL),
MAP ("sectoff@l", (int) BFD_RELOC_LO16_BASEREL),
MAP ("sectoff@h", (int) BFD_RELOC_HI16_BASEREL),
MAP ("sectoff@ha", (int) BFD_RELOC_HI16_S_BASEREL),
@@ -1683,7 +1683,7 @@ ppc_elf_validate_fix (fixp, seg)
&& fixp->fx_r_type != BFD_RELOC_HI16_GOTOFF
&& fixp->fx_r_type != BFD_RELOC_LO16_GOTOFF
&& fixp->fx_r_type != BFD_RELOC_HI16_S_GOTOFF
- && fixp->fx_r_type != BFD_RELOC_32_BASEREL
+ && fixp->fx_r_type != BFD_RELOC_16_BASEREL
&& fixp->fx_r_type != BFD_RELOC_LO16_BASEREL
&& fixp->fx_r_type != BFD_RELOC_HI16_BASEREL
&& fixp->fx_r_type != BFD_RELOC_HI16_S_BASEREL
@@ -2236,7 +2236,7 @@ md_assemble (str)
case BFD_RELOC_LO16_PLTOFF:
reloc = BFD_RELOC_PPC64_PLT16_LO_DS;
break;
- case BFD_RELOC_32_BASEREL:
+ case BFD_RELOC_16_BASEREL:
reloc = BFD_RELOC_PPC64_SECTOFF_DS;
break;
case BFD_RELOC_LO16_BASEREL:
@@ -5280,7 +5280,6 @@ md_apply_fix3 (fixP, valP, seg)
case BFD_RELOC_RVA:
case BFD_RELOC_32_PCREL:
- case BFD_RELOC_32_BASEREL:
case BFD_RELOC_PPC_EMB_NADDR32:
md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
value, 4);
@@ -5305,6 +5304,7 @@ md_apply_fix3 (fixP, valP, seg)
case BFD_RELOC_LO16_GOTOFF:
case BFD_RELOC_HI16_GOTOFF:
case BFD_RELOC_HI16_S_GOTOFF:
+ case BFD_RELOC_16_BASEREL:
case BFD_RELOC_LO16_BASEREL:
case BFD_RELOC_HI16_BASEREL:
case BFD_RELOC_HI16_S_BASEREL:
diff --git a/contrib/binutils/gas/config/tc-s390.c b/contrib/binutils/gas/config/tc-s390.c
new file mode 100644
index 0000000..4e09ab5
--- /dev/null
+++ b/contrib/binutils/gas/config/tc-s390.c
@@ -0,0 +1,1977 @@
+/* tc-s390.c -- Assemble for the S390
+ Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
+ Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
+
+ 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 "as.h"
+#include "safe-ctype.h"
+#include "subsegs.h"
+#include "struc-symbol.h"
+
+#include "opcode/s390.h"
+#include "elf/s390.h"
+
+/* The default architecture. */
+#ifndef DEFAULT_ARCH
+#define DEFAULT_ARCH "s390"
+#endif
+static char *default_arch = DEFAULT_ARCH;
+/* Either 32 or 64, selects file format. */
+static int s390_arch_size;
+/* Current architecture. Start with the smallest instruction set. */
+static enum s390_opcode_arch_val current_architecture = S390_OPCODE_ESA;
+static int current_arch_mask = 1 << S390_OPCODE_ESA;
+static int current_arch_requested = 0;
+
+/* Whether to use user friendly register names. Default is true. */
+#ifndef TARGET_REG_NAMES_P
+#define TARGET_REG_NAMES_P true
+#endif
+
+static boolean reg_names_p = TARGET_REG_NAMES_P;
+
+/* Set to TRUE if we want to warn about zero base/index registers. */
+static boolean warn_areg_zero = FALSE;
+
+/* Generic assembler global variables which must be defined by all
+ targets. */
+
+const char comment_chars[] = "#";
+
+/* Characters which start a comment at the beginning of a line. */
+const char line_comment_chars[] = "#";
+
+/* Characters which may be used to separate multiple commands on a
+ single line. */
+const char line_separator_chars[] = ";";
+
+/* Characters which are used to indicate an exponent in a floating
+ point number. */
+const char EXP_CHARS[] = "eE";
+
+/* Characters which mean that a number is a floating point constant,
+ as in 0d1.0. */
+const char FLT_CHARS[] = "dD";
+
+/* The target specific pseudo-ops which we support. */
+
+/* Define the prototypes for the pseudo-ops */
+static void s390_byte PARAMS ((int));
+static void s390_elf_cons PARAMS ((int));
+static void s390_bss PARAMS ((int));
+static void s390_insn PARAMS ((int));
+static void s390_literals PARAMS ((int));
+
+const pseudo_typeS md_pseudo_table[] =
+{
+ { "align", s_align_bytes, 0 },
+ /* Pseudo-ops which must be defined. */
+ { "bss", s390_bss, 0 },
+ { "insn", s390_insn, 0 },
+ /* Pseudo-ops which must be overridden. */
+ { "byte", s390_byte, 0 },
+ { "short", s390_elf_cons, 2 },
+ { "long", s390_elf_cons, 4 },
+ { "quad", s390_elf_cons, 8 },
+ { "ltorg", s390_literals, 0 },
+ { "string", stringer, 2 },
+ { NULL, NULL, 0 }
+};
+
+
+/* Structure to hold information about predefined registers. */
+struct pd_reg
+ {
+ char *name;
+ int value;
+ };
+
+/* List of registers that are pre-defined:
+
+ Each access register has a predefined name of the form:
+ a<reg_num> which has the value <reg_num>.
+
+ Each control register has a predefined name of the form:
+ c<reg_num> which has the value <reg_num>.
+
+ Each general register has a predefined name of the form:
+ r<reg_num> which has the value <reg_num>.
+
+ Each floating point register a has predefined name of the form:
+ f<reg_num> which has the value <reg_num>.
+
+ There are individual registers as well:
+ sp has the value 15
+ lit has the value 12
+
+ The table is sorted. Suitable for searching by a binary search. */
+
+static const struct pd_reg pre_defined_registers[] =
+{
+ { "a0", 0 }, /* Access registers */
+ { "a1", 1 },
+ { "a10", 10 },
+ { "a11", 11 },
+ { "a12", 12 },
+ { "a13", 13 },
+ { "a14", 14 },
+ { "a15", 15 },
+ { "a2", 2 },
+ { "a3", 3 },
+ { "a4", 4 },
+ { "a5", 5 },
+ { "a6", 6 },
+ { "a7", 7 },
+ { "a8", 8 },
+ { "a9", 9 },
+
+ { "c0", 0 }, /* Control registers */
+ { "c1", 1 },
+ { "c10", 10 },
+ { "c11", 11 },
+ { "c12", 12 },
+ { "c13", 13 },
+ { "c14", 14 },
+ { "c15", 15 },
+ { "c2", 2 },
+ { "c3", 3 },
+ { "c4", 4 },
+ { "c5", 5 },
+ { "c6", 6 },
+ { "c7", 7 },
+ { "c8", 8 },
+ { "c9", 9 },
+
+ { "f0", 0 }, /* Floating point registers */
+ { "f1", 1 },
+ { "f10", 10 },
+ { "f11", 11 },
+ { "f12", 12 },
+ { "f13", 13 },
+ { "f14", 14 },
+ { "f15", 15 },
+ { "f2", 2 },
+ { "f3", 3 },
+ { "f4", 4 },
+ { "f5", 5 },
+ { "f6", 6 },
+ { "f7", 7 },
+ { "f8", 8 },
+ { "f9", 9 },
+
+ { "lit", 13 }, /* Pointer to literal pool */
+
+ { "r0", 0 }, /* General purpose registers */
+ { "r1", 1 },
+ { "r10", 10 },
+ { "r11", 11 },
+ { "r12", 12 },
+ { "r13", 13 },
+ { "r14", 14 },
+ { "r15", 15 },
+ { "r2", 2 },
+ { "r3", 3 },
+ { "r4", 4 },
+ { "r5", 5 },
+ { "r6", 6 },
+ { "r7", 7 },
+ { "r8", 8 },
+ { "r9", 9 },
+
+ { "sp", 15 }, /* Stack pointer */
+
+};
+
+#define REG_NAME_CNT (sizeof (pre_defined_registers) / sizeof (struct pd_reg))
+
+static int reg_name_search
+ PARAMS ((const struct pd_reg *, int, const char *));
+static boolean register_name PARAMS ((expressionS *));
+static void init_default_arch PARAMS ((void));
+static void s390_insert_operand
+ PARAMS ((unsigned char *, const struct s390_operand *, offsetT, char *,
+ unsigned int));
+static char *md_gather_operands
+ PARAMS ((char *, unsigned char *, const struct s390_opcode *));
+
+/* Given NAME, find the register number associated with that name, return
+ the integer value associated with the given name or -1 on failure. */
+
+static int
+reg_name_search (regs, regcount, name)
+ const struct pd_reg *regs;
+ int regcount;
+ const char *name;
+{
+ int middle, low, high;
+ int cmp;
+
+ low = 0;
+ high = regcount - 1;
+
+ do
+ {
+ middle = (low + high) / 2;
+ cmp = strcasecmp (name, regs[middle].name);
+ if (cmp < 0)
+ high = middle - 1;
+ else if (cmp > 0)
+ low = middle + 1;
+ else
+ return regs[middle].value;
+ }
+ while (low <= high);
+
+ return -1;
+}
+
+
+/*
+ * Summary of register_name().
+ *
+ * in: Input_line_pointer points to 1st char of operand.
+ *
+ * out: A expressionS.
+ * The operand may have been a register: in this case, X_op == O_register,
+ * X_add_number is set to the register number, and truth is returned.
+ * Input_line_pointer->(next non-blank) char after operand, or is in its
+ * original state.
+ */
+
+static boolean
+register_name (expressionP)
+ expressionS *expressionP;
+{
+ int reg_number;
+ char *name;
+ char *start;
+ char c;
+
+ /* Find the spelling of the operand. */
+ start = name = input_line_pointer;
+ if (name[0] == '%' && ISALPHA (name[1]))
+ name = ++input_line_pointer;
+ else
+ return false;
+
+ c = get_symbol_end ();
+ reg_number = reg_name_search (pre_defined_registers, REG_NAME_CNT, name);
+
+ /* Put back the delimiting char. */
+ *input_line_pointer = c;
+
+ /* Look to see if it's in the register table. */
+ if (reg_number >= 0)
+ {
+ expressionP->X_op = O_register;
+ expressionP->X_add_number = reg_number;
+
+ /* Make the rest nice. */
+ expressionP->X_add_symbol = NULL;
+ expressionP->X_op_symbol = NULL;
+ return true;
+ }
+
+ /* Reset the line as if we had not done anything. */
+ input_line_pointer = start;
+ return false;
+}
+
+/* Local variables. */
+
+/* Opformat hash table. */
+static struct hash_control *s390_opformat_hash;
+
+/* Opcode hash table. */
+static struct hash_control *s390_opcode_hash;
+
+/* Flags to set in the elf header */
+static flagword s390_flags = 0;
+
+symbolS *GOT_symbol; /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
+
+#ifndef WORKING_DOT_WORD
+const int md_short_jump_size = 4;
+const int md_long_jump_size = 4;
+#endif
+
+CONST char *md_shortopts = "A:m:kVQ:";
+struct option md_longopts[] = {
+ {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof (md_longopts);
+
+/* Initialize the default opcode arch and word size from the default
+ architecture name. */
+static void
+init_default_arch ()
+{
+ if (current_arch_requested)
+ return;
+
+ if (strcmp (default_arch, "s390") == 0)
+ {
+ s390_arch_size = 32;
+ current_architecture = S390_OPCODE_ESA;
+ }
+ else if (strcmp (default_arch, "s390x") == 0)
+ {
+ s390_arch_size = 64;
+ current_architecture = S390_OPCODE_ESAME;
+ }
+ else
+ as_fatal ("Invalid default architecture, broken assembler.");
+ current_arch_mask = 1 << current_architecture;
+}
+
+/* Called by TARGET_FORMAT. */
+const char *
+s390_target_format ()
+{
+ /* We don't get a chance to initialize anything before we're called,
+ so handle that now. */
+ if (! s390_arch_size)
+ init_default_arch ();
+
+ return s390_arch_size == 64 ? "elf64-s390" : "elf32-s390";
+}
+
+int
+md_parse_option (c, arg)
+ int c;
+ char *arg;
+{
+ switch (c)
+ {
+ /* -k: Ignore for FreeBSD compatibility. */
+ case 'k':
+ break;
+ case 'm':
+ if (arg != NULL && strcmp (arg, "regnames") == 0)
+ reg_names_p = true;
+
+ else if (arg != NULL && strcmp (arg, "no-regnames") == 0)
+ reg_names_p = false;
+
+ else if (arg != NULL && strcmp (arg, "warn-areg-zero") == 0)
+ warn_areg_zero = TRUE;
+
+ else if (arg != NULL && strcmp (arg, "31") == 0)
+ s390_arch_size = 31;
+
+ else if (arg != NULL && strcmp (arg, "64") == 0)
+ s390_arch_size = 64;
+
+ else
+ {
+ as_bad (_("invalid switch -m%s"), arg);
+ return 0;
+ }
+ break;
+
+ case 'A':
+ if (arg != NULL && strcmp (arg, "esa") == 0)
+ current_architecture = S390_OPCODE_ESA;
+ else if (arg != NULL && strcmp (arg, "esame") == 0)
+ current_architecture = S390_OPCODE_ESAME;
+ else
+ as_bad ("invalid architecture -A%s", arg);
+ current_arch_mask = 1 << current_architecture;
+ current_arch_requested = 1;
+ break;
+
+ /* -V: SVR4 argument to print version ID. */
+ case 'V':
+ print_version_id ();
+ break;
+
+ /* -Qy, -Qn: SVR4 arguments controlling whether a .comment section
+ should be emitted or not. FIXME: Not implemented. */
+ case 'Q':
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+void
+md_show_usage (stream)
+ FILE *stream;
+{
+ fprintf (stream, _("\
+ S390 options:\n\
+ -mregnames Allow symbolic names for registers\n\
+ -mwarn-areg-zero Warn about zero base/index registers\n\
+ -mno-regnames Do not allow symbolic names for registers\n\
+ -m31 Set file format to 31 bit format\n\
+ -m64 Set file format to 64 bit format\n"));
+ fprintf (stream, _("\
+ -V print assembler version number\n\
+ -Qy, -Qn ignored\n"));
+}
+
+/* This function is called when the assembler starts up. It is called
+ after the options have been parsed and the output file has been
+ opened. */
+
+void
+md_begin ()
+{
+ register const struct s390_opcode *op;
+ const struct s390_opcode *op_end;
+ boolean dup_insn = false;
+ const char *retval;
+
+ /* Give a warning if the combination -m64-bit and -Aesa is used. */
+ if (s390_arch_size == 64 && current_arch_mask == (1 << S390_OPCODE_ESA))
+ as_warn ("The 64 bit file format is used without esame instructions.");
+
+ /* Set the ELF flags if desired. */
+ if (s390_flags)
+ bfd_set_private_flags (stdoutput, s390_flags);
+
+ /* Insert the opcode formats into a hash table. */
+ s390_opformat_hash = hash_new ();
+
+ op_end = s390_opformats + s390_num_opformats;
+ for (op = s390_opformats; op < op_end; op++)
+ {
+ retval = hash_insert (s390_opformat_hash, op->name, (PTR) op);
+ if (retval != (const char *) NULL)
+ {
+ as_bad (_("Internal assembler error for instruction format %s"),
+ op->name);
+ dup_insn = true;
+ }
+ }
+
+ /* Insert the opcodes into a hash table. */
+ s390_opcode_hash = hash_new ();
+
+ op_end = s390_opcodes + s390_num_opcodes;
+ for (op = s390_opcodes; op < op_end; op++)
+ {
+ retval = hash_insert (s390_opcode_hash, op->name, (PTR) op);
+ if (retval != (const char *) NULL)
+ {
+ as_bad (_("Internal assembler error for instruction %s"), op->name);
+ dup_insn = true;
+ }
+ }
+
+ if (dup_insn)
+ abort ();
+
+ record_alignment (text_section, 2);
+ record_alignment (data_section, 2);
+ record_alignment (bss_section, 2);
+
+}
+
+/* Called after all assembly has been done. */
+void
+s390_md_end ()
+{
+ if (s390_arch_size == 64)
+ bfd_set_arch_mach (stdoutput, bfd_arch_s390, bfd_mach_s390_64);
+ else
+ bfd_set_arch_mach (stdoutput, bfd_arch_s390, bfd_mach_s390_31);
+}
+
+void
+s390_align_code (fragP, count)
+ fragS *fragP;
+ int count;
+{
+ /* We use nop pattern 0x0707. */
+ if (count > 0)
+ {
+ memset (fragP->fr_literal + fragP->fr_fix, 0x07, count);
+ fragP->fr_var = count;
+ }
+}
+
+/* Insert an operand value into an instruction. */
+
+static void
+s390_insert_operand (insn, operand, val, file, line)
+ unsigned char *insn;
+ const struct s390_operand *operand;
+ offsetT val;
+ char *file;
+ unsigned int line;
+{
+ addressT uval;
+ int offset;
+
+ if (operand->flags & (S390_OPERAND_SIGNED|S390_OPERAND_PCREL))
+ {
+ offsetT min, max;
+
+ max = ((offsetT) 1 << (operand->bits - 1)) - 1;
+ min = - ((offsetT) 1 << (operand->bits - 1));
+ /* Halve PCREL operands. */
+ if (operand->flags & S390_OPERAND_PCREL)
+ val >>= 1;
+ /* Check for underflow / overflow. */
+ if (val < min || val > max)
+ {
+ const char *err =
+ "operand out of range (%s not between %ld and %ld)";
+ char buf[100];
+
+ if (operand->flags & S390_OPERAND_PCREL)
+ {
+ val <<= 1;
+ min <<= 1;
+ max <<= 1;
+ }
+ sprint_value (buf, val);
+ if (file == (char *) NULL)
+ as_bad (err, buf, (int) min, (int) max);
+ else
+ as_bad_where (file, line, err, buf, (int) min, (int) max);
+ return;
+ }
+ /* val is ok, now restrict it to operand->bits bits. */
+ uval = (addressT) val & ((((addressT) 1 << (operand->bits-1)) << 1) - 1);
+ }
+ else
+ {
+ addressT min, max;
+
+ max = (((addressT) 1 << (operand->bits - 1))<<1) - 1;
+ min = (offsetT) 0;
+ uval = (addressT) val;
+ /* Length x in an instructions has real length x+1. */
+ if (operand->flags & S390_OPERAND_LENGTH)
+ uval--;
+ /* Check for underflow / overflow. */
+ if (uval < min || uval > max)
+ {
+ const char *err =
+ "operand out of range (%s not between %ld and %ld)";
+ char buf[100];
+
+ if (operand->flags & S390_OPERAND_LENGTH)
+ {
+ uval++;
+ min++;
+ max++;
+ }
+ sprint_value (buf, uval);
+ if (file == (char *) NULL)
+ as_bad (err, buf, (int) min, (int) max);
+ else
+ as_bad_where (file, line, err, buf, (int) min, (int) max);
+ return;
+ }
+ }
+
+ /* Insert fragments of the operand byte for byte. */
+ offset = operand->shift + operand->bits;
+ uval <<= (-offset) & 7;
+ insn += (offset - 1)/8;
+ while (uval != 0)
+ {
+ *insn-- |= uval;
+ uval >>= 8;
+ }
+}
+
+/* Structure used to hold suffixes. */
+typedef enum
+ {
+ ELF_SUFFIX_NONE = 0,
+ ELF_SUFFIX_GOT,
+ ELF_SUFFIX_PLT,
+ ELF_SUFFIX_GOTENT
+ }
+elf_suffix_type;
+
+struct map_bfd
+ {
+ char *string;
+ int length;
+ elf_suffix_type suffix;
+ };
+
+static elf_suffix_type s390_elf_suffix PARAMS ((char **, expressionS *));
+static int s390_exp_compare PARAMS ((expressionS *exp1, expressionS *exp2));
+static elf_suffix_type s390_lit_suffix
+ PARAMS ((char **, expressionS *, elf_suffix_type));
+
+
+/* Parse @got/@plt/@gotoff. and return the desired relocation. */
+static elf_suffix_type
+s390_elf_suffix (str_p, exp_p)
+ char **str_p;
+ expressionS *exp_p;
+{
+ static struct map_bfd mapping[] =
+ {
+ { "got", 3, ELF_SUFFIX_GOT },
+ { "got12", 5, ELF_SUFFIX_GOT },
+ { "plt", 3, ELF_SUFFIX_PLT },
+ { "gotent", 6, ELF_SUFFIX_GOTENT },
+ { NULL, 0, ELF_SUFFIX_NONE }
+ };
+
+ struct map_bfd *ptr;
+ char *str = *str_p;
+ char *ident;
+ int len;
+
+ if (*str++ != '@')
+ return ELF_SUFFIX_NONE;
+
+ ident = str;
+ while (ISALNUM (*str))
+ str++;
+ len = str - ident;
+
+ for (ptr = &mapping[0]; ptr->length > 0; ptr++)
+ if (len == ptr->length
+ && strncasecmp (ident, ptr->string, ptr->length) == 0)
+ {
+ if (exp_p->X_add_number != 0)
+ as_warn (_("identifier+constant@%s means identifier@%s+constant"),
+ ptr->string, ptr->string);
+ /* Now check for identifier@suffix+constant. */
+ if (*str == '-' || *str == '+')
+ {
+ char *orig_line = input_line_pointer;
+ expressionS new_exp;
+
+ input_line_pointer = str;
+ expression (&new_exp);
+
+ switch (new_exp.X_op)
+ {
+ case O_constant: /* X_add_number (a constant expression). */
+ exp_p->X_add_number += new_exp.X_add_number;
+ str = input_line_pointer;
+ break;
+ case O_symbol: /* X_add_symbol + X_add_number. */
+ /* this case is used for e.g. xyz@PLT+.Label. */
+ exp_p->X_add_number += new_exp.X_add_number;
+ exp_p->X_op_symbol = new_exp.X_add_symbol;
+ exp_p->X_op = O_add;
+ str = input_line_pointer;
+ break;
+ case O_uminus: /* (- X_add_symbol) + X_add_number. */
+ /* this case is used for e.g. xyz@PLT-.Label. */
+ exp_p->X_add_number += new_exp.X_add_number;
+ exp_p->X_op_symbol = new_exp.X_add_symbol;
+ exp_p->X_op = O_subtract;
+ str = input_line_pointer;
+ break;
+ default:
+ break;
+ }
+
+ /* If s390_elf_suffix has not been called with
+ &input_line_pointer as first parameter, we have
+ clobbered the input_line_pointer. We have to
+ undo that. */
+ if (&input_line_pointer != str_p)
+ input_line_pointer = orig_line;
+ }
+ *str_p = str;
+ return ptr->suffix;
+ }
+
+ return BFD_RELOC_UNUSED;
+}
+
+/* Structure used to hold a literal pool entry. */
+struct s390_lpe
+ {
+ struct s390_lpe *next;
+ expressionS ex;
+ FLONUM_TYPE floatnum; /* used if X_op == O_big && X_add_number <= 0 */
+ LITTLENUM_TYPE bignum[4]; /* used if X_op == O_big && X_add_number > 0 */
+ int nbytes;
+ bfd_reloc_code_real_type reloc;
+ symbolS *sym;
+ };
+
+static struct s390_lpe *lpe_free_list = NULL;
+static struct s390_lpe *lpe_list = NULL;
+static struct s390_lpe *lpe_list_tail = NULL;
+static symbolS *lp_sym = NULL;
+static int lp_count = 0;
+static int lpe_count = 0;
+
+static int
+s390_exp_compare(exp1, exp2)
+ expressionS *exp1;
+ expressionS *exp2;
+{
+ if (exp1->X_op != exp2->X_op)
+ return 0;
+
+ switch (exp1->X_op)
+ {
+ case O_constant: /* X_add_number must be equal. */
+ case O_register:
+ return exp1->X_add_number == exp2->X_add_number;
+
+ case O_big:
+ as_bad (_("Can't handle O_big in s390_exp_compare"));
+
+ case O_symbol: /* X_add_symbol & X_add_number must be equal. */
+ case O_symbol_rva:
+ case O_uminus:
+ case O_bit_not:
+ case O_logical_not:
+ return (exp1->X_add_symbol == exp2->X_add_symbol)
+ && (exp1->X_add_number == exp2->X_add_number);
+
+ case O_multiply: /* X_add_symbol,X_op_symbol&X_add_number must be equal. */
+ case O_divide:
+ case O_modulus:
+ case O_left_shift:
+ case O_right_shift:
+ case O_bit_inclusive_or:
+ case O_bit_or_not:
+ case O_bit_exclusive_or:
+ case O_bit_and:
+ case O_add:
+ case O_subtract:
+ case O_eq:
+ case O_ne:
+ case O_lt:
+ case O_le:
+ case O_ge:
+ case O_gt:
+ case O_logical_and:
+ case O_logical_or:
+ return (exp1->X_add_symbol == exp2->X_add_symbol)
+ && (exp1->X_op_symbol == exp2->X_op_symbol)
+ && (exp1->X_add_number == exp2->X_add_number);
+ default:
+ return 0;
+ }
+}
+
+/* Test for @lit and if its present make an entry in the literal pool and
+ modify the current expression to be an offset into the literal pool. */
+static elf_suffix_type
+s390_lit_suffix (str_p, exp_p, suffix)
+ char **str_p;
+ expressionS *exp_p;
+ elf_suffix_type suffix;
+{
+ bfd_reloc_code_real_type reloc;
+ char tmp_name[64];
+ char *str = *str_p;
+ char *ident;
+ struct s390_lpe *lpe;
+ int nbytes, len;
+
+ if (*str++ != ':')
+ return suffix; /* No modification. */
+
+ /* We look for a suffix of the form "@lit1", "@lit2", "@lit4" or "@lit8". */
+ ident = str;
+ while (ISALNUM (*str))
+ str++;
+ len = str - ident;
+ if (len != 4 || strncasecmp (ident, "lit", 3) != 0
+ || (ident[3]!='1' && ident[3]!='2' && ident[3]!='4' && ident[3]!='8'))
+ return suffix; /* no modification */
+ nbytes = ident[3] - '0';
+
+ reloc = BFD_RELOC_UNUSED;
+ if (suffix == ELF_SUFFIX_GOT)
+ {
+ if (nbytes == 2)
+ reloc = BFD_RELOC_390_GOT16;
+ else if (nbytes == 4)
+ reloc = BFD_RELOC_32_GOT_PCREL;
+ else if (nbytes == 8)
+ reloc = BFD_RELOC_390_GOT64;
+ }
+ else if (suffix == ELF_SUFFIX_PLT)
+ {
+ if (nbytes == 4)
+ reloc = BFD_RELOC_390_PLT32;
+ else if (nbytes == 8)
+ reloc = BFD_RELOC_390_PLT64;
+ }
+
+ if (suffix != ELF_SUFFIX_NONE && reloc == BFD_RELOC_UNUSED)
+ as_bad (_("Invalid suffix for literal pool entry"));
+
+ /* Search the pool if the new entry is a duplicate. */
+ if (exp_p->X_op == O_big)
+ {
+ /* Special processing for big numbers. */
+ for (lpe = lpe_list; lpe != NULL; lpe = lpe->next)
+ {
+ if (lpe->ex.X_op == O_big)
+ {
+ if (exp_p->X_add_number <= 0 && lpe->ex.X_add_number <= 0)
+ {
+ if (memcmp (&generic_floating_point_number, &lpe->floatnum,
+ sizeof (FLONUM_TYPE)) == 0)
+ break;
+ }
+ else if (exp_p->X_add_number == lpe->ex.X_add_number)
+ {
+ if (memcmp (generic_bignum, lpe->bignum,
+ sizeof (LITTLENUM_TYPE)*exp_p->X_add_number) == 0)
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Processing for 'normal' data types. */
+ for (lpe = lpe_list; lpe != NULL; lpe = lpe->next)
+ if (lpe->nbytes == nbytes && lpe->reloc == reloc
+ && s390_exp_compare(exp_p, &lpe->ex) != 0)
+ break;
+ }
+
+ if (lpe == NULL)
+ {
+ /* A new literal. */
+ if (lpe_free_list != NULL)
+ {
+ lpe = lpe_free_list;
+ lpe_free_list = lpe_free_list->next;
+ }
+ else
+ {
+ lpe = (struct s390_lpe *) xmalloc(sizeof (struct s390_lpe));
+ }
+
+ lpe->ex = *exp_p;
+
+ if (exp_p->X_op == O_big)
+ {
+ if (exp_p->X_add_number <= 0)
+ lpe->floatnum = generic_floating_point_number;
+ else if (exp_p->X_add_number <= 4)
+ memcpy (lpe->bignum, generic_bignum,
+ exp_p->X_add_number*sizeof (LITTLENUM_TYPE));
+ else
+ as_bad (_("Big number is too big"));
+ }
+
+ lpe->nbytes = nbytes;
+ lpe->reloc = reloc;
+ /* Literal pool name defined ? */
+ if (lp_sym == NULL)
+ {
+ sprintf (tmp_name, ".L\001%i", lp_count);
+ lp_sym = symbol_make(tmp_name);
+ }
+
+ /* Make name for literal pool entry. */
+ sprintf (tmp_name, ".L\001%i\002%i", lp_count, lpe_count);
+ lpe_count++;
+ lpe->sym = symbol_make(tmp_name);
+
+ /* Add to literal pool list. */
+ lpe->next = NULL;
+ if (lpe_list_tail != NULL)
+ {
+ lpe_list_tail->next = lpe;
+ lpe_list_tail = lpe;
+ }
+ else
+ lpe_list = lpe_list_tail = lpe;
+ }
+
+ /* Now change exp_p to the offset into the literal pool.
+ Thats the expression: .L^Ax^By-.L^Ax */
+ exp_p->X_add_symbol = lpe->sym;
+ exp_p->X_op_symbol = lp_sym;
+ exp_p->X_op = O_subtract;
+ exp_p->X_add_number = 0;
+
+ *str_p = str;
+
+ /* We change the suffix type to ELF_SUFFIX_NONE, because
+ the difference of two local labels is just a number. */
+ return ELF_SUFFIX_NONE;
+}
+
+/* Like normal .long/.short/.word, except support @got, etc.
+ clobbers input_line_pointer, checks end-of-line. */
+static void
+s390_elf_cons (nbytes)
+ register int nbytes; /* 1=.byte, 2=.word, 4=.long */
+{
+ expressionS exp;
+ elf_suffix_type suffix;
+
+ if (is_it_end_of_statement ())
+ {
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ do
+ {
+ expression (&exp);
+
+ if (exp.X_op == O_symbol
+ && *input_line_pointer == '@'
+ && (suffix = s390_elf_suffix (&input_line_pointer, &exp)) != ELF_SUFFIX_NONE)
+ {
+ bfd_reloc_code_real_type reloc;
+ reloc_howto_type *reloc_howto;
+ int size;
+ char *where;
+
+ if (nbytes == 2 && suffix == ELF_SUFFIX_GOT)
+ reloc = BFD_RELOC_390_GOT16;
+ else if (nbytes == 4 && suffix == ELF_SUFFIX_GOT)
+ reloc = BFD_RELOC_32_GOT_PCREL;
+ else if (nbytes == 8 && suffix == ELF_SUFFIX_GOT)
+ reloc = BFD_RELOC_390_GOT64;
+ else if (nbytes == 4 && suffix == ELF_SUFFIX_PLT)
+ reloc = BFD_RELOC_390_PLT32;
+ else if (nbytes == 8 && suffix == ELF_SUFFIX_PLT)
+ reloc = BFD_RELOC_390_PLT64;
+ else
+ reloc = BFD_RELOC_UNUSED;
+
+ if (reloc != BFD_RELOC_UNUSED)
+ {
+ reloc_howto = bfd_reloc_type_lookup (stdoutput, reloc);
+ size = bfd_get_reloc_size (reloc_howto);
+ if (size > nbytes)
+ as_bad (_("%s relocations do not fit in %d bytes"),
+ reloc_howto->name, nbytes);
+ where = frag_more (nbytes);
+ md_number_to_chars (where, 0, size);
+ /* To make fixup_segment do the pc relative conversion the
+ pcrel parameter on the fix_new_exp call needs to be false. */
+ fix_new_exp (frag_now, where - frag_now->fr_literal,
+ size, &exp, false, reloc);
+ }
+ else
+ as_bad (_("relocation not applicable"));
+ }
+ else
+ emit_expr (&exp, (unsigned int) nbytes);
+ }
+ while (*input_line_pointer++ == ',');
+
+ input_line_pointer--; /* Put terminator back into stream. */
+ demand_empty_rest_of_line ();
+}
+
+/* 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 ``.''. */
+
+struct s390_fixup
+ {
+ expressionS exp;
+ int opindex;
+ bfd_reloc_code_real_type reloc;
+ };
+
+#define MAX_INSN_FIXUPS (4)
+
+/* This routine is called for each instruction to be assembled. */
+
+static char *
+md_gather_operands (str, insn, opcode)
+ char *str;
+ unsigned char *insn;
+ const struct s390_opcode *opcode;
+{
+ struct s390_fixup fixups[MAX_INSN_FIXUPS];
+ const struct s390_operand *operand;
+ const unsigned char *opindex_ptr;
+ elf_suffix_type suffix;
+ bfd_reloc_code_real_type reloc;
+ int skip_optional;
+ int parentheses;
+ char *f;
+ int fc, i;
+
+ while (ISSPACE (*str)) str++;
+
+ parentheses = 0;
+ skip_optional = 0;
+
+ /* Gather the operands. */
+ fc = 0;
+ for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++)
+ {
+ expressionS ex;
+ char *hold;
+
+ operand = s390_operands + *opindex_ptr;
+
+ if (skip_optional && (operand->flags & S390_OPERAND_INDEX))
+ {
+ /* We do an early skip. For D(X,B) constructions the index
+ register is skipped (X is optional). For D(L,B) the base
+ register will be the skipped operand, because L is NOT
+ optional. */
+ skip_optional = 0;
+ continue;
+ }
+
+ /* Gather the operand. */
+ hold = input_line_pointer;
+ input_line_pointer = str;
+
+ if (! register_name (&ex)) /* parse the operand */
+ expression (&ex);
+
+ str = input_line_pointer;
+ input_line_pointer = hold;
+
+ /* Write the operand to the insn. */
+ if (ex.X_op == O_illegal)
+ as_bad (_("illegal operand"));
+ else if (ex.X_op == O_absent)
+ as_bad (_("missing operand"));
+ else if (ex.X_op == O_register || ex.X_op == O_constant)
+ {
+ s390_lit_suffix (&str, &ex, ELF_SUFFIX_NONE);
+
+ if (ex.X_op != O_register && ex.X_op != O_constant)
+ {
+ /* We need to generate a fixup for the
+ expression returned by s390_lit_suffix. */
+ if (fc >= MAX_INSN_FIXUPS)
+ as_fatal (_("too many fixups"));
+ fixups[fc].exp = ex;
+ fixups[fc].opindex = *opindex_ptr;
+ fixups[fc].reloc = BFD_RELOC_UNUSED;
+ ++fc;
+ }
+ else
+ {
+ if ((operand->flags & S390_OPERAND_INDEX)
+ && ex.X_add_number == 0
+ && warn_areg_zero == TRUE)
+ as_warn ("index register specified but zero");
+ if ((operand->flags & S390_OPERAND_BASE)
+ && ex.X_add_number == 0
+ && warn_areg_zero == TRUE)
+ as_warn ("base register specified but zero");
+ s390_insert_operand (insn, operand, ex.X_add_number, NULL, 0);
+ }
+ }
+ else
+ {
+ suffix = s390_elf_suffix (&str, &ex);
+ suffix = s390_lit_suffix (&str, &ex, suffix);
+ reloc = BFD_RELOC_UNUSED;
+
+ if (suffix == ELF_SUFFIX_GOT)
+ {
+ if (operand->flags & S390_OPERAND_DISP)
+ reloc = BFD_RELOC_390_GOT12;
+ else if ((operand->flags & S390_OPERAND_SIGNED)
+ && (operand->bits == 16))
+ reloc = BFD_RELOC_390_GOT16;
+ else if ((operand->flags & S390_OPERAND_PCREL)
+ && (operand->bits == 32))
+ reloc = BFD_RELOC_390_GOTENT;
+ }
+ else if (suffix == ELF_SUFFIX_PLT)
+ {
+ if ((operand->flags & S390_OPERAND_PCREL)
+ && (operand->bits == 16))
+ reloc = BFD_RELOC_390_PLT16DBL;
+ else if ((operand->flags & S390_OPERAND_PCREL)
+ && (operand->bits == 32))
+ reloc = BFD_RELOC_390_PLT32DBL;
+ }
+ else if (suffix == ELF_SUFFIX_GOTENT)
+ {
+ if ((operand->flags & S390_OPERAND_PCREL)
+ && (operand->bits == 32))
+ reloc = BFD_RELOC_390_GOTENT;
+ }
+
+ if (suffix != ELF_SUFFIX_NONE && reloc == BFD_RELOC_UNUSED)
+ as_bad (_("invalid operand suffix"));
+ /* We need to generate a fixup of type 'reloc' for this
+ expression. */
+ if (fc >= MAX_INSN_FIXUPS)
+ as_fatal (_("too many fixups"));
+ fixups[fc].exp = ex;
+ fixups[fc].opindex = *opindex_ptr;
+ fixups[fc].reloc = reloc;
+ ++fc;
+ }
+
+ /* Check the next character. The call to expression has advanced
+ str past any whitespace. */
+ if (operand->flags & S390_OPERAND_DISP)
+ {
+ /* After a displacement a block in parentheses can start. */
+ if (*str != '(')
+ {
+ /* Check if parethesed block can be skipped. If the next
+ operand is neiter an optional operand nor a base register
+ then we have a syntax error. */
+ operand = s390_operands + *(++opindex_ptr);
+ if (!(operand->flags & (S390_OPERAND_INDEX|S390_OPERAND_BASE)))
+ as_bad (_("syntax error; missing '(' after displacement"));
+
+ /* Ok, skip all operands until S390_OPERAND_BASE. */
+ while (!(operand->flags & S390_OPERAND_BASE))
+ operand = s390_operands + *(++opindex_ptr);
+
+ /* If there is a next operand it must be seperated by a comma. */
+ if (opindex_ptr[1] != '\0')
+ {
+ if (*str++ != ',')
+ as_bad (_("syntax error; expected ,"));
+ }
+ }
+ else
+ {
+ /* We found an opening parentheses. */
+ str++;
+ for (f = str; *f != '\0'; f++)
+ if (*f == ',' || *f == ')')
+ break;
+ /* If there is no comma until the closing parentheses OR
+ there is a comma right after the opening parentheses,
+ we have to skip optional operands. */
+ if (*f == ',' && f == str)
+ {
+ /* comma directly after '(' ? */
+ skip_optional = 1;
+ str++;
+ }
+ else
+ skip_optional = (*f != ',');
+ }
+ }
+ else if (operand->flags & S390_OPERAND_BASE)
+ {
+ /* After the base register the parenthesed block ends. */
+ if (*str++ != ')')
+ as_bad (_("syntax error; missing ')' after base register"));
+ skip_optional = 0;
+ /* If there is a next operand it must be seperated by a comma. */
+ if (opindex_ptr[1] != '\0')
+ {
+ if (*str++ != ',')
+ as_bad (_("syntax error; expected ,"));
+ }
+ }
+ else
+ {
+ /* We can find an 'early' closing parentheses in e.g. D(L) instead
+ of D(L,B). In this case the base register has to be skipped. */
+ if (*str == ')')
+ {
+ operand = s390_operands + *(++opindex_ptr);
+
+ if (!(operand->flags & S390_OPERAND_BASE))
+ as_bad (_("syntax error; ')' not allowed here"));
+ str++;
+ }
+ /* If there is a next operand it must be seperated by a comma. */
+ if (opindex_ptr[1] != '\0')
+ {
+ if (*str++ != ',')
+ as_bad (_("syntax error; expected ,"));
+ }
+ }
+ }
+
+ while (ISSPACE (*str))
+ ++str;
+
+ if (*str != '\0')
+ {
+ char *linefeed;
+
+ if ((linefeed = strchr (str, '\n')) != NULL)
+ *linefeed = '\0';
+ as_bad (_("junk at end of line: `%s'"), str);
+ if (linefeed != NULL)
+ *linefeed = '\n';
+ }
+
+ /* Write out the instruction. */
+ f = frag_more (opcode->oplen);
+ memcpy (f, insn, opcode->oplen);
+ dwarf2_emit_insn (opcode->oplen);
+
+ /* Create any fixups. At this point we do not use a
+ bfd_reloc_code_real_type, but instead just use the
+ BFD_RELOC_UNUSED plus the operand index. This lets us easily
+ handle fixups for any operand type, although that is admittedly
+ not a very exciting feature. We pick a BFD reloc type in
+ md_apply_fix3. */
+ for (i = 0; i < fc; i++)
+ {
+ operand = s390_operands + fixups[i].opindex;
+
+ if (fixups[i].reloc != BFD_RELOC_UNUSED)
+ {
+ reloc_howto_type *reloc_howto;
+ fixS *fixP;
+ int size;
+
+ reloc_howto = bfd_reloc_type_lookup (stdoutput, fixups[i].reloc);
+ if (!reloc_howto)
+ abort ();
+
+ size = bfd_get_reloc_size (reloc_howto);
+
+ if (size < 1 || size > 4)
+ abort ();
+
+ fixP = fix_new_exp (frag_now,
+ f - frag_now->fr_literal + (operand->shift/8),
+ size, &fixups[i].exp, reloc_howto->pc_relative,
+ fixups[i].reloc);
+ /* Turn off overflow checking in fixup_segment. This is necessary
+ because fixup_segment will signal an overflow for large 4 byte
+ quantities for GOT12 relocations. */
+ if ( fixups[i].reloc == BFD_RELOC_390_GOT12
+ || fixups[i].reloc == BFD_RELOC_390_GOT16)
+ fixP->fx_no_overflow = 1;
+ }
+ else
+ fix_new_exp (frag_now, f - frag_now->fr_literal, 4, &fixups[i].exp,
+ (operand->flags & S390_OPERAND_PCREL) != 0,
+ ((bfd_reloc_code_real_type)
+ (fixups[i].opindex + (int) BFD_RELOC_UNUSED)));
+ }
+ return str;
+}
+
+/* This routine is called for each instruction to be assembled. */
+
+void
+md_assemble (str)
+ char *str;
+{
+ const struct s390_opcode *opcode;
+ unsigned char insn[6];
+ char *s;
+
+ /* Get the opcode. */
+ for (s = str; *s != '\0' && ! ISSPACE (*s); s++)
+ ;
+ if (*s != '\0')
+ *s++ = '\0';
+
+ /* Look up the opcode in the hash table. */
+ opcode = (struct s390_opcode *) hash_find (s390_opcode_hash, str);
+ if (opcode == (const struct s390_opcode *) NULL)
+ {
+ as_bad (_("Unrecognized opcode: `%s'"), str);
+ return;
+ }
+ else if (!(opcode->architecture & current_arch_mask))
+ {
+ as_bad ("Opcode %s not available in this architecture", str);
+ return;
+ }
+
+ memcpy (insn, opcode->opcode, sizeof (insn));
+ md_gather_operands (s, insn, opcode);
+}
+
+#ifndef WORKING_DOT_WORD
+/* Handle long and short jumps. We don't support these */
+void
+md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
+ char *ptr;
+ addressT from_addr, to_addr;
+ fragS *frag;
+ symbolS *to_symbol;
+{
+ abort ();
+}
+
+void
+md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
+ char *ptr;
+ addressT from_addr, to_addr;
+ fragS *frag;
+ symbolS *to_symbol;
+{
+ abort ();
+}
+#endif
+
+void
+s390_bss (ignore)
+ int ignore ATTRIBUTE_UNUSED;
+{
+ /* We don't support putting frags in the BSS segment, we fake it
+ by marking in_bss, then looking at s_skip for clues. */
+
+ subseg_set (bss_section, 0);
+ demand_empty_rest_of_line ();
+}
+
+/* Pseudo-op handling. */
+
+void
+s390_insn (ignore)
+ int ignore ATTRIBUTE_UNUSED;
+{
+ expressionS exp;
+ const struct s390_opcode *opformat;
+ unsigned char insn[6];
+ char *s;
+
+ /* Get the opcode format. */
+ s = input_line_pointer;
+ while (*s != '\0' && *s != ',' && ! ISSPACE (*s))
+ s++;
+ if (*s != ',')
+ as_bad (_("Invalid .insn format\n"));
+ *s++ = '\0';
+
+ /* Look up the opcode in the hash table. */
+ opformat = (struct s390_opcode *)
+ hash_find (s390_opformat_hash, input_line_pointer);
+ if (opformat == (const struct s390_opcode *) NULL)
+ {
+ as_bad (_("Unrecognized opcode format: `%s'"), input_line_pointer);
+ return;
+ }
+ input_line_pointer = s;
+ expression (&exp);
+ if (exp.X_op == O_constant)
+ {
+ if ( ((opformat->oplen == 6) && (exp.X_op > 0) && (exp.X_op < (1ULL << 48)))
+ || ((opformat->oplen == 4) && (exp.X_op > 0) && (exp.X_op < (1ULL << 32)))
+ || ((opformat->oplen == 2) && (exp.X_op > 0) && (exp.X_op < (1ULL << 16))))
+ md_number_to_chars (insn, exp.X_add_number, opformat->oplen);
+ else
+ as_bad (_("Invalid .insn format\n"));
+ }
+ else if (exp.X_op == O_big)
+ {
+ if (exp.X_add_number > 0
+ && opformat->oplen == 6
+ && generic_bignum[3] == 0)
+ {
+ md_number_to_chars (insn, generic_bignum[2], 2);
+ md_number_to_chars (&insn[2], generic_bignum[1], 2);
+ md_number_to_chars (&insn[4], generic_bignum[0], 2);
+ }
+ else
+ as_bad (_("Invalid .insn format\n"));
+ }
+ else
+ as_bad (_("second operand of .insn not a constant\n"));
+
+ if (strcmp (opformat->name, "e") != 0 && *input_line_pointer++ != ',')
+ as_bad (_("missing comma after insn constant\n"));
+
+ if ((s = strchr (input_line_pointer, '\n')) != NULL)
+ *s = '\0';
+ input_line_pointer = md_gather_operands (input_line_pointer, insn,
+ opformat);
+ if (s != NULL)
+ *s = '\n';
+ demand_empty_rest_of_line ();
+}
+
+/* The .byte pseudo-op. This is similar to the normal .byte
+ pseudo-op, but it can also take a single ASCII string. */
+
+static void
+s390_byte (ignore)
+ int ignore ATTRIBUTE_UNUSED;
+{
+ if (*input_line_pointer != '\"')
+ {
+ cons (1);
+ return;
+ }
+
+ /* Gather characters. A real double quote is doubled. Unusual
+ characters are not permitted. */
+ ++input_line_pointer;
+ while (1)
+ {
+ char c;
+
+ c = *input_line_pointer++;
+
+ if (c == '\"')
+ {
+ if (*input_line_pointer != '\"')
+ break;
+ ++input_line_pointer;
+ }
+
+ FRAG_APPEND_1_CHAR (c);
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* The .ltorg pseudo-op.This emits all literals defined since the last
+ .ltorg or the invocation of gas. Literals are defined with the
+ @lit suffix. */
+
+static void
+s390_literals (ignore)
+ int ignore ATTRIBUTE_UNUSED;
+{
+ struct s390_lpe *lpe;
+
+ if (lp_sym == NULL || lpe_count == 0)
+ return; /* nothing to be done */
+
+ /* Emit symbol for start of literal pool. */
+ S_SET_SEGMENT (lp_sym, now_seg);
+ S_SET_VALUE (lp_sym, (valueT) frag_now_fix ());
+ lp_sym->sy_frag = frag_now;
+
+ while (lpe_list)
+ {
+ lpe = lpe_list;
+ lpe_list = lpe_list->next;
+ S_SET_SEGMENT (lpe->sym, now_seg);
+ S_SET_VALUE (lpe->sym, (valueT) frag_now_fix ());
+ lpe->sym->sy_frag = frag_now;
+
+ /* Emit literal pool entry. */
+ if (lpe->reloc != BFD_RELOC_UNUSED)
+ {
+ reloc_howto_type *reloc_howto =
+ bfd_reloc_type_lookup (stdoutput, lpe->reloc);
+ int size = bfd_get_reloc_size (reloc_howto);
+ char *where;
+
+ if (size > lpe->nbytes)
+ as_bad (_("%s relocations do not fit in %d bytes"),
+ reloc_howto->name, lpe->nbytes);
+ where = frag_more (lpe->nbytes);
+ md_number_to_chars (where, 0, size);
+ fix_new_exp (frag_now, where - frag_now->fr_literal,
+ size, &lpe->ex, reloc_howto->pc_relative, lpe->reloc);
+ }
+ else
+ {
+ if (lpe->ex.X_op == O_big)
+ {
+ if (lpe->ex.X_add_number <= 0)
+ generic_floating_point_number = lpe->floatnum;
+ else
+ memcpy (generic_bignum, lpe->bignum,
+ lpe->ex.X_add_number*sizeof (LITTLENUM_TYPE));
+ }
+ emit_expr (&lpe->ex, lpe->nbytes);
+ }
+
+ lpe->next = lpe_free_list;
+ lpe_free_list = lpe;
+ }
+ lpe_list_tail = NULL;
+ lp_sym = NULL;
+ lp_count++;
+ lpe_count = 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;
+}
+
+/* Align a section (I don't know why this is machine dependent). */
+
+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));
+}
+
+/* We don't have any form of relaxing. */
+
+int
+md_estimate_size_before_relax (fragp, seg)
+ fragS *fragp ATTRIBUTE_UNUSED;
+ asection *seg ATTRIBUTE_UNUSED;
+{
+ abort ();
+ return 0;
+}
+
+/* Convert a machine dependent frag. We never generate these. */
+
+void
+md_convert_frag (abfd, sec, fragp)
+ bfd *abfd ATTRIBUTE_UNUSED;
+ asection *sec ATTRIBUTE_UNUSED;
+ fragS *fragp ATTRIBUTE_UNUSED;
+{
+ abort ();
+}
+
+symbolS *
+md_undefined_symbol (name)
+ char *name;
+{
+ if (*name == '_' && *(name+1) == 'G'
+ && strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
+ {
+ if (!GOT_symbol)
+ {
+ if (symbol_find (name))
+ as_bad (_("GOT already in symbol table"));
+ GOT_symbol = symbol_new (name, undefined_section,
+ (valueT) 0, &zero_address_frag);
+ }
+ return GOT_symbol;
+ }
+ return 0;
+}
+
+/* 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 ATTRIBUTE_UNUSED;
+{
+ return fixp->fx_frag->fr_address + fixp->fx_where;
+}
+
+/* Here we decide which fixups can be adjusted to make them relative to
+ the beginning of the section instead of the symbol. Basically we need
+ to make sure that the dynamic relocations are done correctly, so in
+ some cases we force the original symbol to be used. */
+int
+tc_s390_fix_adjustable(fixP)
+ fixS * fixP;
+{
+ /* Prevent all adjustments to global symbols. */
+ if (S_IS_EXTERN (fixP->fx_addsy))
+ return 0;
+ if (S_IS_WEAK (fixP->fx_addsy))
+ return 0;
+ /* Don't adjust pc-relative references to merge sections. */
+ if ((S_GET_SEGMENT(fixP->fx_addsy)->flags & SEC_MERGE) != 0
+ && fixP->fx_pcrel)
+ return 0;
+ /* adjust_reloc_syms doesn't know about the GOT. */
+ if ( fixP->fx_r_type == BFD_RELOC_32_GOTOFF
+ || fixP->fx_r_type == BFD_RELOC_390_PLT16DBL
+ || fixP->fx_r_type == BFD_RELOC_390_PLT32
+ || fixP->fx_r_type == BFD_RELOC_390_PLT32DBL
+ || fixP->fx_r_type == BFD_RELOC_390_PLT64
+ || fixP->fx_r_type == BFD_RELOC_390_GOT12
+ || fixP->fx_r_type == BFD_RELOC_390_GOT16
+ || fixP->fx_r_type == BFD_RELOC_32_GOT_PCREL
+ || fixP->fx_r_type == BFD_RELOC_390_GOT64
+ || fixP->fx_r_type == BFD_RELOC_390_GOTENT
+ || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ return 0;
+ return 1;
+}
+
+/* Return true if we must always emit a reloc for a type and false if
+ there is some hope of resolving it a assembly time. */
+int
+tc_s390_force_relocation (fixp)
+ struct fix *fixp;
+{
+ /* Ensure we emit a relocation for every reference to the global
+ offset table or to the procedure link table. */
+ switch (fixp->fx_r_type)
+ {
+ case BFD_RELOC_390_GOT12:
+ case BFD_RELOC_32_GOT_PCREL:
+ case BFD_RELOC_32_GOTOFF:
+ case BFD_RELOC_390_GOTPC:
+ case BFD_RELOC_390_GOT16:
+ case BFD_RELOC_390_GOTPCDBL:
+ case BFD_RELOC_390_GOT64:
+ case BFD_RELOC_390_GOTENT:
+ case BFD_RELOC_390_PLT32:
+ case BFD_RELOC_390_PLT16DBL:
+ case BFD_RELOC_390_PLT32DBL:
+ case BFD_RELOC_390_PLT64:
+ case BFD_RELOC_VTABLE_INHERIT:
+ case BFD_RELOC_VTABLE_ENTRY:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+/* 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. */
+
+void
+md_apply_fix3 (fixP, valP, seg)
+ fixS *fixP;
+ valueT *valP;
+ segT seg;
+{
+ char *where;
+ valueT value = * valP;
+
+ where = fixP->fx_frag->fr_literal + fixP->fx_where;
+
+ if (fixP->fx_subsy != NULL)
+ {
+ if ((fixP->fx_addsy != NULL
+ && S_GET_SEGMENT (fixP->fx_addsy) == S_GET_SEGMENT (fixP->fx_subsy)
+ && SEG_NORMAL (S_GET_SEGMENT (fixP->fx_addsy)))
+ || (S_GET_SEGMENT (fixP->fx_subsy) == absolute_section))
+ value += S_GET_VALUE (fixP->fx_subsy);
+ if (!S_IS_DEFINED (fixP->fx_subsy))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("unresolved fx_subsy symbol that must be resolved"));
+ value -= S_GET_VALUE(fixP->fx_subsy);
+
+ if (S_GET_SEGMENT (fixP->fx_subsy) == seg && ! fixP->fx_pcrel)
+ value += MD_PCREL_FROM_SECTION (fixP, seg);
+ }
+
+ if (fixP->fx_addsy != NULL)
+ {
+ if ((fixP->fx_subsy != NULL
+ && S_GET_SEGMENT (fixP->fx_addsy) == S_GET_SEGMENT (fixP->fx_subsy)
+ && SEG_NORMAL (S_GET_SEGMENT(fixP->fx_addsy)))
+ || (S_GET_SEGMENT (fixP->fx_addsy) == seg
+ && fixP->fx_pcrel && TC_RELOC_RTSYM_LOC_FIXUP (fixP))
+ || (!fixP->fx_pcrel
+ && S_GET_SEGMENT (fixP->fx_addsy) == absolute_section)
+ || (S_GET_SEGMENT (fixP->fx_addsy) != undefined_section
+ && !bfd_is_com_section (S_GET_SEGMENT (fixP->fx_addsy))
+ && TC_FIX_ADJUSTABLE(fixP)))
+ value -= S_GET_VALUE (fixP->fx_addsy);
+
+ if (fixP->fx_pcrel)
+ value += fixP->fx_frag->fr_address + fixP->fx_where;
+ }
+ else
+ fixP->fx_done = 1;
+
+ if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
+ {
+ const struct s390_operand *operand;
+ int opindex;
+
+ opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
+ operand = &s390_operands[opindex];
+
+ if (fixP->fx_done)
+ {
+ /* Insert the fully resolved operand value. */
+ s390_insert_operand (where, operand, (offsetT) value,
+ fixP->fx_file, fixP->fx_line);
+ return;
+ }
+
+ /* Determine a BFD reloc value based on the operand information.
+ We are only prepared to turn a few of the operands into
+ relocs. */
+ fixP->fx_offset = value;
+ if (operand->bits == 12 && operand->shift == 20)
+ {
+ fixP->fx_size = 2;
+ fixP->fx_where += 2;
+ fixP->fx_r_type = BFD_RELOC_390_12;
+ }
+ else if (operand->bits == 12 && operand->shift == 36)
+ {
+ fixP->fx_size = 2;
+ fixP->fx_where += 4;
+ fixP->fx_r_type = BFD_RELOC_390_12;
+ }
+ else if (operand->bits == 8 && operand->shift == 8)
+ {
+ fixP->fx_size = 1;
+ fixP->fx_where += 1;
+ fixP->fx_r_type = BFD_RELOC_8;
+ }
+ else if (operand->bits == 16 && operand->shift == 16)
+ {
+ fixP->fx_size = 2;
+ fixP->fx_where += 2;
+ if (operand->flags & S390_OPERAND_PCREL)
+ {
+ fixP->fx_r_type = BFD_RELOC_390_PC16DBL;
+ fixP->fx_offset += 2;
+ }
+ else
+ fixP->fx_r_type = BFD_RELOC_16;
+ }
+ else if (operand->bits == 32 && operand->shift == 16
+ && (operand->flags & S390_OPERAND_PCREL))
+ {
+ fixP->fx_size = 4;
+ fixP->fx_where += 2;
+ fixP->fx_offset += 2;
+ fixP->fx_r_type = BFD_RELOC_390_PC32DBL;
+ }
+ else
+ {
+ char *sfile;
+ unsigned int sline;
+
+ /* Use expr_symbol_where to see if this is an expression
+ symbol. */
+ if (expr_symbol_where (fixP->fx_addsy, &sfile, &sline))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("unresolved expression that must be resolved"));
+ else
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("unsupported relocation type"));
+ fixP->fx_done = 1;
+ return;
+ }
+ }
+ else
+ {
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_8:
+ if (fixP->fx_pcrel)
+ abort ();
+ if (fixP->fx_done)
+ md_number_to_chars (where, value, 1);
+ break;
+ case BFD_RELOC_390_12:
+ case BFD_RELOC_390_GOT12:
+ if (fixP->fx_done)
+ {
+ unsigned short mop;
+
+ mop = bfd_getb16 ((unsigned char *) where);
+ mop |= (unsigned short) (value & 0xfff);
+ bfd_putb16 ((bfd_vma) mop, (unsigned char *) where);
+ }
+ break;
+
+ case BFD_RELOC_16:
+ case BFD_RELOC_GPREL16:
+ case BFD_RELOC_16_GOT_PCREL:
+ case BFD_RELOC_16_GOTOFF:
+ if (fixP->fx_pcrel)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "cannot emit PC relative %s relocation%s%s",
+ bfd_get_reloc_code_name (fixP->fx_r_type),
+ fixP->fx_addsy != NULL ? " against " : "",
+ (fixP->fx_addsy != NULL
+ ? S_GET_NAME (fixP->fx_addsy)
+ : ""));
+ if (fixP->fx_done)
+ md_number_to_chars (where, value, 2);
+ break;
+ case BFD_RELOC_390_GOT16:
+ if (fixP->fx_done)
+ md_number_to_chars (where, value, 2);
+ break;
+ case BFD_RELOC_390_PC16DBL:
+ case BFD_RELOC_390_PLT16DBL:
+ value += 2;
+ if (fixP->fx_done)
+ md_number_to_chars (where, (offsetT) value >> 1, 2);
+ break;
+
+ case BFD_RELOC_32:
+ if (fixP->fx_pcrel)
+ fixP->fx_r_type = BFD_RELOC_32_PCREL;
+ else
+ fixP->fx_r_type = BFD_RELOC_32;
+ if (fixP->fx_done)
+ md_number_to_chars (where, value, 4);
+ break;
+ case BFD_RELOC_32_PCREL:
+ case BFD_RELOC_32_BASEREL:
+ fixP->fx_r_type = BFD_RELOC_32_PCREL;
+ if (fixP->fx_done)
+ md_number_to_chars (where, value, 4);
+ break;
+ case BFD_RELOC_32_GOT_PCREL:
+ case BFD_RELOC_390_PLT32:
+ if (fixP->fx_done)
+ md_number_to_chars (where, value, 4);
+ break;
+ case BFD_RELOC_390_PC32DBL:
+ case BFD_RELOC_390_PLT32DBL:
+ case BFD_RELOC_390_GOTPCDBL:
+ case BFD_RELOC_390_GOTENT:
+ value += 2;
+ if (fixP->fx_done)
+ md_number_to_chars (where, (offsetT) value >> 1, 4);
+ break;
+
+ case BFD_RELOC_32_GOTOFF:
+ if (fixP->fx_done)
+ md_number_to_chars (where, value, sizeof (int));
+ break;
+
+ case BFD_RELOC_390_GOT64:
+ case BFD_RELOC_390_PLT64:
+ if (fixP->fx_done)
+ md_number_to_chars (where, value, 8);
+ break;
+
+ case BFD_RELOC_64:
+ if (fixP->fx_pcrel)
+ fixP->fx_r_type = BFD_RELOC_64_PCREL;
+ else
+ fixP->fx_r_type = BFD_RELOC_64;
+ if (fixP->fx_done)
+ md_number_to_chars (where, value, 8);
+ break;
+
+ case BFD_RELOC_64_PCREL:
+ fixP->fx_r_type = BFD_RELOC_64_PCREL;
+ if (fixP->fx_done)
+ md_number_to_chars (where, value, 8);
+ break;
+
+ case BFD_RELOC_VTABLE_INHERIT:
+ case BFD_RELOC_VTABLE_ENTRY:
+ fixP->fx_done = 0;
+ return;
+
+ default:
+ {
+ const char *reloc_name = bfd_get_reloc_code_name (fixP->fx_r_type);
+
+ if (reloc_name != NULL)
+ fprintf (stderr, "Gas failure, reloc type %s\n", reloc_name);
+ else
+ fprintf (stderr, "Gas failure, reloc type #%i\n", fixP->fx_r_type);
+ fflush (stderr);
+ abort ();
+ }
+ }
+
+ fixP->fx_offset = value;
+ }
+}
+
+/* Generate a reloc for a fixup. */
+
+arelent *
+tc_gen_reloc (seg, fixp)
+ asection *seg ATTRIBUTE_UNUSED;
+ fixS *fixp;
+{
+ bfd_reloc_code_real_type code;
+ arelent *reloc;
+
+ code = fixp->fx_r_type;
+ if (GOT_symbol && fixp->fx_addsy == GOT_symbol)
+ {
+ if ( (s390_arch_size == 32 && code == BFD_RELOC_32_PCREL)
+ || (s390_arch_size == 64 && code == BFD_RELOC_64_PCREL))
+ code = BFD_RELOC_390_GOTPC;
+ if (code == BFD_RELOC_390_PC32DBL)
+ code = BFD_RELOC_390_GOTPCDBL;
+ }
+
+ reloc = (arelent *) xmalloc (sizeof (arelent));
+ reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+ *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
+ reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+ reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
+ if (reloc->howto == NULL)
+ {
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("cannot represent relocation type %s"),
+ bfd_get_reloc_code_name (code));
+ /* Set howto to a garbage value so that we can keep going. */
+ reloc->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
+ assert (reloc->howto != NULL);
+ }
+ reloc->addend = fixp->fx_offset;
+
+ return reloc;
+}
diff --git a/contrib/binutils/gas/config/tc-s390.h b/contrib/binutils/gas/config/tc-s390.h
new file mode 100644
index 0000000..1837b1a
--- /dev/null
+++ b/contrib/binutils/gas/config/tc-s390.h
@@ -0,0 +1,115 @@
+/* tc-s390.h -- Header file for tc-s390.c.
+ Copyright 2000, 2001 Free Software Foundation, Inc.
+ Written by Martin Schwidefsky (schwidefsky@de.ibm.com).
+
+ 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_S390
+
+#ifdef ANSI_PROTOTYPES
+struct fix;
+#endif
+
+#ifndef BFD_ASSEMBLER
+ #error S390 support requires BFD_ASSEMBLER
+#endif
+
+/* This expression evaluates to false if the relocation is for a local object
+ for which we still want to do the relocation at runtime. True if we
+ are willing to perform this relocation while building the .o file.
+ This is only used for pcrel relocations, so GOTOFF does not need to be
+ checked here. I am not sure if some of the others are ever used with
+ pcrel, but it is easier to be safe than sorry. */
+
+#define TC_RELOC_RTSYM_LOC_FIXUP(FIX) \
+ ((FIX)->fx_r_type != BFD_RELOC_390_GOTENT \
+ && ((FIX)->fx_addsy == NULL \
+ || (! S_IS_EXTERNAL ((FIX)->fx_addsy) \
+ && ! S_IS_WEAK ((FIX)->fx_addsy) \
+ && S_IS_DEFINED ((FIX)->fx_addsy) \
+ && ! S_IS_COMMON ((FIX)->fx_addsy))))
+
+#define TC_FORCE_RELOCATION(FIXP) tc_s390_force_relocation(FIXP)
+extern int tc_s390_force_relocation PARAMS ((struct fix *));
+
+#define tc_fix_adjustable(X) tc_s390_fix_adjustable(X)
+extern int tc_s390_fix_adjustable PARAMS ((struct fix *));
+
+#define TC_FIX_ADJUSTABLE(fixP) \
+ (! symbol_used_in_reloc_p ((fixP)->fx_addsy) && tc_fix_adjustable (fixP))
+
+/* The target BFD architecture. */
+#define TARGET_ARCH bfd_arch_s390
+extern enum bfd_architecture s390_arch PARAMS ((void));
+
+/* The target BFD format. */
+#define TARGET_FORMAT s390_target_format()
+extern const char * s390_target_format PARAMS ((void));
+
+/* Set the endianness we are using. */
+#define TARGET_BYTES_BIG_ENDIAN 1
+
+/* Whether or not the target is big endian */
+extern int target_big_endian;
+
+/* Permit temporary numeric labels. */
+#define LOCAL_LABELS_FB 1
+
+/* $ is used to refer to the current location. */
+/* #define DOLLAR_DOT */
+
+/* We need to be able to make relocations involving the difference of
+ two symbols. This includes the difference of two symbols when
+ one of them is undefined (this comes up in PIC code generation).
+ */
+#define UNDEFINED_DIFFERENCE_OK
+
+/* foo-. gets turned into PC relative relocs */
+#define DIFF_EXPR_OK
+
+/* We don't need to handle .word strangely. */
+#define WORKING_DOT_WORD
+
+#define md_number_to_chars number_to_chars_bigendian
+
+#define md_do_align(n, fill, len, max, around) \
+if ((n) && !need_pass_2 && (fill == 0) && \
+ (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0) { \
+ char *p; \
+ p = frag_var (rs_align_code, 15, 1, (relax_substateT) max, \
+ (symbolS *) 0, (offsetT) (n), (char *) 0); \
+ *p = 0x07; \
+ goto around; \
+}
+
+extern void s390_align_code PARAMS ((fragS *, int));
+
+#define HANDLE_ALIGN(fragP) \
+if (fragP->fr_type == rs_align_code) \
+ s390_align_code (fragP, (fragP->fr_next->fr_address \
+ - fragP->fr_address \
+ - fragP->fr_fix));
+
+/* call md_pcrel_from_section, not md_pcrel_from */
+#define MD_PCREL_FROM_SECTION(FIXP, SEC) md_pcrel_from_section(FIXP, SEC)
+extern long md_pcrel_from_section PARAMS ((struct fix *, segT));
+
+#define md_operand(x)
+
+extern void s390_md_end PARAMS ((void));
+#define md_end() s390_md_end ()
diff --git a/contrib/binutils/gas/doc/as.1 b/contrib/binutils/gas/doc/as.1
index 5f0971c..99d3284 100644
--- a/contrib/binutils/gas/doc/as.1
+++ b/contrib/binutils/gas/doc/as.1
@@ -129,7 +129,7 @@
.\" ========================================================================
.\"
.IX Title "AS 1"
-.TH AS 1 "2002-03-08" "binutils-2.12" "GNU Development Tools"
+.TH AS 1 "2002-05-14" "binutils-2.12.1" "GNU Development Tools"
.UC
.SH "NAME"
\&\s-1AS\s0 \- the portable \s-1GNU\s0 assembler.
diff --git a/contrib/binutils/gas/stabs.c b/contrib/binutils/gas/stabs.c
index 60b03c4..c692c2c 100644
--- a/contrib/binutils/gas/stabs.c
+++ b/contrib/binutils/gas/stabs.c
@@ -240,6 +240,14 @@ s_stab_generic (what, stab_secname, stabstr_secname)
other = longint;
desc = get_absolute_expression ();
+
+ if ((desc > 0xffff) || (desc < -0x8000))
+ /* This could happen for example with a source file with a huge
+ number of lines. The only cure is to use a different debug
+ format, probably DWARF. */
+ as_warn (_(".stab%c: description field '%x' too big, try a different debug format"),
+ what, desc);
+
if (what == 's' || what == 'n')
{
if (*input_line_pointer != ',')
diff --git a/contrib/binutils/gas/symbols.c b/contrib/binutils/gas/symbols.c
index 5dd3040..5a55fca 100644
--- a/contrib/binutils/gas/symbols.c
+++ b/contrib/binutils/gas/symbols.c
@@ -986,6 +986,7 @@ resolve_symbol_value (symp)
case O_bit_not:
case O_logical_not:
left = resolve_symbol_value (add_symbol);
+ seg_left = S_GET_SEGMENT (add_symbol);
if (op == O_uminus)
left = -left;
@@ -996,7 +997,7 @@ resolve_symbol_value (symp)
final_val += left + symp->sy_frag->fr_address;
if (final_seg == expr_section || final_seg == undefined_section)
- final_seg = absolute_section;
+ final_seg = seg_left;
resolved = symbol_resolved_p (add_symbol);
break;
@@ -1062,15 +1063,19 @@ resolve_symbol_value (symp)
Don't emit messages unless we're finalizing the symbol value,
otherwise we may get the same message multiple times. */
- if (op != O_eq && op != O_ne
- && (seg_left != absolute_section
- || seg_right != absolute_section)
- && ((op != O_subtract
- && op != O_lt && op != O_le && op != O_ge && op != O_gt)
- || seg_left != seg_right
- || (seg_left == undefined_section
- && add_symbol != op_symbol))
- && finalize_syms)
+ if ((op == O_eq || op == O_ne)
+ || ((op == O_subtract
+ || op == O_lt || op == O_le || op == O_ge || op == O_gt)
+ && seg_left == seg_right
+ && (seg_left != undefined_section
+ || add_symbol == op_symbol))
+ || (seg_left == absolute_section
+ && seg_right == absolute_section))
+ {
+ if (final_seg == expr_section || final_seg == undefined_section)
+ final_seg = absolute_section;
+ }
+ else if (finalize_syms)
{
char *file;
unsigned int line;
@@ -1105,6 +1110,9 @@ resolve_symbol_value (symp)
as_bad (_("invalid section for operation setting `%s'"),
S_GET_NAME (symp));
}
+ /* Prevent the error propagating. */
+ if (final_seg == expr_section || final_seg == undefined_section)
+ final_seg = absolute_section;
}
/* Check for division by zero. */
@@ -1160,7 +1168,15 @@ resolve_symbol_value (symp)
final_val += symp->sy_frag->fr_address + left;
if (final_seg == expr_section || final_seg == undefined_section)
- final_seg = absolute_section;
+ {
+ if (seg_left == undefined_section
+ || seg_right == undefined_section)
+ final_seg = undefined_section;
+ else if (seg_left == absolute_section)
+ final_seg = seg_right;
+ else
+ final_seg = seg_left;
+ }
resolved = (symbol_resolved_p (add_symbol)
&& symbol_resolved_p (op_symbol));
break;
OpenPOWER on IntegriCloud