3 Copyright (C) 1989-1995 Alan R. Baldwin
4 721 Berkeley St., Kent, Ohio 44240
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 3, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
27 * The module asexpr.c contains the routines to evaluate
28 * arithmetic/numerical expressions. The functions in
29 * asexpr.c perform a recursive evaluation of the arithmetic
30 * expression read from the assembler-source text line.
31 * The expression may include binary/unary operators, brackets,
32 * symbols, labels, and constants in hexadecimal, decimal, octal
33 * and binary. Arithmetic operations are prioritized and
34 * evaluated by normal arithmetic conventions.
36 * asexpr.c contains the following functions:
45 * asexpr.c contains no local/static variables
48 /*)Function VOID expr(esp, n)
50 * expr * esp pointer to an expr structure
51 * int n a firewall priority; all top
52 * level calls (from the user)
53 * should be made with n set to 0.
55 * The function expr() evaluates an expression and
56 * stores its value and relocation information into
57 * the expr structure supplied by the user.
60 * int c current assembler-source
62 * int p current operator priority
63 * area * ap pointer to an area structure
64 * exp re internal expr structure
67 * char ctype[] array of character types, one per
71 * VOID abscheck() asexpr.c
72 * VOID clrexpr() asexpr.c
73 * VOID expr() asexpr.c
75 * int oprio() asexpr.c
76 * VOID qerr() assubr.c
77 * VOID rerr() assubr.c
78 * VOID term() asexpr.c
79 * VOID unget() aslex.c
83 * An expression is evaluated modifying the user supplied
84 * expr structure, a sym structure maybe created for an
85 * undefined symbol, and the parse of the expression may
86 * terminate if a 'q' error occurs.
91 register struct expr *esp;
99 while (ctype[c = getnb()] & BINOP) {
101 * Handle binary operators + - * / & | % ^ << >>
103 if ((p = oprio(c)) <= n)
105 if ((c == '>' || c == '<') && c != get())
109 esp->e_rlcf |= re.e_rlcf;
112 * esp + re, at least one must be absolute
114 if (esp->e_base.e_ap == NULL) {
116 * esp is absolute (constant),
119 esp->e_base.e_ap = re.e_base.e_ap;
121 if (re.e_base.e_ap) {
123 * re should be absolute (constant)
127 if (esp->e_flag && re.e_flag)
131 esp->e_addr += re.e_addr;
137 if ((ap = re.e_base.e_ap) != NULL) {
138 if (esp->e_base.e_ap == ap) {
139 esp->e_base.e_ap = NULL;
146 esp->e_addr -= re.e_addr;
149 * Both operands (esp and re) must be constants
156 esp->e_addr *= re.e_addr;
160 esp->e_addr /= re.e_addr;
164 esp->e_addr &= re.e_addr;
168 esp->e_addr |= re.e_addr;
172 esp->e_addr %= re.e_addr;
176 esp->e_addr ^= re.e_addr;
180 esp->e_addr <<= re.e_addr;
184 esp->e_addr >>= re.e_addr;
196 /*)Function Addr_T absexpr()
198 * The function absexpr() evaluates an expression, verifies it
199 * is absolute (i.e. not position dependent or relocatable), and
203 * expr e expr structure
209 * VOID abscheck() asexpr.c
210 * VOID clrexpr() asexpr.c
211 * VOID expr() asexpr.c
214 * If the expression is not absolute then
215 * a 'r' error is reported.
229 /*)Function VOID term(esp)
231 * expr * esp pointer to an expr structure
233 * The function term() evaluates a single constant
234 * or symbol value prefaced by any unary operator
235 * ( +, -, ~, ', ", >, or < ). This routine is also
236 * responsible for setting the relocation type to symbol
237 * based (e.flag != 0) on global references.
240 * int c current character
241 * char id[] symbol name
242 * char * jp pointer to assembler-source text
243 * int n constant evaluation running sum
244 * int r current evaluation radix
245 * sym * sp pointer to a sym structure
246 * tsym * tp pointer to a tsym structure
247 * int v current digit evaluation
250 * char ctype[] array of character types, one per
252 * sym * symp pointer to a symbol structure
255 * VOID abscheck() asexpr.c
256 * int digit() asexpr.c
257 * VOID err() assubr.c
258 * VOID expr() asexpr.c
259 * int is_abs() asexpr.c
261 * VOID getid() aslex.c
262 * int getmap() aslex.c
263 * int getnb() aslex.c
264 * sym * lookup() assym.c
265 * VOID qerr() assubr.c
266 * VOID unget() aslex.c
269 * An arithmetic term is evaluated, a symbol structure
270 * may be created, term evaluation may be terminated
276 register struct expr *esp;
279 register const char *jp;
287 * Discard the unary '+' at this point and
288 * also any reference to numerical arguments
289 * associated with the '#' prefix.
291 while (c == '+' || c == '#') { c = getnb(); }
293 * Evaluate all binary operators
294 * by recursively calling expr().
298 if (getnb() != RTTERM)
305 esp->e_addr = 0 - esp->e_addr;
311 esp->e_addr = ~esp->e_addr;
315 esp->e_mode = S_USER;
316 esp->e_addr = getmap(-1)&0377;
320 esp->e_mode = S_USER;
322 esp->e_addr = (getmap(-1)&0377)<<8;
323 esp->e_addr |= (getmap(-1)&0377);
325 esp->e_addr = (getmap(-1)&0377);
326 esp->e_addr |= (getmap(-1)&0377)<<8;
330 if (c == '>' || c == '<') {
334 * evaluate msb/lsb directly
342 * let linker perform msb/lsb, lsb is default
344 esp->e_rlcf |= R_BYT2;
346 esp->e_rlcf |= R_MSB;
351 * Evaluate digit sequences as local symbols
352 * if followed by a '$' or as constants.
354 if (ctype[c] & DIGIT) {
355 esp->e_mode = S_USER;
357 while (ctype[(unsigned char)(*jp)] & RAD10) {
362 while ((v = digit(c, 10)) >= 0) {
368 if (n == tp->t_num) {
369 esp->e_base.e_ap = tp->t_area;
370 esp->e_addr = tp->t_addr;
411 while ((v = digit(c, r)) >= 0) {
420 * Evaluate '$' sequences as a temporary radix
421 * if followed by a '%', '&', '#', or '$'.
425 if (c == '%' || c == '&' || c == '#' || c == '$') {
444 while ((v = digit(c, r)) >= 0) {
449 esp->e_mode = S_USER;
457 * Evaluate symbols and labels
459 if (ctype[c] & LETTER) {
460 esp->e_mode = S_USER;
463 if (sp->s_type == S_NEW) {
464 if (sp->s_flag&S_GBL) {
466 esp->e_base.e_sp = sp;
471 esp->e_mode = sp->s_type;
472 esp->e_addr = sp->s_addr;
473 esp->e_base.e_ap = sp->s_area;
483 /*)Function int digit(c, r)
485 * int c digit character
486 * int r current radix
488 * The function digit() returns the value of c
489 * in the current radix r. If the c value is not
490 * a number of the current radix then a -1 is returned.
496 * char ctype[] array of character types, one per
511 if (ctype[c] & RAD16) {
512 if (c >= 'A' && c <= 'F')
513 return (c - 'A' + 10);
514 if (c >= 'a' && c <= 'f')
515 return (c - 'a' + 10);
520 if (ctype[c] & RAD10)
534 /*)Function VOID abscheck(esp)
536 * expr * esp pointer to an expr structure
538 * The function abscheck() tests the evaluation of an
539 * expression to verify it is absolute. If the evaluation
540 * is relocatable then an 'r' error is noted and the expression
543 * Note: The area type (i.e. ABS) is not checked because
544 * the linker can be told to explicitly relocate an
554 * VOID rerr() assubr.c
557 * The expression may be changed to absolute and the
563 register struct expr *esp;
565 if (esp->e_flag || esp->e_base.e_ap) {
567 esp->e_base.e_ap = NULL;
572 /*)Function int is_abs(esp)
574 * expr * esp pointer to an expr structure
576 * The function is_abs() tests the evaluation of an
577 * expression to verify it is absolute. If the evaluation
578 * is absolute then 1 is returned, else 0 is returned.
580 * Note: The area type (i.e. ABS) is not checked because
581 * the linker can be told to explicitly relocate an
599 register struct expr *esp;
601 if (esp->e_flag || esp->e_base.e_ap) {
607 /*)Function int oprio(c)
609 * int c operator character
611 * The function oprio() returns a relative priority
612 * for all valid unary and binary operators.
631 if (c == '*' || c == '/' || c == '%')
633 if (c == '+' || c == '-')
635 if (c == '<' || c == '>')
646 /*)Function VOID clrexpr(esp)
648 * expr * esp pointer to expression structure
650 * The function clrexpr() clears the expression structure.
662 * expression structure cleared.
667 register struct expr *esp;
672 esp->e_base.e_ap = NULL;