2000-08-11 Kazu Hirata <kazu@hxi.com>
[deliverable/binutils-gdb.git] / gas / frags.c
index 3526603f1edac3e682b343e84b3846b01990449d..5c31b7e89318d527d9154691b739c7a442aff131 100644 (file)
@@ -1,92 +1,91 @@
 /* frags.c - manage frags -
-   Copyright (C) 1987, 1990, 1991 Free Software Foundation, Inc.
+   Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000
+   Free Software Foundation, Inc.
 
-This file is part of GAS, the GNU Assembler.
+   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 1, or (at your option)
-any later version.
+   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.
+   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.  */
-
-/* static const char rcsid[] = "$Id$"; */
+   You should have received a copy of the GNU General Public License
+   along with GAS; see the file COPYING.  If not, write to the Free
+   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
 
 #include "as.h"
 #include "subsegs.h"
 #include "obstack.h"
 
-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;
+\f
+/* Initialization for frag routines.  */
+void
+frag_init ()
+{
+  zero_address_frag.fr_type = rs_fill;
+  bss_address_frag.fr_type = rs_fill;
+}
+\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()
  *
- * 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 (&frchain_now->frch_obstack) < nchars)
+    {
+      unsigned int n;
+      long oldc;
+
+      frag_wane (frag_now);
+      frag_new (0);
+      oldc = frchain_now->frch_obstack.chunk_size;
+      frchain_now->frch_obstack.chunk_size = 2 * nchars + SIZEOF_STRUCT_FRAG;
+      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 (&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()
@@ -96,63 +95,63 @@ unsigned int nchars;
  * [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.
+ * 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)
-int old_frags_var_max_size;    /* Number of chars (already allocated on
-                                  obstack frags) */
- /* in variable_length part of frag. */
+void 
+frag_new (old_frags_var_max_size)
+     /* 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;
-/*    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;
-    frag_now->fr_next = NULL;
+  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_octets () - old_frags_var_max_size;
+  /* Make sure its type is valid.  */
+  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. */
+  obstack_finish (&frchain_now->frch_obstack);
+  frchP = frchain_now;
+  know (frchP);
+  former_last_fragP = frchP->frch_last;
+  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
+     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;
+  }
+#endif
+
+  assert (frchain_now->frch_last == frag_now);
+
+  frag_now->fr_next = NULL;
 }                              /* frag_new() */
 \f
 /*
@@ -165,15 +164,28 @@ 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;
+  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"));
+      mri_common_symbol = NULL;
+    }
 
-    frag_grow (nchars);
-    retval = obstack_next_free (&frags);
-    obstack_blank_fast (&frags, nchars);
-    return (retval);
+  frag_grow (nchars);
+  retval = obstack_next_free (&frchain_now->frch_obstack);
+  obstack_blank_fast (&frchain_now->frch_obstack, nchars);
+  return (retval);
 }                              /* frag_more() */
 \f
 /*
@@ -187,32 +199,39 @@ 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;
+     offsetT 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 (&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;
+#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);
+}
 \f
 /*
  *                     frag_variant()
@@ -220,35 +239,38 @@ char *opcode;
  * 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 *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;
+     offsetT 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 (&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;
+#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() */
 \f
 /*
@@ -256,30 +278,95 @@ char *frag_variant(type, max_chars, var, subtype, symbol, offset, opcode, pcrel_
  *
  * 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;
 }
 \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)
-int alignment;
-int fill_character;
+void 
+frag_align (alignment, fill_character, max)
+     int alignment;
+     int fill_character;
+     int max;
 {
-    *(frag_var (rs_align, 1, 1, (relax_substateT)0, (symbolS *)0,
- (long)alignment, (char *)0)) = fill_character;
-} /* frag_align() */
+  if (now_seg == absolute_section)
+    {
+      addressT new_off;
+      addressT mask;
+
+      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;
+    }
+  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, 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) max,
+               (symbolS *) 0, (offsetT) alignment, (char *) 0);
+  memcpy (p, fill_pattern, n_fill);
+}
+
+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);
+}
+
+addressT
+frag_now_fix ()
+{
+  return frag_now_fix_octets() / OCTETS_PER_BYTE;
+}
+
+void
+frag_append_1_char (datum)
+     int datum;
+{
+  if (obstack_room (&frchain_now->frch_obstack) <= 1)
+    {
+      frag_wane (frag_now);
+      frag_new (0);
+    }
+  obstack_1grow (&frchain_now->frch_obstack, datum);
+}
 
-/* end: frags.c */
+/* end of frags.c */
This page took 0.029579 seconds and 4 git commands to generate.