Pristine Ack-5.5
[Ack-5.5.git] / mach / proto / as / comm6.c
1 /* $Id: comm6.c,v 2.23 1994/06/24 13:22:11 ceriel Exp $ */
2 /*
3  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
4  * See the copyright notice in the ACK home directory, in the file "Copyright".
5  */
6 /* @(#)comm6.c  1.7 */
7 /*
8  * implement pseudo instructions
9  */
10
11 #include        "comm0.h"
12 #include        "comm1.h"
13 #include        "y.tab.h"
14
15 newequate(ip, typ)
16 register item_t *ip;
17 register int typ;
18 {
19         typ &= ~S_EXT;
20         if (typ & S_COM)
21                 typ = S_UND;
22         else if ((typ & S_VAR) && (typ & S_TYP) != S_ABS)
23                 typ = S_UND;
24 #ifdef THREE_PASS
25         else if (pass == PASS_1 && typ == S_UND)
26                 typ = S_VAR;
27         else if (pass == PASS_2 && (ip->i_type & S_TYP) == S_UND)
28                 ip->i_type |= typ;
29 #endif /* THREE_PASS */
30         if (typ == S_UND)
31                 serror("illegal equate");
32         if (pass == PASS_3)
33                 assert((ip->i_type & S_TYP) == (typ & S_TYP));
34         newident(ip, typ);
35 }
36
37 newident(ip, typ)
38 register item_t *ip;
39 {
40         register flag;
41 #ifdef GENLAB
42         static char genlab[] = GENLAB;
43 #endif /* GENLAB */
44
45         if (pass == PASS_1) {
46                 /* printf("declare %s: %o\n", ip->i_name, typ); */
47                 if (ip->i_type & ~S_EXT)
48                         serror("multiple declared");
49                 else
50                         --unresolved;
51                 ip->i_type |= typ;
52         }
53         if (PASS_SYMB == 0)
54                 return;
55 #ifdef THREE_PASS
56         if (ip->i_type & S_EXT)
57                 flag = SYM_EXT;
58         else
59                 flag = SYM_LOC;
60 #else
61         flag = SYM_EXT|SYM_LOC; /* S_EXT not stable in PASS_1 */
62 #endif /* THREE_PASS */
63 #ifdef GENLAB
64         if (!(flag & SYM_EXT) &&
65             strncmp(ip->i_name, genlab, sizeof(genlab)-1) == 0)
66                 flag = SYM_LAB;
67 #endif /* GENLAB */
68         if (sflag & flag)
69                 newsymb(
70                         ip->i_name,
71                         ip->i_type & (S_EXT|S_TYP),
72                         0,
73                         load(ip)
74                 );
75 }
76
77 newlabel(ip)
78 register item_t *ip;
79 {
80 #if DEBUG != 0
81 #ifdef THREE_PASS
82         register ADDR_T oldval = ip->i_valu;
83 #endif
84 #endif
85
86         if (DOTSCT == NULL)
87                 nosect();
88         ip->i_type &= ~S_TYP;
89         ip->i_type |= DOTTYP;
90         if (store(ip, (valu_t) DOTVAL) == 0)
91                 return;
92 #ifdef THREE_PASS
93         assert(pass != PASS_2 || oldval - (ADDR_T) ip->i_valu == DOTGAIN);
94 #endif
95 }
96
97 newsect(ip)
98 register item_t *ip;
99 {
100         register int typ;
101         register sect_t *sp = NULL;
102
103         typ = ip->i_type & S_TYP;
104         if (typ == S_UND) {
105                 /*
106                  * new section
107                  */
108                 assert(pass == PASS_1);
109                 --unresolved;
110                 typ = outhead.oh_nsect + S_MIN;
111                 outhead.oh_nsect++;
112                 if (outhead.oh_nsect > SECTMAX || typ > S_MAX)
113                         fatal("too many sections");
114                 sp = &sect[typ - S_MIN];
115                 sp->s_item = ip;
116                 sp->s_lign = ALIGNSECT;
117 #ifndef ASLD
118                 ip->i_type = typ;
119 #else
120                 ip->i_type = typ | S_EXT;
121 #endif
122                 ip->i_valu = 0;
123         } else if (typ >= S_MIN) {
124                 sp = &sect[typ - S_MIN];
125                 if (sp->s_item != ip)
126                         sp = NULL;
127         }
128         if (sp == NULL)
129                 serror("multiple declared");
130         else
131                 switchsect(typ);
132 }
133
134 /*ARGSUSED*/
135 newbase(base)
136 valu_t base;
137 {
138 #ifdef ASLD
139         register sect_t *sp;
140         
141         if ((sp = DOTSCT) == NULL)
142                 nosect();
143         if (sp->s_flag & BASED)
144                 serror("already based");
145         sp->s_base = base;
146         sp->s_flag |= BASED;
147         DOTVAL += base;
148 #else
149         warning(".base ignored");
150 #endif
151 }
152
153 /*
154  * NOTE: A rather different solution is used for ASLD and not ASLD:
155  * ASLD, or local commons:
156  *   -  maximum length of .comm is recorded in i_valu during PASS_1
157  *   -  address of .comm is recorded in i_valu in later passes:
158  *      assigned at end of PASS_1, corrected for s_gain at end of PASS_2
159  * not ASLD:
160  *   -  maximum length of .comm is recorded in i_valu during PASS_1
161  *   -  i_valu is used for relocation info during PASS_3
162  */
163 newcomm(ip, val)
164 register item_t *ip;
165 valu_t val;
166 {
167         if (pass == PASS_1) {
168                 if (DOTSCT == NULL)
169                         nosect();
170                 if (val == 0)
171                         serror("bad size");
172                 /* printf("declare %s: %o\n", ip->i_name, DOTTYP); */
173                 if ((ip->i_type & ~S_EXT) == S_UND) {
174                         --unresolved;
175                         ip->i_type = S_COM|DOTTYP|(ip->i_type&S_EXT);
176                         ip->i_valu = val;
177                         new_common(ip);
178                 } else if (ip->i_type == (S_COM|DOTTYP|(ip->i_type&S_EXT))) {
179                         if (ip->i_valu < val)
180                                 ip->i_valu = val;
181                 } else
182                         serror("multiple declared");
183         }
184 }
185
186 switchsect(newtyp)
187 int newtyp;
188 {
189         register sect_t *sp;
190         
191         if (sp = DOTSCT)
192                 sp->s_size = DOTVAL - sp->s_base;
193         if (newtyp == S_UND) {
194                 DOTSCT = NULL;
195                 DOTTYP = newtyp;
196                 return;
197         }
198         assert(newtyp >= S_MIN);
199         sp = &sect[newtyp - S_MIN];
200         DOTVAL = sp->s_size + sp->s_base;
201         DOTSCT = sp;
202         DOTTYP = newtyp;
203 }
204
205 align(bytes)
206 valu_t bytes;
207 {
208         register valu_t gap;
209         register sect_t *sp;
210
211         if ((sp = DOTSCT) == NULL)
212                 nosect();
213         if (bytes == 0)
214                 bytes = ALIGNWORD;
215         if (sp->s_lign % bytes)
216                 if (bytes % sp->s_lign)
217                         serror("illegal alignment");
218                 else
219                         sp->s_lign = bytes;
220         if (pass == PASS_1)
221                 /*
222                  * be pessimistic: biggest gap possible
223                  */
224                 gap = bytes - 1;
225         else {
226                 /*
227                  * calculate gap correctly;
228                  * will be the same in PASS_2 and PASS_3
229                  */
230                 if ((gap = DOTVAL % bytes) != 0)
231                         gap = bytes - gap;
232 #ifdef THREE_PASS
233                 if (pass == PASS_2)
234                         /*
235                          * keep track of gain with respect to PASS_1
236                          */
237                         DOTGAIN += (bytes - 1) - gap;
238 #endif
239         }
240         DOTVAL += gap;
241         sp->s_zero += gap;
242 }
243
244 #ifdef RELOCATION
245 newrelo(s, n)
246 {
247         int     iscomm;
248         struct outrelo  outrelo;
249
250         if (rflag == 0)
251                 return;
252         if (PASS_RELO == 0)
253                 return;
254         s &= ~S_DOT;
255         assert((s & ~(S_COM|S_VAR|S_TYP)) == 0);
256 #ifdef ASLD
257 #ifndef THREE_PASS
258         if (s == S_UND)
259                 serror("bad relocation");
260 #endif
261 #endif
262         /*
263          * always relocation info if S_VAR to solve problems with:
264          *      move    b,d0
265          *      b=a
266          *  a:  .data2  0
267          * but no relocation info if S_VAR is set, but type is S_ABS.
268          */
269         iscomm = s & S_COM;
270         s &= ~S_COM;
271         if ((n & RELPC) == 0 && ((s & ~S_VAR) == S_ABS))
272                 return;
273         if ((n & RELPC) != 0 && s == DOTTYP
274 #ifndef ASLD
275             && ! iscomm
276 #endif
277            )
278                 return;
279         if (pass != PASS_3) {
280                 outhead.oh_nrelo++;
281                 return;
282         }
283         s &= ~S_VAR;
284         outrelo.or_type = (char)n;
285         outrelo.or_sect = (char)DOTTYP;
286 #ifndef ASLD
287         if (s == S_UND || iscomm) {
288                 assert(relonami != 0);
289                 outrelo.or_nami = relonami-1;
290                 relonami = 0;
291         } else
292 #endif
293         if (s < S_MIN) {
294                 assert(s == S_ABS);
295                 /*
296                  * use first non existing entry (argh)
297                  */
298                 outrelo.or_nami = outhead.oh_nname;
299         } else {
300                 /*
301                  * section symbols are at the end
302                  */
303                 outrelo.or_nami = outhead.oh_nname
304                                 - outhead.oh_nsect
305                                 + (s - S_MIN)
306                                 ;
307         }
308         outrelo.or_addr = (long)DOTVAL;
309         wr_relo(&outrelo, 1);
310 }
311 #endif
312
313 long
314 new_string(s)
315         char    *s;
316 {
317         long    r = 0;
318
319         if (s) {
320                 long len = strlen(s) + 1;
321
322                 r = outhead.oh_nchar;
323                 if (pass == PASS_3) wr_string(s, len);
324                 outhead.oh_nchar += len;
325         }
326         return r;
327 }
328
329 newsymb(name, type, desc, valu)
330 register char *name;
331 valu_t valu;
332 {
333         struct outname outname;
334
335         if (name && *name == 0)
336                 name = 0;
337         assert(PASS_SYMB);
338         if (pass != PASS_3) {
339                 new_string(name);
340                 outhead.oh_nname++;
341                 return;
342         }
343         nname++;
344         outname.on_foff = new_string(name);
345         outname.on_type = type;
346         outname.on_desc = desc;
347         outname.on_valu = valu;
348         if (sizeof(valu) != sizeof(long))
349                 outname.on_valu &= ~(((0xFFFFFFFF)<<(4*sizeof(valu_t)))<<(4*sizeof(valu_t)));
350         wr_name(&outname, 1);
351 }
352
353 new_common(ip)
354         item_t *ip;
355 {
356         register struct common_t *cp;
357         static nleft = 0;
358         static struct common_t *next;
359
360         if (--nleft < 0) {
361                 next = (struct common_t *) malloc(MEMINCR);
362                 if (next == 0) {
363                         fatal("out of memory");
364                 }
365                 nleft += (MEMINCR / sizeof (struct common_t));
366         }
367         cp = next++;
368         cp->c_next = commons;
369         cp->c_it = ip;
370         commons = cp;
371 }