4 * (C) Copyright 1989-1995
15 //#if !defined(_MSC_VER)
22 * The module asexpr.c contains the routines to evaluate
23 * arithmetic/numerical expressions. The functions in
24 * asexpr.c perform a recursive evaluation of the arithmetic
25 * expression read from the assembler-source text line.
26 * The expression may include binary/unary operators, brackets,
27 * symbols, labels, and constants in hexadecimal, decimal, octal
28 * and binary. Arithmetic operations are prioritized and
29 * evaluated by normal arithmetic conventions.
31 * asexpr.c contains the following functions:
40 * asexpr.c contains no local/static variables
43 /*)Function VOID expr(esp, n)
45 * expr * esp pointer to an expr structure
46 * int n a firewall priority; all top
47 * level calls (from the user)
48 * should be made with n set to 0.
50 * The function expr() evaluates an expression and
51 * stores its value and relocation information into
52 * the expr structure supplied by the user.
55 * int c current assembler-source
57 * int p current operator priority
58 * area * ap pointer to an area structure
59 * exp re internal expr structure
62 * char ctype[] array of character types, one per
66 * VOID abscheck() asexpr.c
67 * VOID clrexpr() asexpr.c
68 * VOID expr() asexpr.c
70 * int oprio() asexpr.c
71 * VOID qerr() assubr.c
72 * VOID rerr() assubr.c
73 * VOID term() asexpr.c
74 * VOID unget() aslex.c
78 * An expression is evaluated modifying the user supplied
79 * expr structure, a sym structure maybe created for an
80 * undefined symbol, and the parse of the expression may
81 * terminate if a 'q' error occurs.
86 register struct expr *esp;
94 while (ctype[c = getnb()] & BINOP) {
96 * Handle binary operators + - * / & | % ^ << >>
98 if ((p = oprio(c)) <= n)
100 if ((c == '>' || c == '<') && c != get())
104 esp->e_rlcf |= re.e_rlcf;
107 * esp + re, at least one must be absolute
109 if (esp->e_base.e_ap == NULL) {
111 * esp is absolute (constant),
114 esp->e_base.e_ap = re.e_base.e_ap;
116 if (re.e_base.e_ap) {
118 * re should be absolute (constant)
122 if (esp->e_flag && re.e_flag)
126 esp->e_addr += re.e_addr;
132 if ((ap = re.e_base.e_ap) != NULL) {
133 if (esp->e_base.e_ap == ap) {
134 esp->e_base.e_ap = NULL;
141 esp->e_addr -= re.e_addr;
144 * Both operands (esp and re) must be constants
146 /* SD :- moved the abscheck to each case
147 case and change the right shift operator.. if
148 right shift by 8 bits of a relocatable address then
149 the user wants the higher order byte. set the R_MSB
150 for the expression */
156 esp->e_addr *= re.e_addr;
162 esp->e_addr /= re.e_addr;
168 esp->e_addr &= re.e_addr;
174 esp->e_addr |= re.e_addr;
180 esp->e_addr %= re.e_addr;
186 esp->e_addr ^= re.e_addr;
192 esp->e_addr <<= re.e_addr;
198 /* if the left is a relative address &
199 the right side is == 8 then */
200 if (esp->e_base.e_ap && re.e_addr == 8) {
201 esp->e_rlcf |= R_MSB ;
204 else if (esp->e_base.e_ap && re.e_addr == 16)
208 esp->e_rlcf |= R_HIB;
214 "(expr >> 16) is only meaningful in "
221 /* else continue with the normal processing */
223 esp->e_addr >>= re.e_addr;
235 /*)Function Addr_T absexpr()
237 * The function absexpr() evaluates an expression, verifies it
238 * is absolute (i.e. not position dependent or relocatable), and
242 * expr e expr structure
248 * VOID abscheck() asexpr.c
249 * VOID clrexpr() asexpr.c
250 * VOID expr() asexpr.c
253 * If the expression is not absolute then
254 * a 'r' error is reported.
268 /*)Function VOID term(esp)
270 * expr * esp pointer to an expr structure
272 * The function term() evaluates a single constant
273 * or symbol value prefaced by any unary operator
274 * ( +, -, ~, ', ", >, or < ). This routine is also
275 * responsible for setting the relocation type to symbol
276 * based (e.flag != 0) on global references.
279 * int c current character
280 * char id[] symbol name
281 * char * jp pointer to assembler-source text
282 * int n constant evaluation running sum
283 * int r current evaluation radix
284 * sym * sp pointer to a sym structure
285 * tsym * tp pointer to a tsym structure
286 * int v current digit evaluation
289 * char ctype[] array of character types, one per
291 * sym * symp pointer to a symbol structure
294 * VOID abscheck() asexpr.c
295 * int digit() asexpr.c
296 * VOID err() assubr.c
297 * VOID expr() asexpr.c
298 * int is_abs() asexpr.c
300 * VOID getid() aslex.c
301 * int getmap() aslex.c
302 * int getnb() aslex.c
303 * sym * lookup() assym.c
304 * VOID qerr() assubr.c
305 * VOID unget() aslex.c
308 * An arithmetic term is evaluated, a symbol structure
309 * may be created, term evaluation may be terminated
315 register struct expr *esp;
326 * Discard the unary '+' at this point and
327 * also any reference to numerical arguments
328 * associated with the '#' prefix.
330 while (c == '+' || c == '#') { c = getnb(); }
332 * Evaluate all binary operators
333 * by recursively calling expr().
337 if (getnb() != RTTERM)
344 esp->e_addr = -esp->e_addr;
350 esp->e_addr = ~esp->e_addr;
354 esp->e_mode = S_USER;
355 esp->e_addr = getmap(-1)&0377;
359 esp->e_mode = S_USER;
361 esp->e_addr = (getmap(-1)&0377)<<8;
362 esp->e_addr |= (getmap(-1)&0377);
364 esp->e_addr = (getmap(-1)&0377);
365 esp->e_addr |= (getmap(-1)&0377)<<8;
369 if (c == '>' || c == '<') {
373 * evaluate msb/lsb directly
381 * let linker perform msb/lsb, lsb is default
383 esp->e_rlcf |= R_BYT2;
385 esp->e_rlcf |= R_MSB;
390 * Evaluate digit sequences as local symbols
391 * if followed by a '$' or as constants.
393 if (ctype[c] & DIGIT) {
394 esp->e_mode = S_USER;
396 while (ctype[(int)*jp] & RAD10) {
401 while ((v = digit(c, 10)) >= 0) {
407 if (n == tp->t_num) {
408 esp->e_base.e_ap = tp->t_area;
409 esp->e_addr = tp->t_addr;
450 while ((v = digit(c, r)) >= 0) {
459 * Evaluate '$' sequences as a temporary radix
460 * if followed by a '%', '&', '#', or '$'.
464 if (c == '%' || c == '&' || c == '#' || c == '$') {
483 while ((v = digit(c, r)) >= 0) {
488 esp->e_mode = S_USER;
496 * Evaluate symbols and labels
498 if (ctype[c] & LETTER) {
499 esp->e_mode = S_USER;
502 if (sp->s_type == S_NEW) {
504 if (sp->s_flag&S_GBL) {
506 esp->e_base.e_sp = sp;
511 esp->e_mode = sp->s_type;
512 esp->e_addr = sp->s_addr;
513 esp->e_base.e_ap = sp->s_area;
523 /*)Function int digit(c, r)
525 * int c digit character
526 * int r current radix
528 * The function digit() returns the value of c
529 * in the current radix r. If the c value is not
530 * a number of the current radix then a -1 is returned.
536 * char ctype[] array of character types, one per
551 if (ctype[c] & RAD16) {
552 if (c >= 'A' && c <= 'F')
553 return (c - 'A' + 10);
554 if (c >= 'a' && c <= 'f')
555 return (c - 'a' + 10);
560 if (ctype[c] & RAD10)
574 /*)Function VOID abscheck(esp)
576 * expr * esp pointer to an expr structure
578 * The function abscheck() tests the evaluation of an
579 * expression to verify it is absolute. If the evaluation
580 * is relocatable then an 'r' error is noted and the expression
583 * Note: The area type (i.e. ABS) is not checked because
584 * the linker can be told to explicitly relocate an
594 * VOID rerr() assubr.c
597 * The expression may be changed to absolute and the
603 register struct expr *esp;
605 if (esp->e_flag || esp->e_base.e_ap) {
607 esp->e_base.e_ap = NULL;
612 /*)Function int is_abs(esp)
614 * expr * esp pointer to an expr structure
616 * The function is_abs() tests the evaluation of an
617 * expression to verify it is absolute. If the evaluation
618 * is absolute then 1 is returned, else 0 is returned.
620 * Note: The area type (i.e. ABS) is not checked because
621 * the linker can be told to explicitly relocate an
639 register struct expr *esp;
641 if (esp->e_flag || esp->e_base.e_ap) {
647 /*)Function int oprio(c)
649 * int c operator character
651 * The function oprio() returns a relative priority
652 * for all valid unary and binary operators.
671 if (c == '*' || c == '/' || c == '%')
673 if (c == '+' || c == '-')
675 if (c == '<' || c == '>')
686 /*)Function VOID clrexpr(esp)
688 * expr * esp pointer to expression structure
690 * The function clrexpr() clears the expression structure.
702 * expression structure cleared.
707 register struct expr *esp;
712 esp->e_base.e_ap = NULL;