This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.git] / gas / frags.c
1 /* frags.c - manage frags -
2
3    Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
4
5    This file is part of GAS, the GNU Assembler.
6
7    GAS is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2, or (at your option)
10    any later version.
11
12    GAS is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GAS; see the file COPYING.  If not, write to
19    the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 #include "as.h"
22 #include "subsegs.h"
23 #include "obstack.h"
24
25 struct obstack frags;           /* All, and only, frags live here. */
26
27 extern fragS zero_address_frag;
28 extern fragS bss_address_frag;
29 \f
30 /* Initialization for frag routines.  */
31 void
32 frag_init ()
33 {
34   zero_address_frag.fr_type = rs_fill;
35   bss_address_frag.fr_type = rs_fill;
36   obstack_begin (&frags, 5000);
37 }
38 \f
39 /*
40  *                      frag_grow()
41  *
42  * Try to augment current frag by nchars chars.
43  * If there is no room, close of the current frag with a ".fill 0"
44  * and begin a new frag. Unless the new frag has nchars chars available
45  * do not return. Do not set up any fields of *now_frag.
46  */
47 void 
48 frag_grow (nchars)
49      unsigned int nchars;
50 {
51   if (obstack_room (&frags) < nchars)
52     {
53       unsigned int n, oldn;
54       long oldc;
55
56       frag_wane (frag_now);
57       frag_new (0);
58       oldn = (unsigned) -1;
59       oldc = frags.chunk_size;
60       frags.chunk_size = 2 * nchars;
61       while ((n = obstack_room (&frags)) < nchars && n < oldn)
62         {
63           frag_wane (frag_now);
64           frag_new (0);
65           oldn = n;
66         }
67       frags.chunk_size = oldc;
68     }
69   if (obstack_room (&frags) < nchars)
70     as_fatal ("Can't extend frag %d. chars", nchars);
71 }                               /* frag_grow() */
72 \f
73 /*
74  *                      frag_new()
75  *
76  * Call this to close off a completed frag, and start up a new (empty)
77  * frag, in the same subsegment as the old frag.
78  * [frchain_now remains the same but frag_now is updated.]
79  * Because this calculates the correct value of fr_fix by
80  * looking at the obstack 'frags', it needs to know how many
81  * characters at the end of the old frag belong to (the maximal)
82  * fr_var: the rest must belong to fr_fix.
83  * It doesn't actually set up the old frag's fr_var: you may have
84  * set fr_var == 1, but allocated 10 chars to the end of the frag:
85  * in this case you pass old_frags_var_max_size == 10.
86  *
87  * Make a new frag, initialising some components. Link new frag at end
88  * of frchain_now.
89  */
90 void 
91 frag_new (old_frags_var_max_size)
92      int old_frags_var_max_size;/* Number of chars (already allocated on
93                                    obstack frags) */
94      /* in variable_length part of frag. */
95 {
96   register fragS *former_last_fragP;
97   register frchainS *frchP;
98   long tmp;
99
100   frag_now->fr_fix = frag_now_fix () - old_frags_var_max_size;
101   /* Fix up old frag's fr_fix. */
102
103   obstack_finish (&frags);
104   /* This will align the obstack so the next struct we allocate on it
105      will begin at a correct boundary. */
106   frchP = frchain_now;
107   know (frchP);
108   former_last_fragP = frchP->frch_last;
109   know (former_last_fragP);
110   know (former_last_fragP == frag_now);
111   obstack_blank (&frags, SIZEOF_STRUCT_FRAG);
112   /* We expect this will begin at a correct boundary for a struct. */
113   tmp = obstack_alignment_mask (&frags);
114   obstack_alignment_mask (&frags) = 0;  /* Turn off alignment */
115   /* If we ever hit a machine where strings must be aligned, we Lose
116      Big.  */
117   frag_now = (fragS *) obstack_finish (&frags);
118   obstack_alignment_mask (&frags) = tmp;        /* Restore alignment */
119
120   /* Just in case we don't get zero'd bytes */
121   memset (frag_now, '\0', SIZEOF_STRUCT_FRAG);
122
123   /* Generally, frag_now->points to an address rounded up to next
124      alignment.  However, characters will add to obstack frags
125      IMMEDIATELY after the struct frag, even if they are not starting
126      at an alignment address. */
127   former_last_fragP->fr_next = frag_now;
128   frchP->frch_last = frag_now;
129
130 #ifndef NO_LISTING
131   {
132     extern struct list_info_struct *listing_tail;
133     frag_now->line = listing_tail;
134   }
135 #endif
136
137   frag_now->fr_next = NULL;
138 }                               /* frag_new() */
139 \f
140 /*
141  *                      frag_more()
142  *
143  * Start a new frag unless we have n more chars of room in the current frag.
144  * Close off the old frag with a .fill 0.
145  *
146  * Return the address of the 1st char to write into. Advance
147  * frag_now_growth past the new chars.
148  */
149
150 char *
151 frag_more (nchars)
152      int nchars;
153 {
154   register char *retval;
155
156   if (now_seg == absolute_section)
157     {
158       as_bad ("attempt to allocate data in absolute section");
159       subseg_set (text_section, 0);
160     }
161
162   if (mri_common_symbol != NULL)
163     {
164       as_bad ("attempt to allocate data in common section");
165       mri_common_symbol = NULL;
166     }
167
168   frag_grow (nchars);
169   retval = obstack_next_free (&frags);
170   obstack_blank_fast (&frags, nchars);
171   return (retval);
172 }                               /* frag_more() */
173 \f
174 /*
175  *                      frag_var()
176  *
177  * Start a new frag unless we have max_chars more chars of room in the current frag.
178  * Close off the old frag with a .fill 0.
179  *
180  * Set up a machine_dependent relaxable frag, then start a new frag.
181  * Return the address of the 1st char of the var part of the old frag
182  * to write into.
183  */
184
185 char *
186 frag_var (type, max_chars, var, subtype, symbol, offset, opcode)
187      relax_stateT type;
188      int max_chars;
189      int var;
190      relax_substateT subtype;
191      symbolS *symbol;
192      long offset;
193      char *opcode;
194 {
195   register char *retval;
196
197   frag_grow (max_chars);
198   retval = obstack_next_free (&frags);
199   obstack_blank_fast (&frags, max_chars);
200   frag_now->fr_var = var;
201   frag_now->fr_type = type;
202   frag_now->fr_subtype = subtype;
203   frag_now->fr_symbol = symbol;
204   frag_now->fr_offset = offset;
205   frag_now->fr_opcode = opcode;
206   /* default these to zero. */
207   frag_now->fr_pcrel_adjust = 0;
208   frag_now->fr_bsr = 0;
209   frag_new (max_chars);
210   return (retval);
211 }
212 \f
213 /*
214  *                      frag_variant()
215  *
216  * OVE: This variant of frag_var assumes that space for the tail has been
217  *      allocated by caller.
218  *      No call to frag_grow is done.
219  *      Two new arguments have been added.
220  */
221
222 char *
223 frag_variant (type, max_chars, var, subtype, symbol, offset, opcode)
224      relax_stateT type;
225      int max_chars;
226      int var;
227      relax_substateT subtype;
228      symbolS *symbol;
229      long offset;
230      char *opcode;
231 {
232   register char *retval;
233
234   retval = obstack_next_free (&frags);
235   frag_now->fr_var = var;
236   frag_now->fr_type = type;
237   frag_now->fr_subtype = subtype;
238   frag_now->fr_symbol = symbol;
239   frag_now->fr_offset = offset;
240   frag_now->fr_opcode = opcode;
241   frag_now->fr_pcrel_adjust = 0;
242   frag_now->fr_bsr = 0;
243   frag_new (max_chars);
244   return (retval);
245 }                               /* frag_variant() */
246 \f
247 /*
248  *                      frag_wane()
249  *
250  * Reduce the variable end of a frag to a harmless state.
251  */
252 void 
253 frag_wane (fragP)
254      register fragS *fragP;
255 {
256   fragP->fr_type = rs_fill;
257   fragP->fr_offset = 0;
258   fragP->fr_var = 0;
259 }
260 \f
261 /*
262  *                      frag_align()
263  *
264  * Make a frag for ".align foo,bar". Call is "frag_align (foo,bar);".
265  * Foo & bar are absolute integers.
266  *
267  * Call to close off the current frag with a ".align", then start a new
268  * (so far empty) frag, in the same subsegment as the last frag.
269  */
270
271 void 
272 frag_align (alignment, fill_character)
273      int alignment;
274      int fill_character;
275 {
276   char *p;
277   p = frag_var (rs_align, 1, 1, (relax_substateT) 0,
278                 (symbolS *) 0, (long) alignment, (char *) 0);
279   *p = fill_character;
280 }
281
282 void 
283 frag_align_pattern (alignment, fill_pattern, n_fill)
284      int alignment;
285      const char *fill_pattern;
286      int n_fill;
287 {
288   char *p;
289   p = frag_var (rs_align, n_fill, n_fill, (relax_substateT) 0,
290                 (symbolS *) 0, (long) alignment, (char *) 0);
291   memcpy (p, fill_pattern, n_fill);
292 }
293
294 int
295 frag_now_fix ()
296 {
297   if (now_seg == absolute_section)
298     return abs_section_offset;
299   return (char*)obstack_next_free (&frags) - frag_now->fr_literal;
300 }
301
302 void
303 frag_append_1_char (datum)
304      int datum;
305 {
306   if (obstack_room (&frags) <= 1)
307     {
308       frag_wane (frag_now);
309       frag_new (0);
310     }
311   obstack_1grow (&frags, datum);
312 }
313
314 /* end of frags.c */