aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog28
-rw-r--r--gas/config/obj-coff.c23
-rw-r--r--gas/frags.c373
-rw-r--r--gas/read.c344
-rw-r--r--gas/read.h10
-rw-r--r--gas/subsegs.c34
-rw-r--r--gas/symbols.c99
-rw-r--r--gas/symbols.h26
-rw-r--r--gas/write.c23
9 files changed, 696 insertions, 264 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index de98956..4969b99 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,5 +1,33 @@
Tue Aug 8 13:07:05 1995 Ian Lance Taylor <ian@cygnus.com>
+ * struc-symbol.h (struct symbol): Add sy_mri_common bit.
+ * read.h (mri_comon_symbol): Declare.
+ (s_mri_common): Declare.
+ * read.c (mri_line_label): New static variable.
+ (mri_common_symbol): New global variable.
+ (potable): Add "common" and "common.s".
+ (read_a_source_file): In MRI mode, set mri_line_label for a label
+ at the start of a line.
+ (s_mri_common): New function.
+ (s_space): Handle mri_common_symbol.
+ * symbols.c (colon): Change return value from void to symbolS *,
+ and return new symbol. If mri_common_symbol is set, attach the
+ new symbol to it.
+ (resolve_symbol_value): Handle an sy_mri_common symbol.
+ * symbols.h (colon): Change return value in declaration.
+ * subsegs.c (subseg_set_rest): Clear mri_common_symbol.
+ (subseg_set (both versions)): Likewise.
+ * frags.c (frag_more): Warn if mri_common_symbol is not NULL.
+ * write.c (adjust_reloc_syms): Skip sy_mri_common symbols.
+ (write_object_file): Discard sy_mri_common symbols.
+ (fixup_segment): Change relocations against sy_mri_common symbols
+ to be against the common symbol itself.
+ * config/obj-coff.c (yank_symbols): Discard sy_mri_common symbols.
+ (fixup_segment): Change relocations against sy_mri_common symbols
+ to be against the common symbol itself.
+ * config/obj-aout.c (obj_crawl_symbol_chain): Discard
+ sy_mri_common symbols.
+
* doc/c-m68k.texi: Add documentation for CPU specific options, and
for Motorola syntax.
diff --git a/gas/config/obj-coff.c b/gas/config/obj-coff.c
index 11a5daa..b48900b 100644
--- a/gas/config/obj-coff.c
+++ b/gas/config/obj-coff.c
@@ -2481,6 +2481,15 @@ yank_symbols ()
symbolP;
symbolP = symbolP ? symbol_next (symbolP) : symbol_rootP)
{
+ if (symbolP->sy_mri_common)
+ {
+ if (S_GET_STORAGE_CLASS (symbolP) == C_EXT)
+ as_bad ("%s: global symbols not supported in common sections",
+ S_GET_NAME (symbolP));
+ symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
+ continue;
+ }
+
if (!SF_GET_DEBUG (symbolP))
{
/* Debug symbols do not need all this rubbish */
@@ -3593,7 +3602,7 @@ fixup_segment (segP, this_segment_type)
register fixS * fixP;
register symbolS *add_symbolP;
register symbolS *sub_symbolP;
- register long add_number;
+ long add_number;
register int size;
register char *place;
register long where;
@@ -3632,6 +3641,14 @@ fixup_segment (segP, this_segment_type)
add_number = fixP->fx_offset;
pcrel = fixP->fx_pcrel;
+ if (add_symbolP->sy_mri_common)
+ {
+ know (add_symbolP->sy_value.X_op == O_symbol);
+ add_number += S_GET_VALUE (add_symbolP);
+ fixP->fx_offset = add_number;
+ add_symbolP = fixP->fx_addsy = add_symbolP->sy_value.X_add_symbol;
+ }
+
if (add_symbolP)
{
add_symbol_segment = S_GET_SEGMENT (add_symbolP);
@@ -3680,6 +3697,10 @@ fixup_segment (segP, this_segment_type)
fixP->fx_addsy = NULL;
fixP->fx_subsy = NULL;
fixP->fx_done = 1;
+#ifdef TC_M68K /* is this right? */
+ pcrel = 0;
+ fixP->fx_pcrel = 0;
+#endif
}
}
else
diff --git a/gas/frags.c b/gas/frags.c
index 9185341..f52692e 100644
--- a/gas/frags.c
+++ b/gas/frags.c
@@ -1,90 +1,74 @@
/* frags.c - manage frags -
- Copyright (C) 1987, 1990, 1991 Free Software Foundation, Inc.
-
+
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
This file is part of GAS, the GNU Assembler.
-
+
GAS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-
+
GAS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with GAS; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "as.h"
#include "subsegs.h"
#include "obstack.h"
-struct obstack frags; /* All, and only, frags live here. */
+struct obstack frags; /* All, and only, frags live here. */
-fragS zero_address_frag = {
- 0, /* fr_address */
- NULL, /* fr_next */
- 0, /* fr_fix */
- 0, /* fr_var */
- 0, /* fr_symbol */
- 0, /* fr_offset */
- NULL, /* fr_opcode */
- rs_fill, /* fr_type */
- 0, /* fr_subtype */
- 0, /* fr_pcrel_adjust */
- 0, /* fr_bsr */
- 0 /* fr_literal [0] */
- };
-
-fragS bss_address_frag = {
- 0, /* fr_address. Gets filled in to make up
- sy_value-s. */
- NULL, /* fr_next */
- 0, /* fr_fix */
- 0, /* fr_var */
- 0, /* fr_symbol */
- 0, /* fr_offset */
- NULL, /* fr_opcode */
- rs_fill, /* fr_type */
- 0, /* fr_subtype */
- 0, /* fr_pcrel_adjust */
- 0, /* fr_bsr */
- 0 /* fr_literal [0] */
- };
+extern fragS zero_address_frag;
+extern fragS bss_address_frag;
+
+/* Initialization for frag routines. */
+void
+frag_init ()
+{
+ zero_address_frag.fr_type = rs_fill;
+ bss_address_frag.fr_type = rs_fill;
+ obstack_begin (&frags, 5000);
+}
/*
* frag_grow()
*
- * Internal.
* Try to augment current frag by nchars chars.
* If there is no room, close of the current frag with a ".fill 0"
* and begin a new frag. Unless the new frag has nchars chars available
* do not return. Do not set up any fields of *now_frag.
*/
-static void frag_grow(nchars)
-unsigned int nchars;
+void
+frag_grow (nchars)
+ unsigned int nchars;
{
- if (obstack_room (&frags) < nchars) {
- unsigned int n,oldn;
- long oldc;
-
- frag_wane(frag_now);
- frag_new(0);
- oldn=(unsigned)-1;
- oldc=frags.chunk_size;
- frags.chunk_size=2*nchars;
- while((n=obstack_room(&frags))<nchars && n<oldn) {
- frag_wane(frag_now);
- frag_new(0);
- oldn=n;
- }
- frags.chunk_size=oldc;
+ if (obstack_room (&frags) < nchars)
+ {
+ unsigned int n, oldn;
+ long oldc;
+
+ frag_wane (frag_now);
+ frag_new (0);
+ oldn = (unsigned) -1;
+ oldc = frags.chunk_size;
+ frags.chunk_size = 2 * nchars;
+ while ((n = obstack_room (&frags)) < nchars && n < oldn)
+ {
+ frag_wane (frag_now);
+ frag_new (0);
+ oldn = n;
}
- if (obstack_room (&frags) < nchars)
- as_fatal("Can't extend frag %d. chars", nchars);
-} /* frag_grow() */
+ frags.chunk_size = oldc;
+ }
+ if (obstack_room (&frags) < nchars)
+ as_fatal ("Can't extend frag %d. chars", nchars);
+} /* frag_grow() */
/*
* frag_new()
@@ -103,62 +87,54 @@ unsigned int nchars;
* Make a new frag, initialising some components. Link new frag at end
* of frchain_now.
*/
-void frag_new(old_frags_var_max_size)
-int old_frags_var_max_size; /* Number of chars (already allocated on
+void
+frag_new (old_frags_var_max_size)
+ int old_frags_var_max_size;/* Number of chars (already allocated on
obstack frags) */
-/* in variable_length part of frag. */
+ /* in variable_length part of frag. */
{
- register fragS * former_last_fragP;
- /* char *throw_away_pointer; JF unused */
- register frchainS * frchP;
- long tmp; /* JF */
-
- frag_now->fr_fix = (char *) (obstack_next_free (&frags)) -
- (frag_now->fr_literal) - old_frags_var_max_size;
- /* Fix up old frag's fr_fix. */
-
- obstack_finish (&frags);
- /* This will align the obstack so the */
- /* next struct we allocate on it will */
- /* begin at a correct boundary. */
- frchP = frchain_now;
- know (frchP);
- former_last_fragP = frchP->frch_last;
- know (former_last_fragP);
- know (former_last_fragP == frag_now);
- obstack_blank (&frags, SIZEOF_STRUCT_FRAG);
- /* We expect this will begin at a correct */
- /* boundary for a struct. */
- tmp=obstack_alignment_mask(&frags);
- obstack_alignment_mask(&frags)=0; /* Turn off alignment */
- /* If we ever hit a machine
- where strings must be
- aligned, we Lose Big */
- frag_now=(fragS *)obstack_finish(&frags);
- obstack_alignment_mask(&frags)=tmp; /* Restore alignment */
-
- /* Just in case we don't get zero'd bytes */
- bzero(frag_now, SIZEOF_STRUCT_FRAG);
-
- /* obstack_unaligned_done (&frags, &frag_now); */
- /* know (frags.obstack_c_next_free == frag_now->fr_literal); */
- /* Generally, frag_now->points to an */
- /* address rounded up to next alignment. */
- /* However, characters will add to obstack */
- /* frags IMMEDIATELY after the struct frag, */
- /* even if they are not starting at an */
- /* alignment address. */
- former_last_fragP->fr_next = frag_now;
- frchP->frch_last = frag_now;
-
+ register fragS *former_last_fragP;
+ register frchainS *frchP;
+ long tmp;
+
+ frag_now->fr_fix = frag_now_fix () - old_frags_var_max_size;
+ /* Fix up old frag's fr_fix. */
+
+ obstack_finish (&frags);
+ /* This will align the obstack so the next struct we allocate on it
+ will begin at a correct boundary. */
+ frchP = frchain_now;
+ know (frchP);
+ former_last_fragP = frchP->frch_last;
+ know (former_last_fragP);
+ know (former_last_fragP == frag_now);
+ obstack_blank (&frags, SIZEOF_STRUCT_FRAG);
+ /* We expect this will begin at a correct boundary for a struct. */
+ tmp = obstack_alignment_mask (&frags);
+ obstack_alignment_mask (&frags) = 0; /* Turn off alignment */
+ /* If we ever hit a machine where strings must be aligned, we Lose
+ Big. */
+ frag_now = (fragS *) obstack_finish (&frags);
+ obstack_alignment_mask (&frags) = tmp; /* Restore alignment */
+
+ /* Just in case we don't get zero'd bytes */
+ memset (frag_now, '\0', SIZEOF_STRUCT_FRAG);
+
+ /* Generally, frag_now->points to an address rounded up to next
+ alignment. However, characters will add to obstack frags
+ IMMEDIATELY after the struct frag, even if they are not starting
+ at an alignment address. */
+ former_last_fragP->fr_next = frag_now;
+ frchP->frch_last = frag_now;
+
#ifndef NO_LISTING
- {
- extern struct list_info_struct *listing_tail;
- frag_now->line = listing_tail;
- }
+ {
+ extern struct list_info_struct *listing_tail;
+ frag_now->line = listing_tail;
+ }
#endif
-
- frag_now->fr_next = NULL;
+
+ frag_now->fr_next = NULL;
} /* frag_new() */
/*
@@ -171,15 +147,22 @@ int old_frags_var_max_size; /* Number of chars (already allocated on
* frag_now_growth past the new chars.
*/
-char *frag_more (nchars)
-int nchars;
+char *
+frag_more (nchars)
+ int nchars;
{
- register char *retval;
-
- frag_grow (nchars);
- retval = obstack_next_free (&frags);
- obstack_blank_fast (&frags, nchars);
- return (retval);
+ register char *retval;
+
+ if (mri_common_symbol != NULL)
+ {
+ as_bad ("attempt to allocate data in common section");
+ mri_common_symbol = NULL;
+ }
+
+ frag_grow (nchars);
+ retval = obstack_next_free (&frags);
+ obstack_blank_fast (&frags, nchars);
+ return (retval);
} /* frag_more() */
/*
@@ -193,32 +176,33 @@ int nchars;
* to write into.
*/
-char *frag_var(type, max_chars, var, subtype, symbol, offset, opcode)
-relax_stateT type;
-int max_chars;
-int var;
-relax_substateT subtype;
-symbolS *symbol;
-long offset;
-char *opcode;
+char *
+frag_var (type, max_chars, var, subtype, symbol, offset, opcode)
+ relax_stateT type;
+ int max_chars;
+ int var;
+ relax_substateT subtype;
+ symbolS *symbol;
+ long offset;
+ char *opcode;
{
- register char *retval;
-
- frag_grow (max_chars);
- retval = obstack_next_free (&frags);
- obstack_blank_fast (&frags, max_chars);
- frag_now->fr_var = var;
- frag_now->fr_type = type;
- frag_now->fr_subtype = subtype;
- frag_now->fr_symbol = symbol;
- frag_now->fr_offset = offset;
- frag_now->fr_opcode = opcode;
- /* default these to zero. */
- frag_now->fr_pcrel_adjust = 0;
- frag_now->fr_bsr = 0;
- frag_new (max_chars);
- return (retval);
-} /* frag_var() */
+ register char *retval;
+
+ frag_grow (max_chars);
+ retval = obstack_next_free (&frags);
+ obstack_blank_fast (&frags, max_chars);
+ frag_now->fr_var = var;
+ frag_now->fr_type = type;
+ frag_now->fr_subtype = subtype;
+ frag_now->fr_symbol = symbol;
+ frag_now->fr_offset = offset;
+ frag_now->fr_opcode = opcode;
+ /* default these to zero. */
+ frag_now->fr_pcrel_adjust = 0;
+ frag_now->fr_bsr = 0;
+ frag_new (max_chars);
+ return (retval);
+}
/*
* frag_variant()
@@ -229,32 +213,29 @@ char *opcode;
* Two new arguments have been added.
*/
-char *frag_variant(type, max_chars, var, subtype, symbol, offset, opcode, pcrel_adjust,bsr)
-relax_stateT type;
-int max_chars;
-int var;
-relax_substateT subtype;
-symbolS *symbol;
-long offset;
-char *opcode;
-int pcrel_adjust;
-char bsr;
+char *
+frag_variant (type, max_chars, var, subtype, symbol, offset, opcode)
+ relax_stateT type;
+ int max_chars;
+ int var;
+ relax_substateT subtype;
+ symbolS *symbol;
+ long offset;
+ char *opcode;
{
- register char *retval;
-
- /* frag_grow (max_chars); */
- retval = obstack_next_free (&frags);
- /* obstack_blank_fast (&frags, max_chars); */ /* OVE: so far the only diff */
- frag_now->fr_var = var;
- frag_now->fr_type = type;
- frag_now->fr_subtype = subtype;
- frag_now->fr_symbol = symbol;
- frag_now->fr_offset = offset;
- frag_now->fr_opcode = opcode;
- frag_now->fr_pcrel_adjust = pcrel_adjust;
- frag_now->fr_bsr = bsr;
- frag_new (max_chars);
- return (retval);
+ register char *retval;
+
+ retval = obstack_next_free (&frags);
+ frag_now->fr_var = var;
+ frag_now->fr_type = type;
+ frag_now->fr_subtype = subtype;
+ frag_now->fr_symbol = symbol;
+ frag_now->fr_offset = offset;
+ frag_now->fr_opcode = opcode;
+ frag_now->fr_pcrel_adjust = 0;
+ frag_now->fr_bsr = 0;
+ frag_new (max_chars);
+ return (retval);
} /* frag_variant() */
/*
@@ -262,12 +243,13 @@ char bsr;
*
* Reduce the variable end of a frag to a harmless state.
*/
-void frag_wane(fragP)
-register fragS * fragP;
+void
+frag_wane (fragP)
+ register fragS *fragP;
{
- fragP->fr_type = rs_fill;
- fragP->fr_offset = 0;
- fragP->fr_var = 0;
+ fragP->fr_type = rs_fill;
+ fragP->fr_offset = 0;
+ fragP->fr_var = 0;
}
/*
@@ -280,12 +262,45 @@ register fragS * fragP;
* (so far empty) frag, in the same subsegment as the last frag.
*/
-void frag_align(alignment, fill_character)
-int alignment;
-int fill_character;
+void
+frag_align (alignment, fill_character)
+ int alignment;
+ int fill_character;
{
- *(frag_var (rs_align, 1, 1, (relax_substateT)0, (symbolS *)0,
- (long)alignment, (char *)0)) = fill_character;
-} /* frag_align() */
+ char *p;
+ p = frag_var (rs_align, 1, 1, (relax_substateT) 0,
+ (symbolS *) 0, (long) alignment, (char *) 0);
+ *p = fill_character;
+}
+
+void
+frag_align_pattern (alignment, fill_pattern, n_fill)
+ int alignment;
+ const char *fill_pattern;
+ int n_fill;
+{
+ char *p;
+ p = frag_var (rs_align, n_fill, n_fill, (relax_substateT) 0,
+ (symbolS *) 0, (long) alignment, (char *) 0);
+ memcpy (p, fill_pattern, n_fill);
+}
+
+int
+frag_now_fix ()
+{
+ return (char*)obstack_next_free (&frags) - frag_now->fr_literal;
+}
+
+void
+frag_append_1_char (datum)
+ int datum;
+{
+ if (obstack_room (&frags) <= 1)
+ {
+ frag_wane (frag_now);
+ frag_new (0);
+ }
+ obstack_1grow (&frags, datum);
+}
/* end of frags.c */
diff --git a/gas/read.c b/gas/read.c
index 05996ff..bacd186 100644
--- a/gas/read.c
+++ b/gas/read.c
@@ -42,7 +42,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307
#include "as.h"
#include "subsegs.h"
-
+#include "libiberty.h"
#include "obstack.h"
#include "listing.h"
@@ -84,7 +84,7 @@ die horribly;
#endif
/* used by is_... macros. our ctype[] */
-const char lex_type[256] =
+char lex_type[256] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ABCDEFGHIJKLMNO */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* PQRSTUVWXYZ[\]^_ */
@@ -169,6 +169,15 @@ struct broken_word *broken_words;
int new_broken_words;
#endif
+/* If this line had an MRI style label, it is stored in this variable.
+ This is used by some of the MRI pseudo-ops. */
+static symbolS *mri_line_label;
+
+/* This global variable is used to support MRI common sections. We
+ translate such sections into a common symbol. This variable is
+ non-NULL when we are in an MRI common section. */
+symbolS *mri_common_symbol;
+
char *demand_copy_string PARAMS ((int *lenP));
int is_it_end_of_statement PARAMS ((void));
static segT get_segmented_expression PARAMS ((expressionS *expP));
@@ -193,11 +202,14 @@ read_begin ()
for (p = line_separator_chars; *p; p++)
is_end_of_line[(unsigned char) *p] = 1;
/* Use more. FIXME-SOMEDAY. */
+
+ if (flag_mri)
+ lex_type['?'] = 3;
}
/* set up pseudo-op tables */
-struct hash_control *po_hash;
+static struct hash_control *po_hash;
static const pseudo_typeS potable[] =
{
@@ -209,7 +221,20 @@ static const pseudo_typeS potable[] =
/* block */
{"byte", cons, 1},
{"comm", s_comm, 0},
+ {"common", s_mri_common, 0},
+ {"common.s", s_mri_common, 1},
{"data", s_data, 0},
+ {"dc", cons, 2},
+ {"dc.b", cons, 1},
+ {"dc.d", float_cons, 'd'},
+ {"dc.l", cons, 4},
+ {"dc.s", float_cons, 'f'},
+ {"dc.w", cons, 2},
+ {"dc.x", float_cons, 'x'},
+ {"ds", s_space, 2},
+ {"ds.b", s_space, 1},
+ {"ds.l", s_space, 4},
+ {"ds.w", s_space, 2},
#ifdef S_SET_DESC
{"desc", s_desc, 0},
#endif
@@ -282,6 +307,7 @@ static const pseudo_typeS potable[] =
/* type */
/* use */
/* val */
+ {"xdef", s_globl, 0},
{"xstabs", s_xstab, 's'},
{"word", cons, 2},
{"zero", s_space, 0},
@@ -385,23 +411,44 @@ read_a_source_file (name)
if (input_line_pointer[-1] == '\n')
bump_line_counters ();
-#if defined (MRI) || defined (LABELS_WITHOUT_COLONS)
- /* Text at the start of a line must be a label, we run down
- and stick a colon in. */
- if (is_name_beginner (*input_line_pointer))
+ if (flag_mri
+#ifdef LABELS_WITHOUT_COLONS
+ || 1
+#endif
+ )
{
- char *line_start = input_line_pointer;
- char c = get_symbol_end ();
- colon (line_start);
- *input_line_pointer = c;
- if (c == ':')
- input_line_pointer++;
+ mri_line_label = NULL;
+
+ /* Text at the start of a line must be a label, we
+ run down and stick a colon in. */
+ if (is_name_beginner (*input_line_pointer))
+ {
+ char *line_start = input_line_pointer;
+ char c = get_symbol_end ();
+
+ /* In MRI mode, the EQU pseudoop must be handled
+ specially. */
+ if (flag_mri)
+ {
+ if ((strncasecmp (input_line_pointer + 1, "EQU", 3)
+ == 0)
+ && (input_line_pointer[4] == ' '
+ || input_line_pointer[4] == '\t'))
+ {
+ input_line_pointer += 4;
+ equals (line_start);
+ continue;
+ }
+ }
+ mri_line_label = colon (line_start);
+ *input_line_pointer = c;
+ if (c == ':')
+ input_line_pointer++;
+ }
}
-#endif
}
-
/*
* We are at the begining of a line, or similar place.
* We expect a well-formed assembler statement.
@@ -464,11 +511,6 @@ read_a_source_file (name)
}
else
{ /* expect pseudo-op or machine instruction */
-#ifdef MRI
- if (!done_pseudo (s))
-
-#else
-
pop = NULL;
#define IGNORE_OPCODE_CASE
@@ -484,12 +526,18 @@ read_a_source_file (name)
}
#endif
+ if (flag_mri
#ifdef NO_PSEUDO_DOT
- /* The m88k uses pseudo-ops without a period. */
- pop = (pseudo_typeS *) hash_find (po_hash, s);
- if (pop != NULL && pop->poc_handler == NULL)
- pop = NULL;
+ || 1
#endif
+ )
+ {
+ /* The MRI assembler and the m88k use pseudo-ops
+ without a period. */
+ pop = (pseudo_typeS *) hash_find (po_hash, s);
+ if (pop != NULL && pop->poc_handler == NULL)
+ pop = NULL;
+ }
if (pop != NULL || *s == '.')
{
@@ -528,7 +576,6 @@ read_a_source_file (name)
(*pop->poc_handler) (pop->poc_val);
}
else
-#endif
{ /* machine instruction */
/* WARNING: c has char, which may be end-of-line. */
/* Also: input_line_pointer->`\0` where c was. */
@@ -917,6 +964,104 @@ s_comm (ignore)
demand_empty_rest_of_line ();
} /* s_comm() */
+/* The MRI COMMON pseudo-op. We handle this by creating a common
+ symbol with the appropriate name. We make s_space do the right
+ thing by increasing the size. */
+
+void
+s_mri_common (small)
+ int small;
+{
+ char *name;
+ char c;
+ char *alc = NULL;
+ symbolS *sym;
+ offsetT align;
+
+ if (! flag_mri)
+ {
+ s_comm (0);
+ return;
+ }
+
+ SKIP_WHITESPACE ();
+
+ name = input_line_pointer;
+ if (! isdigit ((unsigned char) *name))
+ c = get_symbol_end ();
+ else
+ {
+ do
+ {
+ ++input_line_pointer;
+ }
+ while (isdigit ((unsigned char) *input_line_pointer));
+ c = *input_line_pointer;
+ *input_line_pointer = '\0';
+
+ if (mri_line_label != NULL)
+ {
+ alc = (char *) xmalloc (strlen (S_GET_NAME (mri_line_label))
+ + (input_line_pointer - name)
+ + 1);
+ sprintf (alc, "%s%s", name, S_GET_NAME (mri_line_label));
+ name = alc;
+ }
+ }
+
+ sym = symbol_find_or_make (name);
+ *input_line_pointer = c;
+ if (alc != NULL)
+ free (alc);
+
+ if (*input_line_pointer != ',')
+ align = 0;
+ else
+ {
+ ++input_line_pointer;
+ align = get_absolute_expression ();
+ }
+
+ if (S_IS_DEFINED (sym))
+ {
+#if defined (S_IS_COMMON) || defined (BFD_ASSEMBLER)
+ if (! S_IS_COMMON (sym))
+#endif
+ {
+ as_bad ("attempt to re-define symbol `%s'", S_GET_NAME (sym));
+ ignore_rest_of_line ();
+ return;
+ }
+ }
+
+ S_SET_EXTERNAL (sym);
+ mri_common_symbol = sym;
+
+#ifdef S_SET_ALIGN
+ if (align != 0)
+ S_SET_ALIGN (sym, align);
+#endif
+
+ if (mri_line_label != NULL)
+ {
+ mri_line_label->sy_value.X_op = O_symbol;
+ mri_line_label->sy_value.X_add_symbol = sym;
+ mri_line_label->sy_value.X_add_number = S_GET_VALUE (sym);
+ mri_line_label->sy_frag = &zero_address_frag;
+ S_SET_SEGMENT (mri_line_label, expr_section);
+ }
+
+ /* FIXME: We just ignore the small argument, which distinguishes
+ COMMON and COMMON.S. I don't know what we can do about it. */
+
+ /* Ignore the type and hptype. */
+ if (*input_line_pointer == ',')
+ input_line_pointer += 2;
+ if (*input_line_pointer == ',')
+ input_line_pointer += 2;
+ demand_empty_rest_of_line ();
+}
+
void
s_data (ignore)
int ignore;
@@ -1457,12 +1602,27 @@ s_space (mult)
return;
}
+ /* If we are secretly in an MRI common section, then creating
+ space just increases the size of the common symbol. */
+ if (mri_common_symbol != NULL)
+ {
+ S_SET_VALUE (mri_common_symbol,
+ S_GET_VALUE (mri_common_symbol) + repeat);
+ demand_empty_rest_of_line ();
+ return;
+ }
+
if (!need_pass_2)
p = frag_var (rs_fill, 1, 1, (relax_substateT) 0, (symbolS *) 0,
repeat, (char *) 0);
}
else
{
+ if (mri_common_symbol != NULL)
+ {
+ as_bad ("space allocation too complex in common section");
+ mri_common_symbol = NULL;
+ }
if (!need_pass_2)
p = frag_var (rs_space, 1, 1, (relax_substateT) 0,
make_expr_symbol (&exp), 0L, (char *) 0);
@@ -1659,17 +1819,15 @@ pseudo_set (symbolP)
are defined, which is the normal case, then only simple expressions
are permitted. */
+static void
+parse_mri_cons PARAMS ((expressionS *exp, unsigned int nbytes));
+
#ifndef TC_PARSE_CONS_EXPRESSION
#ifdef BITFIELD_CONS_EXPRESSIONS
#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_bitfield_cons (EXP, NBYTES)
static void
parse_bitfield_cons PARAMS ((expressionS *exp, unsigned int nbytes));
#endif
-#ifdef MRI
-#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_mri_cons (EXP)
-static void
-parse_mri_cons PARAMS ((expressionS *exp));
-#endif
#ifdef REPEAT_CONS_EXPRESSIONS
#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_repeat_cons (EXP, NBYTES)
static void
@@ -1703,7 +1861,10 @@ cons (nbytes)
do
{
- TC_PARSE_CONS_EXPRESSION (&exp, (unsigned int) nbytes);
+ if (flag_mri)
+ parse_mri_cons (&exp, (unsigned int) nbytes);
+ else
+ TC_PARSE_CONS_EXPRESSION (&exp, (unsigned int) nbytes);
emit_expr (&exp, (unsigned int) nbytes);
}
while (*input_line_pointer++ == ',');
@@ -2076,20 +2237,34 @@ parse_bitfield_cons (exp, nbytes)
#endif /* BITFIELD_CONS_EXPRESSIONS */
-#ifdef MRI
+/* Handle an MRI style string expression. */
static void
parse_mri_cons (exp, nbytes)
expressionS *exp;
unsigned int nbytes;
{
- if (*input_line_pointer == '\'')
+ if (*input_line_pointer != '\''
+ && (input_line_pointer[1] != '\''
+ || (*input_line_pointer != 'A'
+ && *input_line_pointer != 'E')))
+ TC_PARSE_CONS_EXPRESSION (exp, nbytes);
+ else
{
- /* An MRI style string, cut into as many bytes as will fit into
- a nbyte chunk, left justify if necessary, and separate with
- commas so we can try again later */
int scan = 0;
unsigned int result = 0;
+
+ /* An MRI style string. Cut into as many bytes as will fit into
+ a nbyte chunk, left justify if necessary, and separate with
+ commas so we can try again later. */
+ if (*input_line_pointer == 'A')
+ ++input_line_pointer;
+ else if (*input_line_pointer == 'E')
+ {
+ as_bad ("EBCDIC constants are not supported");
+ ++input_line_pointer;
+ }
+
input_line_pointer++;
for (scan = 0; scan < nbytes; scan++)
{
@@ -2125,11 +2300,7 @@ parse_mri_cons (exp, nbytes)
else
input_line_pointer++;
}
- else
- expression (&exp);
}
-
-#endif /* MRI */
#ifdef REPEAT_CONS_EXPRESSIONS
@@ -2221,14 +2392,93 @@ float_cons (float_type)
if (input_line_pointer[0] == '0' && isalpha (input_line_pointer[1]))
input_line_pointer += 2;
- err = md_atof (float_type, temp, &length);
- know (length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
- know (length > 0);
- if (err)
+ /* Accept :xxxx, where the x's are hex digits, for a floating
+ point with the exact digits specified. */
+ if (input_line_pointer[0] == ':')
{
- as_bad ("Bad floating literal: %s", err);
- ignore_rest_of_line ();
- return;
+ int i;
+
+ switch (float_type)
+ {
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ length = 4;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ length = 8;
+ break;
+
+ case 'x':
+ case 'X':
+ length = 12;
+ break;
+
+ case 'p':
+ case 'P':
+ length = 12;
+ break;
+
+ default:
+ as_bad ("Unknown floating type type '%c'", float_type);
+ ignore_rest_of_line ();
+ return;
+ }
+
+ /* It would be nice if we could go through expression to
+ parse the hex constant, but if we get a bignum it's a
+ pain to sort it into the buffer correctly. */
+ i = 0;
+ ++input_line_pointer;
+ while (hex_p (*input_line_pointer) || *input_line_pointer == '_')
+ {
+ int d;
+
+ /* The MRI assembler accepts arbitrary underscores
+ strewn about through the hex constant, so we ignore
+ them as well. */
+ if (*input_line_pointer == '_')
+ {
+ ++input_line_pointer;
+ continue;
+ }
+
+ if (i >= length)
+ {
+ as_warn ("Floating point constant too large");
+ ignore_rest_of_line ();
+ return;
+ }
+ d = hex_value (*input_line_pointer) << 4;
+ ++input_line_pointer;
+ while (*input_line_pointer == '_')
+ ++input_line_pointer;
+ if (hex_p (*input_line_pointer))
+ {
+ d += hex_value (*input_line_pointer);
+ ++input_line_pointer;
+ }
+ temp[i++] = d;
+ }
+ if (i < length)
+ memset (temp + i, 0, length - i);
+ }
+ else
+ {
+ err = md_atof (float_type, temp, &length);
+ know (length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
+ know (length > 0);
+ if (err)
+ {
+ as_bad ("Bad floating literal: %s", err);
+ ignore_rest_of_line ();
+ return;
+ }
}
if (!need_pass_2)
diff --git a/gas/read.h b/gas/read.h
index f0691ae..3a3d82d 100644
--- a/gas/read.h
+++ b/gas/read.h
@@ -16,7 +16,7 @@
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
extern char *input_line_pointer;/* -> char we are parsing now. */
@@ -47,9 +47,11 @@ extern char *input_line_pointer;/* -> char we are parsing now. */
#define is_a_char(c) (((unsigned)(c)) <= CHAR_MASK)
#endif /* is_a_char() */
-extern const char lex_type[];
+extern char lex_type[];
extern char is_end_of_line[];
+extern int target_big_endian;
+
/* These are initialized by the CPU specific target files (tc-*.c). */
extern const char comment_chars[];
extern const char line_comment_chars[];
@@ -58,6 +60,9 @@ extern const char line_separator_chars[];
/* This flag whether to generate line info for asm file */
extern int generate_asm_lineno;
+/* This is used to support MRI common sections. */
+extern symbolS *mri_common_symbol;
+
unsigned int get_stab_string_offset PARAMS ((const char *string,
const char *stabstr_secname));
@@ -81,6 +86,7 @@ void s_align_ptwo PARAMS ((int));
void s_app_file PARAMS ((int));
void s_app_line PARAMS ((int));
void s_comm PARAMS ((int));
+void s_mri_common PARAMS ((int));
void s_data PARAMS ((int));
void s_desc PARAMS ((int));
void s_else PARAMS ((int arg));
diff --git a/gas/subsegs.c b/gas/subsegs.c
index 5ce2e9e..e360d32 100644
--- a/gas/subsegs.c
+++ b/gas/subsegs.c
@@ -16,7 +16,7 @@
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/*
* Segments & sub-segments.
@@ -38,7 +38,7 @@ segment_info_type segment_info[SEG_MAXIMUM_ORDINAL];
frchainS *data0_frchainP, *bss0_frchainP;
#endif /* MANY_SEGMENTS */
-char *const seg_name[] =
+char const *const seg_name[] =
{
"absolute",
#ifdef MANY_SEGMENTS
@@ -87,7 +87,6 @@ subsegs_begin ()
know (SEG_MAXIMUM_ORDINAL == SEG_REGISTER);
#endif
- obstack_begin (&frags, 5000);
frchain_root = NULL;
frchain_now = NULL; /* Warn new_subseg() that we are booting. */
/* Fake up 1st frag. It won't be used=> is ok if obstack...
@@ -198,7 +197,7 @@ subseg_set_rest (seg, subseg)
if (frag_now) /* If not bootstrapping. */
{
- frag_now->fr_fix = (char*) obstack_next_free (&frags) - frag_now->fr_literal;
+ frag_now->fr_fix = frag_now_fix ();
frag_wane (frag_now); /* Close off any frag in old subseg. */
}
/*
@@ -261,22 +260,22 @@ subseg_set_rest (seg, subseg)
* This should be the only code that creates a frchainS.
*/
newP = (frchainS *) obstack_alloc (&frags, sizeof (frchainS));
- memset (newP, 0, sizeof (frchainS));
- /* This begines on a good boundary because a obstack_done()
- preceeded it. It implies an obstack_done(), so we expect
- the next object allocated to begin on a correct boundary. */
- *lastPP = newP;
- newP->frch_next = frcP; /* perhaps NULL */
- (frcP = newP)->frch_subseg = subseg;
+ newP->frch_root = 0;
+ newP->frch_subseg = subseg;
newP->frch_seg = seg;
newP->frch_last = NULL;
#ifdef BFD_ASSEMBLER
newP->fix_root = NULL;
newP->fix_tail = NULL;
#endif
+ obstack_begin (&newP->frch_obstack, 5000);
+
+ *lastPP = newP;
+ newP->frch_next = frcP; /* perhaps NULL */
+ frcP = newP;
}
/*
- * Here with frcP ->ing to the frchainS for subseg.
+ * Here with frcP pointing to the frchainS for subseg.
*/
frchain_now = frcP;
/*
@@ -308,6 +307,8 @@ subseg_set_rest (seg, subseg)
frcP->frch_root = new_fragP;
}
frcP->frch_last = new_fragP;
+
+ mri_common_symbol = NULL;
}
/*
@@ -385,6 +386,7 @@ subseg_set (seg, subseg) /* begin assembly for a new sub-segment */
{ /* we just changed sub-segments */
subseg_set_rest (seg, subseg);
}
+ mri_common_symbol = NULL;
}
#else /* BFD_ASSEMBLER */
@@ -478,6 +480,7 @@ subseg_set (secptr, subseg)
{
if (! (secptr == now_seg && subseg == now_subseg))
subseg_set_rest (secptr, subseg);
+ mri_common_symbol = NULL;
}
#ifndef obj_sec_sym_ok_for_reloc
@@ -516,14 +519,15 @@ section_symbol (sec)
#define EMIT_SECTION_SYMBOLS 1
#endif
- if (EMIT_SECTION_SYMBOLS
+ if (! EMIT_SECTION_SYMBOLS
#ifdef BFD_ASSEMBLER
&& symbol_table_frozen
#endif
)
- s = symbol_new (sec->name, sec, 0, &zero_address_frag);
- else
+ /* Here we know it won't be going into the symbol table. */
s = symbol_create (sec->name, sec, 0, &zero_address_frag);
+ else
+ s = symbol_new (sec->name, sec, 0, &zero_address_frag);
S_CLEAR_EXTERNAL (s);
/* Use the BFD section symbol, if possible. */
diff --git a/gas/symbols.c b/gas/symbols.c
index 8fd395f..3e8d1de 100644
--- a/gas/symbols.c
+++ b/gas/symbols.c
@@ -16,7 +16,7 @@
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* #define DEBUG_SYMS / * to debug symbol list maintenance */
@@ -27,6 +27,10 @@
#include "obstack.h" /* For "symbols.h" */
#include "subsegs.h"
+/* This is non-zero if symbols are case sensitive, which is the
+ default. */
+int symbols_case_sensitive = 1;
+
#ifndef WORKING_DOT_WORD
extern int new_broken_words;
#endif
@@ -109,6 +113,15 @@ symbol_create (name, segment, valu, frag)
tc_canonicalize_symbol_name (preserved_copy_of_name);
#endif
+ if (! symbols_case_sensitive)
+ {
+ unsigned char *s;
+
+ for (s = (unsigned char *) preserved_copy_of_name; *s != '\0'; s++)
+ if (islower (*s))
+ *s = toupper (*s);
+ }
+
symbolP = (symbolS *) obstack_alloc (&notes, sizeof (symbolS));
/* symbol must be born in some fixed state. This seems as good as any. */
@@ -150,7 +163,7 @@ symbol_create (name, segment, valu, frag)
* Gripes if we are redefining a symbol incompatibly (and ignores it).
*
*/
-void
+symbolS *
colon (sym_name) /* just seen "x:" - rattle symbols & frags */
register char *sym_name; /* symbol name, as a cannonical string */
/* We copy this string: OK to alter later. */
@@ -204,7 +217,7 @@ colon (sym_name) /* just seen "x:" - rattle symbols & frags */
{
#ifdef RESOLVE_SYMBOL_REDEFINITION
if (RESOLVE_SYMBOL_REDEFINITION (symbolP))
- return;
+ return symbolP;
#endif
/*
* Now check for undefined symbols
@@ -311,9 +324,23 @@ colon (sym_name) /* just seen "x:" - rattle symbols & frags */
symbol_table_insert (symbolP);
} /* if we have seen this symbol before */
+ if (mri_common_symbol != NULL)
+ {
+ /* This symbol is actually being defined within an MRI common
+ section. This requires special handling. */
+ symbolP->sy_value.X_op = O_symbol;
+ symbolP->sy_value.X_add_symbol = mri_common_symbol;
+ symbolP->sy_value.X_add_number = S_GET_VALUE (mri_common_symbol);
+ symbolP->sy_frag = &zero_address_frag;
+ S_SET_SEGMENT (symbolP, expr_section);
+ symbolP->sy_mri_common = 1;
+ }
+
#ifdef tc_frob_label
tc_frob_label (symbolP);
#endif
+
+ return symbolP;
}
@@ -417,6 +444,17 @@ symbol_find_base (name, strip_underscore)
}
#endif
+ if (! symbols_case_sensitive)
+ {
+ unsigned char *copy;
+
+ copy = (unsigned char *) alloca (strlen (name) + 1);
+ name = (const char *) copy;
+ for (; *copy != '\0'; copy++)
+ if (islower (*copy))
+ *copy = toupper (*copy);
+ }
+
return ((symbolS *) hash_find (sy_hash, name));
}
@@ -616,6 +654,16 @@ resolve_symbol_value (symp)
case O_symbol:
resolve_symbol_value (symp->sy_value.X_add_symbol);
+ if (symp->sy_mri_common)
+ {
+ /* This is a symbol inside an MRI common section. The
+ relocation routines are going to handle it specially.
+ Don't change the value. */
+ S_SET_VALUE (symp, symp->sy_value.X_add_number);
+ resolved = symp->sy_value.X_add_symbol->sy_resolved;
+ break;
+ }
+
#if 0 /* I thought this was needed for some of the i386-svr4 PIC
support, but it appears I was wrong, and it breaks rs6000
support. */
@@ -698,6 +746,12 @@ resolve_symbol_value (symp)
case O_bit_exclusive_or:
case O_bit_and:
case O_subtract:
+ case O_eq:
+ case O_ne:
+ case O_lt:
+ case O_le:
+ case O_ge:
+ case O_gt:
resolve_symbol_value (symp->sy_value.X_add_symbol);
resolve_symbol_value (symp->sy_value.X_op_symbol);
seg_left = S_GET_SEGMENT (symp->sy_value.X_add_symbol);
@@ -727,6 +781,12 @@ resolve_symbol_value (symp)
case O_bit_and: val = left & right; break;
case O_add: val = left + right; break;
case O_subtract: val = left - right; break;
+ case O_eq: val = left == right ? ~ (offsetT) 0 : 0;
+ case O_ne: val = left != right ? ~ (offsetT) 0 : 0;
+ case O_lt: val = left < right ? ~ (offsetT) 0 : 0;
+ case O_le: val = left <= right ? ~ (offsetT) 0 : 0;
+ case O_ge: val = left >= right ? ~ (offsetT) 0 : 0;
+ case O_gt: val = left > right ? ~ (offsetT) 0 : 0;
default: abort ();
}
S_SET_VALUE (symp,
@@ -1205,17 +1265,22 @@ S_IS_LOCAL (s)
symbolS *s;
{
flagword flags = s->bsym->flags;
+ const char *name;
/* sanity check */
if (flags & BSF_LOCAL && flags & BSF_GLOBAL)
abort ();
- return (S_GET_NAME (s)
+ name = S_GET_NAME (s);
+ return (name != NULL
&& ! S_IS_DEBUG (s)
- && (strchr (S_GET_NAME (s), '\001')
- || strchr (S_GET_NAME (s), '\002')
- || (S_LOCAL_NAME (s)
- && !flag_keep_locals)));
+ && (strchr (name, '\001')
+ || strchr (name, '\002')
+ || (! flag_keep_locals
+ && (LOCAL_LABEL (name)
+ || (flag_mri
+ && name[0] == '?'
+ && name[1] == '?')))));
}
int
@@ -1456,6 +1521,24 @@ print_expr_1 (file, exp)
case O_bit_and:
fprintf (file, "bit_and");
break;
+ case O_eq:
+ fprintf (file, "eq");
+ break;
+ case O_ne:
+ fprintf (file, "ne");
+ break;
+ case O_lt:
+ fprintf (file, "lt");
+ break;
+ case O_le:
+ fprintf (file, "le");
+ break;
+ case O_ge:
+ fprintf (file, "ge");
+ break;
+ case O_gt:
+ fprintf (file, "gt");
+ break;
case O_add:
indent_level++;
fprintf (file, "add\n%*s<", indent_level * 4, "");
diff --git a/gas/symbols.h b/gas/symbols.h
index 3912c08..df07dbf 100644
--- a/gas/symbols.h
+++ b/gas/symbols.h
@@ -1,6 +1,5 @@
/* symbols.h -
-
- Copyright (C) 1987, 1990, 1992 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1990, 1992, 1993, 1994 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@@ -16,7 +15,7 @@
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
extern struct obstack notes; /* eg FixS live here. */
@@ -28,9 +27,11 @@ extern symbolS *symbol_lastP; /* last struct symbol we made, or NULL */
extern symbolS abs_symbol;
-extern symbolS *dot_text_symbol;
-extern symbolS *dot_data_symbol;
-extern symbolS *dot_bss_symbol;
+extern int symbol_table_frozen;
+
+/* This is non-zero if symbols are case sensitive, which is the
+ default. */
+extern int symbols_case_sensitive;
char *decode_local_label_name PARAMS ((char *s));
symbolS *symbol_find PARAMS ((CONST char *name));
@@ -39,23 +40,23 @@ symbolS *symbol_find_or_make PARAMS ((char *name));
symbolS *symbol_make PARAMS ((CONST char *name));
symbolS *symbol_new PARAMS ((CONST char *name, segT segment, valueT value,
fragS * frag));
-void colon PARAMS ((char *sym_name));
+symbolS *symbol_create PARAMS ((CONST char *name, segT segment, valueT value,
+ fragS * frag));
+symbolS *colon PARAMS ((char *sym_name));
void local_colon PARAMS ((int n));
void symbol_begin PARAMS ((void));
void symbol_table_insert PARAMS ((symbolS * symbolP));
-void verify_symbol_chain PARAMS ((symbolS * rootP, symbolS * lastP));
+void resolve_symbol_value PARAMS ((symbolS *));
-#ifdef LOCAL_LABELS_DOLLAR
int dollar_label_defined PARAMS ((long l));
void dollar_label_clear PARAMS ((void));
void define_dollar_label PARAMS ((long l));
char *dollar_label_name PARAMS ((long l, int augend));
-#endif /* LOCAL_LABELS_DOLLAR */
-#ifdef LOCAL_LABELS_FB
void fb_label_instance_inc PARAMS ((long label));
char *fb_label_name PARAMS ((long n, long augend));
-#endif /* LOCAL_LABELS_FB */
+
+extern void copy_symbol_attributes PARAMS ((symbolS *, symbolS *));
/* Get and set the values of symbols. These used to be macros. */
extern valueT S_GET_VALUE PARAMS ((symbolS *));
@@ -75,6 +76,7 @@ extern void S_SET_SEGMENT PARAMS ((symbolS *, segT));
extern void S_SET_EXTERNAL PARAMS ((symbolS *));
extern void S_SET_NAME PARAMS ((symbolS *, char *));
extern void S_CLEAR_EXTERNAL PARAMS ((symbolS *));
+extern void S_SET_WEAK PARAMS ((symbolS *));
#endif
/* end of symbols.h */
diff --git a/gas/write.c b/gas/write.c
index df8f66e..f9ec214 100644
--- a/gas/write.c
+++ b/gas/write.c
@@ -630,6 +630,12 @@ adjust_reloc_syms (abfd, sec, xxx)
sym = fixp->fx_addsy;
symsec = sym->bsym->section;
+ if (sym->sy_mri_common)
+ {
+ /* These symbols are handled specially in fixup_segment. */
+ goto done;
+ }
+
/* If it's one of these sections, assume the symbol is
definitely going to be output. The code in
md_estimate_size_before_relax in tc-mips.c uses this test
@@ -1578,6 +1584,15 @@ write_object_file ()
int punt = 0;
const char *name;
+ if (symp->sy_mri_common)
+ {
+ if (S_IS_EXTERNAL (symp))
+ as_bad ("%s: global symbols not supported in common sections",
+ S_GET_NAME (symp));
+ symbol_remove (symp, &symbol_rootP, &symbol_lastP);
+ continue;
+ }
+
name = S_GET_NAME (symp);
if (name)
{
@@ -2154,6 +2169,14 @@ fixup_segment (fixP, this_segment_type)
pcrel = fixP->fx_pcrel;
plt = fixP->fx_plt;
+ if (add_symbolP->sy_mri_common)
+ {
+ know (add_symbolP->sy_value.X_op == O_symbol);
+ add_number += S_GET_VALUE (add_symbolP);
+ fixP->fx_offset = add_number;
+ add_symbolP = fixP->fx_addsy = add_symbolP->sy_value.X_add_symbol;
+ }
+
if (add_symbolP)
add_symbol_segment = S_GET_SEGMENT (add_symbolP);