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/>. */
26 * The module asexpr.c contains the routines to evaluate
27 * arithmetic/numerical expressions. The functions in
28 * asexpr.c perform a recursive evaluation of the arithmetic
29 * expression read from the assembler-source text line.
30 * The expression may include binary/unary operators, brackets,
31 * symbols, labels, and constants in hexadecimal, decimal, octal
32 * and binary. Arithmetic operations are prioritized and
33 * evaluated by normal arithmetic conventions.
35 * asexpr.c contains the following functions:
44 * asexpr.c contains no local/static variables
47 /*)Function VOID expr(esp, n)
49 * expr * esp pointer to an expr structure
50 * int n a firewall priority; all top
51 * level calls (from the user)
52 * should be made with n set to 0.
54 * The function expr() evaluates an expression and
55 * stores its value and relocation information into
56 * the expr structure supplied by the user.
59 * int c current assembler-source
61 * int p current operator priority
62 * area * ap pointer to an area structure
63 * exp re internal expr structure
66 * char ctype[] array of character types, one per
70 * VOID abscheck() asexpr.c
71 * VOID clrexpr() asexpr.c
72 * VOID expr() asexpr.c
74 * int oprio() asexpr.c
75 * VOID qerr() assubr.c
76 * VOID rerr() assubr.c
77 * VOID term() asexpr.c
78 * VOID unget() aslex.c
82 * An expression is evaluated modifying the user supplied
83 * expr structure, a sym structure maybe created for an
84 * undefined symbol, and the parse of the expression may
85 * terminate if a 'q' error occurs.
89 expr(register struct expr *esp, int n)
96 while (ctype[c = getnb()] & BINOP) {
98 * Handle binary operators + - * / & | % ^ << >>
100 if ((p = oprio(c)) <= n)
102 if ((c == '>' || c == '<') && c != get())
106 esp->e_rlcf |= re.e_rlcf;
109 * esp + re, at least one must be absolute
111 if (esp->e_base.e_ap == NULL) {
113 * esp is absolute (constant),
116 esp->e_base.e_ap = re.e_base.e_ap;
118 if (re.e_base.e_ap) {
120 * re should be absolute (constant)
124 if (esp->e_flag && re.e_flag)
128 esp->e_addr += re.e_addr;
134 if ((ap = re.e_base.e_ap) != NULL) {
135 if (esp->e_base.e_ap == ap) {
136 esp->e_base.e_ap = NULL;
143 esp->e_addr -= re.e_addr;
146 * Both operands (esp and re) must be constants
148 /* SD :- moved the abscheck to each case
149 case and change the right shift operator.. if
150 right shift by 8 bits of a relocatable address then
151 the user wants the higher order byte. set the R_MSB
152 for the expression */
158 esp->e_addr *= re.e_addr;
164 esp->e_addr /= re.e_addr;
170 esp->e_addr &= re.e_addr;
176 esp->e_addr |= re.e_addr;
182 esp->e_addr %= re.e_addr;
188 esp->e_addr ^= re.e_addr;
194 esp->e_addr <<= re.e_addr;
200 /* if the left is a relative address &
201 the right side is == 8 then */
202 if (esp->e_base.e_ap && re.e_addr == 8) {
203 esp->e_rlcf |= R_MSB ;
206 else if (esp->e_base.e_ap && re.e_addr == 16)
210 esp->e_rlcf |= R_HIB;
216 "(expr >> 16) is only meaningful in "
223 /* else continue with the normal processing */
225 esp->e_addr >>= re.e_addr;
237 /*)Function Addr_T absexpr()
239 * The function absexpr() evaluates an expression, verifies it
240 * is absolute (i.e. not position dependent or relocatable), and
244 * expr e expr structure
250 * VOID abscheck() asexpr.c
251 * VOID clrexpr() asexpr.c
252 * VOID expr() asexpr.c
255 * If the expression is not absolute then
256 * a 'r' error is reported.
270 /*)Function VOID term(esp)
272 * expr * esp pointer to an expr structure
274 * The function term() evaluates a single constant
275 * or symbol value prefaced by any unary operator
276 * ( +, -, ~, ', ", >, or < ). This routine is also
277 * responsible for setting the relocation type to symbol
278 * based (e.flag != 0) on global references.
281 * int c current character
282 * char id[] symbol name
283 * char * jp pointer to assembler-source text
284 * int n constant evaluation running sum
285 * int r current evaluation radix
286 * sym * sp pointer to a sym structure
287 * tsym * tp pointer to a tsym structure
288 * int v current digit evaluation
291 * char ctype[] array of character types, one per
293 * sym * symp pointer to a symbol structure
296 * VOID abscheck() asexpr.c
297 * int digit() asexpr.c
298 * VOID err() assubr.c
299 * VOID expr() asexpr.c
300 * int is_abs() asexpr.c
302 * VOID getid() aslex.c
303 * int getmap() aslex.c
304 * int getnb() aslex.c
305 * sym * lookup() assym.c
306 * VOID qerr() assubr.c
307 * VOID unget() aslex.c
310 * An arithmetic term is evaluated, a symbol structure
311 * may be created, term evaluation may be terminated
316 term(register struct expr *esp)
319 register const char *jp;
327 * Discard the unary '+' at this point and
328 * also any reference to numerical arguments
329 * associated with the '#' prefix.
331 while (c == '+' || c == '#') { c = getnb(); }
333 * Evaluate all binary operators
334 * by recursively calling expr().
338 if (getnb() != RTTERM)
345 esp->e_addr = 0-esp->e_addr;
351 esp->e_addr = ~esp->e_addr;
355 esp->e_mode = S_USER;
356 esp->e_addr = getmap(-1)&0377;
360 esp->e_mode = S_USER;
362 esp->e_addr = (getmap(-1)&0377)<<8;
363 esp->e_addr |= (getmap(-1)&0377);
365 esp->e_addr = (getmap(-1)&0377);
366 esp->e_addr |= (getmap(-1)&0377)<<8;
370 if (c == '>' || c == '<') {
374 * evaluate msb/lsb directly
382 * let linker perform msb/lsb, lsb is default
384 esp->e_rlcf |= R_BYT2;
386 esp->e_rlcf |= R_MSB;
391 * Evaluate digit sequences as local symbols
392 * if followed by a '$' or as constants.
394 if (ctype[c] & DIGIT) {
395 esp->e_mode = S_USER;
397 while (ctype[(int)*jp] & RAD10) {
402 while ((v = digit(c, 10)) >= 0) {
408 if (n == tp->t_num) {
409 esp->e_base.e_ap = tp->t_area;
410 esp->e_addr = tp->t_addr;
451 while ((v = digit(c, r)) >= 0) {
460 * Evaluate '$' sequences as a temporary radix
461 * if followed by a '%', '&', '#', or '$'.
465 if (c == '%' || c == '&' || c == '#' || c == '$') {
484 while ((v = digit(c, r)) >= 0) {
489 esp->e_mode = S_USER;
497 * Evaluate symbols and labels
499 if (ctype[c] & LETTER) {
500 esp->e_mode = S_USER;
503 if (sp->s_type == S_NEW) {
505 if (sp->s_flag&S_GBL) {
507 esp->e_base.e_sp = sp;
512 esp->e_mode = sp->s_type;
513 esp->e_addr = sp->s_addr;
514 esp->e_base.e_ap = sp->s_area;
524 /*)Function int digit(c, r)
526 * int c digit character
527 * int r current radix
529 * The function digit() returns the value of c
530 * in the current radix r. If the c value is not
531 * a number of the current radix then a -1 is returned.
537 * char ctype[] array of character types, one per
548 digit(register int c, register int r)
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
602 abscheck(register struct expr *esp)
604 if (esp->e_flag || esp->e_base.e_ap) {
606 esp->e_base.e_ap = NULL;
611 /*)Function int is_abs(esp)
613 * expr * esp pointer to an expr structure
615 * The function is_abs() tests the evaluation of an
616 * expression to verify it is absolute. If the evaluation
617 * is absolute then 1 is returned, else 0 is returned.
619 * Note: The area type (i.e. ABS) is not checked because
620 * the linker can be told to explicitly relocate an
637 is_abs (register struct expr *esp)
639 if (esp->e_flag || esp->e_base.e_ap) {
645 /*)Function int oprio(c)
647 * int c operator character
649 * The function oprio() returns a relative priority
650 * for all valid unary and binary operators.
666 oprio(register int c)
668 if (c == '*' || c == '/' || c == '%')
670 if (c == '+' || c == '-')
672 if (c == '<' || c == '>')
683 /*)Function VOID clrexpr(esp)
685 * expr * esp pointer to expression structure
687 * The function clrexpr() clears the expression structure.
699 * expression structure cleared.
703 clrexpr(register struct expr *esp)
708 esp->e_base.e_ap = NULL;