/* frags.c - manage frags -
- Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 97, 1998
+ Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ 1999, 2000
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
extern fragS bss_address_frag;
\f
/* Initialization for frag routines. */
+
void
frag_init ()
{
/* 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;
return ptr;
}
\f
-/*
- * frag_grow()
- *
- * 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.
- */
-void
+/* 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. */
+
+void
frag_grow (nchars)
unsigned int nchars;
{
frag_new (0);
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);
- }
+ if (frchain_now->frch_obstack.chunk_size > 0)
+ while ((n = obstack_room (&frchain_now->frch_obstack)) < nchars
+ && (unsigned long) frchain_now->frch_obstack.chunk_size > nchars)
+ {
+ frag_wane (frag_now);
+ frag_new (0);
+ }
frchain_now->frch_obstack.chunk_size = oldc;
}
if (obstack_room (&frchain_now->frch_obstack) < nchars)
- as_fatal (_("Can't extend frag %d. chars"), nchars);
+ as_fatal (_("can't extend frag %u chars"), nchars);
}
\f
-/*
- * frag_new()
- *
- * Call this to close off a completed frag, and start up a new (empty)
- * frag, in the same subsegment as the old frag.
- * [frchain_now remains the same but frag_now is updated.]
- * Because this calculates the correct value of fr_fix by
- * looking at the obstack 'frags', it needs to know how many
- * characters at the end of the old frag belong to (the maximal)
- * fr_var: the rest must belong to fr_fix.
- * It doesn't actually set up the old frag's fr_var: you may have
- * set fr_var == 1, but allocated 10 chars to the end of the frag:
- * in this case you pass old_frags_var_max_size == 10.
- *
- * Make a new frag, initialising some components. Link new frag at end
- * of frchain_now.
- */
-void
+/* Call this to close off a completed frag, and start up a new (empty)
+ frag, in the same subsegment as the old frag.
+ [frchain_now remains the same but frag_now is updated.]
+ Because this calculates the correct value of fr_fix by
+ looking at the obstack 'frags', it needs to know how many
+ characters at the end of the old frag belong to the maximal
+ variable part; The rest must belong to fr_fix.
+ It doesn't actually set up the old frag's fr_var. You may have
+ set fr_var == 1, but allocated 10 chars to the end of the frag;
+ In this case you pass old_frags_var_max_size == 10.
+ In fact, you may use fr_var for something totally unrelated to the
+ size of the variable part of the frag; None of the generic frag
+ handling code makes use of fr_var.
+
+ Make a new frag, initialising some components. Link new frag at end
+ of frchain_now. */
+
+void
frag_new (old_frags_var_max_size)
/* Number of chars (already allocated on obstack frags) in
- variable_length part of frag. */
+ variable_length part of frag. */
int old_frags_var_max_size;
{
fragS *former_last_fragP;
assert (frag_now->fr_type != 0);
/* This will align the obstack so the next struct we allocate on it
- will begin at a correct boundary. */
+ will begin at a correct boundary. */
obstack_finish (&frchain_now->frch_obstack);
frchP = frchain_now;
know (frchP);
/* 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. */
+ at an alignment address. */
former_last_fragP->fr_next = frag_now;
frchP->frch_last = frag_now;
assert (frchain_now->frch_last == frag_now);
frag_now->fr_next = NULL;
-} /* frag_new() */
+}
\f
-/*
- * frag_more()
- *
- * Start a new frag unless we have n more chars of room in the current frag.
- * Close off the old frag with a .fill 0.
- *
- * Return the address of the 1st char to write into. Advance
- * frag_now_growth past the new chars.
- */
+/* Start a new frag unless we have n more chars of room in the current frag.
+ Close off the old frag with a .fill 0.
+
+ Return the address of the 1st char to write into. Advance
+ frag_now_growth past the new chars. */
char *
frag_more (nchars)
retval = obstack_next_free (&frchain_now->frch_obstack);
obstack_blank_fast (&frchain_now->frch_obstack, nchars);
return (retval);
-} /* frag_more() */
+}
\f
-/*
- * frag_var()
- *
- * Start a new frag unless we have max_chars more chars of room in the current frag.
- * Close off the old frag with a .fill 0.
- *
- * Set up a machine_dependent relaxable frag, then start a new frag.
- * Return the address of the 1st char of the var part of the old frag
- * to write into.
- */
+/* Start a new frag unless we have max_chars more chars of room in the
+ current frag. Close off the old frag with a .fill 0.
+
+ Set up a machine_dependent relaxable frag, then start a new frag.
+ Return the address of the 1st char of the var part of the old frag
+ to write into. */
char *
frag_var (type, max_chars, var, subtype, symbol, offset, opcode)
return (retval);
}
\f
-/*
- * frag_variant()
- *
- * OVE: This variant of frag_var assumes that space for the tail has been
- * allocated by caller.
- * No call to frag_grow is done.
- */
+/* OVE: This variant of frag_var assumes that space for the tail has been
+ allocated by caller.
+ No call to frag_grow is done. */
char *
frag_variant (type, max_chars, var, subtype, symbol, offset, opcode)
as_where (&frag_now->fr_file, &frag_now->fr_line);
frag_new (max_chars);
return (retval);
-} /* frag_variant() */
+}
\f
-/*
- * frag_wane()
- *
- * Reduce the variable end of a frag to a harmless state.
- */
-void
+/* Reduce the variable end of a frag to a harmless state. */
+
+void
frag_wane (fragP)
register fragS *fragP;
{
the maximum number of characters to skip when doing the alignment,
or 0 if there is no maximum. */
-void
+void
frag_align (alignment, fill_character, max)
int alignment;
int fill_character;
if (now_seg == absolute_section)
{
addressT new_off;
+ addressT mask;
- new_off = ((abs_section_offset + alignment - 1)
- &~ ((1 << alignment) - 1));
+ mask = (~(addressT) 0) << alignment;
+ new_off = (abs_section_offset + ~mask) & mask;
if (max == 0 || new_off - abs_section_offset <= (addressT) max)
abs_section_offset = new_off;
}
FILL_PATTERN. MAX is the maximum number of characters to skip when
doing the alignment, or 0 if there is no maximum. */
-void
+void
frag_align_pattern (alignment, fill_pattern, n_fill, max)
int alignment;
const char *fill_pattern;
memcpy (p, fill_pattern, n_fill);
}
+/* The NOP_OPCODE is for the alignment fill value. Fill it with a nop
+ instruction so that the disassembler does not choke on it. */
+#ifndef NOP_OPCODE
+#define NOP_OPCODE 0x00
+#endif
+
+/* Use this to restrict the amount of memory allocated for representing
+ the alignment code. Needs to be large enough to hold any fixed sized
+ prologue plus the replicating portion. */
+#ifndef MAX_MEM_FOR_RS_ALIGN_CODE
+ /* Assume that if HANDLE_ALIGN is not defined then no special action
+ is required to code fill, which means that we get just repeat the
+ one NOP_OPCODE byte. */
+# ifndef HANDLE_ALIGN
+# define MAX_MEM_FOR_RS_ALIGN_CODE 1
+# else
+# define MAX_MEM_FOR_RS_ALIGN_CODE ((1 << alignment) - 1)
+# endif
+#endif
+
+void
+frag_align_code (alignment, max)
+ int alignment;
+ int max;
+{
+ char *p;
+
+ p = frag_var (rs_align_code, MAX_MEM_FOR_RS_ALIGN_CODE, 1,
+ (relax_substateT) max, (symbolS *) 0,
+ (offsetT) alignment, (char *) 0);
+ *p = NOP_OPCODE;
+}
+
addressT
frag_now_fix_octets ()
{
if (now_seg == absolute_section)
return abs_section_offset;
- return ((char*) obstack_next_free (&frchain_now->frch_obstack)
- - frag_now->fr_literal);
+ return ((char *) obstack_next_free (&frchain_now->frch_obstack)
+ - frag_now->fr_literal);
}
addressT
frag_now_fix ()
{
- return frag_now_fix_octets() / OCTETS_PER_BYTE;
+ return frag_now_fix_octets () / OCTETS_PER_BYTE;
}
void
}
obstack_1grow (&frchain_now->frch_obstack, datum);
}
-
-/* end of frags.c */