15823Srrh /*
219822Sdist * Copyright (c) 1982 Regents of the University of California.
319822Sdist * All rights reserved. The Berkeley software License Agreement
419822Sdist * specifies the terms and conditions for redistribution.
55823Srrh */
619822Sdist
75823Srrh #ifndef lint
8*32430Sbostic static char sccsid[] = "@(#)asexpr.c 5.4 (Berkeley) 10/22/87";
919822Sdist #endif not lint
105823Srrh
11593Sbill #include <stdio.h>
12593Sbill #include "as.h"
135823Srrh #include "asscan.h"
14593Sbill #include "asexpr.h"
15593Sbill
16593Sbill /*
17593Sbill * Tables for combination of operands.
18593Sbill */
19593Sbill #define XTXRN 5<<1 /* indexes last row/column when right shifted */
20593Sbill
21593Sbill /*
22593Sbill * table for +
23593Sbill */
24593Sbill readonly char pltab[6][6] = {
25593Sbill /* UND ABS TXT DAT BSS EXT */
26593Sbill
27593Sbill /*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF,
28593Sbill /*ABS*/ XUNDEF, XABS, XTEXT, XDATA, XBSS, XXTRN,
29593Sbill /*TXT*/ XUNDEF, XTEXT, ERR, ERR, ERR, ERR,
30593Sbill /*DAT*/ XUNDEF, XDATA, ERR, ERR, ERR, ERR,
31593Sbill /*BSS*/ XUNDEF, XBSS, ERR, ERR, ERR, ERR,
32593Sbill /*EXT*/ XUNDEF, XXTRN, ERR, ERR, ERR, ERR,
33593Sbill };
34593Sbill
35593Sbill /*
36593Sbill * table for -
37593Sbill */
38593Sbill readonly char mintab[6][6] = {
39593Sbill /* UND ABS TXT DAT BSS EXT */
40593Sbill
41593Sbill /*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF,
42593Sbill /*ABS*/ XUNDEF, XABS, ERR, ERR, ERR, ERR,
43593Sbill /*TXT*/ XUNDEF, XTEXT, XABS, ERR, ERR, ERR,
44593Sbill /*DAT*/ XUNDEF, XDATA, ERR, XABS, ERR, ERR,
45593Sbill /*BSS*/ XUNDEF, XBSS, ERR, ERR, XABS, ERR,
46593Sbill /*EXT*/ XUNDEF, XXTRN, ERR, ERR, ERR, ERR,
47593Sbill };
48593Sbill
49593Sbill /*
50593Sbill * table for other operators
51593Sbill */
52593Sbill readonly char othtab[6][6] = {
53593Sbill /* UND ABS TXT DAT BSS EXT */
54593Sbill
55593Sbill /*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF,
56593Sbill /*ABS*/ XUNDEF, XABS, ERR, ERR, ERR, ERR,
57593Sbill /*TXT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR,
58593Sbill /*DAT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR,
59593Sbill /*BSS*/ XUNDEF, ERR, ERR, ERR, ERR, ERR,
60593Sbill /*EXT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR,
61593Sbill };
62593Sbill
combine(op,exp1,exp2)635823Srrh struct exp *combine(op, exp1, exp2)
645823Srrh reg struct exp *exp1, *exp2;
65593Sbill {
665823Srrh reg e1_type, e2_type;
675823Srrh reg back_type;
685823Srrh char *btype = "The assembler can only do arithmetic on 1,2, or 4 byte integers";
69593Sbill
70593Sbill lastnam=0; /* kludge for jxxx instructions */
71593Sbill
72630Shenry e1_type = exp1->e_xtype&XTYPE;
73630Shenry e2_type = exp2->e_xtype&XTYPE;
74593Sbill
75630Shenry if (exp1->e_xtype==XXTRN+XUNDEF)
76593Sbill e1_type = XTXRN;
77630Shenry if (exp2->e_xtype==XXTRN+XUNDEF)
78593Sbill e2_type = XTXRN;
79593Sbill if (passno==1)
80630Shenry if (exp1->e_xloc!=exp2->e_xloc && e1_type==e2_type)
81593Sbill e1_type = e2_type = XTXRN; /* error on != loc ctrs */
82593Sbill e1_type >>= 1; /*dispose of the external (XXTRN) bit*/
83593Sbill e2_type >>= 1;
84593Sbill
855823Srrh switch(exp1->e_number.num_tag){
865823Srrh case TYPB:
875823Srrh case TYPW:
885823Srrh case TYPL:
895823Srrh break;
905823Srrh default:
915823Srrh yyerror(btype);
925823Srrh return(exp1);
935823Srrh }
945823Srrh switch(exp2->e_number.num_tag){
955823Srrh case TYPB:
965823Srrh case TYPW:
975823Srrh case TYPL:
985823Srrh break;
995823Srrh default:
1005823Srrh yyerror(btype);
1015823Srrh return(exp1);
1025823Srrh }
1035823Srrh switch (op){
104593Sbill case PLUS:
105630Shenry exp1->e_xvalue += exp2->e_xvalue;
106630Shenry back_type = pltab[e1_type][e2_type];
107593Sbill break;
108593Sbill case MINUS:
109630Shenry exp1->e_xvalue -= exp2->e_xvalue;
110630Shenry back_type = mintab[e1_type][e2_type];
111593Sbill break;
112593Sbill case IOR:
113630Shenry exp1->e_xvalue |= exp2->e_xvalue;
114593Sbill goto comm;
115593Sbill case XOR:
116630Shenry exp1->e_xvalue ^= exp2->e_xvalue;
117593Sbill goto comm;
118593Sbill case AND:
119630Shenry exp1->e_xvalue &= exp2->e_xvalue;
120593Sbill goto comm;
121593Sbill case ORNOT:
122630Shenry exp1->e_xvalue |= ~exp2->e_xvalue;
123593Sbill goto comm;
124593Sbill case LSH:
125630Shenry exp1->e_xvalue <<= exp2->e_xvalue;
126593Sbill goto comm;
127593Sbill case RSH:
128630Shenry exp1->e_xvalue >>= exp2->e_xvalue;
129593Sbill goto comm;
130593Sbill case TILDE:
131630Shenry exp1->e_xvalue |= ~ exp2->e_xvalue;
132593Sbill goto comm;
133593Sbill case MUL:
134630Shenry exp1->e_xvalue *= exp2->e_xvalue;
135593Sbill goto comm;
136593Sbill case DIV:
137630Shenry if (exp2->e_xvalue == 0)
138593Sbill yyerror("Divide check");
139593Sbill else
140630Shenry exp1->e_xvalue /= exp2->e_xvalue;
141593Sbill goto comm;
142593Sbill case REGOP:
143630Shenry if (exp2->e_xvalue == 0)
144593Sbill yyerror("Divide check (modulo)");
145593Sbill else
146630Shenry exp1->e_xvalue %= exp2->e_xvalue;
147593Sbill goto comm;
148593Sbill
149593Sbill comm:
150630Shenry back_type = othtab[e1_type][e2_type];
151593Sbill break;
152593Sbill default:
153593Sbill yyerror("Internal error: unknown operator");
154593Sbill }
155593Sbill
156593Sbill if (e2_type==(XTXRN>>1))
157630Shenry exp1->e_xname = exp2->e_xname;
158630Shenry exp1->e_xtype = back_type | (
159630Shenry (exp1->e_xtype|exp2->e_xtype) & (XFORW|XXTRN) );
160630Shenry if (back_type==ERR)
161593Sbill yyerror("Relocation error");
162593Sbill return(exp1);
163593Sbill }
164593Sbill
buildtokensets()165593Sbill buildtokensets()
166593Sbill {
167593Sbill #define clobber(val, set) tokensets[(val)] |= (set)
168593Sbill
169593Sbill clobber(SEMI, LINSTBEGIN);
170593Sbill clobber(NL, LINSTBEGIN);
171593Sbill clobber(INT, LINSTBEGIN);
172593Sbill
173593Sbill clobber(NAME, YUKKYEXPRBEG + LINSTBEGIN);
174593Sbill clobber(INSTn, YUKKYEXPRBEG);
175593Sbill clobber(INST0, YUKKYEXPRBEG);
176593Sbill clobber(REG, YUKKYEXPRBEG);
177593Sbill clobber(BFINT, YUKKYEXPRBEG);
178593Sbill
179593Sbill clobber(INT, SAFEEXPRBEG);
1805823Srrh clobber(BIGNUM, SAFEEXPRBEG);
181593Sbill
182593Sbill clobber(PLUS, ADDOPS);
183593Sbill clobber(MINUS, ADDOPS + EBEGOPS);
184593Sbill
185593Sbill clobber(LP, EBEGOPS);
186593Sbill
187593Sbill clobber(IOR, BOOLOPS);
188593Sbill clobber(XOR, BOOLOPS);
189593Sbill clobber(AND, BOOLOPS);
190593Sbill clobber(ORNOT, BOOLOPS);
191593Sbill
192593Sbill clobber(TILDE, MULOPS + EBEGOPS);
193593Sbill clobber(LSH, MULOPS);
194593Sbill clobber(RSH, MULOPS);
195593Sbill clobber(MUL, MULOPS);
196593Sbill clobber(DIV, MULOPS);
197593Sbill clobber(REGOP, MULOPS); /* % */
198593Sbill
199593Sbill }
200593Sbill
201593Sbill /*
202593Sbill * We keep the current token class in this global variable, so
203593Sbill * the recursive descent expression analyzers can talk amongst
204593Sbill * themselves, and so that we may use the macros shift and shift over
205593Sbill */
206593Sbill
207593Sbill extern int yylval; /*the value of the lexical value*/
208593Sbill extern struct exp *xp; /*the next free expression slot*/
209593Sbill
2105823Srrh static inttoktype val;
2115823Srrh
2125823Srrh /*
2135823Srrh * return the value the read head is sitting on
2145823Srrh */
exprparse(inval,backexpr)2155823Srrh inttoktype exprparse(inval, backexpr)
2165823Srrh inttoktype inval;
217593Sbill struct exp **backexpr;
218593Sbill {
2195823Srrh reg struct exp *lexpr;
2205823Srrh inttoktype op;
221593Sbill
222593Sbill val = inval;
223593Sbill lexpr = boolterm();
224593Sbill while (INTOKSET(val, ADDOPS)){
225593Sbill op = val;
226593Sbill shift;
227593Sbill lexpr = combine(op, lexpr, boolterm());
228593Sbill }
229593Sbill *backexpr = lexpr;
230593Sbill return(val);
231593Sbill }
232593Sbill
boolterm()233593Sbill struct exp *boolterm()
234593Sbill {
2355823Srrh reg struct exp *lexpr;
2365823Srrh inttoktype op;
237593Sbill
238593Sbill lexpr = term();
239593Sbill while(INTOKSET(val, BOOLOPS)){
240593Sbill op = val;
241593Sbill shift;
242593Sbill lexpr = combine(op, lexpr, term());
243593Sbill }
244593Sbill return(lexpr);
245593Sbill }
246593Sbill
term()247593Sbill struct exp *term()
248593Sbill {
2495823Srrh reg struct exp *lexpr;
2505823Srrh inttoktype op;
251593Sbill
252593Sbill lexpr = factor();
253593Sbill while(INTOKSET(val, MULOPS)){
254593Sbill op = val;
255593Sbill shift;
256593Sbill lexpr = combine(op, lexpr, factor());
257593Sbill }
258593Sbill return(lexpr);
259593Sbill }
260593Sbill
factor()261593Sbill struct exp *factor()
262593Sbill {
263593Sbill struct exp *lexpr;
2645823Srrh inttoktype op;
265593Sbill extern int droppedLP; /*called exprparse after consuming an LP*/
266593Sbill
267593Sbill if (val == LP || droppedLP){
268593Sbill if (droppedLP)
269593Sbill droppedLP = 0;
270593Sbill else
271593Sbill shift; /*the LP*/
272593Sbill val = exprparse(val, &lexpr);
273593Sbill if (val != RP)
274593Sbill yyerror("right parenthesis expected");
275593Sbill else
276593Sbill shift;
277593Sbill } else
278593Sbill if (INTOKSET(val, YUKKYEXPRBEG)){
279593Sbill lexpr = yukkyexpr(val, yylval);
280593Sbill shift;
281593Sbill }
282593Sbill else if (INTOKSET(val, SAFEEXPRBEG)){
283593Sbill lexpr = (struct exp *)yylval;
284593Sbill shift;
285593Sbill }
286593Sbill else if ( (val == TILDE) || (val == MINUS) ){
287593Sbill op = val;
288593Sbill shift;
289593Sbill lexpr = xp++;
290630Shenry lexpr->e_xtype = XABS;
2915823Srrh lexpr->e_number = Znumber;
2925823Srrh lexpr->e_number.num_tag = TYPL;
293593Sbill lexpr = combine(op, lexpr, factor());
2945823Srrh } else {
295593Sbill yyerror("Bad expression syntax");
296593Sbill lexpr = xp++;
297630Shenry lexpr->e_xtype = XABS;
2985823Srrh lexpr->e_number = Znumber;
2995823Srrh lexpr->e_number.num_tag = TYPL;
300593Sbill }
301593Sbill return(lexpr);
302593Sbill }
303593Sbill
yukkyexpr(val,np)304593Sbill struct exp *yukkyexpr(val, np)
305593Sbill int val;
3065823Srrh reg np;
307593Sbill {
3085823Srrh reg struct exp *locxp;
3095823Srrh extern int exprisname; /*last factor is a name*/
3105823Srrh int off = 0;
311593Sbill
312593Sbill exprisname = 0;
313593Sbill locxp = xp++;
3145823Srrh locxp->e_number = Znumber;
3155823Srrh locxp->e_number.num_tag = TYPL;
3165823Srrh
3175823Srrh switch(val){
3185823Srrh case BFINT:
3195823Srrh yylval = ((struct exp *)np)->e_xvalue;
3205823Srrh if (yylval < 0) {
3215823Srrh yylval = -yylval;
3225823Srrh yylval--;
3235823Srrh off = -1;
3245823Srrh if (lgensym[yylval] == 1)
3255823Srrh yyerror("Reference to undefined local label %db", yylval);
3265823Srrh } else {
3275823Srrh yylval--;
3285823Srrh genref[yylval] = 1;
329593Sbill }
3305823Srrh (void)sprintf(yytext, "L%d\001%d", yylval, lgensym[yylval] + off);
3315823Srrh yylval = np = (int)*lookup(passno == 1);
3325823Srrh lastnam = (struct symtab *)np;
3335823Srrh /* FALLTHROUGH */
3345823Srrh case NAME:
33530098Sdonn exprisname = (int) np;
336630Shenry locxp->e_xtype = ((struct symtab *)np)->s_type;
337630Shenry if (( ((struct symtab *)np)->s_type&XTYPE)==XUNDEF) { /*forward*/
338630Shenry locxp->e_xname = (struct symtab *)np;
339630Shenry locxp->e_xvalue = 0;
340593Sbill if (passno==1)
341630Shenry ((struct symtab *)np)->s_type |= XFORW;
342593Sbill } else { /*otherwise, just get the value*/
343630Shenry locxp->e_xvalue = ((struct symtab *)np)->s_value;
344630Shenry locxp->e_xname = NULL;
345593Sbill }
3465823Srrh break;
3475823Srrh default:
3485823Srrh yyerror("Internal Error in yukkyexpr");
3495823Srrh /* FALLTHROUGH */
3505823Srrh
3515823Srrh case INSTn:
3525823Srrh case INST0:
3535823Srrh case REG:
354630Shenry locxp->e_xtype = XABS;
355630Shenry locxp->e_xvalue = ( (int)np) & 0xFF;
356630Shenry locxp->e_xloc = 0;
357630Shenry locxp->e_xname = NULL;
3585823Srrh break;
359593Sbill }
360593Sbill
361593Sbill return(locxp);
362593Sbill }
363593Sbill
36412944Srrh /*
36512944Srrh * Print definitions for token kinds
36612944Srrh */
36712944Srrh static char pdirect[] = "directive";
36812944Srrh static char pinstr[] = "instruction";
36912944Srrh static char phunk[] = "lexeme";
37012944Srrh static char psmall[] = "small symbol";
37112944Srrh static char pcntrl[] = "control token";
372593Sbill
37312944Srrh #define DIRECT pdirect
37412944Srrh #define INSTR pinstr
37512944Srrh #define HUNK phunk
37612944Srrh #define SMALL psmall
37712944Srrh #define CNTRL pcntrl
37812944Srrh
379593Sbill struct Tok_Desc{
380593Sbill int tok_which;
38112944Srrh char *tok_kind;
382593Sbill char *tok_name;
383593Sbill };
38412944Srrh struct Tok_Desc *tok_name[LASTTOKEN - FIRSTTOKEN + 1];
38512944Srrh
38612944Srrh struct Tok_Desc tok_desc[] = {
38712944Srrh FIRSTTOKEN, DIRECT, "first token",
38812944Srrh
38912944Srrh IBYTE, DIRECT, ".byte",
39012944Srrh IWORD, DIRECT, ".word",
39112944Srrh IINT, DIRECT, ".int",
39212944Srrh ILONG, DIRECT, ".long",
39312944Srrh IQUAD, DIRECT, ".quad",
39412944Srrh IOCTA, DIRECT, ".octa",
39512944Srrh IFFLOAT, DIRECT, ".ffloat",
39612944Srrh IDFLOAT, DIRECT, ".dfloat",
39712944Srrh IGFLOAT, DIRECT, ".gfloat",
39812944Srrh IHFLOAT, DIRECT, ".hfloat",
39912944Srrh IASCII, DIRECT, ".ascii",
40012944Srrh IASCIZ, DIRECT, ".asciz",
40112944Srrh IFILL, DIRECT, ".fill",
40212944Srrh ISPACE, DIRECT, ".space",
40312944Srrh
40412944Srrh IDATA, DIRECT, ".data",
40512944Srrh ITEXT, DIRECT, ".text",
40612944Srrh IGLOBAL, DIRECT, ".global",
40712944Srrh IALIGN, DIRECT, ".align",
40812944Srrh
40912944Srrh ISET, DIRECT, ".set",
41012944Srrh ICOMM, DIRECT, ".comm",
41112944Srrh ILCOMM, DIRECT, ".lcomm",
41212944Srrh IORG, DIRECT, ".org",
41312944Srrh ILSYM, DIRECT, ".lsym",
41412944Srrh
41512944Srrh ISTAB, DIRECT, ".stab",
41612944Srrh ISTABSTR, DIRECT, ".stabstr",
41712944Srrh ISTABNONE, DIRECT, ".stabnone",
41812944Srrh ISTABDOT, DIRECT, ".stabdot",
41912944Srrh
42012944Srrh IFILE, DIRECT, ".file",
42112944Srrh ILINENO, DIRECT, ".lineno",
42212944Srrh IABORT, DIRECT, ".abort",
42312944Srrh
42412944Srrh IJXXX, INSTR, "jump pseudo",
42512944Srrh INST0, INSTR, "0 argument inst",
42612944Srrh INSTn, INSTR, "n argument inst",
42712944Srrh
42812944Srrh PARSEEOF, CNTRL, "parse end of file",
42912944Srrh ILINESKIP, CNTRL, "skip lines",
43012944Srrh VOID, CNTRL, "void",
43112944Srrh SKIP, CNTRL, "skip",
43212944Srrh NL, CNTRL, "new line",
43312944Srrh SCANEOF, CNTRL, "scanner end of file",
43412944Srrh BADCHAR, CNTRL, "bad character",
43512944Srrh SH, CNTRL, "comment, #",
43612944Srrh
43712944Srrh INT, HUNK, "int",
43812944Srrh BFINT, HUNK, "local label",
43912944Srrh BIGNUM, HUNK, "big number",
44012944Srrh NAME, HUNK, "name",
44112944Srrh STRING, HUNK, "string",
44212944Srrh REG, HUNK, "register specifier",
44312944Srrh
44412944Srrh SIZESPEC, SMALL, "size specifier, [BWLbwl]",
44512944Srrh SIZEQUOTE, SMALL, "sizequote, [^']",
44612944Srrh LITOP, SMALL, "litop",
44712944Srrh
44812944Srrh MP, SMALL, "minus parenthesis, -(",
44912944Srrh REGOP, SMALL, "register operator, %",
45012944Srrh
45112944Srrh SP, SMALL, "space",
45212944Srrh ALPH, SMALL, "alphabetic character, [A-Za-z_]",
45312944Srrh DIG, SMALL, "digit character, [A-Fa-f0-9]",
45412944Srrh
45512944Srrh SQ, SMALL, "single quote, '",
45612944Srrh DQ, SMALL, "double quote, \"",
45712944Srrh
45812944Srrh LSH, SMALL, "arithmetic left shift, <",
45912944Srrh RSH, SMALL, "arithmetic right shift, >",
46012944Srrh XOR, SMALL, "exclusive or, ^",
46112944Srrh
46212944Srrh PLUS, SMALL, "plus, +",
46312944Srrh MINUS, SMALL, "minus, -",
46412944Srrh MUL, SMALL, "multiply, *",
46512944Srrh DIV, SMALL, "divide, /",
46612944Srrh SEMI, SMALL, "semi colon, ;",
46712944Srrh COLON, SMALL, "colon, :",
46812944Srrh IOR, SMALL, "inclusive or, |",
46912944Srrh AND, SMALL, "and, &",
47012944Srrh
47112944Srrh TILDE, SMALL, "one's complement, ~",
47212944Srrh ORNOT, SMALL, "ornot, !",
47312944Srrh CM, SMALL, "comma",
47412944Srrh
47512944Srrh LB, SMALL, "left bracket, [",
47612944Srrh RB, SMALL, "right bracket, ]",
47712944Srrh LP, SMALL, "left parenthesis, (",
47812944Srrh RP, SMALL, "right parentheis, )",
47912944Srrh
48012944Srrh LASTTOKEN, SMALL, "last token",
48112944Srrh };
482593Sbill /*
483593Sbill * turn a token type into a string
484593Sbill */
tok_to_name(token)485593Sbill char *tok_to_name(token)
486593Sbill {
4875823Srrh static int fixed = 0;
48812944Srrh static char buf[64];
48912944Srrh static struct Tok_Desc NA = {0, (char *)0, "NOT ASSIGNED"};
49012944Srrh int i;
49112944Srrh char *cp;
4925823Srrh
493593Sbill if (!fixed){
494593Sbill for (i = FIRSTTOKEN; i <= LASTTOKEN; i++)
49512944Srrh tok_name[i] = &NA;
49612944Srrh for (i = 0; i <= sizeof(tok_desc)/sizeof(struct Tok_Desc); i++){
49712944Srrh tok_name[tok_desc[i].tok_which] = &tok_desc[i];
498593Sbill }
499593Sbill fixed = 1;
500593Sbill }
50112944Srrh if (FIRSTTOKEN <= token && token <= LASTTOKEN){
502*32430Sbostic (void)sprintf(buf, "%s %s", tok_name[token]->tok_kind,
50312944Srrh tok_name[token]->tok_name);
50412944Srrh return(buf);
50512944Srrh } else {
506593Sbill panic("Unknown token number, %d\n", token);
50712944Srrh /*NOTREACHED*/
50812944Srrh }
509593Sbill }
510