4 * (C) Copyright 1989-1995
19 * The module asexpr.c contains the routines to evaluate
20 * arithmetic/numerical expressions. The functions in
21 * asexpr.c perform a recursive evaluation of the arithmetic
22 * expression read from the assembler-source text line.
23 * The expression may include binary/unary operators, brackets,
24 * symbols, labels, and constants in hexadecimal, decimal, octal
25 * and binary. Arithmetic operations are prioritized and
26 * evaluated by normal arithmetic conventions.
28 * asexpr.c contains the following functions:
37 * asexpr.c contains no local/static variables
40 /*)Function VOID expr(esp, n)
42 * expr * esp pointer to an expr structure
43 * int n a firewall priority; all top
44 * level calls (from the user)
45 * should be made with n set to 0.
47 * The function expr() evaluates an expression and
48 * stores its value and relocation information into
49 * the expr structure supplied by the user.
52 * int c current assembler-source
54 * int p current operator priority
55 * area * ap pointer to an area structure
56 * exp re internal expr structure
59 * char ctype[] array of character types, one per
63 * VOID abscheck() asexpr.c
64 * VOID clrexpr() asexpr.c
65 * VOID expr() asexpr.c
67 * int oprio() asexpr.c
68 * VOID qerr() assubr.c
69 * VOID rerr() assubr.c
70 * VOID term() asexpr.c
71 * VOID unget() aslex.c
75 * An expression is evaluated modifying the user supplied
76 * expr structure, a sym structure maybe created for an
77 * undefined symbol, and the parse of the expression may
78 * terminate if a 'q' error occurs.
82 expr(register struct expr *esp, int n)
89 while (ctype[c = getnb()] & BINOP) {
91 * Handle binary operators + - * / & | % ^ << >>
93 if ((p = oprio(c)) <= n)
95 if ((c == '>' || c == '<') && c != get())
99 esp->e_rlcf |= re.e_rlcf;
102 * esp + re, at least one must be absolute
104 if (esp->e_base.e_ap == NULL) {
106 * esp is absolute (constant),
109 esp->e_base.e_ap = re.e_base.e_ap;
111 if (re.e_base.e_ap) {
113 * re should be absolute (constant)
117 if (esp->e_flag && re.e_flag)
121 esp->e_addr += re.e_addr;
127 if ((ap = re.e_base.e_ap) != NULL) {
128 if (esp->e_base.e_ap == ap) {
129 esp->e_base.e_ap = NULL;
136 esp->e_addr -= re.e_addr;
139 * Both operands (esp and re) must be constants
141 /* SD :- moved the abscheck to each case
142 case and change the right shift operator.. if
143 right shift by 8 bits of a relocatable address then
144 the user wants the higher order byte. set the R_MSB
145 for the expression */
151 esp->e_addr *= re.e_addr;
157 esp->e_addr /= re.e_addr;
163 esp->e_addr &= re.e_addr;
169 esp->e_addr |= re.e_addr;
175 esp->e_addr %= re.e_addr;
181 esp->e_addr ^= re.e_addr;
187 esp->e_addr <<= re.e_addr;
193 /* if the left is a relative address &
194 the right side is == 8 then */
195 if (esp->e_base.e_ap && re.e_addr == 8) {
196 esp->e_rlcf |= R_MSB ;
199 else if (esp->e_base.e_ap && re.e_addr == 16)
203 esp->e_rlcf |= R_HIB;
209 // "(expr >> 16) is only meaningful in "
210 // ".flat24 mode.\n");
216 /* else continue with the normal processing */
218 esp->e_addr >>= re.e_addr;
230 /*)Function Addr_T absexpr()
232 * The function absexpr() evaluates an expression, verifies it
233 * is absolute (i.e. not position dependent or relocatable), and
237 * expr e expr structure
243 * VOID abscheck() asexpr.c
244 * VOID clrexpr() asexpr.c
245 * VOID expr() asexpr.c
248 * If the expression is not absolute then
249 * a 'r' error is reported.
263 /*)Function VOID term(esp)
265 * expr * esp pointer to an expr structure
267 * The function term() evaluates a single constant
268 * or symbol value prefaced by any unary operator
269 * ( +, -, ~, ', ", >, or < ). This routine is also
270 * responsible for setting the relocation type to symbol
271 * based (e.flag != 0) on global references.
274 * int c current character
275 * char id[] symbol name
276 * char * jp pointer to assembler-source text
277 * int n constant evaluation running sum
278 * int r current evaluation radix
279 * sym * sp pointer to a sym structure
280 * tsym * tp pointer to a tsym structure
281 * int v current digit evaluation
284 * char ctype[] array of character types, one per
286 * sym * symp pointer to a symbol structure
289 * VOID abscheck() asexpr.c
290 * int digit() asexpr.c
291 * VOID err() assubr.c
292 * VOID expr() asexpr.c
293 * int is_abs() asexpr.c
295 * VOID getid() aslex.c
296 * int getmap() aslex.c
297 * int getnb() aslex.c
298 * sym * lookup() assym.c
299 * VOID qerr() assubr.c
300 * VOID unget() aslex.c
303 * An arithmetic term is evaluated, a symbol structure
304 * may be created, term evaluation may be terminated
309 term(register struct expr *esp)
320 * Discard the unary '+' at this point and
321 * also any reference to numerical arguments
322 * associated with the '#' prefix.
324 while (c == '+' || c == '#') { c = getnb(); }
326 * Evaluate all binary operators
327 * by recursively calling expr().
331 if (getnb() != RTTERM)
338 esp->e_addr = 0-esp->e_addr;
344 esp->e_addr = ~esp->e_addr;
348 esp->e_mode = S_USER;
349 esp->e_addr = getmap(-1)&0377;
353 esp->e_mode = S_USER;
355 esp->e_addr = (getmap(-1)&0377)<<8;
356 esp->e_addr |= (getmap(-1)&0377);
358 esp->e_addr = (getmap(-1)&0377);
359 esp->e_addr |= (getmap(-1)&0377)<<8;
363 if (c == '>' || c == '<') {
367 * evaluate msb/lsb directly
375 * let linker perform msb/lsb, lsb is default
377 esp->e_rlcf |= R_BYT2;
379 esp->e_rlcf |= R_MSB;
384 * Evaluate digit sequences as local symbols
385 * if followed by a '$' or as constants.
387 if (ctype[c] & DIGIT) {
388 esp->e_mode = S_USER;
390 while (ctype[(int)*jp] & RAD10) {
395 while ((v = digit(c, 10)) >= 0) {
401 if (n == tp->t_num) {
402 esp->e_base.e_ap = tp->t_area;
403 esp->e_addr = tp->t_addr;
444 while ((v = digit(c, r)) >= 0) {
453 * Evaluate '$' sequences as a temporary radix
454 * if followed by a '%', '&', '#', or '$'.
458 if (c == '%' || c == '&' || c == '#' || c == '$') {
477 while ((v = digit(c, r)) >= 0) {
482 esp->e_mode = S_USER;
490 * Evaluate symbols and labels
492 if (ctype[c] & LETTER) {
493 esp->e_mode = S_USER;
496 if (sp->s_type == S_NEW) {
498 if (sp->s_flag&S_GBL) {
500 esp->e_base.e_sp = sp;
505 esp->e_mode = sp->s_type;
506 esp->e_addr = sp->s_addr;
507 esp->e_base.e_ap = sp->s_area;
517 /*)Function int digit(c, r)
519 * int c digit character
520 * int r current radix
522 * The function digit() returns the value of c
523 * in the current radix r. If the c value is not
524 * a number of the current radix then a -1 is returned.
530 * char ctype[] array of character types, one per
541 digit(register int c, register int r)
544 if (ctype[c] & RAD16) {
545 if (c >= 'A' && c <= 'F')
546 return (c - 'A' + 10);
547 if (c >= 'a' && c <= 'f')
548 return (c - 'a' + 10);
553 if (ctype[c] & RAD10)
567 /*)Function VOID abscheck(esp)
569 * expr * esp pointer to an expr structure
571 * The function abscheck() tests the evaluation of an
572 * expression to verify it is absolute. If the evaluation
573 * is relocatable then an 'r' error is noted and the expression
576 * Note: The area type (i.e. ABS) is not checked because
577 * the linker can be told to explicitly relocate an
587 * VOID rerr() assubr.c
590 * The expression may be changed to absolute and the
595 abscheck(register struct expr *esp)
597 if (esp->e_flag || esp->e_base.e_ap) {
599 esp->e_base.e_ap = NULL;
604 /*)Function int is_abs(esp)
606 * expr * esp pointer to an expr structure
608 * The function is_abs() tests the evaluation of an
609 * expression to verify it is absolute. If the evaluation
610 * is absolute then 1 is returned, else 0 is returned.
612 * Note: The area type (i.e. ABS) is not checked because
613 * the linker can be told to explicitly relocate an
630 is_abs (register struct expr *esp)
632 if (esp->e_flag || esp->e_base.e_ap) {
638 /*)Function int oprio(c)
640 * int c operator character
642 * The function oprio() returns a relative priority
643 * for all valid unary and binary operators.
659 oprio(register int c)
661 if (c == '*' || c == '/' || c == '%')
663 if (c == '+' || c == '-')
665 if (c == '<' || c == '>')
676 /*)Function VOID clrexpr(esp)
678 * expr * esp pointer to expression structure
680 * The function clrexpr() clears the expression structure.
692 * expression structure cleared.
696 clrexpr(register struct expr *esp)
701 esp->e_base.e_ap = NULL;