/* frags.c - manage frags -
-
- Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 97, 1998
+ Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
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. */
+ 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 "as.h"
#include "subsegs.h"
#include "obstack.h"
-struct obstack frags; /* All, and only, frags live here. */
-
extern fragS zero_address_frag;
extern fragS bss_address_frag;
\f
{
zero_address_frag.fr_type = rs_fill;
bss_address_frag.fr_type = rs_fill;
- obstack_begin (&frags, 5000);
+}
+\f
+/* Allocate a frag on the specified obstack.
+ Call this routine from everywhere else, so that all the weird alignment
+ hackery can be done in just one place. */
+fragS *
+frag_alloc (ob)
+ struct obstack *ob;
+{
+ fragS *ptr;
+ int oalign;
+
+ (void) obstack_alloc (ob, 0);
+ oalign = obstack_alignment_mask (ob);
+ obstack_alignment_mask (ob) = 0;
+ ptr = (fragS *) obstack_alloc (ob, SIZEOF_STRUCT_FRAG);
+ obstack_alignment_mask (ob) = oalign;
+ memset (ptr, 0, SIZEOF_STRUCT_FRAG);
+ return ptr;
}
\f
/*
frag_grow (nchars)
unsigned int nchars;
{
- if (obstack_room (&frags) < nchars)
+ if (obstack_room (&frchain_now->frch_obstack) < nchars)
{
- unsigned int n, oldn;
+ unsigned int n;
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)
+ oldc = frchain_now->frch_obstack.chunk_size;
+ frchain_now->frch_obstack.chunk_size = 2 * nchars + SIZEOF_STRUCT_FRAG;
+ while ((n = obstack_room (&frchain_now->frch_obstack)) < nchars)
{
frag_wane (frag_now);
frag_new (0);
- oldn = n;
}
- frags.chunk_size = oldc;
+ frchain_now->frch_obstack.chunk_size = oldc;
}
- if (obstack_room (&frags) < nchars)
- as_fatal ("Can't extend frag %d. chars", nchars);
-} /* frag_grow() */
+ if (obstack_room (&frchain_now->frch_obstack) < nchars)
+ as_fatal (_("Can't extend frag %d. chars"), nchars);
+}
\f
/*
* frag_new()
*/
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. */
+ /* Number of chars (already allocated on obstack frags) in
+ variable_length part of frag. */
+ int old_frags_var_max_size;
{
- register fragS *former_last_fragP;
- register frchainS *frchP;
- long tmp;
+ fragS *former_last_fragP;
+ frchainS *frchP;
+
+ assert (frchain_now->frch_last == frag_now);
+ /* Fix up old frag's fr_fix. */
frag_now->fr_fix = frag_now_fix () - old_frags_var_max_size;
- /* Fix up old frag's fr_fix. */
+ /* Make sure its type is valid. */
+ assert (frag_now->fr_type != 0);
- obstack_finish (&frags);
/* This will align the obstack so the next struct we allocate on it
will begin at a correct boundary. */
+ obstack_finish (&frchain_now->frch_obstack);
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);
+ assert (former_last_fragP != 0);
+ assert (former_last_fragP == frag_now);
+ frag_now = frag_alloc (&frchP->frch_obstack);
+
+ as_where (&frag_now->fr_file, &frag_now->fr_line);
/* Generally, frag_now->points to an address rounded up to next
alignment. However, characters will add to obstack frags
}
#endif
+ assert (frchain_now->frch_last == frag_now);
+
frag_now->fr_next = NULL;
} /* frag_new() */
\f
{
register char *retval;
+ if (now_seg == absolute_section)
+ {
+ as_bad (_("attempt to allocate data in absolute section"));
+ subseg_set (text_section, 0);
+ }
+
if (mri_common_symbol != NULL)
{
- as_bad ("attempt to allocate data in common section");
+ 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);
+ retval = obstack_next_free (&frchain_now->frch_obstack);
+ obstack_blank_fast (&frchain_now->frch_obstack, nchars);
return (retval);
} /* frag_more() */
\f
int var;
relax_substateT subtype;
symbolS *symbol;
- long offset;
+ offsetT offset;
char *opcode;
{
register char *retval;
frag_grow (max_chars);
- retval = obstack_next_free (&frags);
- obstack_blank_fast (&frags, max_chars);
+ retval = obstack_next_free (&frchain_now->frch_obstack);
+ obstack_blank_fast (&frchain_now->frch_obstack, 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;
+#ifdef USING_CGEN
+ frag_now->fr_cgen.insn = 0;
+ frag_now->fr_cgen.opindex = 0;
+ frag_now->fr_cgen.opinfo = 0;
+#endif
+#ifdef TC_FRAG_INIT
+ TC_FRAG_INIT (frag_now);
+#endif
+ as_where (&frag_now->fr_file, &frag_now->fr_line);
frag_new (max_chars);
return (retval);
}
* OVE: This variant of frag_var assumes that space for the tail has been
* allocated by caller.
* No call to frag_grow is done.
- * Two new arguments have been added.
*/
char *
int var;
relax_substateT subtype;
symbolS *symbol;
- long offset;
+ offsetT offset;
char *opcode;
{
register char *retval;
- retval = obstack_next_free (&frags);
+ retval = obstack_next_free (&frchain_now->frch_obstack);
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;
+#ifdef USING_CGEN
+ frag_now->fr_cgen.insn = 0;
+ frag_now->fr_cgen.opindex = 0;
+ frag_now->fr_cgen.opinfo = 0;
+#endif
+#ifdef TC_FRAG_INIT
+ TC_FRAG_INIT (frag_now);
+#endif
+ as_where (&frag_now->fr_file, &frag_now->fr_line);
frag_new (max_chars);
return (retval);
} /* frag_variant() */
fragP->fr_var = 0;
}
\f
-/*
- * frag_align()
- *
- * Make a frag for ".align foo,bar". Call is "frag_align (foo,bar);".
- * Foo & bar are absolute integers.
- *
- * Call to close off the current frag with a ".align", then start a new
- * (so far empty) frag, in the same subsegment as the last frag.
- */
+/* Make an alignment frag. The size of this frag will be adjusted to
+ force the next frag to have the appropriate alignment. ALIGNMENT
+ is the power of two to which to align. FILL_CHARACTER is the
+ character to use to fill in any bytes which are skipped. MAX is
+ the maximum number of characters to skip when doing the alignment,
+ or 0 if there is no maximum. */
void
-frag_align (alignment, fill_character)
+frag_align (alignment, fill_character, max)
int alignment;
int fill_character;
+ int max;
{
- char *p;
- p = frag_var (rs_align, 1, 1, (relax_substateT) 0,
- (symbolS *) 0, (long) alignment, (char *) 0);
- *p = fill_character;
+ if (now_seg == absolute_section)
+ {
+ addressT new_off;
+
+ new_off = ((abs_section_offset + alignment - 1)
+ &~ ((1 << alignment) - 1));
+ if (max == 0 || new_off - abs_section_offset <= (addressT) max)
+ abs_section_offset = new_off;
+ }
+ else
+ {
+ char *p;
+
+ p = frag_var (rs_align, 1, 1, (relax_substateT) max,
+ (symbolS *) 0, (offsetT) alignment, (char *) 0);
+ *p = fill_character;
+ }
}
+/* Make an alignment frag like frag_align, but fill with a repeating
+ pattern rather than a single byte. ALIGNMENT is the power of two
+ to which to align. FILL_PATTERN is the fill pattern to repeat in
+ the bytes which are skipped. N_FILL is the number of bytes in
+ FILL_PATTERN. MAX is the maximum number of characters to skip when
+ doing the alignment, or 0 if there is no maximum. */
+
void
-frag_align_pattern (alignment, fill_pattern, n_fill)
+frag_align_pattern (alignment, fill_pattern, n_fill, max)
int alignment;
const char *fill_pattern;
int n_fill;
+ int max;
{
char *p;
- p = frag_var (rs_align, n_fill, n_fill, (relax_substateT) 0,
- (symbolS *) 0, (long) alignment, (char *) 0);
+
+ p = frag_var (rs_align, n_fill, n_fill, (relax_substateT) max,
+ (symbolS *) 0, (offsetT) alignment, (char *) 0);
memcpy (p, fill_pattern, n_fill);
}
-int
+addressT
frag_now_fix ()
{
- return (char*)obstack_next_free (&frags) - frag_now->fr_literal;
+ if (now_seg == absolute_section)
+ return abs_section_offset;
+ return (addressT) ((char*) obstack_next_free (&frchain_now->frch_obstack)
+ - frag_now->fr_literal);
}
void
frag_append_1_char (datum)
int datum;
{
- if (obstack_room (&frags) <= 1)
+ if (obstack_room (&frchain_now->frch_obstack) <= 1)
{
frag_wane (frag_now);
frag_new (0);
}
- obstack_1grow (&frags, datum);
+ obstack_1grow (&frchain_now->frch_obstack, datum);
}
/* end of frags.c */