386BSD 0.1 development
[unix-history] / usr / src / usr.bin / gas / subsegs.c
CommitLineData
484e23e5
WJ
1/* subsegs.c - subsegments -
2 Copyright (C) 1987 Free Software Foundation, Inc.
3
4This file is part of GAS, the GNU Assembler.
5
6GAS is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 1, or (at your option)
9any later version.
10
11GAS is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GAS; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20/*
21 * Segments & sub-segments.
22 */
23
24#include "as.h"
25#include "subsegs.h"
26#include "obstack.h"
27#include "frags.h"
28#include "struc-symbol.h"
29#include "write.h"
30
31frchainS* frchain_root,
32 * frchain_now, /* Commented in "subsegs.h". */
33 * data0_frchainP;
34
35
36const int /* in: segT out: N_TYPE bits */
37seg_N_TYPE[] = {
38 N_ABS,
39 N_TEXT,
40 N_DATA,
41 N_BSS,
42 N_UNDF,
43 N_UNDF,
44 N_UNDF,
45 N_UNDF,
46 N_UNDF,
47 N_UNDF
48};
49
50
51char * const /* in: segT out: char* */
52seg_name[] = {
53 "absolute",
54 "text",
55 "data",
56 "bss",
57 "unknown",
58 "absent",
59 "pass1",
60 "ASSEMBLER-INTERNAL-LOGIC-ERROR!",
61 "bignum/flonum",
62 "difference",
63 ""
64 }; /* Used by error reporters, dumpers etc. */
65
66const segT N_TYPE_seg [N_TYPE+2] = /* N_TYPE == 0x1E = 32-2 */
67{
68 SEG_UNKNOWN, /* N_UNDF == 0 */
69 SEG_GOOF,
70 SEG_ABSOLUTE, /* N_ABS == 2 */
71 SEG_GOOF,
72 SEG_TEXT, /* N_TEXT == 4 */
73 SEG_GOOF,
74 SEG_DATA, /* N_DATA == 6 */
75 SEG_GOOF,
76 SEG_BSS, /* N_BSS == 8 */
77 SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
78 SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
79 SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF
80};
81\f
82void
83subsegs_begin()
84{
85 /* Check table(s) seg_name[], seg_N_TYPE[] is in correct order */
86 know( SEG_ABSOLUTE ==0 );
87 know( SEG_TEXT ==1 );
88 know( SEG_DATA ==2 );
89 know( SEG_BSS ==3 );
90 know( SEG_UNKNOWN ==4 );
91 know( SEG_NONE ==5 );
92 know( SEG_PASS1 ==6 );
93 know( SEG_GOOF ==7 );
94 know( SEG_BIG ==8 );
95 know( SEG_DIFFERENCE ==9 );
96 know( SEG_MAXIMUM_ORDINAL == SEG_DIFFERENCE );
97 know( seg_name [(int) SEG_MAXIMUM_ORDINAL + 1] [0] == 0 );
98
99 obstack_begin( &frags, 5000);
100 frchain_root = NULL;
101 frchain_now = NULL; /* Warn new_subseg() that we are booting. */
102 /* Fake up 1st frag. */
103 /* It won't be used=> is ok if obstack... */
104 /* pads the end of it for alignment. */
105 frag_now=(fragS *)obstack_alloc(&frags,SIZEOF_STRUCT_FRAG);
106 /* obstack_1blank( &frags, SIZEOF_STRUCT_FRAG, & frag_now ); */
107 /* This 1st frag will not be in any frchain. */
108 /* We simply give subseg_new somewhere to scribble. */
109 now_subseg = 42; /* Lie for 1st call to subseg_new. */
110 subseg_new (SEG_DATA, 0); /* .data 0 */
111 data0_frchainP = frchain_now;
112}
113\f
114/*
115 * subseg_change()
116 *
117 * Change the subsegment we are in, BUT DO NOT MAKE A NEW FRAG for the
118 * subsegment. If we are already in the correct subsegment, change nothing.
119 * This is used eg as a worker for subseg_new [which does make a new frag_now]
120 * and for changing segments after we have read the source. We construct eg
121 * fixSs even after the source file is read, so we do have to keep the
122 * segment context correct.
123 */
124void
125subseg_change (seg, subseg)
126 register segT seg;
127 register int subseg;
128{
129 now_seg = seg;
130 now_subseg = subseg;
131 if (seg == SEG_DATA)
132 {
133 seg_fix_rootP = & data_fix_root;
134 }
135 else
136 {
137 know (seg == SEG_TEXT);
138 seg_fix_rootP = & text_fix_root;
139 }
140}
141\f
142/*
143 * subseg_new()
144 *
145 * If you attempt to change to the current subsegment, nothing happens.
146 *
147 * In: segT, subsegT code for new subsegment.
148 * frag_now -> incomplete frag for current subsegment.
149 * If frag_now==NULL, then there is no old, incomplete frag, so
150 * the old frag is not closed off.
151 *
152 * Out: now_subseg, now_seg updated.
153 * Frchain_now points to the (possibly new) struct frchain for this
154 * sub-segment.
155 * Frchain_root updated if needed.
156 */
157
158void
159subseg_new (seg, subseg) /* begin assembly for a new sub-segment */
160 register segT seg; /* SEG_DATA or SEG_TEXT */
161 register subsegT subseg;
162{
163 long tmp; /* JF for obstack alignment hacking */
164
165 know( seg == SEG_DATA || seg == SEG_TEXT );
166
167 if (seg != now_seg || subseg != now_subseg)
168 { /* we just changed sub-segments */
169 register frchainS * frcP; /* crawl frchain chain */
170 register frchainS** lastPP; /* address of last pointer */
171 frchainS * newP; /* address of new frchain */
172 register fragS * former_last_fragP;
173 register fragS * new_fragP;
174
175 if (frag_now) /* If not bootstrapping. */
176 {
177 frag_now -> fr_fix = obstack_next_free(& frags) - frag_now -> fr_literal;
178 frag_wane(frag_now); /* Close off any frag in old subseg. */
179 }
180/*
181 * It would be nice to keep an obstack for each subsegment, if we swap
182 * subsegments a lot. Hence we would have much fewer frag_wanes().
183 */
184 {
185
186 obstack_finish( &frags);
187 /*
188 * If we don't do the above, the next object we put on obstack frags
189 * will appear to start at the fr_literal of the current frag.
190 * Also, above ensures that the next object will begin on a
191 * address that is aligned correctly for the engine that runs
192 * this program.
193 */
194 }
195 subseg_change (seg, (int)subseg);
196 /*
197 * Attempt to find or make a frchain for that sub seg.
198 * Crawl along chain of frchainSs, begins @ frchain_root.
199 * If we need to make a frchainS, link it into correct
200 * position of chain rooted in frchain_root.
201 */
202 for (frcP = * (lastPP = & frchain_root);
203 frcP
204 && (int)(frcP -> frch_seg) <= (int)seg;
205 frcP = * ( lastPP = & frcP -> frch_next)
206 )
207 {
208 if ( (int)(frcP -> frch_seg) == (int)seg
209 && frcP -> frch_subseg >= subseg)
210 {
211 break;
212 }
213 }
214 /*
215 * frcP: Address of the 1st frchainS in correct segment with
216 * frch_subseg >= subseg.
217 * We want to either use this frchainS, or we want
218 * to insert a new frchainS just before it.
219 *
220 * If frcP==NULL, then we are at the end of the chain
221 * of frchainS-s. A NULL frcP means we fell off the end
222 * of the chain looking for a
223 * frch_subseg >= subseg, so we
224 * must make a new frchainS.
225 *
226 * If we ever maintain a pointer to
227 * the last frchainS in the chain, we change that pointer
228 * ONLY when frcP==NULL.
229 *
230 * lastPP: Address of the pointer with value frcP;
231 * Never NULL.
232 * May point to frchain_root.
233 *
234 */
235 if ( ! frcP
236 || ( (int)(frcP -> frch_seg) > (int)seg
237 || frcP->frch_subseg > subseg)) /* Kinky logic only works with 2 segments. */
238 {
239 /*
240 * This should be the only code that creates a frchainS.
241 */
242 newP=(frchainS *)obstack_alloc(&frags,sizeof(frchainS));
243 /* obstack_1blank( &frags, sizeof(frchainS), &newP); */
244 /* This begines on a good boundary */
245 /* because a obstack_done() preceeded it. */
246 /* It implies an obstack_done(), so we */
247 /* expect the next object allocated to */
248 /* begin on a correct boundary. */
249 *lastPP = newP;
250 newP -> frch_next = frcP; /* perhaps NULL */
251 (frcP = newP) -> frch_subseg = subseg;
252 newP -> frch_seg = seg;
253 newP -> frch_last = NULL;
254 }
255 /*
256 * Here with frcP ->ing to the frchainS for subseg.
257 */
258 frchain_now = frcP;
259 /*
260 * Make a fresh frag for the subsegment.
261 */
262 /* We expect this to happen on a correct */
263 /* boundary since it was proceeded by a */
264 /* obstack_done(). */
265 tmp=obstack_alignment_mask(&frags); /* JF disable alignment */
266 obstack_alignment_mask(&frags)=0;
267 frag_now=(fragS *)obstack_alloc(&frags,SIZEOF_STRUCT_FRAG);
268 obstack_alignment_mask(&frags)=tmp;
269 /* know( frags . obstack_c_next_free == frag_now -> fr_literal ); */
270 /* But we want any more chars to come */
271 /* immediately after the structure we just made. */
272 new_fragP = frag_now;
273 new_fragP -> fr_next = NULL;
274 /*
275 * Append new frag to current frchain.
276 */
277 former_last_fragP = frcP -> frch_last;
278 if (former_last_fragP)
279 {
280 know( former_last_fragP -> fr_next == NULL );
281 know( frchain_now -> frch_root );
282 former_last_fragP -> fr_next = new_fragP;
283 }
284 else
285 {
286 frcP -> frch_root = new_fragP;
287 }
288 frcP -> frch_last = new_fragP;
289 } /* if (changing subsegments) */
290} /* subseg_new() */
291
292/* end: subsegs.c */