1*a9fa9459Szrj /* frags.c - manage frags -
2*a9fa9459Szrj Copyright (C) 1987-2016 Free Software Foundation, Inc.
3*a9fa9459Szrj
4*a9fa9459Szrj This file is part of GAS, the GNU Assembler.
5*a9fa9459Szrj
6*a9fa9459Szrj GAS is free software; you can redistribute it and/or modify
7*a9fa9459Szrj it under the terms of the GNU General Public License as published by
8*a9fa9459Szrj the Free Software Foundation; either version 3, or (at your option)
9*a9fa9459Szrj any later version.
10*a9fa9459Szrj
11*a9fa9459Szrj GAS is distributed in the hope that it will be useful,
12*a9fa9459Szrj but WITHOUT ANY WARRANTY; without even the implied warranty of
13*a9fa9459Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14*a9fa9459Szrj GNU General Public License for more details.
15*a9fa9459Szrj
16*a9fa9459Szrj You should have received a copy of the GNU General Public License
17*a9fa9459Szrj along with GAS; see the file COPYING. If not, write to the Free
18*a9fa9459Szrj Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
19*a9fa9459Szrj 02110-1301, USA. */
20*a9fa9459Szrj
21*a9fa9459Szrj #include "as.h"
22*a9fa9459Szrj #include "subsegs.h"
23*a9fa9459Szrj #include "obstack.h"
24*a9fa9459Szrj
25*a9fa9459Szrj extern fragS zero_address_frag;
26*a9fa9459Szrj extern fragS predefined_address_frag;
27*a9fa9459Szrj
28*a9fa9459Szrj static int totalfrags;
29*a9fa9459Szrj
30*a9fa9459Szrj int
get_frag_count(void)31*a9fa9459Szrj get_frag_count (void)
32*a9fa9459Szrj {
33*a9fa9459Szrj return totalfrags;
34*a9fa9459Szrj }
35*a9fa9459Szrj
36*a9fa9459Szrj void
clear_frag_count(void)37*a9fa9459Szrj clear_frag_count (void)
38*a9fa9459Szrj {
39*a9fa9459Szrj totalfrags = 0;
40*a9fa9459Szrj }
41*a9fa9459Szrj
42*a9fa9459Szrj /* Initialization for frag routines. */
43*a9fa9459Szrj
44*a9fa9459Szrj void
frag_init(void)45*a9fa9459Szrj frag_init (void)
46*a9fa9459Szrj {
47*a9fa9459Szrj zero_address_frag.fr_type = rs_fill;
48*a9fa9459Szrj predefined_address_frag.fr_type = rs_fill;
49*a9fa9459Szrj }
50*a9fa9459Szrj
51*a9fa9459Szrj /* Check that we're not trying to assemble into a section that can't
52*a9fa9459Szrj allocate frags (currently, this is only possible in the absolute
53*a9fa9459Szrj section), or into an mri common. */
54*a9fa9459Szrj
55*a9fa9459Szrj static void
frag_alloc_check(const struct obstack * ob)56*a9fa9459Szrj frag_alloc_check (const struct obstack *ob)
57*a9fa9459Szrj {
58*a9fa9459Szrj if (ob->chunk_size == 0)
59*a9fa9459Szrj {
60*a9fa9459Szrj as_bad (_("attempt to allocate data in absolute section"));
61*a9fa9459Szrj subseg_set (text_section, 0);
62*a9fa9459Szrj }
63*a9fa9459Szrj
64*a9fa9459Szrj if (mri_common_symbol != NULL)
65*a9fa9459Szrj {
66*a9fa9459Szrj as_bad (_("attempt to allocate data in common section"));
67*a9fa9459Szrj mri_common_symbol = NULL;
68*a9fa9459Szrj }
69*a9fa9459Szrj }
70*a9fa9459Szrj
71*a9fa9459Szrj /* Allocate a frag on the specified obstack.
72*a9fa9459Szrj Call this routine from everywhere else, so that all the weird alignment
73*a9fa9459Szrj hackery can be done in just one place. */
74*a9fa9459Szrj
75*a9fa9459Szrj fragS *
frag_alloc(struct obstack * ob)76*a9fa9459Szrj frag_alloc (struct obstack *ob)
77*a9fa9459Szrj {
78*a9fa9459Szrj fragS *ptr;
79*a9fa9459Szrj int oalign;
80*a9fa9459Szrj
81*a9fa9459Szrj (void) obstack_alloc (ob, 0);
82*a9fa9459Szrj oalign = obstack_alignment_mask (ob);
83*a9fa9459Szrj obstack_alignment_mask (ob) = 0;
84*a9fa9459Szrj ptr = (fragS *) obstack_alloc (ob, SIZEOF_STRUCT_FRAG);
85*a9fa9459Szrj obstack_alignment_mask (ob) = oalign;
86*a9fa9459Szrj memset (ptr, 0, SIZEOF_STRUCT_FRAG);
87*a9fa9459Szrj totalfrags++;
88*a9fa9459Szrj return ptr;
89*a9fa9459Szrj }
90*a9fa9459Szrj
91*a9fa9459Szrj /* Try to augment current frag by nchars chars.
92*a9fa9459Szrj If there is no room, close of the current frag with a ".fill 0"
93*a9fa9459Szrj and begin a new frag. Unless the new frag has nchars chars available
94*a9fa9459Szrj do not return. Do not set up any fields of *now_frag. */
95*a9fa9459Szrj
96*a9fa9459Szrj void
frag_grow(size_t nchars)97*a9fa9459Szrj frag_grow (size_t nchars)
98*a9fa9459Szrj {
99*a9fa9459Szrj if (obstack_room (&frchain_now->frch_obstack) < nchars)
100*a9fa9459Szrj {
101*a9fa9459Szrj size_t oldc;
102*a9fa9459Szrj size_t newc;
103*a9fa9459Szrj
104*a9fa9459Szrj /* Try to allocate a bit more than needed right now. But don't do
105*a9fa9459Szrj this if we would waste too much memory. Especially necessary
106*a9fa9459Szrj for extremely big (like 2GB initialized) frags. */
107*a9fa9459Szrj if (nchars < 0x10000)
108*a9fa9459Szrj newc = 2 * nchars;
109*a9fa9459Szrj else
110*a9fa9459Szrj newc = nchars + 0x10000;
111*a9fa9459Szrj newc += SIZEOF_STRUCT_FRAG;
112*a9fa9459Szrj
113*a9fa9459Szrj /* Check for possible overflow. */
114*a9fa9459Szrj if (newc < nchars)
115*a9fa9459Szrj as_fatal (_("can't extend frag %lu chars"), (unsigned long) nchars);
116*a9fa9459Szrj
117*a9fa9459Szrj /* Force to allocate at least NEWC bytes, but not less than the
118*a9fa9459Szrj default. */
119*a9fa9459Szrj oldc = obstack_chunk_size (&frchain_now->frch_obstack);
120*a9fa9459Szrj if (newc > oldc)
121*a9fa9459Szrj obstack_chunk_size (&frchain_now->frch_obstack) = newc;
122*a9fa9459Szrj
123*a9fa9459Szrj while (obstack_room (&frchain_now->frch_obstack) < nchars)
124*a9fa9459Szrj {
125*a9fa9459Szrj /* Not enough room in this frag. Close it and start a new one.
126*a9fa9459Szrj This must be done in a loop because the created frag may not
127*a9fa9459Szrj be big enough if the current obstack chunk is used. */
128*a9fa9459Szrj frag_wane (frag_now);
129*a9fa9459Szrj frag_new (0);
130*a9fa9459Szrj }
131*a9fa9459Szrj
132*a9fa9459Szrj /* Restore the old chunk size. */
133*a9fa9459Szrj obstack_chunk_size (&frchain_now->frch_obstack) = oldc;
134*a9fa9459Szrj }
135*a9fa9459Szrj }
136*a9fa9459Szrj
137*a9fa9459Szrj /* Call this to close off a completed frag, and start up a new (empty)
138*a9fa9459Szrj frag, in the same subsegment as the old frag.
139*a9fa9459Szrj [frchain_now remains the same but frag_now is updated.]
140*a9fa9459Szrj Because this calculates the correct value of fr_fix by
141*a9fa9459Szrj looking at the obstack 'frags', it needs to know how many
142*a9fa9459Szrj characters at the end of the old frag belong to the maximal
143*a9fa9459Szrj variable part; The rest must belong to fr_fix.
144*a9fa9459Szrj It doesn't actually set up the old frag's fr_var. You may have
145*a9fa9459Szrj set fr_var == 1, but allocated 10 chars to the end of the frag;
146*a9fa9459Szrj In this case you pass old_frags_var_max_size == 10.
147*a9fa9459Szrj In fact, you may use fr_var for something totally unrelated to the
148*a9fa9459Szrj size of the variable part of the frag; None of the generic frag
149*a9fa9459Szrj handling code makes use of fr_var.
150*a9fa9459Szrj
151*a9fa9459Szrj Make a new frag, initialising some components. Link new frag at end
152*a9fa9459Szrj of frchain_now. */
153*a9fa9459Szrj
154*a9fa9459Szrj void
frag_new(size_t old_frags_var_max_size)155*a9fa9459Szrj frag_new (size_t old_frags_var_max_size
156*a9fa9459Szrj /* Number of chars (already allocated on obstack frags) in
157*a9fa9459Szrj variable_length part of frag. */)
158*a9fa9459Szrj {
159*a9fa9459Szrj fragS *former_last_fragP;
160*a9fa9459Szrj frchainS *frchP;
161*a9fa9459Szrj
162*a9fa9459Szrj gas_assert (frchain_now->frch_last == frag_now);
163*a9fa9459Szrj
164*a9fa9459Szrj /* Fix up old frag's fr_fix. */
165*a9fa9459Szrj frag_now->fr_fix = frag_now_fix_octets () - old_frags_var_max_size;
166*a9fa9459Szrj /* Make sure its type is valid. */
167*a9fa9459Szrj gas_assert (frag_now->fr_type != 0);
168*a9fa9459Szrj
169*a9fa9459Szrj /* This will align the obstack so the next struct we allocate on it
170*a9fa9459Szrj will begin at a correct boundary. */
171*a9fa9459Szrj obstack_finish (&frchain_now->frch_obstack);
172*a9fa9459Szrj frchP = frchain_now;
173*a9fa9459Szrj know (frchP);
174*a9fa9459Szrj former_last_fragP = frchP->frch_last;
175*a9fa9459Szrj gas_assert (former_last_fragP != 0);
176*a9fa9459Szrj gas_assert (former_last_fragP == frag_now);
177*a9fa9459Szrj frag_now = frag_alloc (&frchP->frch_obstack);
178*a9fa9459Szrj
179*a9fa9459Szrj frag_now->fr_file = as_where (&frag_now->fr_line);
180*a9fa9459Szrj
181*a9fa9459Szrj /* Generally, frag_now->points to an address rounded up to next
182*a9fa9459Szrj alignment. However, characters will add to obstack frags
183*a9fa9459Szrj IMMEDIATELY after the struct frag, even if they are not starting
184*a9fa9459Szrj at an alignment address. */
185*a9fa9459Szrj former_last_fragP->fr_next = frag_now;
186*a9fa9459Szrj frchP->frch_last = frag_now;
187*a9fa9459Szrj
188*a9fa9459Szrj #ifndef NO_LISTING
189*a9fa9459Szrj {
190*a9fa9459Szrj extern struct list_info_struct *listing_tail;
191*a9fa9459Szrj frag_now->line = listing_tail;
192*a9fa9459Szrj }
193*a9fa9459Szrj #endif
194*a9fa9459Szrj
195*a9fa9459Szrj gas_assert (frchain_now->frch_last == frag_now);
196*a9fa9459Szrj
197*a9fa9459Szrj frag_now->fr_next = NULL;
198*a9fa9459Szrj }
199*a9fa9459Szrj
200*a9fa9459Szrj /* Start a new frag unless we have n more chars of room in the current frag.
201*a9fa9459Szrj Close off the old frag with a .fill 0.
202*a9fa9459Szrj
203*a9fa9459Szrj Return the address of the 1st char to write into. Advance
204*a9fa9459Szrj frag_now_growth past the new chars. */
205*a9fa9459Szrj
206*a9fa9459Szrj char *
frag_more(size_t nchars)207*a9fa9459Szrj frag_more (size_t nchars)
208*a9fa9459Szrj {
209*a9fa9459Szrj char *retval;
210*a9fa9459Szrj
211*a9fa9459Szrj frag_alloc_check (&frchain_now->frch_obstack);
212*a9fa9459Szrj frag_grow (nchars);
213*a9fa9459Szrj retval = obstack_next_free (&frchain_now->frch_obstack);
214*a9fa9459Szrj obstack_blank_fast (&frchain_now->frch_obstack, nchars);
215*a9fa9459Szrj return retval;
216*a9fa9459Szrj }
217*a9fa9459Szrj
218*a9fa9459Szrj /* Close the current frag, setting its fields for a relaxable frag. Start a
219*a9fa9459Szrj new frag. */
220*a9fa9459Szrj
221*a9fa9459Szrj static void
frag_var_init(relax_stateT type,size_t max_chars,size_t var,relax_substateT subtype,symbolS * symbol,offsetT offset,char * opcode)222*a9fa9459Szrj frag_var_init (relax_stateT type, size_t max_chars, size_t var,
223*a9fa9459Szrj relax_substateT subtype, symbolS *symbol, offsetT offset,
224*a9fa9459Szrj char *opcode)
225*a9fa9459Szrj {
226*a9fa9459Szrj frag_now->fr_var = var;
227*a9fa9459Szrj frag_now->fr_type = type;
228*a9fa9459Szrj frag_now->fr_subtype = subtype;
229*a9fa9459Szrj frag_now->fr_symbol = symbol;
230*a9fa9459Szrj frag_now->fr_offset = offset;
231*a9fa9459Szrj frag_now->fr_opcode = opcode;
232*a9fa9459Szrj #ifdef USING_CGEN
233*a9fa9459Szrj frag_now->fr_cgen.insn = 0;
234*a9fa9459Szrj frag_now->fr_cgen.opindex = 0;
235*a9fa9459Szrj frag_now->fr_cgen.opinfo = 0;
236*a9fa9459Szrj #endif
237*a9fa9459Szrj #ifdef TC_FRAG_INIT
238*a9fa9459Szrj TC_FRAG_INIT (frag_now);
239*a9fa9459Szrj #endif
240*a9fa9459Szrj frag_now->fr_file = as_where (&frag_now->fr_line);
241*a9fa9459Szrj
242*a9fa9459Szrj frag_new (max_chars);
243*a9fa9459Szrj }
244*a9fa9459Szrj
245*a9fa9459Szrj /* Start a new frag unless we have max_chars more chars of room in the
246*a9fa9459Szrj current frag. Close off the old frag with a .fill 0.
247*a9fa9459Szrj
248*a9fa9459Szrj Set up a machine_dependent relaxable frag, then start a new frag.
249*a9fa9459Szrj Return the address of the 1st char of the var part of the old frag
250*a9fa9459Szrj to write into. */
251*a9fa9459Szrj
252*a9fa9459Szrj char *
frag_var(relax_stateT type,size_t max_chars,size_t var,relax_substateT subtype,symbolS * symbol,offsetT offset,char * opcode)253*a9fa9459Szrj frag_var (relax_stateT type, size_t max_chars, size_t var,
254*a9fa9459Szrj relax_substateT subtype, symbolS *symbol, offsetT offset,
255*a9fa9459Szrj char *opcode)
256*a9fa9459Szrj {
257*a9fa9459Szrj char *retval;
258*a9fa9459Szrj
259*a9fa9459Szrj frag_grow (max_chars);
260*a9fa9459Szrj retval = obstack_next_free (&frchain_now->frch_obstack);
261*a9fa9459Szrj obstack_blank_fast (&frchain_now->frch_obstack, max_chars);
262*a9fa9459Szrj frag_var_init (type, max_chars, var, subtype, symbol, offset, opcode);
263*a9fa9459Szrj return retval;
264*a9fa9459Szrj }
265*a9fa9459Szrj
266*a9fa9459Szrj /* OVE: This variant of frag_var assumes that space for the tail has been
267*a9fa9459Szrj allocated by caller.
268*a9fa9459Szrj No call to frag_grow is done. */
269*a9fa9459Szrj
270*a9fa9459Szrj char *
frag_variant(relax_stateT type,size_t max_chars,size_t var,relax_substateT subtype,symbolS * symbol,offsetT offset,char * opcode)271*a9fa9459Szrj frag_variant (relax_stateT type, size_t max_chars, size_t var,
272*a9fa9459Szrj relax_substateT subtype, symbolS *symbol, offsetT offset,
273*a9fa9459Szrj char *opcode)
274*a9fa9459Szrj {
275*a9fa9459Szrj char *retval;
276*a9fa9459Szrj
277*a9fa9459Szrj retval = obstack_next_free (&frchain_now->frch_obstack);
278*a9fa9459Szrj frag_var_init (type, max_chars, var, subtype, symbol, offset, opcode);
279*a9fa9459Szrj
280*a9fa9459Szrj return retval;
281*a9fa9459Szrj }
282*a9fa9459Szrj
283*a9fa9459Szrj /* Reduce the variable end of a frag to a harmless state. */
284*a9fa9459Szrj
285*a9fa9459Szrj void
frag_wane(fragS * fragP)286*a9fa9459Szrj frag_wane (fragS *fragP)
287*a9fa9459Szrj {
288*a9fa9459Szrj fragP->fr_type = rs_fill;
289*a9fa9459Szrj fragP->fr_offset = 0;
290*a9fa9459Szrj fragP->fr_var = 0;
291*a9fa9459Szrj }
292*a9fa9459Szrj
293*a9fa9459Szrj /* Return the number of bytes by which the current frag can be grown. */
294*a9fa9459Szrj
295*a9fa9459Szrj size_t
frag_room(void)296*a9fa9459Szrj frag_room (void)
297*a9fa9459Szrj {
298*a9fa9459Szrj return obstack_room (&frchain_now->frch_obstack);
299*a9fa9459Szrj }
300*a9fa9459Szrj
301*a9fa9459Szrj /* Make an alignment frag. The size of this frag will be adjusted to
302*a9fa9459Szrj force the next frag to have the appropriate alignment. ALIGNMENT
303*a9fa9459Szrj is the power of two to which to align. FILL_CHARACTER is the
304*a9fa9459Szrj character to use to fill in any bytes which are skipped. MAX is
305*a9fa9459Szrj the maximum number of characters to skip when doing the alignment,
306*a9fa9459Szrj or 0 if there is no maximum. */
307*a9fa9459Szrj
308*a9fa9459Szrj void
frag_align(int alignment,int fill_character,int max)309*a9fa9459Szrj frag_align (int alignment, int fill_character, int max)
310*a9fa9459Szrj {
311*a9fa9459Szrj if (now_seg == absolute_section)
312*a9fa9459Szrj {
313*a9fa9459Szrj addressT new_off;
314*a9fa9459Szrj addressT mask;
315*a9fa9459Szrj
316*a9fa9459Szrj mask = (~(addressT) 0) << alignment;
317*a9fa9459Szrj new_off = (abs_section_offset + ~mask) & mask;
318*a9fa9459Szrj if (max == 0 || new_off - abs_section_offset <= (addressT) max)
319*a9fa9459Szrj abs_section_offset = new_off;
320*a9fa9459Szrj }
321*a9fa9459Szrj else
322*a9fa9459Szrj {
323*a9fa9459Szrj char *p;
324*a9fa9459Szrj
325*a9fa9459Szrj p = frag_var (rs_align, 1, 1, (relax_substateT) max,
326*a9fa9459Szrj (symbolS *) 0, (offsetT) alignment, (char *) 0);
327*a9fa9459Szrj *p = fill_character;
328*a9fa9459Szrj }
329*a9fa9459Szrj }
330*a9fa9459Szrj
331*a9fa9459Szrj /* Make an alignment frag like frag_align, but fill with a repeating
332*a9fa9459Szrj pattern rather than a single byte. ALIGNMENT is the power of two
333*a9fa9459Szrj to which to align. FILL_PATTERN is the fill pattern to repeat in
334*a9fa9459Szrj the bytes which are skipped. N_FILL is the number of bytes in
335*a9fa9459Szrj FILL_PATTERN. MAX is the maximum number of characters to skip when
336*a9fa9459Szrj doing the alignment, or 0 if there is no maximum. */
337*a9fa9459Szrj
338*a9fa9459Szrj void
frag_align_pattern(int alignment,const char * fill_pattern,size_t n_fill,int max)339*a9fa9459Szrj frag_align_pattern (int alignment, const char *fill_pattern,
340*a9fa9459Szrj size_t n_fill, int max)
341*a9fa9459Szrj {
342*a9fa9459Szrj char *p;
343*a9fa9459Szrj
344*a9fa9459Szrj p = frag_var (rs_align, n_fill, n_fill, (relax_substateT) max,
345*a9fa9459Szrj (symbolS *) 0, (offsetT) alignment, (char *) 0);
346*a9fa9459Szrj memcpy (p, fill_pattern, n_fill);
347*a9fa9459Szrj }
348*a9fa9459Szrj
349*a9fa9459Szrj /* The NOP_OPCODE is for the alignment fill value. Fill it with a nop
350*a9fa9459Szrj instruction so that the disassembler does not choke on it. */
351*a9fa9459Szrj #ifndef NOP_OPCODE
352*a9fa9459Szrj #define NOP_OPCODE 0x00
353*a9fa9459Szrj #endif
354*a9fa9459Szrj
355*a9fa9459Szrj /* Use this to restrict the amount of memory allocated for representing
356*a9fa9459Szrj the alignment code. Needs to be large enough to hold any fixed sized
357*a9fa9459Szrj prologue plus the replicating portion. */
358*a9fa9459Szrj #ifndef MAX_MEM_FOR_RS_ALIGN_CODE
359*a9fa9459Szrj /* Assume that if HANDLE_ALIGN is not defined then no special action
360*a9fa9459Szrj is required to code fill, which means that we get just repeat the
361*a9fa9459Szrj one NOP_OPCODE byte. */
362*a9fa9459Szrj # ifndef HANDLE_ALIGN
363*a9fa9459Szrj # define MAX_MEM_FOR_RS_ALIGN_CODE 1
364*a9fa9459Szrj # else
365*a9fa9459Szrj # define MAX_MEM_FOR_RS_ALIGN_CODE ((1 << alignment) - 1)
366*a9fa9459Szrj # endif
367*a9fa9459Szrj #endif
368*a9fa9459Szrj
369*a9fa9459Szrj void
frag_align_code(int alignment,int max)370*a9fa9459Szrj frag_align_code (int alignment, int max)
371*a9fa9459Szrj {
372*a9fa9459Szrj char *p;
373*a9fa9459Szrj
374*a9fa9459Szrj p = frag_var (rs_align_code, MAX_MEM_FOR_RS_ALIGN_CODE, 1,
375*a9fa9459Szrj (relax_substateT) max, (symbolS *) 0,
376*a9fa9459Szrj (offsetT) alignment, (char *) 0);
377*a9fa9459Szrj *p = NOP_OPCODE;
378*a9fa9459Szrj }
379*a9fa9459Szrj
380*a9fa9459Szrj addressT
frag_now_fix_octets(void)381*a9fa9459Szrj frag_now_fix_octets (void)
382*a9fa9459Szrj {
383*a9fa9459Szrj if (now_seg == absolute_section)
384*a9fa9459Szrj return abs_section_offset;
385*a9fa9459Szrj
386*a9fa9459Szrj return ((char *) obstack_next_free (&frchain_now->frch_obstack)
387*a9fa9459Szrj - frag_now->fr_literal);
388*a9fa9459Szrj }
389*a9fa9459Szrj
390*a9fa9459Szrj addressT
frag_now_fix(void)391*a9fa9459Szrj frag_now_fix (void)
392*a9fa9459Szrj {
393*a9fa9459Szrj return frag_now_fix_octets () / OCTETS_PER_BYTE;
394*a9fa9459Szrj }
395*a9fa9459Szrj
396*a9fa9459Szrj void
frag_append_1_char(int datum)397*a9fa9459Szrj frag_append_1_char (int datum)
398*a9fa9459Szrj {
399*a9fa9459Szrj frag_alloc_check (&frchain_now->frch_obstack);
400*a9fa9459Szrj if (obstack_room (&frchain_now->frch_obstack) <= 1)
401*a9fa9459Szrj {
402*a9fa9459Szrj frag_wane (frag_now);
403*a9fa9459Szrj frag_new (0);
404*a9fa9459Szrj }
405*a9fa9459Szrj obstack_1grow (&frchain_now->frch_obstack, datum);
406*a9fa9459Szrj }
407*a9fa9459Szrj
408*a9fa9459Szrj /* Return TRUE if FRAG1 and FRAG2 have a fixed relationship between
409*a9fa9459Szrj their start addresses. Set OFFSET to the difference in address
410*a9fa9459Szrj not already accounted for in the frag FR_ADDRESS. */
411*a9fa9459Szrj
412*a9fa9459Szrj bfd_boolean
frag_offset_fixed_p(const fragS * frag1,const fragS * frag2,offsetT * offset)413*a9fa9459Szrj frag_offset_fixed_p (const fragS *frag1, const fragS *frag2, offsetT *offset)
414*a9fa9459Szrj {
415*a9fa9459Szrj const fragS *frag;
416*a9fa9459Szrj offsetT off;
417*a9fa9459Szrj
418*a9fa9459Szrj /* Start with offset initialised to difference between the two frags.
419*a9fa9459Szrj Prior to assigning frag addresses this will be zero. */
420*a9fa9459Szrj off = frag1->fr_address - frag2->fr_address;
421*a9fa9459Szrj if (frag1 == frag2)
422*a9fa9459Szrj {
423*a9fa9459Szrj *offset = off;
424*a9fa9459Szrj return TRUE;
425*a9fa9459Szrj }
426*a9fa9459Szrj
427*a9fa9459Szrj /* Maybe frag2 is after frag1. */
428*a9fa9459Szrj frag = frag1;
429*a9fa9459Szrj while (frag->fr_type == rs_fill)
430*a9fa9459Szrj {
431*a9fa9459Szrj off += frag->fr_fix + frag->fr_offset * frag->fr_var;
432*a9fa9459Szrj frag = frag->fr_next;
433*a9fa9459Szrj if (frag == NULL)
434*a9fa9459Szrj break;
435*a9fa9459Szrj if (frag == frag2)
436*a9fa9459Szrj {
437*a9fa9459Szrj *offset = off;
438*a9fa9459Szrj return TRUE;
439*a9fa9459Szrj }
440*a9fa9459Szrj }
441*a9fa9459Szrj
442*a9fa9459Szrj /* Maybe frag1 is after frag2. */
443*a9fa9459Szrj off = frag1->fr_address - frag2->fr_address;
444*a9fa9459Szrj frag = frag2;
445*a9fa9459Szrj while (frag->fr_type == rs_fill)
446*a9fa9459Szrj {
447*a9fa9459Szrj off -= frag->fr_fix + frag->fr_offset * frag->fr_var;
448*a9fa9459Szrj frag = frag->fr_next;
449*a9fa9459Szrj if (frag == NULL)
450*a9fa9459Szrj break;
451*a9fa9459Szrj if (frag == frag1)
452*a9fa9459Szrj {
453*a9fa9459Szrj *offset = off;
454*a9fa9459Szrj return TRUE;
455*a9fa9459Szrj }
456*a9fa9459Szrj }
457*a9fa9459Szrj
458*a9fa9459Szrj return FALSE;
459*a9fa9459Szrj }
460