15827Srrh /*
219824Sdist * Copyright (c) 1982 Regents of the University of California.
319824Sdist * All rights reserved. The Berkeley software License Agreement
419824Sdist * specifies the terms and conditions for redistribution.
55827Srrh */
619824Sdist
75827Srrh #ifndef lint
8*30099Sdonn static char sccsid[] = "@(#)asparse.c 5.3 (Berkeley) 11/17/86";
95827Srrh #endif not lint
105827Srrh
11597Sbill #include <stdio.h>
12597Sbill #include "as.h"
13597Sbill #include "asscan.h"
14597Sbill #include "assyms.h"
155827Srrh #include "asexpr.h"
16597Sbill
17597Sbill int lgensym[10];
18597Sbill char genref[10];
19597Sbill
20597Sbill long bitfield;
21597Sbill int bitoff;
22597Sbill int curlen; /* current length of literals */
23597Sbill
24597Sbill /*
25597Sbill * The following three variables are communication between various
26597Sbill * modules to special case a number of things. They are properly
27597Sbill * categorized as hacks.
28597Sbill */
29597Sbill extern struct symtab *lastnam;/*last name seen by the lexical analyzer*/
30597Sbill int exprisname; /*last factor in an expression was a name*/
31597Sbill int droppedLP; /*one is analyzing an expression beginning with*/
32597Sbill /*a left parenthesis, which has already been*/
33597Sbill /*shifted. (Used to parse (<expr>)(rn)*/
34597Sbill
3513459Srrh char yytext[NCPName+2]; /*the lexical image*/
36597Sbill int yylval; /*the lexical value; sloppy typing*/
375827Srrh struct Opcode yyopcode; /* lexical value for an opcode */
385827Srrh Bignum yybignum; /* lexical value for a big number */
39597Sbill /*
40597Sbill * Expression and argument managers
41597Sbill */
42597Sbill struct exp *xp; /*next free expression slot, used by expr.c*/
43597Sbill struct exp explist[NEXP]; /*max of 20 expressions in one opcode*/
44597Sbill struct arg arglist[NARG]; /*building up operands in instructions*/
45597Sbill /*
46597Sbill * Sets to accelerate token discrimination
47597Sbill */
48597Sbill char tokensets[(LASTTOKEN) - (FIRSTTOKEN) + 1];
49597Sbill
5013513Srrh static char UDotsname[64]; /*name of the assembly source*/
51597Sbill
yyparse()525827Srrh yyparse()
53597Sbill {
545827Srrh reg struct exp *locxp;
555827Srrh /*
565827Srrh * loc1xp and ptrloc1xp are used in the
575827Srrh * expression lookahead
585827Srrh */
595827Srrh struct exp *loc1xp; /*must be non register*/
605827Srrh struct exp **ptrloc1xp = & loc1xp;
615827Srrh struct exp *pval; /*hacking expr:expr*/
62597Sbill
635827Srrh reg struct symtab *np;
645827Srrh reg int argcnt;
65597Sbill
665827Srrh reg inttoktype val; /*what yylex gives*/
675827Srrh reg inttoktype auxval; /*saves val*/
68597Sbill
695827Srrh reg struct arg *ap; /*first free argument*/
70597Sbill
715827Srrh reg struct symtab *p;
725827Srrh reg struct symtab *stpt;
73597Sbill
7413513Srrh struct strdesc *stringp; /*handles string lists*/
75597Sbill
765827Srrh int regno; /*handles arguments*/
775827Srrh int *ptrregno = ®no;
785827Srrh int sawmul; /*saw * */
795827Srrh int sawindex; /*saw [rn]*/
805827Srrh int sawsize;
815827Srrh int seg_type; /*the kind of segment: data or text*/
825827Srrh int seg_number; /*the segment number*/
835827Srrh int space_value; /*how much .space needs*/
845827Srrh int fill_rep; /*how many reps for .fill */
855827Srrh int fill_size; /*how many bytes for .fill */
86597Sbill
875827Srrh int field_width; /*how wide a field is to be*/
885827Srrh int field_value; /*the value to stuff in a field*/
895827Srrh char *stabname; /*name of stab dealing with*/
905827Srrh ptrall stabstart; /*where the stab starts in the buffer*/
915827Srrh int reloc_how; /* how to relocate expressions */
925827Srrh int toconv; /* how to convert bignums */
9313274Srrh int incasetable; /* set if in a case table */
94597Sbill
9513274Srrh incasetable = 0;
96597Sbill xp = explist;
97597Sbill ap = arglist;
98597Sbill
99597Sbill val = yylex();
100597Sbill
101597Sbill while (val != PARSEEOF){ /* primary loop */
102597Sbill
103597Sbill while (INTOKSET(val, LINSTBEGIN)){
104597Sbill if (val == INT) {
105632Shenry int i = ((struct exp *)yylval)->e_xvalue;
106597Sbill shift;
1075827Srrh if (val != COLON){
1085827Srrh yyerror("Local label %d is not followed by a ':' for a label definition",
1095827Srrh i);
1105827Srrh goto errorfix;
1115827Srrh }
112597Sbill if (i < 0 || i > 9) {
113597Sbill yyerror("Local labels are 0-9");
114597Sbill goto errorfix;
115597Sbill }
1165827Srrh (void)sprintf(yytext, "L%d\001%d", i, lgensym[i]);
117597Sbill lgensym[i]++;
118597Sbill genref[i] = 0;
119597Sbill yylval = (int)*lookup(passno == 1);
120597Sbill val = NAME;
121597Sbill np = (struct symtab *)yylval;
122597Sbill goto restlab;
123597Sbill }
124597Sbill if (val == NL){
125597Sbill lineno++;
126597Sbill shift;
127597Sbill } else
128597Sbill if (val == SEMI)
129597Sbill shift;
130597Sbill else { /*its a name, so we have a label or def */
131597Sbill if (val != NAME){
132597Sbill ERROR("Name expected for a label");
133597Sbill }
134597Sbill np = (struct symtab *)yylval;
135597Sbill shiftover(NAME);
136597Sbill if (val != COLON) {
137597Sbill yyerror("\"%s\" is not followed by a ':' for a label definition",
13813513Srrh FETCHNAME(np));
139597Sbill goto errorfix;
140597Sbill }
141597Sbill restlab:
142597Sbill shift;
14323578Smckusick flushfield(NBWD/4);
144632Shenry if ((np->s_type&XTYPE)!=XUNDEF) {
14515235Sralph if ( (np->s_type&XTYPE) != dotp->e_xtype
14615235Sralph || np->s_value != dotp->e_xvalue
14715235Sralph || ( passno == 1
14815235Sralph && np->s_index != dotp->e_xloc) ) {
14915235Sralph if (passno == 1)
15015235Sralph yyerror("%s redefined",
15113513Srrh FETCHNAME(np));
15215235Sralph else
15315235Sralph yyerror("%s redefined: PHASE ERROR, 1st: %d, 2nd: %d",
15413513Srrh FETCHNAME(np),
155632Shenry np->s_value,
156632Shenry dotp->e_xvalue);
157597Sbill }
158597Sbill }
159632Shenry np->s_type &= ~(XTYPE|XFORW);
160632Shenry np->s_type |= dotp->e_xtype;
161632Shenry np->s_value = dotp->e_xvalue;
162597Sbill if (passno == 1){
163632Shenry np->s_index = dotp-usedot;
16413513Srrh if (FETCHNAME(np)[0] == 'L'){
165597Sbill nlabels++;
166597Sbill }
167632Shenry np->s_tag = LABELID;
168597Sbill }
169597Sbill } /*end of this being a label*/
17015235Sralph } /*end of consuming all labels, NLs and SEMIS */
171597Sbill
172597Sbill xp = explist;
173597Sbill ap = arglist;
174597Sbill
175597Sbill /*
176597Sbill * process the INSTRUCTION body
177597Sbill */
178597Sbill switch(val){
179597Sbill
180597Sbill default:
181597Sbill ERROR("Unrecognized instruction or directive");
182597Sbill
183597Sbill case IABORT:
184597Sbill shift;
185597Sbill sawabort();
186597Sbill /*NOTREACHED*/
187597Sbill break;
188597Sbill
189597Sbill case PARSEEOF:
1905827Srrh tokptr -= sizeof(bytetoktype);
191597Sbill *tokptr++ = VOID;
192597Sbill tokptr[1] = VOID;
193597Sbill tokptr[2] = PARSEEOF;
194597Sbill break;
195597Sbill
196597Sbill case IFILE:
197597Sbill shift;
19813513Srrh stringp = (struct strdesc *)yylval;
199597Sbill shiftover(STRING);
200597Sbill dotsname = &UDotsname[0];
20113513Srrh movestr(dotsname, stringp->sd_string,
20213513Srrh min(stringp->sd_strlen, sizeof(UDotsname)));
203597Sbill break;
204597Sbill
205597Sbill case ILINENO:
206597Sbill shift; /*over the ILINENO*/
207597Sbill expr(locxp, val);
208632Shenry lineno = locxp->e_xvalue;
209597Sbill break;
210597Sbill
211597Sbill case ISET: /* .set <name> , <expr> */
212597Sbill shift;
213597Sbill np = (struct symtab *)yylval;
214597Sbill shiftover(NAME);
215597Sbill shiftover(CM);
216597Sbill expr(locxp, val);
217632Shenry np->s_type &= (XXTRN|XFORW);
218632Shenry np->s_type |= locxp->e_xtype&(XTYPE|XFORW);
219632Shenry np->s_value = locxp->e_xvalue;
220597Sbill if (passno==1)
221632Shenry np->s_index = locxp->e_xloc;
222632Shenry if ((locxp->e_xtype&XTYPE) == XUNDEF)
223597Sbill yyerror("Illegal set?");
224597Sbill break;
225597Sbill
226597Sbill case ILSYM: /*.lsym name , expr */
227597Sbill shift;
228597Sbill np = (struct symtab *)yylval;
229597Sbill shiftover(NAME);
230597Sbill shiftover(CM);
231597Sbill expr(locxp, val);
232597Sbill /*
233597Sbill * Build the unique occurance of the
234597Sbill * symbol.
235597Sbill * The character scanner will have
236597Sbill * already entered it into the symbol
237597Sbill * table, but we should remove it
238597Sbill */
239597Sbill if (passno == 1){
240597Sbill stpt = (struct symtab *)symalloc();
241632Shenry stpt->s_name = np->s_name;
242632Shenry np->s_tag = OBSOLETE; /*invalidate original */
243597Sbill nforgotten++;
244597Sbill np = stpt;
2455827Srrh if ( (locxp->e_xtype & XTYPE) != XABS)
2465827Srrh yyerror("Illegal second argument to lsym");
2475827Srrh np->s_value = locxp->e_xvalue;
2485827Srrh np->s_type = XABS;
249632Shenry np->s_tag = ILSYM;
250597Sbill }
251597Sbill break;
252597Sbill
253597Sbill case IGLOBAL: /*.globl <name> */
254597Sbill shift;
255597Sbill np = (struct symtab *)yylval;
256597Sbill shiftover(NAME);
257632Shenry np->s_type |= XXTRN;
258597Sbill break;
259597Sbill
260597Sbill case IDATA: /*.data [ <expr> ] */
261597Sbill case ITEXT: /*.text [ <expr> ] */
262597Sbill seg_type = -val;
263597Sbill shift;
264597Sbill if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){
265597Sbill expr(locxp, val);
266597Sbill seg_type = -seg_type; /*now, it is positive*/
267597Sbill }
268597Sbill
269597Sbill if (seg_type < 0) { /*there wasn't an associated expr*/
270597Sbill seg_number = 0;
271597Sbill seg_type = -seg_type;
272597Sbill } else {
2735827Srrh if ( ((locxp->e_xtype & XTYPE) != XABS) /* tekmdp */
2745827Srrh || (seg_number = locxp->e_xvalue) >= NLOC) {
275597Sbill yyerror("illegal location counter");
276597Sbill seg_number = 0;
277597Sbill }
278597Sbill }
279597Sbill if (seg_type == IDATA)
280597Sbill seg_number += NLOC;
28123578Smckusick flushfield(NBWD/4);
282597Sbill dotp = &usedot[seg_number];
283597Sbill if (passno==2) { /* go salt away in pass 2*/
284597Sbill txtfil = usefile[seg_number];
285597Sbill relfil = rusefile[seg_number];
286597Sbill }
287597Sbill break;
288597Sbill
289597Sbill /*
290597Sbill * Storage filler directives:
291597Sbill *
292597Sbill * .byte [<exprlist>]
293597Sbill *
294597Sbill * exprlist: empty | exprlist outexpr
295597Sbill * outexpr: <expr> | <expr> : <expr>
296597Sbill */
29723578Smckusick case IBYTE: curlen = NBWD/4; goto elist;
29823578Smckusick case IWORD: curlen = NBWD/2; goto elist;
29923578Smckusick case IINT: curlen = NBWD; goto elist;
30023578Smckusick case ILONG: curlen = NBWD; goto elist;
301597Sbill
302597Sbill elist:
303597Sbill seg_type = val;
304597Sbill shift;
305597Sbill
306597Sbill /*
307597Sbill * Expression List processing
308597Sbill */
309597Sbill if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){
310597Sbill do{
311597Sbill /*
312597Sbill * expression list consists of a list of :
313597Sbill * <expr>
314597Sbill * <expr> : <expr>
315597Sbill * (pack expr2 into expr1 bits
316597Sbill */
317597Sbill expr(locxp, val);
318597Sbill /*
319597Sbill * now, pointing at the next token
320597Sbill */
321597Sbill if (val == COLON){
322597Sbill shiftover(COLON);
323597Sbill expr(pval, val);
3245827Srrh if ((locxp->e_xtype & XTYPE) != XABS) /* tekmdp */
3255827Srrh yyerror("Width not absolute");
326632Shenry field_width = locxp->e_xvalue;
327597Sbill locxp = pval;
3285827Srrh if (bitoff + field_width > curlen)
329597Sbill flushfield(curlen);
330597Sbill if (field_width > curlen)
331597Sbill yyerror("Expression crosses field boundary");
332597Sbill } else {
333597Sbill field_width = curlen;
334597Sbill flushfield(curlen);
335597Sbill }
336597Sbill
3375827Srrh if ((locxp->e_xtype & XTYPE) != XABS) {
338597Sbill if (bitoff)
339597Sbill yyerror("Illegal relocation in field");
340674Shenry switch(curlen){
34123578Smckusick case NBWD/4: reloc_how = TYPB; break;
34223578Smckusick case NBWD/2: reloc_how = TYPW; break;
34323578Smckusick case NBWD: reloc_how = TYPL; break;
344674Shenry }
345597Sbill if (passno == 1){
346674Shenry dotp->e_xvalue += ty_nbyte[reloc_how];
347597Sbill } else {
348674Shenry outrel(locxp, reloc_how);
349597Sbill }
350597Sbill } else {
35113274Srrh /*
35213274Srrh *
35313274Srrh * See if we are doing a case instruction.
35413274Srrh * If so, then see if the branch distance,
35513274Srrh * stored as a word,
35613274Srrh * is going to loose sig bits.
35713274Srrh */
35813274Srrh if (passno == 2 && incasetable){
35913274Srrh if ( (locxp->e_xvalue < -32768)
36013274Srrh ||(locxp->e_xvalue > 32767)){
36113274Srrh yyerror("Case will branch too far");
36213274Srrh }
36313274Srrh }
364632Shenry field_value = locxp->e_xvalue & ( (1L << field_width)-1);
365597Sbill bitfield |= field_value << bitoff;
366597Sbill bitoff += field_width;
367597Sbill }
368597Sbill xp = explist;
3695827Srrh if (auxval = (val == CM))
3705827Srrh shift;
371597Sbill } while (auxval);
3725827Srrh } /* there existed an expression at all */
373597Sbill
374597Sbill flushfield(curlen);
37523578Smckusick if ( ( curlen == NBWD/4) && bitoff)
376632Shenry dotp->e_xvalue ++;
377597Sbill break;
378597Sbill /*end of case IBYTE, IWORD, ILONG, IINT*/
379597Sbill
380597Sbill case ISPACE: /* .space <expr> */
381597Sbill shift;
382597Sbill expr(locxp, val);
3835827Srrh if ((locxp->e_xtype & XTYPE) != XABS) /* tekmdp */
384597Sbill yyerror("Space size not absolute");
385632Shenry space_value = locxp->e_xvalue;
386597Sbill ospace:
38723578Smckusick flushfield(NBWD/4);
38813446Srrh {
38913446Srrh static char spacebuf[128];
39013446Srrh while (space_value > sizeof(spacebuf)){
39113446Srrh outs(spacebuf, sizeof(spacebuf));
39213446Srrh space_value -= sizeof(spacebuf);
39313446Srrh }
39413446Srrh outs(spacebuf, space_value);
395597Sbill }
396597Sbill break;
397597Sbill
398647Shenry /*
399647Shenry * .fill rep, size, value
400647Shenry * repeat rep times: fill size bytes with (truncated) value
401647Shenry * size must be between 1 and 8
402647Shenry */
403647Shenry case IFILL:
404597Sbill shift;
405597Sbill expr(locxp, val);
4065827Srrh if ( (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */
407597Sbill yyerror("Fill repetition count not absolute");
408647Shenry fill_rep = locxp->e_xvalue;
409597Sbill shiftover(CM);
410597Sbill expr(locxp, val);
4115827Srrh if ( (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */
412647Shenry yyerror("Fill size not absolute");
413647Shenry fill_size = locxp->e_xvalue;
414647Shenry if (fill_size <= 0 || fill_size > 8)
415647Shenry yyerror("Fill count not in in 1..8");
416647Shenry shiftover(CM);
417647Shenry expr(locxp, val);
4185827Srrh if (passno == 2 && (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */
4195827Srrh yyerror("Fill value not absolute");
42023578Smckusick flushfield(NBWD/4);
42116570Srrh dotp->e_xvalue += fill_rep * fill_size;
42216570Srrh if (passno == 2) {
423647Shenry while(fill_rep-- > 0)
4245827Srrh bwrite((char *)&locxp->e_xvalue, fill_size, txtfil);
425647Shenry }
426597Sbill break;
427597Sbill
42813446Srrh case IASCII: /* .ascii [ <stringlist> ] */
429597Sbill case IASCIZ: /* .asciz [ <stringlist> ] */
430597Sbill auxval = val;
431597Sbill shift;
432597Sbill /*
433597Sbill * Code to consume a string list
434597Sbill *
435597Sbill * stringlist: empty | STRING | stringlist STRING
436597Sbill */
43713446Srrh while (val == STRING){
43813513Srrh int mystrlen;
43923578Smckusick flushfield(NBWD/4);
440597Sbill if (bitoff)
44113446Srrh dotp->e_xvalue++;
44213513Srrh stringp = (struct strdesc *)yylval;
44313446Srrh /*
44413513Srrh * utilize the string scanner cheat;
44513513Srrh * the scanner appended a null byte on the string,
44613513Srrh * but didn't charge it to sd_strlen
44713446Srrh */
44813513Srrh mystrlen = stringp->sd_strlen;
44913513Srrh mystrlen += (auxval == IASCIZ) ? 1 : 0;
45013513Srrh if (passno == 2){
45113513Srrh if (stringp->sd_place & STR_CORE){
45213513Srrh outs(stringp->sd_string, mystrlen);
45313513Srrh } else {
45413513Srrh int i, nread;
45513513Srrh fseek(strfile, stringp->sd_stroff, 0);
45613513Srrh for (i = 0; i < mystrlen;/*VOID*/){
45713513Srrh nread = fread(yytext, 1,
45813513Srrh min(mystrlen - i,
45913513Srrh sizeof(yytext)), strfile);
46013513Srrh outs(yytext, nread);
46113513Srrh i += nread;
46213513Srrh }
46313513Srrh }
46413513Srrh } else {
46513513Srrh dotp->e_xvalue += mystrlen;
46613513Srrh }
467597Sbill shift; /*over the STRING*/
468597Sbill if (val == CM) /*could be a split string*/
469597Sbill shift;
470597Sbill }
471597Sbill break;
472597Sbill
473597Sbill case IORG: /* .org <expr> */
474597Sbill shift;
475597Sbill expr(locxp, val);
476597Sbill
4775827Srrh if ((locxp->e_xtype & XTYPE) == XABS) /* tekmdp */
478597Sbill orgwarn++;
479632Shenry else if ((locxp->e_xtype & ~XXTRN) != dotp->e_xtype)
480597Sbill yyerror("Illegal expression to set origin");
481632Shenry space_value = locxp->e_xvalue - dotp->e_xvalue;
482597Sbill if (space_value < 0)
483597Sbill yyerror("Backwards 'org'");
484597Sbill goto ospace;
485597Sbill break;
486597Sbill
487597Sbill /*
488597Sbill *
489597Sbill * Process stabs. Stabs are created only by the f77
490597Sbill * and the C compiler with the -g flag set.
491597Sbill * We only look at the stab ONCE, during pass 1, and
492597Sbill * virtually remove the stab from the intermediate file
493597Sbill * so it isn't seen during pass2. This makes for some
494597Sbill * hairy processing to handle labels occuring in
495597Sbill * stab entries, but since most expressions in the
496597Sbill * stab are integral we save lots of time in the second
497597Sbill * pass by not looking at the stabs.
498597Sbill * A stab that is tagged floating will be bumped during
499597Sbill * the jxxx resolution phase. A stab tagged fixed will
500597Sbill * not be be bumped.
501597Sbill *
502597Sbill * .stab: Old fashioned stabs
503597Sbill * .stabn: For stabs without names
504597Sbill * .stabs: For stabs with string names
505597Sbill * .stabd: For stabs for line numbers or bracketing,
506597Sbill * without a string name, without
507597Sbill * a final expression. The value of the
508597Sbill * final expression is taken to be the current
509597Sbill * location counter, and is patched by the 2nd pass
510597Sbill *
51113459Srrh * .stab{<expr>,}*NCPName,<expr>, <expr>, <expr>, <expr>
512597Sbill * .stabn <expr>, <expr>, <expr>, <expr>
513597Sbill * .stabs STRING, <expr>, <expr>, <expr>, <expr>
514597Sbill * .stabd <expr>, <expr>, <expr> # .
515597Sbill */
516597Sbill case ISTAB:
51713521Srrh yyerror(".stab directive no longer supported");
518597Sbill goto errorfix;
519597Sbill
520597Sbill tailstab:
521597Sbill expr(locxp, val);
522632Shenry if (! (locxp->e_xvalue & STABTYPS)){
5235827Srrh yyerror("Invalid type in %s", stabname);
524597Sbill goto errorfix;
525597Sbill }
526632Shenry stpt->s_ptype = locxp->e_xvalue;
527597Sbill shiftover(CM);
528597Sbill expr(locxp, val);
529632Shenry stpt->s_other = locxp->e_xvalue;
530597Sbill shiftover(CM);
531597Sbill expr(locxp, val);
532632Shenry stpt->s_desc = locxp->e_xvalue;
533597Sbill shiftover(CM);
534597Sbill exprisname = 0;
535597Sbill expr(locxp, val);
536632Shenry p = locxp->e_xname;
537597Sbill if (p == NULL) { /*absolute expr to begin with*/
538632Shenry stpt->s_value = locxp->e_xvalue;
539632Shenry stpt->s_index = dotp - usedot;
540597Sbill if (exprisname){
54118554Sralph stpt->s_type = locxp->e_xtype;
542632Shenry switch(stpt->s_ptype){
543*30099Sdonn case N_LCSYM:
544*30099Sdonn stpt->s_dest = (struct symtab *)exprisname;
545*30099Sdonn stpt->s_type |= STABFLAG;
546597Sbill case N_GSYM:
547597Sbill case N_FNAME:
548597Sbill case N_RSYM:
549597Sbill case N_SSYM:
550597Sbill case N_LSYM:
551597Sbill case N_PSYM:
552597Sbill case N_BCOMM:
553597Sbill case N_ECOMM:
554597Sbill case N_LENG:
555632Shenry stpt->s_tag = STABFIXED;
556597Sbill break;
557597Sbill default:
558632Shenry stpt->s_tag = STABFLOATING;
559597Sbill break;
560597Sbill }
561597Sbill } else
562632Shenry stpt->s_tag = STABFIXED;
563597Sbill }
564597Sbill else { /*really have a name*/
565632Shenry stpt->s_dest = locxp->e_xname;
566632Shenry stpt->s_index = p->s_index;
567632Shenry stpt->s_type = p->s_type | STABFLAG;
568597Sbill /*
569597Sbill * We will assign a more accruate
570597Sbill * guess of locxp's location when
571597Sbill * we sort the symbol table
572597Sbill * The final value of value is
573597Sbill * given by stabfix()
574597Sbill */
57512591Scsvaf /*
57612591Scsvaf * For exprs of the form (name + value) one needs to remember locxp->e_xvalue
57712591Scsvaf * for use in stabfix. The right place to keep this is in stpt->s_value
57812591Scsvaf * however this gets corrupted at an unknown point.
57912591Scsvaf * As a bandaid hack the value is preserved in s_desc and s_other (a
58012591Scsvaf * short and a char). This destroys these two values and will
58112591Scsvaf * be fixed. May 19 ,1983 Alastair Fyfe
58212591Scsvaf */
58312591Scsvaf if(locxp->e_xvalue) {
58412591Scsvaf stpt->s_other = (locxp->e_xvalue >> 16);
58512591Scsvaf stpt->s_desc = (locxp->e_xvalue & 0x0000ffff);
58612591Scsvaf stpt->s_tag = STABFLOATING;
58712591Scsvaf }
588597Sbill }
589597Sbill /*
590597Sbill * tokptr now points at one token beyond
591597Sbill * the current token stored in val and yylval,
592597Sbill * which are the next tokens after the end of
593597Sbill * this .stab directive. This next token must
594597Sbill * be either a SEMI or NL, so is of width just
595597Sbill * one. Therefore, to point to the next token
596597Sbill * after the end of this stab, just back up one..
597597Sbill */
5985827Srrh buildskip(stabstart, (bytetoktype *)tokptr - sizeof(bytetoktype));
599597Sbill break; /*end of the .stab*/
600597Sbill
601597Sbill case ISTABDOT:
602597Sbill stabname = ".stabd";
603597Sbill stpt = (struct symtab *)yylval;
604597Sbill /*
605597Sbill * We clobber everything after the
606597Sbill * .stabd and its pointer... we MUST
607597Sbill * be able to get back to this .stabd
608597Sbill * so that we can resolve its final value
609597Sbill */
610597Sbill stabstart = tokptr;
611597Sbill shift; /*over the ISTABDOT*/
612597Sbill if (passno == 1){
613597Sbill expr(locxp, val);
614632Shenry if (! (locxp->e_xvalue & STABTYPS)){
615597Sbill yyerror("Invalid type in .stabd");
616597Sbill goto errorfix;
617597Sbill }
618632Shenry stpt->s_ptype = locxp->e_xvalue;
619597Sbill shiftover(CM);
620597Sbill expr(locxp, val);
621632Shenry stpt->s_other = locxp->e_xvalue;
622597Sbill shiftover(CM);
623597Sbill expr(locxp, val);
624632Shenry stpt->s_desc = locxp->e_xvalue;
625597Sbill /*
626597Sbill *
627597Sbill * Now, clobber everything but the
628597Sbill * .stabd pseudo and the pointer
629597Sbill * to its symbol table entry
630597Sbill * tokptr points to the next token,
631597Sbill * build the skip up to this
632597Sbill */
6335827Srrh buildskip(stabstart, (bytetoktype *)tokptr - sizeof(bytetoktype));
634597Sbill }
635597Sbill /*
636597Sbill * pass 1: Assign a good guess for its position
637597Sbill * (ensures they are sorted into right place)/
638597Sbill * pass 2: Fix the actual value
639597Sbill */
640632Shenry stpt->s_value = dotp->e_xvalue;
641632Shenry stpt->s_index = dotp - usedot;
642632Shenry stpt->s_tag = STABFLOATING; /*although it has no effect in pass 2*/
643597Sbill break;
644597Sbill
645597Sbill case ISTABNONE: stabname = ".stabn"; goto shortstab;
646597Sbill
647597Sbill case ISTABSTR: stabname = ".stabs";
648597Sbill shortstab:
649597Sbill auxval = val;
650597Sbill if (passno == 2) goto errorfix;
651597Sbill stpt = (struct symtab *)yylval;
652597Sbill stabstart = tokptr;
6535827Srrh (bytetoktype *)stabstart -= sizeof(struct symtab *);
6545827Srrh (bytetoktype *)stabstart -= sizeof(bytetoktype);
655597Sbill shift;
656597Sbill if (auxval == ISTABSTR){
65713513Srrh stringp = (struct strdesc *)yylval;
658597Sbill shiftover(STRING);
65913513Srrh stpt->s_name = (char *)stringp;
66013446Srrh /*
66113446Srrh * We want the trailing null included in this string.
66213446Srrh * We utilize the cheat the string scanner used,
66313446Srrh * and merely increment the string length
66413446Srrh */
66513513Srrh stringp->sd_strlen += 1;
666597Sbill shiftover(CM);
667597Sbill } else {
66813571Srrh stpt->s_name = (char *)savestr("\0", 0, STR_BOTH);
669597Sbill }
670597Sbill goto tailstab;
671597Sbill break;
672597Sbill
6735827Srrh case ICOMM: /* .comm <name> , <expr> */
674597Sbill case ILCOMM: /* .lcomm <name> , <expr> */
675597Sbill auxval = val;
676597Sbill shift;
677597Sbill np = (struct symtab *)yylval;
678597Sbill shiftover(NAME);
679597Sbill shiftover(CM);
680597Sbill expr(locxp, val);
681597Sbill
6825827Srrh if ( (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */
683597Sbill yyerror("comm size not absolute");
6845827Srrh if (passno == 1 && (np->s_type&XTYPE) != XUNDEF)
68513521Srrh yyerror("Redefinition of %s", FETCHNAME(np));
686597Sbill if (passno==1) {
687632Shenry np->s_value = locxp->e_xvalue;
688597Sbill if (auxval == ICOMM)
689632Shenry np->s_type |= XXTRN;
690597Sbill else {
691632Shenry np->s_type &= ~XTYPE;
692632Shenry np->s_type |= XBSS;
693597Sbill }
694597Sbill }
695597Sbill break;
696597Sbill
697597Sbill case IALIGN: /* .align <expr> */
698597Sbill stpt = (struct symtab *)yylval;
699597Sbill shift;
700597Sbill expr(locxp, val);
701597Sbill jalign(locxp, stpt);
702597Sbill break;
703597Sbill
704597Sbill case INST0: /* instructions w/o arguments*/
70513274Srrh incasetable = 0;
7065827Srrh insout(yyopcode, (struct arg *)0, 0);
707597Sbill shift;
708597Sbill break;
709597Sbill
710597Sbill case INSTn: /* instructions with arguments*/
711597Sbill case IJXXX: /* UNIX style jump instructions */
712597Sbill auxval = val;
713597Sbill /*
714597Sbill * Code to process an argument list
715597Sbill */
716597Sbill ap = arglist;
717597Sbill xp = explist;
718597Sbill
719597Sbill shift; /* bring in the first token for the arg list*/
720597Sbill
721597Sbill for (argcnt = 1; argcnt <= 6; argcnt++, ap++){
722597Sbill /*
723597Sbill * code to process an argument proper
724597Sbill */
725597Sbill sawindex = sawmul = sawsize = 0;
726597Sbill {
727597Sbill switch(val) {
728597Sbill
729597Sbill default:
730597Sbill disp:
731597Sbill if( !(INTOKSET(val,
732597Sbill EBEGOPS
733597Sbill +YUKKYEXPRBEG
734597Sbill +SAFEEXPRBEG)) ) {
735597Sbill ERROR("expression expected");
736597Sbill }
737632Shenry expr(ap->a_xp,val);
738597Sbill overdisp:
739597Sbill if ( val == LP || sawsize){
740597Sbill shiftover(LP);
741597Sbill findreg(regno);
742597Sbill shiftover(RP);
743632Shenry ap->a_atype = ADISP;
744632Shenry ap->a_areg1 = regno;
745597Sbill } else {
746632Shenry ap->a_atype = AEXP;
747632Shenry ap->a_areg1 = 0;
748597Sbill }
749597Sbill goto index;
750597Sbill
751597Sbill case SIZESPEC:
752597Sbill sizespec:
753597Sbill sawsize = yylval;
754597Sbill shift;
755597Sbill goto disp;
756597Sbill
757597Sbill case REG:
758597Sbill case REGOP:
759597Sbill findreg(regno);
760632Shenry ap->a_atype = AREG;
761632Shenry ap->a_areg1 = regno;
762597Sbill break;
763597Sbill
764597Sbill case MUL:
765597Sbill sawmul = 1;
766597Sbill shift;
767597Sbill if (val == LP) goto base;
768597Sbill if (val == LITOP) goto imm;
769597Sbill if (val == SIZESPEC) goto sizespec;
770597Sbill if (INTOKSET(val,
771597Sbill EBEGOPS
772597Sbill +YUKKYEXPRBEG
773597Sbill +SAFEEXPRBEG)) goto disp;
774597Sbill ERROR("expression, '(' or '$' expected");
775597Sbill break;
776597Sbill
777597Sbill case LP:
778597Sbill base:
779597Sbill shift; /*consume the LP*/
780597Sbill /*
781597Sbill * hack the ambiguity of
782597Sbill * movl (expr) (rn), ...
783597Sbill * note that (expr) could also
784597Sbill * be (rn) (by special hole in the
785597Sbill * grammar), which we ensure
786597Sbill * means register indirection, instead
787597Sbill * of an expression with value n
788597Sbill */
789597Sbill if (val != REG && val != REGOP){
790597Sbill droppedLP = 1;
791632Shenry val = exprparse(val, &(ap->a_xp));
792597Sbill droppedLP = 0;
793597Sbill goto overdisp;
794597Sbill }
795597Sbill findreg(regno);
796597Sbill shiftover(RP);
797597Sbill if (val == PLUS){
798597Sbill shift;
799632Shenry ap->a_atype = AINCR;
800597Sbill } else
801632Shenry ap->a_atype = ABASE;
802632Shenry ap->a_areg1 = regno;
803597Sbill goto index;
804597Sbill
805597Sbill case LITOP:
806597Sbill imm:
807597Sbill shift;
808597Sbill expr(locxp, val);
809632Shenry ap->a_atype = AIMM;
810632Shenry ap->a_areg1 = 0;
811632Shenry ap->a_xp = locxp;
812597Sbill goto index;
813597Sbill
814597Sbill case MP:
815597Sbill shift; /* -(reg) */
816597Sbill findreg(regno);
817597Sbill shiftover(RP);
818632Shenry ap->a_atype = ADECR;
819632Shenry ap->a_areg1 = regno;
820597Sbill index: /*look for [reg] */
821597Sbill if (val == LB){
822597Sbill shift;
823597Sbill findreg(regno);
824597Sbill shiftover(RB);
825597Sbill sawindex = 1;
826632Shenry ap->a_areg2 = regno;
827597Sbill }
828597Sbill break;
829597Sbill
830597Sbill } /*end of the switch to process an arg*/
831597Sbill } /*end of processing an argument*/
832597Sbill
833597Sbill if (sawmul){
834597Sbill /*
835597Sbill * Make a concession for *(%r)
836597Sbill * meaning *0(%r)
837597Sbill */
838632Shenry if (ap->a_atype == ABASE) {
839632Shenry ap->a_atype = ADISP;
840632Shenry xp->e_xtype = XABS;
8415827Srrh xp->e_number = Znumber;
8425827Srrh xp->e_number.num_tag = TYPL;
843632Shenry xp->e_xloc = 0;
844632Shenry ap->a_xp = xp++;
845597Sbill }
846632Shenry ap->a_atype |= ASTAR;
847597Sbill sawmul = 0;
848597Sbill }
849597Sbill if (sawindex){
850632Shenry ap->a_atype |= AINDX;
851597Sbill sawindex = 0;
852597Sbill }
853632Shenry ap->a_dispsize = sawsize == 0 ? d124 : sawsize;
854597Sbill if (val != CM) break;
855597Sbill shiftover(CM);
856597Sbill } /*processing all the arguments*/
857597Sbill
858597Sbill if (argcnt > 6){
859597Sbill yyerror("More than 6 arguments");
860597Sbill goto errorfix;
861597Sbill }
862597Sbill
86313274Srrh /*
86413274Srrh * See if this is a case instruction,
86513274Srrh * so we can set up tests on the following
86613274Srrh * vector of branch displacements
86713274Srrh */
86813274Srrh if (yyopcode.Op_eopcode == CORE){
86913274Srrh switch(yyopcode.Op_popcode){
87013274Srrh case 0x8f: /* caseb */
87113274Srrh case 0xaf: /* casew */
87213274Srrh case 0xcf: /* casel */
87313274Srrh incasetable++;
87413274Srrh break;
87513274Srrh default:
87613274Srrh incasetable = 0;
87713274Srrh break;
87813274Srrh }
87913274Srrh }
88013274Srrh
8815827Srrh insout(yyopcode, arglist,
882597Sbill auxval == INSTn ? argcnt : - argcnt);
883597Sbill break;
884597Sbill
8855827Srrh case IQUAD: toconv = TYPQ; goto bignumlist;
8865827Srrh case IOCTA: toconv = TYPO; goto bignumlist;
8875827Srrh
8885827Srrh case IFFLOAT: toconv = TYPF; goto bignumlist;
8895827Srrh case IDFLOAT: toconv = TYPD; goto bignumlist;
8905827Srrh case IGFLOAT: toconv = TYPG; goto bignumlist;
8915827Srrh case IHFLOAT: toconv = TYPH; goto bignumlist;
8925827Srrh bignumlist:
893597Sbill /*
8945827Srrh * eat a list of non 32 bit numbers.
8955827Srrh * IQUAD and IOCTA can, possibly, return
8965827Srrh * INT's, if the numbers are "small".
8975827Srrh *
8985827Srrh * The value of the numbers is coming back
8995827Srrh * as an expression, NOT in yybignum.
900597Sbill */
9015827Srrh shift; /* over the opener */
9025827Srrh if ((val == BIGNUM) || (val == INT)){
903597Sbill do{
9045827Srrh if ((val != BIGNUM) && (val != INT)){
9055827Srrh ERROR(ty_float[toconv]
9065827Srrh ? "floating number expected"
9075827Srrh : "integer number expected" );
908597Sbill }
9095827Srrh dotp->e_xvalue += ty_nbyte[toconv];
9105827Srrh if (passno == 2){
9115827Srrh bignumwrite(
9125827Srrh ((struct exp *)yylval)->e_number,
9135827Srrh toconv);
914597Sbill }
915597Sbill xp = explist;
9165827Srrh shift; /* over this number */
9175827Srrh if (auxval = (val == CM))
9185827Srrh shift; /* over the comma */
9195827Srrh } while (auxval); /* as long as there are commas */
920597Sbill }
921597Sbill break;
9225827Srrh /* end of the case for initialized big numbers */
923597Sbill } /*end of the switch for looking at each reserved word*/
924597Sbill
9255827Srrh continue;
926597Sbill
927597Sbill errorfix:
928597Sbill /*
929597Sbill * got here by either requesting to skip to the
930597Sbill * end of this statement, or by erroring out and
931597Sbill * wanting to apply panic mode recovery
932597Sbill */
933597Sbill while ( (val != NL)
934597Sbill && (val != SEMI)
935597Sbill && (val != PARSEEOF)
936597Sbill ){
937597Sbill shift;
938597Sbill }
939597Sbill if (val == NL)
940597Sbill lineno++;
941597Sbill shift;
942597Sbill
943597Sbill } /*end of the loop to read the entire file, line by line*/
944597Sbill
945597Sbill } /*end of yyparse*/
946597Sbill
947597Sbill /*
948597Sbill * Process a register declaration of the form
949597Sbill * % <expr>
950597Sbill *
951597Sbill * Note:
952597Sbill * The scanner has already processed funny registers of the form
953597Sbill * %dd[+-]*, where dd is a decimal number in the range 00 to 15 (optional
954597Sbill * preceding zero digit). If there was any space between the % and
955597Sbill * the digit, the scanner wouldn't have recognized it, so we
956597Sbill * hack it out here.
957597Sbill */
funnyreg(val,regnoback)9585827Srrh inttoktype funnyreg(val, regnoback) /*what the read head will sit on*/
9595827Srrh inttoktype val; /*what the read head is sitting on*/
960597Sbill int *regnoback; /*call by return*/
961597Sbill {
9625827Srrh reg struct exp *locxp;
9635827Srrh struct exp *loc1xp;
9645827Srrh struct exp **ptrloc1xp = & loc1xp;
965597Sbill
966597Sbill expr(locxp, val); /*and leave the current read head with value*/
967597Sbill if ( (passno == 2) &&
9685827Srrh ( (locxp->e_xtype & XTYPE) != XABS
9695827Srrh || (locxp->e_xvalue < 0)
9705827Srrh || (locxp->e_xvalue >= 16)
971597Sbill )
972597Sbill ){
973597Sbill yyerror("Illegal register");
974597Sbill return(0);
975597Sbill }
976632Shenry *regnoback = locxp->e_xvalue;
977597Sbill return(val);
978597Sbill }
97912945Srrh /*
98012945Srrh * Shift over error
98112945Srrh */
shiftoerror(token)98212945Srrh shiftoerror(token)
98312945Srrh int token;
98412945Srrh {
98512945Srrh char *tok_to_name();
98612945Srrh yyerror("%s expected", tok_to_name(token));
98712945Srrh }
988597Sbill
989597Sbill /*VARARGS1*/
yyerror(s,a1,a2,a3,a4,a5)990597Sbill yyerror(s, a1, a2,a3,a4,a5)
991597Sbill char *s;
992597Sbill {
993597Sbill
994649Shenry #define sink stdout
995597Sbill
9965827Srrh if (anyerrs == 0 && anywarnings == 0 && ! silent)
997597Sbill fprintf(sink, "Assembler:\n");
998597Sbill anyerrs++;
9995827Srrh if (silent)
10005827Srrh return;
1001597Sbill fprintf(sink, "\"%s\", line %d: ", dotsname, lineno);
1002597Sbill fprintf(sink, s, a1, a2,a3,a4,a5);
1003597Sbill fprintf(sink, "\n");
10045827Srrh #undef sink
1005597Sbill }
1006676Shenry
1007676Shenry /*VARARGS1*/
yywarning(s,a1,a2,a3,a4,a5)1008676Shenry yywarning(s, a1, a2,a3,a4,a5)
1009676Shenry char *s;
1010676Shenry {
1011676Shenry #define sink stdout
10125827Srrh if (anyerrs == 0 && anywarnings == 0 && ! silent)
1013676Shenry fprintf(sink, "Assembler:\n");
10145827Srrh anywarnings++;
10155827Srrh if (silent)
10165827Srrh return;
1017676Shenry fprintf(sink, "\"%s\", line %d: WARNING: ", dotsname, lineno);
1018676Shenry fprintf(sink, s, a1, a2,a3,a4,a5);
1019676Shenry fprintf(sink, "\n");
10205827Srrh #undef sink
1021676Shenry }
1022