Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / gnu / usr.bin / as / 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 /*
22  * $FreeBSD: src/gnu/usr.bin/as/frags.c,v 1.6 1999/08/27 23:34:16 peter Exp $
23  * $DragonFly: src/gnu/usr.bin/as/Attic/frags.c,v 1.2 2003/06/17 04:25:44 dillon Exp $
24  */
25 #include "as.h"
26 #include "subsegs.h"
27 #include "obstack.h"
28
29 struct obstack  frags;  /* All, and only, frags live here. */
30
31 fragS zero_address_frag = {
32         0,                      /* fr_address */
33         NULL,                   /* fr_next */
34         0,                      /* fr_fix */
35         0,                      /* fr_var */
36         0,                      /* fr_symbol */
37         0,                      /* fr_offset */
38         NULL,                   /* fr_opcode */
39         rs_fill,                /* fr_type */
40         0,                      /* fr_subtype */
41         0,                      /* fr_pcrel_adjust */
42         0,                      /* fr_bsr */
43         0                       /* fr_literal[0] */
44     };
45
46 fragS bss_address_frag = {
47         0,                      /* fr_address. Gets filled in to make up
48                                    sy_value-s. */
49         NULL,                   /* fr_next */
50         0,                      /* fr_fix */
51         0,                      /* fr_var */
52         0,                      /* fr_symbol */
53         0,                      /* fr_offset */
54         NULL,                   /* fr_opcode */
55         rs_fill,                /* fr_type */
56         0,                      /* fr_subtype */
57         0,                      /* fr_pcrel_adjust */
58         0,                      /* fr_bsr */
59         0                       /* fr_literal[0] */
60     };
61 \f
62 /*
63  *                      frag_grow()
64  *
65  * Internal.
66  * Try to augment current frag by nchars chars.
67  * If there is no room, close of the current frag with a ".fill 0"
68  * and begin a new frag. Unless the new frag has nchars chars available
69  * do not return. Do not set up any fields of *now_frag.
70  */
71 static void frag_grow(nchars)
72 unsigned int nchars;
73 {
74         if (obstack_room (&frags) < nchars) {
75                 unsigned int n,oldn;
76                 long oldc;
77
78                 frag_wane(frag_now);
79                 frag_new(0);
80                 oldn=(unsigned)-1;
81                 oldc=frags.chunk_size;
82                 frags.chunk_size=2*nchars;
83                 while ((n=obstack_room(&frags))<nchars && n<oldn) {
84                         frag_wane(frag_now);
85                         frag_new(0);
86                         oldn=n;
87                 }
88                 frags.chunk_size=oldc;
89         }
90         if (obstack_room (&frags) < nchars)
91             as_fatal("Can't extend frag %d. chars", nchars);
92 } /* frag_grow() */
93 \f
94 /*
95  *                      frag_new()
96  *
97  * Call this to close off a completed frag, and start up a new (empty)
98  * frag, in the same subsegment as the old frag.
99  * [frchain_now remains the same but frag_now is updated.]
100  * Because this calculates the correct value of fr_fix by
101  * looking at the obstack 'frags', it needs to know how many
102  * characters at the end of the old frag belong to (the maximal)
103  * fr_var: the rest must belong to fr_fix.
104  * It doesn't actually set up the old frag's fr_var: you may have
105  * set fr_var == 1, but allocated 10 chars to the end of the frag:
106  * in this case you pass old_frags_var_max_size == 10.
107  *
108  * Make a new frag, initialising some components. Link new frag at end
109  * of frchain_now.
110  */
111 void frag_new(old_frags_var_max_size)
112 int old_frags_var_max_size;     /* Number of chars (already allocated on
113                                    obstack frags) */
114 /* in variable_length part of frag. */
115 {
116         register    fragS * former_last_fragP;
117         /*    char   *throw_away_pointer; JF unused */
118         register    frchainS * frchP;
119         long    tmp;            /* JF */
120
121         frag_now->fr_fix = (char *) (obstack_next_free (&frags)) -
122             (frag_now->fr_literal) - old_frags_var_max_size;
123         /* Fix up old frag's fr_fix. */
124
125         obstack_finish (&frags);
126         /* This will align the obstack so the */
127         /* next struct we allocate on it will */
128         /* begin at a correct boundary. */
129         frchP = frchain_now;
130         know (frchP);
131         former_last_fragP = frchP->frch_last;
132         know (former_last_fragP);
133         know (former_last_fragP == frag_now);
134         obstack_blank (&frags, SIZEOF_STRUCT_FRAG);
135         /* We expect this will begin at a correct */
136         /* boundary for a struct. */
137         tmp=obstack_alignment_mask(&frags);
138         obstack_alignment_mask(&frags)=0;               /* Turn off alignment */
139         /* If we ever hit a machine
140            where strings must be
141            aligned, we Lose Big */
142         frag_now=(fragS *)obstack_finish(&frags);
143         obstack_alignment_mask(&frags)=tmp;             /* Restore alignment */
144
145         /* Just in case we don't get zero'd bytes */
146         memset(frag_now, '\0', SIZEOF_STRUCT_FRAG);
147
148         /*    obstack_unaligned_done (&frags, &frag_now); */
149         /*    know (frags.obstack_c_next_free == frag_now->fr_literal); */
150         /* Generally, frag_now->points to an */
151         /* address rounded up to next alignment. */
152         /* However, characters will add to obstack */
153         /* frags IMMEDIATELY after the struct frag, */
154         /* even if they are not starting at an */
155         /* alignment address. */
156         former_last_fragP->fr_next = frag_now;
157         frchP->frch_last = frag_now;
158
159 #ifndef NO_LISTING
160         {
161                 extern struct list_info_struct *listing_tail;
162                 frag_now->line = listing_tail;
163         }
164 #endif
165
166         frag_now->fr_next = NULL;
167 }                               /* frag_new() */
168 \f
169 /*
170  *                      frag_more()
171  *
172  * Start a new frag unless we have n more chars of room in the current frag.
173  * Close off the old frag with a .fill 0.
174  *
175  * Return the address of the 1st char to write into. Advance
176  * frag_now_growth past the new chars.
177  */
178
179 char *frag_more (nchars)
180 int nchars;
181 {
182         register char  *retval;
183
184         frag_grow (nchars);
185         retval = obstack_next_free (&frags);
186         obstack_blank_fast (&frags, nchars);
187         return (retval);
188 }                               /* frag_more() */
189 \f
190 /*
191  *                      frag_var()
192  *
193  * Start a new frag unless we have max_chars more chars of room in the current frag.
194  * Close off the old frag with a .fill 0.
195  *
196  * Set up a machine_dependent relaxable frag, then start a new frag.
197  * Return the address of the 1st char of the var part of the old frag
198  * to write into.
199  */
200
201 char *frag_var(type, max_chars, var, subtype, symbol, offset, opcode)
202 relax_stateT type;
203 int max_chars;
204 int var;
205 relax_substateT subtype;
206 symbolS *symbol;
207 long offset;
208 char *opcode;
209 {
210         register char  *retval;
211
212         frag_grow (max_chars);
213         retval = obstack_next_free (&frags);
214         obstack_blank_fast (&frags, max_chars);
215         frag_now->fr_var = var;
216         frag_now->fr_type = type;
217         frag_now->fr_subtype = subtype;
218         frag_now->fr_symbol = symbol;
219         frag_now->fr_offset = offset;
220         frag_now->fr_opcode = opcode;
221         /* default these to zero. */
222         frag_now->fr_pcrel_adjust = 0;
223         frag_now->fr_bsr = 0;
224         frag_new (max_chars);
225         return (retval);
226 }                               /* frag_var() */
227 \f
228 /*
229  *                      frag_variant()
230  *
231  * OVE: This variant of frag_var assumes that space for the tail has been
232  *      allocated by caller.
233  *      No call to frag_grow is done.
234  *      Two new arguments have been added.
235  */
236
237 char *frag_variant(type, max_chars, var, subtype, symbol, offset, opcode, pcrel_adjust,bsr)
238 relax_stateT type;
239 int max_chars;
240 int var;
241 relax_substateT subtype;
242 symbolS *symbol;
243 long offset;
244 char *opcode;
245 int pcrel_adjust;
246 char bsr;
247 {
248         register char  *retval;
249
250         /* frag_grow (max_chars); */
251         retval = obstack_next_free (&frags);
252         /*  obstack_blank_fast (&frags, max_chars); */ /* OVE: so far the only diff */
253         frag_now->fr_var = var;
254         frag_now->fr_type = type;
255         frag_now->fr_subtype = subtype;
256         frag_now->fr_symbol = symbol;
257         frag_now->fr_offset = offset;
258         frag_now->fr_opcode = opcode;
259         frag_now->fr_pcrel_adjust = pcrel_adjust;
260         frag_now->fr_bsr = bsr;
261         frag_new(max_chars);
262         return(retval);
263 }                               /* frag_variant() */
264 \f
265 /*
266  *                      frag_wane()
267  *
268  * Reduce the variable end of a frag to a harmless state.
269  */
270 void frag_wane(fragP)
271 register    fragS * fragP;
272 {
273         fragP->fr_type = rs_fill;
274         fragP->fr_offset = 0;
275         fragP->fr_var = 0;
276 }
277 \f
278 /*
279  *                      frag_align()
280  *
281  * Make a frag for ".align foo,bar". Call is "frag_align (foo,bar);".
282  * Foo & bar are absolute integers.
283  *
284  * Call to close off the current frag with a ".align", then start a new
285  * (so far empty) frag, in the same subsegment as the last frag.
286  */
287
288 void frag_align(alignment, fill_character)
289 int alignment;
290 int fill_character;
291 {
292         *(frag_var (rs_align, 1, 1, (relax_substateT)0, (symbolS *)0,
293                     (long)alignment, (char *)0)) = fill_character;
294 } /* frag_align() */
295
296 /* end of frags.c */