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;
221 /* MB added [ for bit access in bdata */
226 /* if the left is a relative address then */
227 if (esp->e_base.e_ap) {
228 esp->e_addr |= (re.e_addr | 0x80) << 8;
231 else if ((esp->e_addr & 0x87) == 0x80) {
232 esp->e_addr |= re.e_addr;
245 /*)Function Addr_T absexpr()
247 * The function absexpr() evaluates an expression, verifies it
248 * is absolute (i.e. not position dependent or relocatable), and
252 * expr e expr structure
258 * VOID abscheck() asexpr.c
259 * VOID clrexpr() asexpr.c
260 * VOID expr() asexpr.c
263 * If the expression is not absolute then
264 * a 'r' error is reported.
278 /*)Function VOID term(esp)
280 * expr * esp pointer to an expr structure
282 * The function term() evaluates a single constant
283 * or symbol value prefaced by any unary operator
284 * ( +, -, ~, ', ", >, or < ). This routine is also
285 * responsible for setting the relocation type to symbol
286 * based (e.flag != 0) on global references.
289 * int c current character
290 * char id[] symbol name
291 * char * jp pointer to assembler-source text
292 * int n constant evaluation running sum
293 * int r current evaluation radix
294 * sym * sp pointer to a sym structure
295 * tsym * tp pointer to a tsym structure
296 * int v current digit evaluation
299 * char ctype[] array of character types, one per
301 * sym * symp pointer to a symbol structure
304 * VOID abscheck() asexpr.c
305 * int digit() asexpr.c
306 * VOID err() assubr.c
307 * VOID expr() asexpr.c
308 * int is_abs() asexpr.c
310 * VOID getid() aslex.c
311 * int getmap() aslex.c
312 * int getnb() aslex.c
313 * sym * lookup() assym.c
314 * VOID qerr() assubr.c
315 * VOID unget() aslex.c
318 * An arithmetic term is evaluated, a symbol structure
319 * may be created, term evaluation may be terminated
324 term(register struct expr *esp)
335 * Discard the unary '+' at this point and
336 * also any reference to numerical arguments
337 * associated with the '#' prefix.
339 while (c == '+' || c == '#') { c = getnb(); }
341 * Evaluate all binary operators
342 * by recursively calling expr().
346 if (getnb() != RTTERM)
353 esp->e_addr = 0-esp->e_addr;
359 esp->e_addr = ~esp->e_addr;
363 esp->e_mode = S_USER;
364 esp->e_addr = getmap(-1)&0377;
368 esp->e_mode = S_USER;
370 esp->e_addr = (getmap(-1)&0377)<<8;
371 esp->e_addr |= (getmap(-1)&0377);
373 esp->e_addr = (getmap(-1)&0377);
374 esp->e_addr |= (getmap(-1)&0377)<<8;
378 if (c == '>' || c == '<') {
382 * evaluate msb/lsb directly
390 * let linker perform msb/lsb, lsb is default
392 esp->e_rlcf |= R_BYT2;
394 esp->e_rlcf |= R_MSB;
399 * Evaluate digit sequences as local symbols
400 * if followed by a '$' or as constants.
402 if (ctype[c] & DIGIT) {
403 esp->e_mode = S_USER;
405 while (ctype[(int)*jp] & RAD10) {
410 while ((v = digit(c, 10)) >= 0) {
416 if (n == tp->t_num) {
417 esp->e_base.e_ap = tp->t_area;
418 esp->e_addr = tp->t_addr;
459 while ((v = digit(c, r)) >= 0) {
468 * Evaluate '$' sequences as a temporary radix
469 * if followed by a '%', '&', '#', or '$'.
473 if (c == '%' || c == '&' || c == '#' || c == '$') {
492 while ((v = digit(c, r)) >= 0) {
497 esp->e_mode = S_USER;
505 * Evaluate symbols and labels
507 if (ctype[c] & LETTER) {
508 esp->e_mode = S_USER;
511 if (sp->s_type == S_NEW) {
513 if (sp->s_flag&S_GBL) {
515 esp->e_base.e_sp = sp;
520 esp->e_mode = sp->s_type;
521 esp->e_addr = sp->s_addr;
522 esp->e_base.e_ap = sp->s_area;
523 /* MB: abused bit 15 of s_addr to indicate bit-addressable bytes */
524 if ((sp->s_addr & 0x8000) && sp->s_area &&
525 (!strcmp(sp->s_area->a_id, "BSEG_BYTES") || !strcmp(sp->s_area->a_id, "BIT_BANK"))) {
526 esp->e_rlcf |= R_BIT | R_BYT2;
537 /*)Function int digit(c, r)
539 * int c digit character
540 * int r current radix
542 * The function digit() returns the value of c
543 * in the current radix r. If the c value is not
544 * a number of the current radix then a -1 is returned.
550 * char ctype[] array of character types, one per
561 digit(register int c, register int r)
564 if (ctype[c] & RAD16) {
565 if (c >= 'A' && c <= 'F')
566 return (c - 'A' + 10);
567 if (c >= 'a' && c <= 'f')
568 return (c - 'a' + 10);
573 if (ctype[c] & RAD10)
587 /*)Function VOID abscheck(esp)
589 * expr * esp pointer to an expr structure
591 * The function abscheck() tests the evaluation of an
592 * expression to verify it is absolute. If the evaluation
593 * is relocatable then an 'r' error is noted and the expression
596 * Note: The area type (i.e. ABS) is not checked because
597 * the linker can be told to explicitly relocate an
607 * VOID rerr() assubr.c
610 * The expression may be changed to absolute and the
615 abscheck(register struct expr *esp)
617 if (esp->e_flag || esp->e_base.e_ap) {
619 esp->e_base.e_ap = NULL;
624 /*)Function int is_abs(esp)
626 * expr * esp pointer to an expr structure
628 * The function is_abs() tests the evaluation of an
629 * expression to verify it is absolute. If the evaluation
630 * is absolute then 1 is returned, else 0 is returned.
632 * Note: The area type (i.e. ABS) is not checked because
633 * the linker can be told to explicitly relocate an
650 is_abs (register struct expr *esp)
652 if (esp->e_flag || esp->e_base.e_ap) {
658 /*)Function int oprio(c)
660 * int c operator character
662 * The function oprio() returns a relative priority
663 * for all valid unary and binary operators.
679 oprio(register int c)
683 if (c == '*' || c == '/' || c == '%')
685 if (c == '+' || c == '-')
687 if (c == '<' || c == '>')
698 /*)Function VOID clrexpr(esp)
700 * expr * esp pointer to expression structure
702 * The function clrexpr() clears the expression structure.
714 * expression structure cleared.
718 clrexpr(register struct expr *esp)
723 esp->e_base.e_ap = NULL;