Commit | Line | Data |
---|---|---|
629188b5 JR |
1 | /* Copyright (c) 1979 Regents of the University of California */ |
2 | #include <stdio.h> | |
3 | #include <a.out.h> | |
4 | #include "as.h" | |
5 | #include "asexpr.h" | |
6 | #include "asscan.h" | |
7 | #include "assyms.h" | |
8 | ||
9 | extern struct exp usedot[];/*information on the dot for each seg*/ | |
10 | struct exp *dotp = &usedot[0]; /*current dot*/ | |
11 | int anyerrs; | |
12 | ||
13 | int passno = 1; | |
14 | ||
15 | FILE *tmpfil; | |
16 | FILE *relfil; /*relocation info sent here*/ | |
17 | FILE *txtfil; /*text (for any text #) sent here*/ | |
18 | ||
19 | int hshused; /*hash slots consumed */ | |
20 | long tsize; | |
21 | long dsize; | |
22 | ||
23 | long bitfield; | |
24 | int bitoff; | |
25 | ||
26 | /* | |
27 | * The following three variables are communication between various | |
28 | * modules to special case a number of things. They are properly | |
29 | * categorized as hacks. | |
30 | */ | |
31 | struct symtab *lastnam; /*last name seen by the lexical analyzer*/ | |
32 | int exprisname; /*last factor in an expression was a name*/ | |
33 | int droppedLP; /*one is analyzing an expression beginning with*/ | |
34 | /*a left parenthesis, which has already been*/ | |
35 | /*shifted. (Used to parse (<expr>)(rn)*/ | |
36 | ||
37 | char yytext[NCPS+2]; | |
38 | static char Dotsname[32]; | |
39 | ||
40 | struct exp *xp; /*next free expression slot, used by expr.c*/ | |
41 | ||
42 | int yylval; /*the lexical value; sloppy typing*/ | |
43 | ||
44 | extern ptrall tokptr; /*points to current token being eaten*/ | |
45 | extern int d124; | |
46 | ||
47 | int yyparse() | |
48 | { | |
49 | register struct exp *locxp; | |
50 | /* | |
51 | * loc1xp and ptrloc1xp are used in the | |
52 | * expression lookahead | |
53 | */ | |
54 | struct exp *loc1xp; /*must be non register*/ | |
55 | struct exp **ptrloc1xp = & loc1xp; | |
56 | struct exp *pval; /*hacking expr:expr*/ | |
57 | ||
58 | register struct symtab *np; | |
59 | register int argcnt; | |
60 | ||
61 | register int val; /*what yylex gives*/ | |
62 | register int auxval; /*saves val*/ | |
63 | ||
64 | register struct arg *ap; /*first free argument*/ | |
65 | ||
66 | struct symtab *p; | |
67 | register struct symtab *stpt; | |
68 | ||
69 | struct strdesc *stringp; /*handles string lists*/ | |
70 | ||
71 | int regno; /*handles arguments*/ | |
72 | int *ptrregno = ®no; | |
73 | int sawmul; /*saw * */ | |
74 | int sawindex; /*saw [rn]*/ | |
75 | int sawsize; | |
76 | int seg_type; /*the kind of segment: data or text*/ | |
77 | int seg_number; /*the segment number*/ | |
78 | long space_value; /*how much .space needs*/ | |
79 | ||
80 | int field_width; /*how wide a field is to be*/ | |
81 | int field_value; /*the value to stuff in a field*/ | |
82 | char *stabname; /*name of stab dealing with*/ | |
83 | ptrall stabstart; /*where the stab starts in the buffer*/ | |
84 | ||
85 | xp = explist; | |
86 | ap = arglist; | |
87 | ||
88 | val = yylex(); | |
89 | while (val != PARSEEOF){ | |
90 | while (INTOKSET(val, LINSTBEGIN)){ | |
91 | if (val == NL){ | |
92 | lineno++; | |
93 | shift; | |
94 | } else | |
95 | if (val == SEMI) | |
96 | shift; | |
97 | else { /*its a name, so we have a label (hopefully*/ | |
98 | if (val != NAME){ | |
99 | ERROR("Name expected for a label"); | |
100 | } | |
101 | np = (struct symtab *)yylval; | |
102 | shiftover(NAME); | |
103 | shiftover(COLON); | |
104 | flushfield(NBPW/4); | |
105 | if ((np->type&XTYPE)!=XUNDEF) { | |
106 | if( (np->type&XTYPE)!=dotp->xtype | |
107 | || np->value!=dotp->xvalue | |
108 | || ( (passno==1) | |
109 | &&(np->index != dotp->xloc) | |
110 | ) | |
111 | ){ | |
112 | #ifndef DEBUG | |
113 | if (np->name[0] != 'L') | |
114 | #endif | |
115 | { | |
116 | yyerror("%.8s redefined", np->name); | |
117 | #ifdef DEBUG | |
118 | printf("name.value=%d, dotp->xvalue=%d\n", | |
119 | np->value, dotp->xvalue); | |
120 | #endif | |
121 | } | |
122 | } | |
123 | } | |
124 | np->type &= ~(XTYPE|XFORW); | |
125 | np->type |= dotp->xtype; | |
126 | np->value = dotp->xvalue; | |
127 | if (passno == 1){ | |
128 | np->index = dotp-usedot; | |
129 | if (np->name[0] == 'L'){ | |
130 | nlabels++; | |
131 | } | |
132 | np->tag = LABELID; | |
133 | } | |
134 | } /*end of this being a label*/ | |
135 | } /*end of to consuming all labels, NLs and SEMIS */ | |
136 | ||
137 | xp = explist; | |
138 | ap = arglist; | |
139 | ||
140 | /* | |
141 | * process the INSTRUCTION body | |
142 | */ | |
143 | switch(val){ | |
144 | default: | |
145 | ERROR("Unrecognized instruction or directive"); | |
146 | ||
147 | case IABORT: | |
148 | shift; | |
149 | sawabort(); | |
150 | /*NOTREACHED*/ | |
151 | break; | |
152 | ||
153 | case PARSEEOF: | |
154 | tokptr -= sizeof(toktype); | |
155 | *tokptr++ = VOID; | |
156 | tokptr[1] = VOID; | |
157 | tokptr[2] = PARSEEOF; | |
158 | break; | |
159 | ||
160 | case IFILE: | |
161 | shift; | |
162 | stringp = (struct strdesc *)yylval; | |
163 | shiftover(STRING); | |
164 | dotsname = &Dotsname[0]; | |
165 | movestr(dotsname, stringp->str, | |
166 | stringp->str_lg >= 32? 32 :stringp->str_lg); | |
167 | dotsname[stringp->str_lg] = '\0'; | |
168 | #ifdef DEBUG | |
169 | if (debug) | |
170 | printf("(from parser) Now considered to be in file %s\n", | |
171 | dotsname); | |
172 | #endif | |
173 | break; | |
174 | ||
175 | case ILINENO: | |
176 | shift; /*over the ILINENO*/ | |
177 | expr(locxp, val); | |
178 | lineno = locxp->xvalue; | |
179 | #ifdef DEBUG | |
180 | if (debug) | |
181 | printf("Now considered to be on line number %d\n", | |
182 | lineno); | |
183 | #endif | |
184 | break; | |
185 | ||
186 | case ISET: { /* .set <name> , <expr> */ | |
187 | shift; | |
188 | np = (struct symtab *)yylval; | |
189 | shiftover(NAME); | |
190 | shiftover(CM); | |
191 | expr(locxp, val); | |
192 | np->type &= (XXTRN|XFORW); | |
193 | np->type |= locxp->xtype&(XTYPE|XFORW); | |
194 | np->value = locxp->xvalue; | |
195 | if (passno==1) | |
196 | np->index = locxp->xloc; | |
197 | if ((locxp->xtype&XTYPE) == XUNDEF) | |
198 | yyerror("Illegal set?"); | |
199 | break; | |
200 | } /*end of case ISET*/ | |
201 | ||
202 | case ILSYM: { /*.lsym name , expr */ | |
203 | shift; | |
204 | np = (struct symtab *)yylval; | |
205 | shiftover(NAME); | |
206 | shiftover(CM); | |
207 | expr(locxp, val); | |
208 | /* | |
209 | * Build the unique occurance of the | |
210 | * symbol. | |
211 | * The character scanner will have | |
212 | * already entered it into the symbol | |
213 | * table, but we should remove it | |
214 | */ | |
215 | if (passno == 1){ | |
216 | stpt = (struct symtab *)symalloc(); | |
217 | movestr(stpt->name, np->name, NCPS); | |
218 | np->tag = OBSOLETE; /*invalidate original */ | |
219 | nforgotten++; | |
220 | np = stpt; | |
221 | if (locxp->xtype != XABS) | |
222 | ("Illegal lsym"); | |
223 | np->value=locxp->xvalue; | |
224 | np->type=XABS; | |
225 | np->tag = ILSYM; | |
226 | } | |
227 | break; | |
228 | } /*end of case ILSYM*/ | |
229 | ||
230 | case IGLOBAL: { /*.globl <name> */ | |
231 | shift; | |
232 | np = (struct symtab *)yylval; | |
233 | shiftover(NAME); | |
234 | np->type |= XXTRN; | |
235 | break; | |
236 | } /*end of case IGLOBAL*/ | |
237 | ||
238 | case IDATA: /*.data [ <expr> ] */ | |
239 | case ITEXT: { /*.text [ <expr> ] */ | |
240 | seg_type = -val; | |
241 | shift; | |
242 | if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){ | |
243 | expr(locxp, val); | |
244 | seg_type = -seg_type; /*now, it is positive*/ | |
245 | } | |
246 | ||
247 | if (seg_type < 0) { /*there wasn't an associated expr*/ | |
248 | seg_number = 0; | |
249 | seg_type = -seg_type; | |
250 | } else { | |
251 | if (locxp->xtype != XABS || (seg_number=locxp->xvalue) >= NLOC) { | |
252 | yyerror("illegal location counter"); | |
253 | seg_number = 0; | |
254 | } | |
255 | } | |
256 | if (seg_type == IDATA) | |
257 | seg_number += NLOC; | |
258 | flushfield(NBPW/4); | |
259 | dotp = &usedot[seg_number]; | |
260 | if (passno==2) { /* go salt away in pass 2*/ | |
261 | if (usefile[seg_number] == NULL) { | |
262 | tmpn2[TMPC] = 'a'+seg_number; | |
263 | if ((usefile[seg_number] = | |
264 | fopen(tmpn2, "w"))==NULL) { | |
265 | yyerror("cannot create temp %s", tmpn2); | |
266 | delexit(); | |
267 | } | |
268 | ||
269 | tmpn3[TMPC] = 'a'+seg_number; | |
270 | if ((rusefile[seg_number] = | |
271 | fopen(tmpn3, "w"))==NULL) { | |
272 | ||
273 | yyerror("cannot create temp %s", | |
274 | tmpn3); | |
275 | } | |
276 | } | |
277 | txtfil = usefile[seg_number]; | |
278 | relfil = rusefile[seg_number]; | |
279 | } | |
280 | ||
281 | break; | |
282 | } /*end of case .TEXT and .DATA*/ | |
283 | ||
284 | /* | |
285 | * Storage filler directives: | |
286 | * | |
287 | * .byte [<exprlist>] | |
288 | * | |
289 | * exprlist: empty | exprlist outexpr | |
290 | * outexpr: <expr> | <expr> : <expr> | |
291 | */ | |
292 | case IBYTE: curlen = NBPW/4; goto elist; | |
293 | ||
294 | case IINT: | |
295 | case ILONG: curlen = NBPW; goto elist; | |
296 | ||
297 | case IWORD: { | |
298 | curlen = NBPW/2; | |
299 | elist: | |
300 | seg_type = val; | |
301 | shift; | |
302 | ||
303 | /* | |
304 | * This processes an expression list | |
305 | */ | |
306 | if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){ | |
307 | do{ | |
308 | /* | |
309 | * expression list consists of a list of : | |
310 | * <expr> | |
311 | * <expr> : <expr> | |
312 | * (pack expr2 into expr1 bits | |
313 | */ | |
314 | expr(locxp, val); | |
315 | /* | |
316 | * now, pointing at the next token | |
317 | */ | |
318 | if (val == COLON){ | |
319 | shiftover(COLON); | |
320 | expr(pval, val); | |
321 | if (locxp->xtype != XABS) | |
322 | yyerror("Width not absolute"); | |
323 | field_width = locxp->xvalue; | |
324 | locxp = pval; | |
325 | if (bitoff + field_width > | |
326 | curlen) | |
327 | flushfield(curlen); | |
328 | if (field_width > curlen) | |
329 | yyerror("Expression crosses field boundary"); | |
330 | } /*value being colon*/ | |
331 | else { | |
332 | field_width = curlen; | |
333 | flushfield(curlen); | |
334 | } | |
335 | ||
336 | if ((locxp->xtype&XTYPE)!=XABS) { | |
337 | if (bitoff) | |
338 | yyerror("Illegal relocation in field"); | |
339 | field_width=LEN1+!PCREL; | |
340 | if (curlen==NBPW) | |
341 | field_width = LEN4 + !PCREL; | |
342 | if (curlen==NBPW/2) | |
343 | field_width = LEN2 + !PCREL; | |
344 | /* | |
345 | * Save relocation information for this non absolute | |
346 | * symbol: | |
347 | * pass 1: saves enough space for the value, and | |
348 | * fixes dotp. | |
349 | * pass 2: writes the address info in ld compatable | |
350 | * format onto one of the relfiles | |
351 | */ | |
352 | outrel(&locxp->xvalue, | |
353 | field_width, | |
354 | locxp->xtype, | |
355 | locxp->xname); | |
356 | } else { | |
357 | field_value = locxp->xvalue & ( (1L << field_width)-1); | |
358 | bitfield |= field_value << bitoff; | |
359 | bitoff += field_width; | |
360 | } | |
361 | if ( auxval = (val == CM)) shift; | |
362 | } while (auxval); | |
363 | } /*existed an expression at all*/ | |
364 | ||
365 | flushfield(curlen); | |
366 | if ( ( curlen == NBPW/4) && bitoff) | |
367 | dotp->xvalue ++; | |
368 | break; | |
369 | } /*end of case IBYTE, IWORD, ILONG, IINT*/ | |
370 | ||
371 | case ISPACE: { /* .space <expr> */ | |
372 | shift; | |
373 | expr(locxp, val); | |
374 | if (locxp->xtype != XABS) | |
375 | yyerror("Space size not absolute"); | |
376 | space_value = locxp->xvalue; | |
377 | ospace: | |
378 | flushfield(NBPW/4); | |
379 | while (space_value > 96){ | |
380 | outs(strbuf[2].str, 96); | |
381 | space_value -= 96; | |
382 | } | |
383 | outs(strbuf[2].str, space_value); | |
384 | break; | |
385 | } /*end of case ISPACE*/ | |
386 | ||
387 | case IASCII: /* .ascii [ <stringlist> ] */ | |
388 | case IASCIZ: { /* .asciz [ <stringlist> ] */ | |
389 | auxval = val; | |
390 | shift; | |
391 | ||
392 | /* | |
393 | * Code to consume a string list | |
394 | * | |
395 | * stringlist: empty | STRING | stringlist STRING | |
396 | */ | |
397 | while (val == STRING){ | |
398 | flushfield(NBPW/4); | |
399 | if (bitoff) | |
400 | dotp->xvalue++; | |
401 | stringp = (struct strdesc *)yylval; | |
402 | outs(stringp->str, stringp->str_lg); | |
403 | shift; /*over the STRING*/ | |
404 | if (val == CM) /*could be a split string*/ | |
405 | shift; | |
406 | } | |
407 | ||
408 | if (auxval == IASCIZ){ | |
409 | flushfield(NBPW/4); | |
410 | outb(0); | |
411 | } | |
412 | break; | |
413 | } /*end of case IASCII and IASIZ*/ | |
414 | ||
415 | case IORG: { /* .org <expr> */ | |
416 | shift; | |
417 | expr(locxp, val); | |
418 | ||
419 | if (locxp->xtype==XABS) | |
420 | orgwarn++; | |
421 | else if (locxp->xtype!=dotp->xtype) | |
422 | yyerror("Illegal expression to set origin"); | |
423 | space_value = locxp->xvalue - dotp->xvalue; | |
424 | if (space_value < 0) | |
425 | yyerror("Backwards 'org'"); | |
426 | goto ospace; | |
427 | break; | |
428 | } /*end of case IORG*/ | |
429 | ||
430 | /* | |
431 | * | |
432 | * Process stabs. Stabs are created only by the f77 | |
433 | * and the C compiler with the -g flag set. | |
434 | * We only look at the stab ONCE, during pass 1, and | |
435 | * virtually remove the stab from the intermediate file | |
436 | * so it isn't seen during pass2. This makes for some | |
437 | * hairy processing to handle labels occuring in | |
438 | * stab entries, but since most expressions in the | |
439 | * stab are integral we save lots of time in the second | |
440 | * pass by not looking at the stabs. | |
441 | * A stab that is tagged floating will be bumped during | |
442 | * the jxxx resolution phase. A stab tagged fixed will | |
443 | * not be be bumped. | |
444 | * | |
445 | * .stab: Old fashioned stabs | |
446 | * .stabn: For stabs without names | |
447 | * .stabs: For stabs with string names | |
448 | * .stabd: For stabs for line numbers or bracketing, | |
449 | * without a string name, without | |
450 | * a final expression. The value of the | |
451 | * final expression is taken to be the current | |
452 | * location counter, and is patched by the 2nd pass | |
453 | * | |
454 | * .stab{<expr>,}*8,<expr>, <expr>, <expr>, <expr> | |
455 | * .stabn <expr>, <expr>, <expr>, <expr> | |
456 | * .stabs STRING, <expr>, <expr>, <expr>, <expr> | |
457 | * .stabd <expr>, <expr>, <expr> # . | |
458 | */ | |
459 | case ISTAB: { | |
460 | stabname = ".stab"; | |
461 | if (passno == 2) goto errorfix; | |
462 | stpt = (struct symtab *)yylval; | |
463 | /* | |
464 | * Make a pointer to the .stab slot. | |
465 | * There is a pointer in the way (stpt), and | |
466 | * tokptr points to the next token. | |
467 | */ | |
468 | stabstart = tokptr; | |
469 | (char *)stabstart -= sizeof(struct symtab *); | |
470 | (char *)stabstart -= sizeof(toktype); | |
471 | shift; | |
472 | for (argcnt = 0; argcnt < 8; argcnt++){ | |
473 | expr(locxp, val); | |
474 | stpt->name[argcnt] = locxp->xvalue; | |
475 | shiftover(CM); | |
476 | } | |
477 | tailstab: | |
478 | expr(locxp, val); | |
479 | if (! (locxp->xvalue & STABTYPS)){ | |
480 | yyerror("Invalid type in %s",stabname); | |
481 | goto errorfix; | |
482 | } | |
483 | stpt->ptype = locxp->xvalue; | |
484 | shiftover(CM); | |
485 | expr(locxp, val); | |
486 | stpt->other = locxp->xvalue; | |
487 | shiftover(CM); | |
488 | expr(locxp, val); | |
489 | stpt->desc = locxp->xvalue; | |
490 | shiftover(CM); | |
491 | exprisname = 0; | |
492 | expr(locxp, val); | |
493 | p = locxp->xname; | |
494 | if (p == NULL) { /*absolute expr to begin with*/ | |
495 | stpt->value = locxp->xvalue; | |
496 | stpt->index = dotp - usedot; | |
497 | if (exprisname){ | |
498 | switch(stpt->ptype){ | |
499 | case N_GSYM: | |
500 | case N_FNAME: | |
501 | case N_RSYM: | |
502 | case N_SSYM: | |
503 | case N_LSYM: | |
504 | case N_PSYM: | |
505 | case N_BCOMM: | |
506 | case N_ECOMM: | |
507 | case N_LENG: | |
508 | stpt->tag = STABFIXED; | |
509 | break; | |
510 | default: | |
511 | stpt->tag = STABFLOATING; | |
512 | break; | |
513 | } | |
514 | } else | |
515 | stpt->tag = STABFIXED; | |
516 | } | |
517 | else { /*really have a name*/ | |
518 | stpt->dest = locxp->xname; | |
519 | stpt->index = p->index; | |
520 | stpt->type = p->type | STABFLAG; | |
521 | /* | |
522 | * We will assign a more accruate | |
523 | * guess of locxp's location when | |
524 | * we sort the symbol table | |
525 | * The final value of value is | |
526 | * given by stabfix() | |
527 | */ | |
528 | stpt->tag = STABFLOAT; | |
529 | #ifdef DSTAB | |
530 | printf("FORWARD REF FOR %s...\n", stabname); | |
531 | printf("value (xname) = %x value(value(xname) = %x\n", | |
532 | stpt->dest,stpt->dest->value); | |
533 | printf("name: %.8s\n\n", | |
534 | (stpt->dest)->name); | |
535 | #endif | |
536 | } | |
537 | /* | |
538 | * tokptr now points at one token beyond | |
539 | * the current token stored in val and yylval, | |
540 | * which are the next tokens after the end of | |
541 | * this .stab directive. This next token must | |
542 | * be either a SEMI or NL, so is of width just | |
543 | * one. Therefore, to point to the next token | |
544 | * after the end of this stab, just back up one.. | |
545 | */ | |
546 | buildskip(stabstart, (char *)tokptr - sizeof(toktype)); | |
547 | break; /*end of the .stab*/ | |
548 | } /*end of ISTAB*/ | |
549 | ||
550 | case ISTABDOT: { | |
551 | stabname = ".stabd"; | |
552 | stpt = (struct symtab *)yylval; | |
553 | /* | |
554 | * We clobber everything after the | |
555 | * .stabd and its pointer... we MUST | |
556 | * be able to get back to this .stabd | |
557 | * so that we can resolve its final value | |
558 | */ | |
559 | stabstart = tokptr; | |
560 | shift; /*over the ISTABDOT*/ | |
561 | if (passno == 1){ | |
562 | expr(locxp, val); | |
563 | if (! (locxp->xvalue & STABTYPS)){ | |
564 | yyerror("Invalid type in .stabd"); | |
565 | goto errorfix; | |
566 | } | |
567 | stpt->ptype = locxp->xvalue; | |
568 | shiftover(CM); | |
569 | expr(locxp, val); | |
570 | stpt->other = locxp->xvalue; | |
571 | shiftover(CM); | |
572 | expr(locxp, val); | |
573 | stpt->desc = locxp->xvalue; | |
574 | /* | |
575 | * | |
576 | * Now, clobber everything but the | |
577 | * .stabd pseudo and the pointer | |
578 | * to its symbol table entry | |
579 | * tokptr points to the next token, | |
580 | * build the skip up to this | |
581 | */ | |
582 | buildskip(stabstart, (toktype *)tokptr - sizeof(toktype)); | |
583 | } | |
584 | /* | |
585 | * pass 1: Assign a good guess for its position | |
586 | * (ensures they are sorted into right place)/ | |
587 | * pass 2: Fix the actual value | |
588 | */ | |
589 | stpt->value = dotp->xvalue; | |
590 | stpt->index = dotp - usedot; | |
591 | stpt->tag = STABFLOAT; /*although it has no effect in pass 2*/ | |
592 | break; | |
593 | } /*end of case ISTABDOT*/ | |
594 | ||
595 | case ISTABNONE: stabname = ".stabn"; goto shortstab; | |
596 | ||
597 | case ISTABSTR: { stabname = ".stabs"; | |
598 | shortstab: | |
599 | auxval = val; | |
600 | if (passno == 2) goto errorfix; | |
601 | stpt = (struct symtab *)yylval; | |
602 | stabstart = tokptr; | |
603 | (char *)stabstart -= sizeof(struct symtab *); | |
604 | (char *)stabstart -= sizeof(toktype); | |
605 | shift; | |
606 | if (auxval == ISTABSTR){ | |
607 | stringp = (struct strdesc *)yylval; | |
608 | shiftover(STRING); | |
609 | auxval = stringp->str_lg > NCPS ? NCPS : stringp->str_lg; | |
610 | shiftover(CM); | |
611 | } else { | |
612 | stringp = &(strbuf[2]); | |
613 | auxval = NCPS; | |
614 | } | |
615 | movestr(stpt->name, stringp->str, auxval); | |
616 | goto tailstab; | |
617 | break; | |
618 | } /*end of case ISTABSTR and ISTABN*/ | |
619 | ||
620 | case ICOMM: /* .comm <name> , <expr> */ | |
621 | case ILCOMM: { /* .lcomm <name> , <expr> */ | |
622 | auxval = val; | |
623 | shift; | |
624 | np = (struct symtab *)yylval; | |
625 | shiftover(NAME); | |
626 | shiftover(CM); | |
627 | expr(locxp, val); | |
628 | ||
629 | if (locxp->xtype != XABS) | |
630 | yyerror("comm size not absolute"); | |
631 | if (passno==1 && (np->type&XTYPE)!=XUNDEF) | |
632 | yyerror("Redefinition of %.8s", np->name); | |
633 | if (passno==1) { | |
634 | np->value = locxp->xvalue; | |
635 | if (auxval == ICOMM) | |
636 | np->type |= XXTRN; | |
637 | else { | |
638 | np->type &= ~XTYPE; | |
639 | np->type |= XBSS; | |
640 | } | |
641 | } | |
642 | break; | |
643 | } /*end of case ICOMM and ILCOMM*/ | |
644 | ||
645 | case IALIGN: { /* .align <expr> */ | |
646 | stpt = (struct symtab *)yylval; | |
647 | shift; | |
648 | expr(locxp, val); | |
649 | jalign(locxp, stpt); | |
650 | break; | |
651 | } /*end of case IALIGN*/ | |
652 | ||
653 | case INST0: { /* instructions w/o arguments*/ | |
654 | insout(yylval, 0, 0); | |
655 | shift; | |
656 | break; | |
657 | } /*end of case INST0*/ | |
658 | ||
659 | case INSTn: /* instructions with arguments*/ | |
660 | case IJXXX: { /* UNIX style jump instructions */ | |
661 | auxval = val; | |
662 | seg_type = yylval; | |
663 | /* | |
664 | * Code to process an argument list | |
665 | */ | |
666 | ap = arglist; | |
667 | xp = explist; /*must be set before bring in the first token*/ | |
668 | ||
669 | shift; /*and bring in the first token for the arg list*/ | |
670 | ||
671 | for (argcnt = 1; argcnt <= 6; argcnt++, ap++){ | |
672 | /* | |
673 | * code to process an argument proper | |
674 | */ | |
675 | sawindex = sawmul = sawsize = 0; | |
676 | { | |
677 | switch(val) { | |
678 | ||
679 | default: { | |
680 | disp: | |
681 | if( !(INTOKSET(val, | |
682 | EBEGOPS | |
683 | +YUKKYEXPRBEG | |
684 | +SAFEEXPRBEG)) ) { | |
685 | ERROR("expression expected"); | |
686 | } | |
687 | expr(ap->xp,val); | |
688 | overdisp: | |
689 | if ( val == LP || sawsize){ | |
690 | shiftover(LP); | |
691 | findreg(regno); | |
692 | shiftover(RP); | |
693 | ap->atype = ADISP; | |
694 | ap->areg1 = regno; | |
695 | } else { | |
696 | ap->atype = AEXP; | |
697 | ap->areg1 = 0; | |
698 | } | |
699 | goto index; | |
700 | } /*end of the default action*/ | |
701 | ||
702 | case SIZESPEC: { | |
703 | sizespec: | |
704 | sawsize = yylval; | |
705 | shift; | |
706 | goto disp; | |
707 | } | |
708 | ||
709 | case REG: | |
710 | case REGOP: { | |
711 | findreg(regno); | |
712 | ap->atype = AREG; | |
713 | ap->areg1 = regno; | |
714 | break; | |
715 | } /*end of case REG*/ | |
716 | ||
717 | case MUL: { | |
718 | sawmul = 1; | |
719 | shift; | |
720 | if (val == LP) goto base; | |
721 | if (val == LITOP) goto imm; | |
722 | if (val == SIZESPEC) goto sizespec; | |
723 | if (INTOKSET(val, | |
724 | EBEGOPS | |
725 | +YUKKYEXPRBEG | |
726 | +SAFEEXPRBEG)) goto disp; | |
727 | ERROR("expression, '(' or '$' expected"); | |
728 | break; | |
729 | } /*end of case MUL*/ | |
730 | ||
731 | case LP: { | |
732 | base: | |
733 | shift; /*consume the LP*/ | |
734 | /* | |
735 | * hack the ambiguity of | |
736 | * movl (expr) (rn), ... | |
737 | * note that (expr) could also | |
738 | * be (rn) (by special hole in the | |
739 | * grammar), which we ensure | |
740 | * means register indirection, instead | |
741 | * of an expression with value n | |
742 | */ | |
743 | if (val != REG && val != REGOP){ | |
744 | droppedLP = 1; | |
745 | val = exprparse(val, &(ap->xp)); | |
746 | droppedLP = 0; | |
747 | goto overdisp; | |
748 | } | |
749 | findreg(regno); | |
750 | shiftover(RP); | |
751 | if (val == PLUS){ | |
752 | shift; | |
753 | ap->atype = AINCR; | |
754 | } else | |
755 | ap->atype = ABASE; | |
756 | ap->areg1 = regno; | |
757 | goto index; | |
758 | } /*end of case LP*/ | |
759 | ||
760 | case LITOP: { | |
761 | imm: | |
762 | shift; | |
763 | expr(locxp, val); | |
764 | ap->atype = AIMM; | |
765 | ap->areg1 = 0; | |
766 | ap->xp = locxp; | |
767 | goto index; | |
768 | } /*end of case LITOP*/ | |
769 | ||
770 | case MP: { | |
771 | shift; /* -(reg) */ | |
772 | findreg(regno); | |
773 | shiftover(RP); | |
774 | ap->atype = ADECR; | |
775 | ap->areg1 = regno; | |
776 | index: /*look for [reg] */ | |
777 | if (val == LB){ | |
778 | shift; | |
779 | findreg(regno); | |
780 | shiftover(RB); | |
781 | sawindex = 1; | |
782 | ap->areg2 = regno; | |
783 | } | |
784 | break; | |
785 | } /*end of case MP*/ | |
786 | ||
787 | } /*end of the switch to process an arg*/ | |
788 | } /*end of processing an argument*/ | |
789 | ||
790 | if (sawmul){ | |
791 | /* | |
792 | * Make a concession for *(%r) | |
793 | * meaning *0(%r) | |
794 | */ | |
795 | if (ap->atype == ABASE) { | |
796 | ap->atype = ADISP; | |
797 | xp->xtype = XABS; | |
798 | xp->xvalue = 0; | |
799 | xp->xloc = 0; | |
800 | ap->xp = xp++; | |
801 | } | |
802 | ap->atype |= ASTAR; | |
803 | sawmul = 0; | |
804 | } | |
805 | if (sawindex){ | |
806 | ap->atype |= AINDX; | |
807 | sawindex = 0; | |
808 | } | |
809 | ap->dispsize = sawsize == 0 ? d124 : sawsize; | |
810 | if (val != CM) break; | |
811 | shiftover(CM); | |
812 | } /*processing all the arguments*/ | |
813 | ||
814 | if (argcnt > 6){ | |
815 | yyerror("More than 6 arguments"); | |
816 | goto errorfix; | |
817 | } | |
818 | ||
819 | insout(seg_type, arglist, | |
820 | auxval == INSTn ? argcnt : - argcnt); | |
821 | break; | |
822 | } /*end of case INSTn and IJXXX*/ | |
823 | ||
824 | case IFLOAT: curlen = 4; goto floatlist; | |
825 | ||
826 | case IDOUBLE: { | |
827 | curlen = 8; | |
828 | floatlist: | |
829 | /* | |
830 | * eat a list of floating point numbers | |
831 | */ | |
832 | shift; | |
833 | if (val == FLTNUM){ | |
834 | do{ | |
835 | if (val == CM) shift; | |
836 | if (val != FLTNUM) { | |
837 | ERROR("floating number expected"); | |
838 | } | |
839 | dotp->xvalue += curlen; | |
840 | if (passno == 2) | |
841 | fwrite( | |
842 | &(((struct exp *)yylval)->doubval.dvalue), | |
843 | 1, curlen, txtfil); | |
844 | shift; | |
845 | } while (val == CM); | |
846 | } | |
847 | break; | |
848 | } /*end of case IFLOAT and IDOUBLE*/ | |
849 | ||
850 | } /*end of the switch for looking at each reserved word*/ | |
851 | ||
852 | /* | |
853 | * If got here, then one has no syntax errors! | |
854 | */ | |
855 | continue; | |
856 | ||
857 | /* | |
858 | * got here by either requesting to skip to the | |
859 | * end of this statement, or by erroring out and | |
860 | * wanting to apply panic mode recovery | |
861 | */ | |
862 | errorfix: { | |
863 | #ifdef DEBUG | |
864 | if (debug) | |
865 | printf("Discarding tokens from here:\n"); | |
866 | #endif | |
867 | while ( (val != NL) | |
868 | && (val != SEMI) | |
869 | && (val != PARSEEOF) | |
870 | ){ | |
871 | #ifdef DEBUG | |
872 | if (debug) | |
873 | printf("****>>>>\t"); | |
874 | #endif | |
875 | shift; | |
876 | } | |
877 | if (val == NL) | |
878 | lineno++; | |
879 | #ifdef DEBUG | |
880 | if (debug) | |
881 | printf("To here.\n"); | |
882 | #endif | |
883 | shift; | |
884 | } | |
885 | ||
886 | } /*end of the loop to read the entire file, line by line*/ | |
887 | ||
888 | ||
889 | } /*end of yyparse*/ | |
890 | ||
891 | /* | |
892 | * Process a register declaration of the form | |
893 | * % <expr> | |
894 | * | |
895 | * Note: | |
896 | * The scanner has already processed funny registers of the form | |
897 | * %dd[+-]*, where dd is a decimal number in the range 00 to 15 (optional | |
898 | * preceding zero digit). If there was any space between the % and | |
899 | * the digit, the scanner wouldn't have recognized it, so we | |
900 | * hack it out here. | |
901 | */ | |
902 | int funnyreg(val, regnoback) /*what the read head will sit on*/ | |
903 | int val; /*what the read head is sitting on*/ | |
904 | int *regnoback; /*call by return*/ | |
905 | { | |
906 | register struct exp *locxp; | |
907 | struct exp *loc1xp; | |
908 | struct exp **ptrloc1xp = & loc1xp; | |
909 | ||
910 | expr(locxp, val); /*and leave the current read head with value*/ | |
911 | if ( (passno == 2) && | |
912 | ( locxp->xtype & XTYPE != XABS | |
913 | || locxp->xvalue < 0 | |
914 | || locxp->xvalue >= 16 | |
915 | ) | |
916 | ){ | |
917 | yyerror("Illegal register"); | |
918 | return(0); | |
919 | } | |
920 | *regnoback = locxp->xvalue; | |
921 | return(val); | |
922 | } | |
923 | ||
924 | /* VARARGS 1*/ | |
925 | yyerror(s, a1, a2) | |
926 | char *s; | |
927 | { | |
928 | FILE *sink; | |
929 | ||
930 | #ifdef DEBUG | |
931 | sink = stdout; | |
932 | #else | |
933 | sink = stderr; | |
934 | #endif | |
935 | ||
936 | if (anyerrs == 0 && ! silent) | |
937 | fprintf(sink, "Assembler:\n"); | |
938 | anyerrs++; | |
939 | if (silent) return; | |
940 | ||
941 | fprintf(sink, "\"%s\", line %d: ", dotsname, lineno); | |
942 | fprintf(sink, s, a1, a2); | |
943 | fprintf(sink, "\n"); | |
944 | } |