* Copyright (c) 1982 Regents of the University of California
static char sccsid
[] = "@(#)asexpr.c 4.5 6/30/83";
* Tables for combination of operands.
#define XTXRN 5<<1 /* indexes last row/column when right shifted */
readonly
char pltab
[6][6] = {
/* UND ABS TXT DAT BSS EXT */
/*UND*/ XUNDEF
, XUNDEF
, XUNDEF
, XUNDEF
, XUNDEF
, XUNDEF
,
/*ABS*/ XUNDEF
, XABS
, XTEXT
, XDATA
, XBSS
, XXTRN
,
/*TXT*/ XUNDEF
, XTEXT
, ERR
, ERR
, ERR
, ERR
,
/*DAT*/ XUNDEF
, XDATA
, ERR
, ERR
, ERR
, ERR
,
/*BSS*/ XUNDEF
, XBSS
, ERR
, ERR
, ERR
, ERR
,
/*EXT*/ XUNDEF
, XXTRN
, ERR
, ERR
, ERR
, ERR
,
readonly
char mintab
[6][6] = {
/* UND ABS TXT DAT BSS EXT */
/*UND*/ XUNDEF
, XUNDEF
, XUNDEF
, XUNDEF
, XUNDEF
, XUNDEF
,
/*ABS*/ XUNDEF
, XABS
, ERR
, ERR
, ERR
, ERR
,
/*TXT*/ XUNDEF
, XTEXT
, XABS
, ERR
, ERR
, ERR
,
/*DAT*/ XUNDEF
, XDATA
, ERR
, XABS
, ERR
, ERR
,
/*BSS*/ XUNDEF
, XBSS
, ERR
, ERR
, XABS
, ERR
,
/*EXT*/ XUNDEF
, XXTRN
, ERR
, ERR
, ERR
, ERR
,
* table for other operators
readonly
char othtab
[6][6] = {
/* UND ABS TXT DAT BSS EXT */
/*UND*/ XUNDEF
, XUNDEF
, XUNDEF
, XUNDEF
, XUNDEF
, XUNDEF
,
/*ABS*/ XUNDEF
, XABS
, ERR
, ERR
, ERR
, ERR
,
/*TXT*/ XUNDEF
, ERR
, ERR
, ERR
, ERR
, ERR
,
/*DAT*/ XUNDEF
, ERR
, ERR
, ERR
, ERR
, ERR
,
/*BSS*/ XUNDEF
, ERR
, ERR
, ERR
, ERR
, ERR
,
/*EXT*/ XUNDEF
, ERR
, ERR
, ERR
, ERR
, ERR
,
struct exp
*combine(op
, exp1
, exp2
)
reg
struct exp
*exp1
, *exp2
;
reg
int e1_type
, e2_type
;
char *btype
= "The assembler can only do arithmetic on 1,2, or 4 byte integers";
lastnam
=0; /* kludge for jxxx instructions */
e1_type
= exp1
->e_xtype
&XTYPE
;
e2_type
= exp2
->e_xtype
&XTYPE
;
if (exp1
->e_xtype
==XXTRN
+XUNDEF
)
if (exp2
->e_xtype
==XXTRN
+XUNDEF
)
if (exp1
->e_xloc
!=exp2
->e_xloc
&& e1_type
==e2_type
)
e1_type
= e2_type
= XTXRN
; /* error on != loc ctrs */
e1_type
>>= 1; /*dispose of the external (XXTRN) bit*/
exp1
->e_xvalue
+= exp2
->e_xvalue
;
back_type
= pltab
[e1_type
][e2_type
];
exp1
->e_xvalue
-= exp2
->e_xvalue
;
back_type
= mintab
[e1_type
][e2_type
];
exp1
->e_xvalue
|= exp2
->e_xvalue
;
exp1
->e_xvalue
^= exp2
->e_xvalue
;
exp1
->e_xvalue
&= exp2
->e_xvalue
;
exp1
->e_xvalue
|= ~exp2
->e_xvalue
;
exp1
->e_xvalue
<<= exp2
->e_xvalue
;
exp1
->e_xvalue
>>= exp2
->e_xvalue
;
exp1
->e_xvalue
|= ~ exp2
->e_xvalue
;
exp1
->e_xvalue
*= exp2
->e_xvalue
;
exp1
->e_xvalue
/= exp2
->e_xvalue
;
yyerror("Divide check (modulo)");
exp1
->e_xvalue
%= exp2
->e_xvalue
;
back_type
= othtab
[e1_type
][e2_type
];
yyerror("Internal error: unknown operator");
exp1
->e_xname
= exp2
->e_xname
;
exp1
->e_xtype
= back_type
| (
(exp1
->e_xtype
|exp2
->e_xtype
) & (XFORW
|XXTRN
) );
yyerror("Relocation error");
#define clobber(val, set) tokensets[(val)] |= (set)
clobber(SEMI
, LINSTBEGIN
);
clobber(INT
, LINSTBEGIN
);
clobber(NAME
, YUKKYEXPRBEG
+ LINSTBEGIN
);
clobber(INSTn
, YUKKYEXPRBEG
);
clobber(INST0
, YUKKYEXPRBEG
);
clobber(REG
, YUKKYEXPRBEG
);
clobber(BFINT
, YUKKYEXPRBEG
);
clobber(INT
, SAFEEXPRBEG
);
clobber(BIGNUM
, SAFEEXPRBEG
);
clobber(MINUS
, ADDOPS
+ EBEGOPS
);
clobber(TILDE
, MULOPS
+ EBEGOPS
);
clobber(REGOP
, MULOPS
); /* % */
* We keep the current token class in this global variable, so
* the recursive descent expression analyzers can talk amongst
* themselves, and so that we may use the macros shift and shift over
extern int yylval
; /*the value of the lexical value*/
extern struct exp
*xp
; /*the next free expression slot*/
* return the value the read head is sitting on
inttoktype
exprparse(inval
, backexpr
)
while (INTOKSET(val
, ADDOPS
)){
lexpr
= combine(op
, lexpr
, boolterm());
while(INTOKSET(val
, BOOLOPS
)){
lexpr
= combine(op
, lexpr
, term());
while(INTOKSET(val
, MULOPS
)){
lexpr
= combine(op
, lexpr
, factor());
extern int droppedLP
; /*called exprparse after consuming an LP*/
if (val
== LP
|| droppedLP
){
val
= exprparse(val
, &lexpr
);
yyerror("right parenthesis expected");
if (INTOKSET(val
, YUKKYEXPRBEG
)){
lexpr
= yukkyexpr(val
, yylval
);
else if (INTOKSET(val
, SAFEEXPRBEG
)){
lexpr
= (struct exp
*)yylval
;
else if ( (val
== TILDE
) || (val
== MINUS
) ){
lexpr
->e_number
= Znumber
;
lexpr
->e_number
.num_tag
= TYPL
;
lexpr
= combine(op
, lexpr
, factor());
yyerror("Bad expression syntax");
lexpr
->e_number
= Znumber
;
lexpr
->e_number
.num_tag
= TYPL
;
struct exp
*yukkyexpr(val
, np
)
extern int exprisname
; /*last factor is a name*/
locxp
->e_number
= Znumber
;
locxp
->e_number
.num_tag
= TYPL
;
yylval
= ((struct exp
*)np
)->e_xvalue
;
if (lgensym
[yylval
] == 1)
yyerror("Reference to undefined local label %db", yylval
);
(void)sprintf(yytext
, "L%d\001%d", yylval
, lgensym
[yylval
] + off
);
yylval
= np
= (int)*lookup(passno
== 1);
lastnam
= (struct symtab
*)np
;
locxp
->e_xtype
= ((struct symtab
*)np
)->s_type
;
if (( ((struct symtab
*)np
)->s_type
&XTYPE
)==XUNDEF
) { /*forward*/
locxp
->e_xname
= (struct symtab
*)np
;
((struct symtab
*)np
)->s_type
|= XFORW
;
} else { /*otherwise, just get the value*/
locxp
->e_xvalue
= ((struct symtab
*)np
)->s_value
;
yyerror("Internal Error in yukkyexpr");
locxp
->e_xvalue
= ( (int)np
) & 0xFF;
* Print definitions for token kinds
static char pdirect
[] = "directive";
static char pinstr
[] = "instruction";
static char phunk
[] = "lexeme";
static char psmall
[] = "small symbol";
static char pcntrl
[] = "control token";
struct Tok_Desc
*tok_name
[LASTTOKEN
- FIRSTTOKEN
+ 1];
struct Tok_Desc tok_desc
[] = {
FIRSTTOKEN
, DIRECT
, "first token",
IFFLOAT
, DIRECT
, ".ffloat",
IDFLOAT
, DIRECT
, ".dfloat",
IASCII
, DIRECT
, ".ascii",
IASCIZ
, DIRECT
, ".asciz",
ISPACE
, DIRECT
, ".space",
IGLOBAL
, DIRECT
, ".global",
IALIGN
, DIRECT
, ".align",
ILCOMM
, DIRECT
, ".lcomm",
ISTABSTR
, DIRECT
, ".stabstr",
ISTABNONE
, DIRECT
, ".stabnone",
ISTABDOT
, DIRECT
, ".stabdot",
ILINENO
, DIRECT
, ".lineno",
IABORT
, DIRECT
, ".abort",
IJXXX
, INSTR
, "jump pseudo",
INST0
, INSTR
, "0 argument inst",
INSTn
, INSTR
, "n argument inst",
PARSEEOF
, CNTRL
, "parse end of file",
ILINESKIP
, CNTRL
, "skip lines",
SCANEOF
, CNTRL
, "scanner end of file",
BADCHAR
, CNTRL
, "bad character",
BFINT
, HUNK
, "local label",
BIGNUM
, HUNK
, "big number",
REG
, HUNK
, "register specifier",
SIZESPEC
, SMALL
, "size specifier, [BWLbwl]",
SIZEQUOTE
, SMALL
, "sizequote, [^']",
MP
, SMALL
, "minus parenthesis, -(",
REGOP
, SMALL
, "register operator, %",
ALPH
, SMALL
, "alphabetic character, [A-Za-z_]",
DIG
, SMALL
, "digit character, [A-Fa-f0-9]",
SQ
, SMALL
, "single quote, '",
DQ
, SMALL
, "double quote, \"",
LSH
, SMALL
, "arithmetic left shift, <",
RSH
, SMALL
, "arithmetic right shift, >",
XOR
, SMALL
, "exclusive or, ^",
MINUS
, SMALL
, "minus, -",
MUL
, SMALL
, "multiply, *",
SEMI
, SMALL
, "semi colon, ;",
COLON
, SMALL
, "colon, :",
IOR
, SMALL
, "inclusive or, |",
TILDE
, SMALL
, "one's complement, ~",
ORNOT
, SMALL
, "ornot, !",
LB
, SMALL
, "left bracket, [",
RB
, SMALL
, "right bracket, ]",
LP
, SMALL
, "left parenthesis, (",
RP
, SMALL
, "right parentheis, )",
LASTTOKEN
, SMALL
, "last token",
* turn a token type into a string
static struct Tok_Desc NA
= {0, (char *)0, "NOT ASSIGNED"};
for (i
= FIRSTTOKEN
; i
<= LASTTOKEN
; i
++)
for (i
= 0; i
<= sizeof(tok_desc
)/sizeof(struct Tok_Desc
); i
++){
tok_name
[tok_desc
[i
].tok_which
] = &tok_desc
[i
];
if (FIRSTTOKEN
<= token
&& token
<= LASTTOKEN
){
sprintf(buf
, "%s %s", tok_name
[token
]->tok_kind
,
tok_name
[token
]->tok_name
);
panic("Unknown token number, %d\n", token
);