/* Copyright (c) 1979 Regents of the University of California */
extern struct exp usedot
[];/*information on the dot for each seg*/
struct exp
*dotp
= &usedot
[0]; /*current dot*/
FILE *relfil
; /*relocation info sent here*/
FILE *txtfil
; /*text (for any text #) sent here*/
int hshused
; /*hash slots consumed */
* The following three variables are communication between various
* modules to special case a number of things. They are properly
struct symtab
*lastnam
; /*last name seen by the lexical analyzer*/
int exprisname
; /*last factor in an expression was a name*/
int droppedLP
; /*one is analyzing an expression beginning with*/
/*a left parenthesis, which has already been*/
/*shifted. (Used to parse (<expr>)(rn)*/
static char Dotsname
[32];
struct exp
*xp
; /*next free expression slot, used by expr.c*/
int yylval
; /*the lexical value; sloppy typing*/
extern ptrall tokptr
; /*points to current token being eaten*/
register struct exp
*locxp
;
* loc1xp and ptrloc1xp are used in the
struct exp
*loc1xp
; /*must be non register*/
struct exp
**ptrloc1xp
= & loc1xp
;
struct exp
*pval
; /*hacking expr:expr*/
register struct symtab
*np
;
register int val
; /*what yylex gives*/
register int auxval
; /*saves val*/
register struct arg
*ap
; /*first free argument*/
register struct symtab
*stpt
;
struct strdesc
*stringp
; /*handles string lists*/
int regno
; /*handles arguments*/
int sawindex
; /*saw [rn]*/
int seg_type
; /*the kind of segment: data or text*/
int seg_number
; /*the segment number*/
long space_value
; /*how much .space needs*/
int field_width
; /*how wide a field is to be*/
int field_value
; /*the value to stuff in a field*/
char *stabname
; /*name of stab dealing with*/
ptrall stabstart
; /*where the stab starts in the buffer*/
while (INTOKSET(val
, LINSTBEGIN
)){
else { /*its a name, so we have a label (hopefully*/
ERROR("Name expected for a label");
np
= (struct symtab
*)yylval
;
if ((np
->type
&XTYPE
)!=XUNDEF
) {
if( (np
->type
&XTYPE
)!=dotp
->xtype
|| np
->value
!=dotp
->xvalue
&&(np
->index
!= dotp
->xloc
)
yyerror("%.8s redefined", np
->name
);
printf("name.value=%d, dotp->xvalue=%d\n",
np
->value
, dotp
->xvalue
);
np
->type
&= ~(XTYPE
|XFORW
);
np
->value
= dotp
->xvalue
;
} /*end of this being a label*/
} /*end of to consuming all labels, NLs and SEMIS */
* process the INSTRUCTION body
ERROR("Unrecognized instruction or directive");
tokptr
-= sizeof(toktype
);
stringp
= (struct strdesc
*)yylval
;
movestr(dotsname
, stringp
->str
,
stringp
->str_lg
>= 32? 32 :stringp
->str_lg
);
dotsname
[stringp
->str_lg
] = '\0';
printf("(from parser) Now considered to be in file %s\n",
shift
; /*over the ILINENO*/
printf("Now considered to be on line number %d\n",
case ISET
: { /* .set <name> , <expr> */
np
= (struct symtab
*)yylval
;
np
->type
&= (XXTRN
|XFORW
);
np
->type
|= locxp
->xtype
&(XTYPE
|XFORW
);
np
->value
= locxp
->xvalue
;
if ((locxp
->xtype
&XTYPE
) == XUNDEF
)
case ILSYM
: { /*.lsym name , expr */
np
= (struct symtab
*)yylval
;
* Build the unique occurance of the
* The character scanner will have
* already entered it into the symbol
* table, but we should remove it
stpt
= (struct symtab
*)symalloc();
movestr(stpt
->name
, np
->name
, NCPS
);
np
->tag
= OBSOLETE
; /*invalidate original */
if (locxp
->xtype
!= XABS
)
case IGLOBAL
: { /*.globl <name> */
np
= (struct symtab
*)yylval
;
} /*end of case IGLOBAL*/
case IDATA
: /*.data [ <expr> ] */
case ITEXT
: { /*.text [ <expr> ] */
if (INTOKSET(val
, EBEGOPS
+YUKKYEXPRBEG
+SAFEEXPRBEG
)){
seg_type
= -seg_type
; /*now, it is positive*/
if (seg_type
< 0) { /*there wasn't an associated expr*/
if (locxp
->xtype
!= XABS
|| (seg_number
=locxp
->xvalue
) >= NLOC
) {
yyerror("illegal location counter");
dotp
= &usedot
[seg_number
];
if (passno
==2) { /* go salt away in pass 2*/
if (usefile
[seg_number
] == NULL
) {
tmpn2
[TMPC
] = 'a'+seg_number
;
if ((usefile
[seg_number
] =
fopen(tmpn2
, "w"))==NULL
) {
yyerror("cannot create temp %s", tmpn2
);
tmpn3
[TMPC
] = 'a'+seg_number
;
if ((rusefile
[seg_number
] =
fopen(tmpn3
, "w"))==NULL
) {
yyerror("cannot create temp %s",
txtfil
= usefile
[seg_number
];
relfil
= rusefile
[seg_number
];
} /*end of case .TEXT and .DATA*/
* Storage filler directives:
* exprlist: empty | exprlist outexpr
* outexpr: <expr> | <expr> : <expr>
case IBYTE
: curlen
= NBPW
/4; goto elist
;
case ILONG
: curlen
= NBPW
; goto elist
;
* This processes an expression list
if (INTOKSET(val
, EBEGOPS
+YUKKYEXPRBEG
+SAFEEXPRBEG
)){
* expression list consists of a list of :
* (pack expr2 into expr1 bits
* now, pointing at the next token
if (locxp
->xtype
!= XABS
)
yyerror("Width not absolute");
field_width
= locxp
->xvalue
;
if (bitoff
+ field_width
>
if (field_width
> curlen
)
yyerror("Expression crosses field boundary");
if ((locxp
->xtype
&XTYPE
)!=XABS
) {
yyerror("Illegal relocation in field");
field_width
= LEN4
+ !PCREL
;
field_width
= LEN2
+ !PCREL
;
* Save relocation information for this non absolute
* pass 1: saves enough space for the value, and
* pass 2: writes the address info in ld compatable
* format onto one of the relfiles
field_value
= locxp
->xvalue
& ( (1L << field_width
)-1);
bitfield
|= field_value
<< bitoff
;
if ( auxval
= (val
== CM
)) shift
;
} /*existed an expression at all*/
if ( ( curlen
== NBPW
/4) && bitoff
)
} /*end of case IBYTE, IWORD, ILONG, IINT*/
case ISPACE
: { /* .space <expr> */
if (locxp
->xtype
!= XABS
)
yyerror("Space size not absolute");
space_value
= locxp
->xvalue
;
while (space_value
> 96){
outs(strbuf
[2].str
, space_value
);
case IASCII
: /* .ascii [ <stringlist> ] */
case IASCIZ
: { /* .asciz [ <stringlist> ] */
* Code to consume a string list
* stringlist: empty | STRING | stringlist STRING
stringp
= (struct strdesc
*)yylval
;
outs(stringp
->str
, stringp
->str_lg
);
shift
; /*over the STRING*/
if (val
== CM
) /*could be a split string*/
} /*end of case IASCII and IASIZ*/
case IORG
: { /* .org <expr> */
else if (locxp
->xtype
!=dotp
->xtype
)
yyerror("Illegal expression to set origin");
space_value
= locxp
->xvalue
- dotp
->xvalue
;
yyerror("Backwards 'org'");
* Process stabs. Stabs are created only by the f77
* and the C compiler with the -g flag set.
* We only look at the stab ONCE, during pass 1, and
* virtually remove the stab from the intermediate file
* so it isn't seen during pass2. This makes for some
* hairy processing to handle labels occuring in
* stab entries, but since most expressions in the
* stab are integral we save lots of time in the second
* pass by not looking at the stabs.
* A stab that is tagged floating will be bumped during
* the jxxx resolution phase. A stab tagged fixed will
* .stab: Old fashioned stabs
* .stabn: For stabs without names
* .stabs: For stabs with string names
* .stabd: For stabs for line numbers or bracketing,
* without a string name, without
* a final expression. The value of the
* final expression is taken to be the current
* location counter, and is patched by the 2nd pass
* .stab{<expr>,}*8,<expr>, <expr>, <expr>, <expr>
* .stabn <expr>, <expr>, <expr>, <expr>
* .stabs STRING, <expr>, <expr>, <expr>, <expr>
* .stabd <expr>, <expr>, <expr> # .
if (passno
== 2) goto errorfix
;
stpt
= (struct symtab
*)yylval
;
* Make a pointer to the .stab slot.
* There is a pointer in the way (stpt), and
* tokptr points to the next token.
(char *)stabstart
-= sizeof(struct symtab
*);
(char *)stabstart
-= sizeof(toktype
);
for (argcnt
= 0; argcnt
< 8; argcnt
++){
stpt
->name
[argcnt
] = locxp
->xvalue
;
if (! (locxp
->xvalue
& STABTYPS
)){
yyerror("Invalid type in %s",stabname
);
stpt
->ptype
= locxp
->xvalue
;
stpt
->other
= locxp
->xvalue
;
stpt
->desc
= locxp
->xvalue
;
if (p
== NULL
) { /*absolute expr to begin with*/
stpt
->value
= locxp
->xvalue
;
stpt
->index
= dotp
- usedot
;
stpt
->tag
= STABFLOATING
;
else { /*really have a name*/
stpt
->dest
= locxp
->xname
;
stpt
->type
= p
->type
| STABFLAG
;
* We will assign a more accruate
* guess of locxp's location when
* we sort the symbol table
* The final value of value is
printf("FORWARD REF FOR %s...\n", stabname
);
printf("value (xname) = %x value(value(xname) = %x\n",
stpt
->dest
,stpt
->dest
->value
);
* tokptr now points at one token beyond
* the current token stored in val and yylval,
* which are the next tokens after the end of
* this .stab directive. This next token must
* be either a SEMI or NL, so is of width just
* one. Therefore, to point to the next token
* after the end of this stab, just back up one..
buildskip(stabstart
, (char *)tokptr
- sizeof(toktype
));
break; /*end of the .stab*/
stpt
= (struct symtab
*)yylval
;
* We clobber everything after the
* .stabd and its pointer... we MUST
* be able to get back to this .stabd
* so that we can resolve its final value
shift
; /*over the ISTABDOT*/
if (! (locxp
->xvalue
& STABTYPS
)){
yyerror("Invalid type in .stabd");
stpt
->ptype
= locxp
->xvalue
;
stpt
->other
= locxp
->xvalue
;
stpt
->desc
= locxp
->xvalue
;
* Now, clobber everything but the
* .stabd pseudo and the pointer
* to its symbol table entry
* tokptr points to the next token,
* build the skip up to this
buildskip(stabstart
, (toktype
*)tokptr
- sizeof(toktype
));
* pass 1: Assign a good guess for its position
* (ensures they are sorted into right place)/
* pass 2: Fix the actual value
stpt
->value
= dotp
->xvalue
;
stpt
->index
= dotp
- usedot
;
stpt
->tag
= STABFLOAT
; /*although it has no effect in pass 2*/
} /*end of case ISTABDOT*/
case ISTABNONE
: stabname
= ".stabn"; goto shortstab
;
case ISTABSTR
: { stabname
= ".stabs";
if (passno
== 2) goto errorfix
;
stpt
= (struct symtab
*)yylval
;
(char *)stabstart
-= sizeof(struct symtab
*);
(char *)stabstart
-= sizeof(toktype
);
stringp
= (struct strdesc
*)yylval
;
auxval
= stringp
->str_lg
> NCPS
? NCPS
: stringp
->str_lg
;
movestr(stpt
->name
, stringp
->str
, auxval
);
} /*end of case ISTABSTR and ISTABN*/
case ICOMM
: /* .comm <name> , <expr> */
case ILCOMM
: { /* .lcomm <name> , <expr> */
np
= (struct symtab
*)yylval
;
if (locxp
->xtype
!= XABS
)
yyerror("comm size not absolute");
if (passno
==1 && (np
->type
&XTYPE
)!=XUNDEF
)
yyerror("Redefinition of %.8s", np
->name
);
np
->value
= locxp
->xvalue
;
} /*end of case ICOMM and ILCOMM*/
case IALIGN
: { /* .align <expr> */
stpt
= (struct symtab
*)yylval
;
case INST0
: { /* instructions w/o arguments*/
case INSTn
: /* instructions with arguments*/
case IJXXX
: { /* UNIX style jump instructions */
* Code to process an argument list
xp
= explist
; /*must be set before bring in the first token*/
shift
; /*and bring in the first token for the arg list*/
for (argcnt
= 1; argcnt
<= 6; argcnt
++, ap
++){
* code to process an argument proper
sawindex
= sawmul
= sawsize
= 0;
ERROR("expression expected");
if ( val
== LP
|| sawsize
){
} /*end of the default action*/
if (val
== LP
) goto base
;
if (val
== LITOP
) goto imm
;
if (val
== SIZESPEC
) goto sizespec
;
+SAFEEXPRBEG
)) goto disp
;
ERROR("expression, '(' or '$' expected");
shift
; /*consume the LP*/
* note that (expr) could also
* be (rn) (by special hole in the
* grammar), which we ensure
* means register indirection, instead
* of an expression with value n
if (val
!= REG
&& val
!= REGOP
){
val
= exprparse(val
, &(ap
->xp
));
index
: /*look for [reg] */
} /*end of the switch to process an arg*/
} /*end of processing an argument*/
* Make a concession for *(%r)
if (ap
->atype
== ABASE
) {
ap
->dispsize
= sawsize
== 0 ? d124
: sawsize
;
} /*processing all the arguments*/
yyerror("More than 6 arguments");
insout(seg_type
, arglist
,
auxval
== INSTn
? argcnt
: - argcnt
);
} /*end of case INSTn and IJXXX*/
case IFLOAT
: curlen
= 4; goto floatlist
;
* eat a list of floating point numbers
ERROR("floating number expected");
&(((struct exp
*)yylval
)->doubval
.dvalue
),
} /*end of case IFLOAT and IDOUBLE*/
} /*end of the switch for looking at each reserved word*/
* If got here, then one has no syntax errors!
* got here by either requesting to skip to the
* end of this statement, or by erroring out and
* wanting to apply panic mode recovery
printf("Discarding tokens from here:\n");
} /*end of the loop to read the entire file, line by line*/
* Process a register declaration of the form
* The scanner has already processed funny registers of the form
* %dd[+-]*, where dd is a decimal number in the range 00 to 15 (optional
* preceding zero digit). If there was any space between the % and
* the digit, the scanner wouldn't have recognized it, so we
int funnyreg(val
, regnoback
) /*what the read head will sit on*/
int val
; /*what the read head is sitting on*/
int *regnoback
; /*call by return*/
register struct exp
*locxp
;
struct exp
**ptrloc1xp
= & loc1xp
;
expr(locxp
, val
); /*and leave the current read head with value*/
( locxp
->xtype
& XTYPE
!= XABS
yyerror("Illegal register");
*regnoback
= locxp
->xvalue
;
if (anyerrs
== 0 && ! silent
)
fprintf(sink
, "Assembler:\n");
fprintf(sink
, "\"%s\", line %d: ", dotsname
, lineno
);
fprintf(sink
, s
, a1
, a2
);