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