date and time created 80/08/13 18:55:18 by bill
[unix-history] / usr / src / old / as.vax / asparse.c
CommitLineData
05353f4b
BJ
1/* Copyright (c) 1980 Regents of the University of California */
2static 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
21int lgensym[10];
22char genref[10];
23
24long bitfield;
25int bitoff;
26int 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 */
33extern struct symtab *lastnam;/*last name seen by the lexical analyzer*/
34int exprisname; /*last factor in an expression was a name*/
35int droppedLP; /*one is analyzing an expression beginning with*/
36 /*a left parenthesis, which has already been*/
37 /*shifted. (Used to parse (<expr>)(rn)*/
38
39char yytext[NCPS+2]; /*the lexical image*/
40int yylval; /*the lexical value; sloppy typing*/
41/*
42 * Expression and argument managers
43 */
44struct exp *xp; /*next free expression slot, used by expr.c*/
45struct exp explist[NEXP]; /*max of 20 expressions in one opcode*/
46struct arg arglist[NARG]; /*building up operands in instructions*/
47/*
48 * Sets to accelerate token discrimination
49 */
50char tokensets[(LASTTOKEN) - (FIRSTTOKEN) + 1];
51
52static char UDotsname[32]; /*name of the assembly source*/
53
54int 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 = &regno;
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);
129nocolon:
130 if (val != COLON) {
131 yyerror("\"%s\" is not followed by a ':' for a label definition",
132 np->name);
133 goto errorfix;
134 }
135restlab:
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 */
984int 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*/
1007yyerror(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}