/* Copyright (c) 1980 Regents of the University of California */ static char sccsid[] = "@(#)asexpr.c 4.2 8/15/80"; #include <stdio.h> #include "as.h" #include "asexpr.h" /* * Tables for combination of operands. */ #define XTXRN 5<<1 /* indexes last row/column when right shifted */ /* * table for + */ 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, }; /* * table for - */ 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) register struct exp *exp1, *exp2; { register e1_type, e2_type; register back_type; lastnam=0; /* kludge for jxxx instructions */ e1_type = exp1->e_xtype&XTYPE; e2_type = exp2->e_xtype&XTYPE; if (exp1->e_xtype==XXTRN+XUNDEF) e1_type = XTXRN; if (exp2->e_xtype==XXTRN+XUNDEF) e2_type = XTXRN; if (passno==1) 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*/ e2_type >>= 1; switch (op) { case PLUS: exp1->e_xvalue += exp2->e_xvalue; back_type = pltab[e1_type][e2_type]; break; case MINUS: exp1->e_xvalue -= exp2->e_xvalue; back_type = mintab[e1_type][e2_type]; break; case IOR: exp1->e_xvalue |= exp2->e_xvalue; goto comm; case XOR: exp1->e_xvalue ^= exp2->e_xvalue; goto comm; case AND: exp1->e_xvalue &= exp2->e_xvalue; goto comm; case ORNOT: exp1->e_xvalue |= ~exp2->e_xvalue; goto comm; case LSH: exp1->e_xvalue <<= exp2->e_xvalue; goto comm; case RSH: exp1->e_xvalue >>= exp2->e_xvalue; goto comm; case TILDE: exp1->e_xvalue |= ~ exp2->e_xvalue; goto comm; case MUL: exp1->e_xvalue *= exp2->e_xvalue; goto comm; case DIV: if (exp2->e_xvalue == 0) yyerror("Divide check"); else exp1->e_xvalue /= exp2->e_xvalue; goto comm; case REGOP: if (exp2->e_xvalue == 0) yyerror("Divide check (modulo)"); else exp1->e_xvalue %= exp2->e_xvalue; goto comm; comm: back_type = othtab[e1_type][e2_type]; break; default: yyerror("Internal error: unknown operator"); } if (e2_type==(XTXRN>>1)) exp1->e_xname = exp2->e_xname; exp1->e_xtype = back_type | ( (exp1->e_xtype|exp2->e_xtype) & (XFORW|XXTRN) ); if (back_type==ERR) yyerror("Relocation error"); return(exp1); } buildtokensets() { #define clobber(val, set) tokensets[(val)] |= (set) clobber(SEMI, LINSTBEGIN); clobber(NL, LINSTBEGIN); clobber(INT, LINSTBEGIN); clobber(NAME, YUKKYEXPRBEG + LINSTBEGIN); clobber(INSTn, YUKKYEXPRBEG); clobber(INST0, YUKKYEXPRBEG); clobber(REG, YUKKYEXPRBEG); clobber(BFINT, YUKKYEXPRBEG); clobber(INT, SAFEEXPRBEG); clobber(FLTNUM, SAFEEXPRBEG); clobber(PLUS, ADDOPS); clobber(MINUS, ADDOPS + EBEGOPS); clobber(LP, EBEGOPS); clobber(IOR, BOOLOPS); clobber(XOR, BOOLOPS); clobber(AND, BOOLOPS); clobber(ORNOT, BOOLOPS); clobber(TILDE, MULOPS + EBEGOPS); clobber(LSH, MULOPS); clobber(RSH, MULOPS); clobber(MUL, MULOPS); clobber(DIV, MULOPS); 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*/ static int val; int exprparse(inval, backexpr) /*return the value the read head is sitting on*/ int inval; struct exp **backexpr; { register struct exp *lexpr; int op; val = inval; lexpr = boolterm(); while (INTOKSET(val, ADDOPS)){ op = val; shift; lexpr = combine(op, lexpr, boolterm()); } *backexpr = lexpr; return(val); } struct exp *boolterm() { register struct exp *lexpr; int op; lexpr = term(); while(INTOKSET(val, BOOLOPS)){ op = val; shift; lexpr = combine(op, lexpr, term()); } return(lexpr); } struct exp *term() { register struct exp *lexpr; int op; lexpr = factor(); while(INTOKSET(val, MULOPS)){ op = val; shift; lexpr = combine(op, lexpr, factor()); } return(lexpr); } struct exp *factor() { struct exp *lexpr; int op; extern int droppedLP; /*called exprparse after consuming an LP*/ if (val == LP || droppedLP){ if (droppedLP) droppedLP = 0; else shift; /*the LP*/ val = exprparse(val, &lexpr); if (val != RP) yyerror("right parenthesis expected"); else shift; } else if (INTOKSET(val, YUKKYEXPRBEG)){ lexpr = yukkyexpr(val, yylval); shift; } else if (INTOKSET(val, SAFEEXPRBEG)){ lexpr = (struct exp *)yylval; shift; } else if ( (val == TILDE) || (val == MINUS) ){ op = val; shift; lexpr = xp++; lexpr->e_xtype = XABS; lexpr->e_xvalue = 0; lexpr = combine(op, lexpr, factor()); } else { yyerror("Bad expression syntax"); lexpr = xp++; lexpr->e_xtype = XABS; lexpr->e_xvalue = 0; } return(lexpr); } struct exp *yukkyexpr(val, np) int val; register np; { register struct exp *locxp; extern int exprisname; /*last factor is a name*/ extern struct symtab *exprxname; /*another stab in the back*/ exprisname = 0; locxp = xp++; if (val == NAME || val == BFINT){ if (val == BFINT) { int off = 0; yylval = ((struct exp *)np)->e_xvalue; if (yylval < 0) { yylval = -yylval; yylval--; off = -1; if (lgensym[yylval] == 1) yyerror("Reference to undefined local label %db", yylval); } else { yylval--; genref[yylval] = 1; } sprintf(yytext, "L%d\001%d", yylval, lgensym[yylval] + off); yylval = np = (int)*lookup(passno == 1); lastnam = (struct symtab *)np; } exprisname++; locxp->e_xtype = ((struct symtab *)np)->s_type; if (( ((struct symtab *)np)->s_type&XTYPE)==XUNDEF) { /*forward*/ locxp->e_xname = (struct symtab *)np; locxp->e_xvalue = 0; if (passno==1) ((struct symtab *)np)->s_type |= XFORW; } else { /*otherwise, just get the value*/ exprxname = (struct symtab *)np; locxp->e_xvalue = ((struct symtab *)np)->s_value; locxp->e_xname = NULL; } } else { /*INSTn or INST0 or REG*/ locxp->e_xtype = XABS; locxp->e_xvalue = ( (int)np) & 0xFF; locxp->e_xloc = 0; locxp->e_xname = NULL; } return(locxp); } #ifdef DEBUG char *tok_name[LASTTOKEN - FIRSTTOKEN + 1]; struct Tok_Desc{ int tok_which; char *tok_name; } tok_desc[] = { FIRSTTOKEN, "firsttoken", /* 0 */ ISPACE, "ispace", /* 1 */ IBYTE, "ibyte", /* 2 */ IWORD, "iword", /* 3 */ IINT, "iint", /* 4 */ ILONG, "ilong", /* 5 */ IDATA, "idata", /* 6 */ IGLOBAL, "iglobal", /* 7 */ ISET, "iset", /* 8 */ ITEXT, "itext", /* 9 */ ICOMM, "icomm", /* 10 */ ILCOMM, "ilcomm", /* 11 */ IFLOAT, "ifloat", /* 12 */ IDOUBLE, "idouble", /* 13 */ IORG, "iorg", /* 14 */ IASCII, "iascii", /* 15 */ IASCIZ, "iasciz", /* 16 */ ILSYM, "ilsym", /* 17 */ IFILE, "ifile", /* 18 */ ILINENO, "ilineno", /* 19 */ IABORT, "iabort", /* 20 */ ISTAB, "istab", /* 23 */ ISTABSTR, "istabstr", /* 24 */ ISTABNONE, "istabnone", /* 25 */ ISTABDOT, "istabdot", /* 26 */ IJXXX, "ijxxx", /* 27 */ IALIGN, "ialign", /* 28 */ INST0, "inst0", /* 29 */ INSTn, "instn", /* 30 */ BFINT, "bfint", /* 31 */ PARSEEOF, "parseeof", /* 32 */ ILINESKIP, "ilineskip", /* 33 */ VOID, "void", /* 34 */ SKIP, "skip", /* 35 */ INT, "int", /* 36 */ FLTNUM, "fltnum", /* 37 */ NAME, "name", /* 38 */ STRING, "string", /* 39 */ QUAD, "quad", /* 40 */ SIZESPEC, "sizespec", /* 41 */ REG, "reg", /* 42 */ MUL, "mul", /* 43 */ LITOP, "litop", /* 44 */ LP, "lp", /* 45 */ MP, "mp", /* 46 */ NEEDSBUF, "needsbuf", /* 48 */ REGOP, "regop", /* 49 */ NL, "nl", /* 50 */ SCANEOF, "scaneof", /* 51 */ BADCHAR, "badchar", /* 52 */ SP, "sp", /* 53 */ ALPH, "alph", /* 54 */ DIG, "dig", /* 55 */ SQ, "sq", /* 56 */ DQ, "dq", /* 57 */ SH, "sh", /* 58 */ LSH, "lsh", /* 59 */ RSH, "rsh", /* 60 */ MINUS, "minus", /* 61 */ SIZEQUOTE, "sizequote", /* 62 */ XOR, "xor", /* 64 */ DIV, "div", /* 65 */ SEMI, "semi", /* 66 */ COLON, "colon", /* 67 */ PLUS, "plus", /* 68 */ IOR, "ior", /* 69 */ AND, "and", /* 70 */ TILDE, "tilde", /* 71 */ ORNOT, "ornot", /* 72 */ CM, "cm", /* 73 */ LB, "lb", /* 74 */ RB, "rb", /* 75 */ RP, "rp", /* 76 */ LASTTOKEN, "lasttoken" /* 80 */ }; /* * turn a token type into a string */ static int fixed = 0; char *tok_to_name(token) { if (!fixed){ int i; for (i = FIRSTTOKEN; i <= LASTTOKEN; i++) tok_name[i] = "NOT ASSIGNED"; for (i = FIRSTTOKEN; i <= sizeof(tok_desc)/sizeof(struct Tok_Desc); i++){ tok_name[tok_desc[i].tok_which] = tok_desc[i].tok_name; } fixed = 1; } if (FIRSTTOKEN <= token && token <= LASTTOKEN) return(tok_name[token]); else panic("Unknown token number, %d\n", token); /*NOTREACHED*/ } #endif DEBUG