129831Ssam /*
229831Ssam * Copyright (c) 1982 Regents of the University of California
329831Ssam */
429831Ssam #ifndef lint
529831Ssam static char sccsid[] = "@(#)asexpr.c 4.5 6/30/83";
629831Ssam
729831Ssam #endif not lint
829831Ssam #include <stdio.h>
929831Ssam #include "as.h"
1029831Ssam #include "asscan.h"
1129831Ssam #include "asexpr.h"
1229831Ssam
1329831Ssam /*
1429831Ssam * Tables for combination of operands.
1529831Ssam */
1629831Ssam #define XTXRN 5<<1 /* indexes last row/column when right shifted */
1729831Ssam
1829831Ssam /*
1929831Ssam * table for +
2029831Ssam */
2129831Ssam readonly char pltab[6][6] = {
2229831Ssam /* UND ABS TXT DAT BSS EXT */
2329831Ssam
2429831Ssam /*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF,
2529831Ssam /*ABS*/ XUNDEF, XABS, XTEXT, XDATA, XBSS, XXTRN,
2629831Ssam /*TXT*/ XUNDEF, XTEXT, ERR, ERR, ERR, ERR,
2729831Ssam /*DAT*/ XUNDEF, XDATA, ERR, ERR, ERR, ERR,
2829831Ssam /*BSS*/ XUNDEF, XBSS, ERR, ERR, ERR, ERR,
2929831Ssam /*EXT*/ XUNDEF, XXTRN, ERR, ERR, ERR, ERR,
3029831Ssam };
3129831Ssam
3229831Ssam /*
3329831Ssam * table for -
3429831Ssam */
3529831Ssam readonly char mintab[6][6] = {
3629831Ssam /* UND ABS TXT DAT BSS EXT */
3729831Ssam
3829831Ssam /*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF,
3929831Ssam /*ABS*/ XUNDEF, XABS, ERR, ERR, ERR, ERR,
4029831Ssam /*TXT*/ XUNDEF, XTEXT, XABS, ERR, ERR, ERR,
4129831Ssam /*DAT*/ XUNDEF, XDATA, ERR, XABS, ERR, ERR,
4229831Ssam /*BSS*/ XUNDEF, XBSS, ERR, ERR, XABS, ERR,
4329831Ssam /*EXT*/ XUNDEF, XXTRN, ERR, ERR, ERR, ERR,
4429831Ssam };
4529831Ssam
4629831Ssam /*
4729831Ssam * table for other operators
4829831Ssam */
4929831Ssam readonly char othtab[6][6] = {
5029831Ssam /* UND ABS TXT DAT BSS EXT */
5129831Ssam
5229831Ssam /*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF,
5329831Ssam /*ABS*/ XUNDEF, XABS, ERR, ERR, ERR, ERR,
5429831Ssam /*TXT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR,
5529831Ssam /*DAT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR,
5629831Ssam /*BSS*/ XUNDEF, ERR, ERR, ERR, ERR, ERR,
5729831Ssam /*EXT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR,
5829831Ssam };
5929831Ssam
combine(op,exp1,exp2)6029831Ssam struct exp *combine(op, exp1, exp2)
6129831Ssam reg struct exp *exp1, *exp2;
6229831Ssam {
6329831Ssam reg int e1_type, e2_type;
6429831Ssam reg int back_type;
6529831Ssam char *btype = "The assembler can only do arithmetic on 1,2, or 4 byte integers";
6629831Ssam
6729831Ssam lastnam=0; /* kludge for jxxx instructions */
6829831Ssam
6929831Ssam e1_type = exp1->e_xtype&XTYPE;
7029831Ssam e2_type = exp2->e_xtype&XTYPE;
7129831Ssam
7229831Ssam if (exp1->e_xtype==XXTRN+XUNDEF)
7329831Ssam e1_type = XTXRN;
7429831Ssam if (exp2->e_xtype==XXTRN+XUNDEF)
7529831Ssam e2_type = XTXRN;
7629831Ssam if (passno==1)
7729831Ssam if (exp1->e_xloc!=exp2->e_xloc && e1_type==e2_type)
7829831Ssam e1_type = e2_type = XTXRN; /* error on != loc ctrs */
7929831Ssam e1_type >>= 1; /*dispose of the external (XXTRN) bit*/
8029831Ssam e2_type >>= 1;
8129831Ssam
8229831Ssam switch (op){
8329831Ssam case PLUS:
8429831Ssam exp1->e_xvalue += exp2->e_xvalue;
8529831Ssam back_type = pltab[e1_type][e2_type];
8629831Ssam break;
8729831Ssam case MINUS:
8829831Ssam exp1->e_xvalue -= exp2->e_xvalue;
8929831Ssam back_type = mintab[e1_type][e2_type];
9029831Ssam break;
9129831Ssam case IOR:
9229831Ssam exp1->e_xvalue |= exp2->e_xvalue;
9329831Ssam goto comm;
9429831Ssam case XOR:
9529831Ssam exp1->e_xvalue ^= exp2->e_xvalue;
9629831Ssam goto comm;
9729831Ssam case AND:
9829831Ssam exp1->e_xvalue &= exp2->e_xvalue;
9929831Ssam goto comm;
10029831Ssam case ORNOT:
10129831Ssam exp1->e_xvalue |= ~exp2->e_xvalue;
10229831Ssam goto comm;
10329831Ssam case LSH:
10429831Ssam exp1->e_xvalue <<= exp2->e_xvalue;
10529831Ssam goto comm;
10629831Ssam case RSH:
10729831Ssam exp1->e_xvalue >>= exp2->e_xvalue;
10829831Ssam goto comm;
10929831Ssam case TILDE:
11029831Ssam exp1->e_xvalue |= ~ exp2->e_xvalue;
11129831Ssam goto comm;
11229831Ssam case MUL:
11329831Ssam exp1->e_xvalue *= exp2->e_xvalue;
11429831Ssam goto comm;
11529831Ssam case DIV:
11629831Ssam if (exp2->e_xvalue == 0)
11729831Ssam yyerror("Divide check");
11829831Ssam else
11929831Ssam exp1->e_xvalue /= exp2->e_xvalue;
12029831Ssam goto comm;
12129831Ssam case REGOP:
12229831Ssam if (exp2->e_xvalue == 0)
12329831Ssam yyerror("Divide check (modulo)");
12429831Ssam else
12529831Ssam exp1->e_xvalue %= exp2->e_xvalue;
12629831Ssam goto comm;
12729831Ssam
12829831Ssam comm:
12929831Ssam back_type = othtab[e1_type][e2_type];
13029831Ssam break;
13129831Ssam default:
13229831Ssam yyerror("Internal error: unknown operator");
13329831Ssam }
13429831Ssam
13529831Ssam if (e2_type==(XTXRN>>1))
13629831Ssam exp1->e_xname = exp2->e_xname;
13729831Ssam exp1->e_xtype = back_type | (
13829831Ssam (exp1->e_xtype|exp2->e_xtype) & (XFORW|XXTRN) );
13929831Ssam if (back_type==ERR)
14029831Ssam yyerror("Relocation error");
14129831Ssam return(exp1);
14229831Ssam }
14329831Ssam
buildtokensets()14429831Ssam buildtokensets()
14529831Ssam {
14629831Ssam #define clobber(val, set) tokensets[(val)] |= (set)
14729831Ssam
14829831Ssam clobber(SEMI, LINSTBEGIN);
14929831Ssam clobber(NL, LINSTBEGIN);
15029831Ssam clobber(INT, LINSTBEGIN);
15129831Ssam
15229831Ssam clobber(NAME, YUKKYEXPRBEG + LINSTBEGIN);
15329831Ssam clobber(INSTn, YUKKYEXPRBEG);
15429831Ssam clobber(INST0, YUKKYEXPRBEG);
15529831Ssam clobber(REG, YUKKYEXPRBEG);
15629831Ssam clobber(BFINT, YUKKYEXPRBEG);
15729831Ssam
15829831Ssam clobber(INT, SAFEEXPRBEG);
15929831Ssam clobber(BIGNUM, SAFEEXPRBEG);
16029831Ssam
16129831Ssam clobber(PLUS, ADDOPS);
16229831Ssam clobber(MINUS, ADDOPS + EBEGOPS);
16329831Ssam
16429831Ssam clobber(LP, EBEGOPS);
16529831Ssam
16629831Ssam clobber(IOR, BOOLOPS);
16729831Ssam clobber(XOR, BOOLOPS);
16829831Ssam clobber(AND, BOOLOPS);
16929831Ssam clobber(ORNOT, BOOLOPS);
17029831Ssam
17129831Ssam clobber(TILDE, MULOPS + EBEGOPS);
17229831Ssam clobber(LSH, MULOPS);
17329831Ssam clobber(RSH, MULOPS);
17429831Ssam clobber(MUL, MULOPS);
17529831Ssam clobber(DIV, MULOPS);
17629831Ssam clobber(REGOP, MULOPS); /* % */
17729831Ssam
17829831Ssam }
17929831Ssam
18029831Ssam /*
18129831Ssam * We keep the current token class in this global variable, so
18229831Ssam * the recursive descent expression analyzers can talk amongst
18329831Ssam * themselves, and so that we may use the macros shift and shift over
18429831Ssam */
18529831Ssam
18629831Ssam extern int yylval; /*the value of the lexical value*/
18729831Ssam extern struct exp *xp; /*the next free expression slot*/
18829831Ssam
18929831Ssam static inttoktype val;
19029831Ssam
19129831Ssam /*
19229831Ssam * return the value the read head is sitting on
19329831Ssam */
exprparse(inval,backexpr)19429831Ssam inttoktype exprparse(inval, backexpr)
19529831Ssam inttoktype inval;
19629831Ssam struct exp **backexpr;
19729831Ssam {
19829831Ssam reg struct exp *lexpr;
19929831Ssam inttoktype op;
20029831Ssam
20129831Ssam val = inval;
20229831Ssam lexpr = boolterm();
20329831Ssam while (INTOKSET(val, ADDOPS)){
20429831Ssam op = val;
20529831Ssam shift;
20629831Ssam lexpr = combine(op, lexpr, boolterm());
20729831Ssam }
20829831Ssam *backexpr = lexpr;
20929831Ssam return(val);
21029831Ssam }
21129831Ssam
boolterm()21229831Ssam struct exp *boolterm()
21329831Ssam {
21429831Ssam reg struct exp *lexpr;
21529831Ssam inttoktype op;
21629831Ssam
21729831Ssam lexpr = term();
21829831Ssam while(INTOKSET(val, BOOLOPS)){
21929831Ssam op = val;
22029831Ssam shift;
22129831Ssam lexpr = combine(op, lexpr, term());
22229831Ssam }
22329831Ssam return(lexpr);
22429831Ssam }
22529831Ssam
term()22629831Ssam struct exp *term()
22729831Ssam {
22829831Ssam reg struct exp *lexpr;
22929831Ssam inttoktype op;
23029831Ssam
23129831Ssam lexpr = factor();
23229831Ssam while(INTOKSET(val, MULOPS)){
23329831Ssam op = val;
23429831Ssam shift;
23529831Ssam lexpr = combine(op, lexpr, factor());
23629831Ssam }
23729831Ssam return(lexpr);
23829831Ssam }
23929831Ssam
factor()24029831Ssam struct exp *factor()
24129831Ssam {
24229831Ssam struct exp *lexpr;
24329831Ssam inttoktype op;
24429831Ssam extern int droppedLP; /*called exprparse after consuming an LP*/
24529831Ssam
24629831Ssam if (val == LP || droppedLP){
24729831Ssam if (droppedLP)
24829831Ssam droppedLP = 0;
24929831Ssam else
25029831Ssam shift; /*the LP*/
25129831Ssam val = exprparse(val, &lexpr);
25229831Ssam if (val != RP)
25329831Ssam yyerror("right parenthesis expected");
25429831Ssam else
25529831Ssam shift;
25629831Ssam } else
25729831Ssam if (INTOKSET(val, YUKKYEXPRBEG)){
25829831Ssam lexpr = yukkyexpr(val, yylval);
25929831Ssam shift;
26029831Ssam }
26129831Ssam else if (INTOKSET(val, SAFEEXPRBEG)){
26229831Ssam lexpr = (struct exp *)yylval;
26329831Ssam shift;
26429831Ssam }
26529831Ssam else if ( (val == TILDE) || (val == MINUS) ){
26629831Ssam op = val;
26729831Ssam shift;
26829831Ssam lexpr = xp++;
26929831Ssam lexpr->e_xtype = XABS;
27029831Ssam lexpr->e_number = Znumber;
27129831Ssam lexpr->e_number.num_tag = TYPL;
27229831Ssam lexpr = combine(op, lexpr, factor());
27329831Ssam } else {
27429831Ssam yyerror("Bad expression syntax");
27529831Ssam lexpr = xp++;
27629831Ssam lexpr->e_xtype = XABS;
27729831Ssam lexpr->e_number = Znumber;
27829831Ssam lexpr->e_number.num_tag = TYPL;
27929831Ssam }
28029831Ssam return(lexpr);
28129831Ssam }
28229831Ssam
yukkyexpr(val,np)28329831Ssam struct exp *yukkyexpr(val, np)
28429831Ssam int val;
28529831Ssam reg int np;
28629831Ssam {
28729831Ssam reg struct exp *locxp;
28829831Ssam extern int exprisname; /*last factor is a name*/
28929831Ssam int off = 0;
29029831Ssam
29129831Ssam exprisname = 0;
29229831Ssam locxp = xp++;
29329831Ssam locxp->e_number = Znumber;
29429831Ssam locxp->e_number.num_tag = TYPL;
29529831Ssam
29629831Ssam switch(val){
29729831Ssam case BFINT:
29829831Ssam yylval = ((struct exp *)np)->e_xvalue;
29929831Ssam if (yylval < 0) {
30029831Ssam yylval = -yylval;
30129831Ssam yylval--;
30229831Ssam off = -1;
30329831Ssam if (lgensym[yylval] == 1)
30429831Ssam yyerror("Reference to undefined local label %db", yylval);
30529831Ssam } else {
30629831Ssam yylval--;
30729831Ssam genref[yylval] = 1;
30829831Ssam }
30929831Ssam (void)sprintf(yytext, "L%d\001%d", yylval, lgensym[yylval] + off);
31029831Ssam yylval = np = (int)*lookup(passno == 1);
31129831Ssam lastnam = (struct symtab *)np;
31229831Ssam /* FALLTHROUGH */
31329831Ssam case NAME:
31431350Ssam exprisname = (int)np;
31529831Ssam locxp->e_xtype = ((struct symtab *)np)->s_type;
31629831Ssam if (( ((struct symtab *)np)->s_type&XTYPE)==XUNDEF) { /*forward*/
31729831Ssam locxp->e_xname = (struct symtab *)np;
31829831Ssam locxp->e_xvalue = 0;
31929831Ssam if (passno==1)
32029831Ssam ((struct symtab *)np)->s_type |= XFORW;
32129831Ssam } else { /*otherwise, just get the value*/
32229831Ssam locxp->e_xvalue = ((struct symtab *)np)->s_value;
32329831Ssam locxp->e_xname = NULL;
32429831Ssam }
32529831Ssam break;
32629831Ssam default:
32729831Ssam yyerror("Internal Error in yukkyexpr");
32829831Ssam /* FALLTHROUGH */
32929831Ssam
33029831Ssam case INSTn:
33129831Ssam case INST0:
33229831Ssam case REG:
33329831Ssam locxp->e_xtype = XABS;
33429831Ssam locxp->e_xvalue = ( (int)np) & 0xFF;
33529831Ssam locxp->e_xloc = 0;
33629831Ssam locxp->e_xname = NULL;
33729831Ssam break;
33829831Ssam }
33929831Ssam
34029831Ssam return(locxp);
34129831Ssam }
34229831Ssam
34329831Ssam /*
34429831Ssam * Print definitions for token kinds
34529831Ssam */
34629831Ssam static char pdirect[] = "directive";
34729831Ssam static char pinstr[] = "instruction";
34829831Ssam static char phunk[] = "lexeme";
34929831Ssam static char psmall[] = "small symbol";
35029831Ssam static char pcntrl[] = "control token";
35129831Ssam
35229831Ssam #define DIRECT pdirect
35329831Ssam #define INSTR pinstr
35429831Ssam #define HUNK phunk
35529831Ssam #define SMALL psmall
35629831Ssam #define CNTRL pcntrl
35729831Ssam
35829831Ssam struct Tok_Desc{
35929831Ssam int tok_which;
36029831Ssam char *tok_kind;
36129831Ssam char *tok_name;
36229831Ssam };
36329831Ssam struct Tok_Desc *tok_name[LASTTOKEN - FIRSTTOKEN + 1];
36429831Ssam
36529831Ssam struct Tok_Desc tok_desc[] = {
36629831Ssam FIRSTTOKEN, DIRECT, "first token",
36729831Ssam
36829831Ssam IBYTE, DIRECT, ".byte",
36929831Ssam IWORD, DIRECT, ".word",
37029831Ssam IINT, DIRECT, ".int",
37129831Ssam ILONG, DIRECT, ".long",
37229831Ssam IQUAD, DIRECT, ".quad",
37329831Ssam IFFLOAT, DIRECT, ".ffloat",
37429831Ssam IDFLOAT, DIRECT, ".dfloat",
37529831Ssam IASCII, DIRECT, ".ascii",
37629831Ssam IASCIZ, DIRECT, ".asciz",
37729831Ssam IFILL, DIRECT, ".fill",
37829831Ssam ISPACE, DIRECT, ".space",
37929831Ssam
38029831Ssam IDATA, DIRECT, ".data",
38129831Ssam ITEXT, DIRECT, ".text",
38229831Ssam IGLOBAL, DIRECT, ".global",
38329831Ssam IALIGN, DIRECT, ".align",
38429831Ssam
38529831Ssam ISET, DIRECT, ".set",
38629831Ssam ICOMM, DIRECT, ".comm",
38729831Ssam ILCOMM, DIRECT, ".lcomm",
38829831Ssam IORG, DIRECT, ".org",
38929831Ssam ILSYM, DIRECT, ".lsym",
39029831Ssam
39129831Ssam ISTAB, DIRECT, ".stab",
39229831Ssam ISTABSTR, DIRECT, ".stabstr",
39329831Ssam ISTABNONE, DIRECT, ".stabnone",
39429831Ssam ISTABDOT, DIRECT, ".stabdot",
39529831Ssam
39629831Ssam IFILE, DIRECT, ".file",
39729831Ssam ILINENO, DIRECT, ".lineno",
39829831Ssam IABORT, DIRECT, ".abort",
39929831Ssam
40029831Ssam IJXXX, INSTR, "jump pseudo",
40129831Ssam INST0, INSTR, "0 argument inst",
40229831Ssam INSTn, INSTR, "n argument inst",
40329831Ssam
40429831Ssam PARSEEOF, CNTRL, "parse end of file",
40529831Ssam ILINESKIP, CNTRL, "skip lines",
40629831Ssam VOID, CNTRL, "void",
40729831Ssam SKIP, CNTRL, "skip",
40829831Ssam NL, CNTRL, "new line",
40929831Ssam SCANEOF, CNTRL, "scanner end of file",
41029831Ssam BADCHAR, CNTRL, "bad character",
41129831Ssam SH, CNTRL, "comment, #",
41229831Ssam
41329831Ssam INT, HUNK, "int",
41429831Ssam BFINT, HUNK, "local label",
41529831Ssam BIGNUM, HUNK, "big number",
41629831Ssam NAME, HUNK, "name",
41729831Ssam STRING, HUNK, "string",
41829831Ssam REG, HUNK, "register specifier",
41929831Ssam
42029831Ssam SIZESPEC, SMALL, "size specifier, [BWLbwl]",
42129831Ssam SIZEQUOTE, SMALL, "sizequote, [^']",
42229831Ssam LITOP, SMALL, "litop",
42329831Ssam
42429831Ssam MP, SMALL, "minus parenthesis, -(",
42529831Ssam REGOP, SMALL, "register operator, %",
42629831Ssam
42729831Ssam SP, SMALL, "space",
42829831Ssam ALPH, SMALL, "alphabetic character, [A-Za-z_]",
42929831Ssam DIG, SMALL, "digit character, [A-Fa-f0-9]",
43029831Ssam
43129831Ssam SQ, SMALL, "single quote, '",
43229831Ssam DQ, SMALL, "double quote, \"",
43329831Ssam
43429831Ssam LSH, SMALL, "arithmetic left shift, <",
43529831Ssam RSH, SMALL, "arithmetic right shift, >",
43629831Ssam XOR, SMALL, "exclusive or, ^",
43729831Ssam
43829831Ssam PLUS, SMALL, "plus, +",
43929831Ssam MINUS, SMALL, "minus, -",
44029831Ssam MUL, SMALL, "multiply, *",
44129831Ssam DIV, SMALL, "divide, /",
44229831Ssam SEMI, SMALL, "semi colon, ;",
44329831Ssam COLON, SMALL, "colon, :",
44429831Ssam IOR, SMALL, "inclusive or, |",
44529831Ssam AND, SMALL, "and, &",
44629831Ssam
44729831Ssam TILDE, SMALL, "one's complement, ~",
44829831Ssam ORNOT, SMALL, "ornot, !",
44929831Ssam CM, SMALL, "comma",
45029831Ssam
45129831Ssam LB, SMALL, "left bracket, [",
45229831Ssam RB, SMALL, "right bracket, ]",
45329831Ssam LP, SMALL, "left parenthesis, (",
45429831Ssam RP, SMALL, "right parentheis, )",
45529831Ssam
45629831Ssam LASTTOKEN, SMALL, "last token",
45729831Ssam };
45829831Ssam /*
45929831Ssam * turn a token type into a string
46029831Ssam */
tok_to_name(token)46129831Ssam char *tok_to_name(token)
46229831Ssam {
46329831Ssam static int fixed = 0;
46429831Ssam static char buf[64];
46529831Ssam static struct Tok_Desc NA = {0, (char *)0, "NOT ASSIGNED"};
46629831Ssam int i;
46729831Ssam
46829831Ssam if (!fixed){
46929831Ssam for (i = FIRSTTOKEN; i <= LASTTOKEN; i++)
47029831Ssam tok_name[i] = &NA;
47129831Ssam for (i = 0; i <= sizeof(tok_desc)/sizeof(struct Tok_Desc); i++){
47229831Ssam tok_name[tok_desc[i].tok_which] = &tok_desc[i];
47329831Ssam }
47429831Ssam fixed = 1;
47529831Ssam }
47629831Ssam if (FIRSTTOKEN <= token && token <= LASTTOKEN){
477*32433Sbostic (void)sprintf(buf, "%s %s", tok_name[token]->tok_kind,
47829831Ssam tok_name[token]->tok_name);
47929831Ssam return(buf);
48029831Ssam } else {
48129831Ssam panic("Unknown token number, %d\n", token);
48229831Ssam /*NOTREACHED*/
48329831Ssam }
48429831Ssam }
485