From 1356d77df3d5860b008035d6ad2f4f1f7093b0fe Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 8 Aug 1995 21:41:30 +0000 Subject: [PATCH] * 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. --- gas/ChangeLog | 28 ++++ gas/config/obj-coff.c | 23 ++- gas/frags.c | 373 ++++++++++++++++++++++-------------------- gas/read.c | 348 +++++++++++++++++++++++++++++++++------ gas/read.h | 10 +- gas/subsegs.c | 34 ++-- gas/symbols.c | 99 ++++++++++- gas/symbols.h | 26 +-- gas/write.c | 23 +++ 9 files changed, 698 insertions(+), 266 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index de98956255..4969b998f3 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,5 +1,33 @@ Tue Aug 8 13:07:05 1995 Ian Lance Taylor + * 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 11a5daa96d..b48900b96f 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 9185341cc7..f52692e271 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))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 05996ff780..bacd186786 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,22 +411,43 @@ 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)) - { - char *line_start = input_line_pointer; - char c = get_symbol_end (); - colon (line_start); - *input_line_pointer = c; - if (c == ':') - input_line_pointer++; - - } + if (flag_mri +#ifdef LABELS_WITHOUT_COLONS + || 1 #endif - } + ) + { + 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++; + } + } + } /* * We are at the begining of a line, or similar place. @@ -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 f0691ae7d3..3a3d82dfe2 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 5ce2e9e33d..e360d32948 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 8fd395fa41..3e8d1deb97 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 (¬es, 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 3912c08c3d..df07dbf831 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 df8f66e984..f9ec214eb5 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);