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 "
217 // ".flat24 mode.\n");
223 /* else continue with the normal processing */
225 esp->e_addr >>= re.e_addr;
228 /* MB added [ for bit access in bdata */
233 /* if the left is a relative address then */
234 if (esp->e_base.e_ap) {
235 esp->e_addr |= (re.e_addr | 0x80) << 8;
238 else if ((esp->e_addr & 0x87) == 0x80) {
239 esp->e_addr |= re.e_addr;
252 /*)Function Addr_T absexpr()
254 * The function absexpr() evaluates an expression, verifies it
255 * is absolute (i.e. not position dependent or relocatable), and
259 * expr e expr structure
265 * VOID abscheck() asexpr.c
266 * VOID clrexpr() asexpr.c
267 * VOID expr() asexpr.c
270 * If the expression is not absolute then
271 * a 'r' error is reported.
285 /*)Function VOID term(esp)
287 * expr * esp pointer to an expr structure
289 * The function term() evaluates a single constant
290 * or symbol value prefaced by any unary operator
291 * ( +, -, ~, ', ", >, or < ). This routine is also
292 * responsible for setting the relocation type to symbol
293 * based (e.flag != 0) on global references.
296 * int c current character
297 * char id[] symbol name
298 * char * jp pointer to assembler-source text
299 * int n constant evaluation running sum
300 * int r current evaluation radix
301 * sym * sp pointer to a sym structure
302 * tsym * tp pointer to a tsym structure
303 * int v current digit evaluation
306 * char ctype[] array of character types, one per
308 * sym * symp pointer to a symbol structure
311 * VOID abscheck() asexpr.c
312 * int digit() asexpr.c
313 * VOID err() assubr.c
314 * VOID expr() asexpr.c
315 * int is_abs() asexpr.c
317 * VOID getid() aslex.c
318 * int getmap() aslex.c
319 * int getnb() aslex.c
320 * sym * lookup() assym.c
321 * VOID qerr() assubr.c
322 * VOID unget() aslex.c
325 * An arithmetic term is evaluated, a symbol structure
326 * may be created, term evaluation may be terminated
331 term(register struct expr *esp)
334 register const char *jp;
342 * Discard the unary '+' at this point and
343 * also any reference to numerical arguments
344 * associated with the '#' prefix.
346 while (c == '+' || c == '#') { c = getnb(); }
348 * Evaluate all binary operators
349 * by recursively calling expr().
353 if (getnb() != RTTERM)
360 esp->e_addr = 0-esp->e_addr;
366 esp->e_addr = ~esp->e_addr;
370 esp->e_mode = S_USER;
371 esp->e_addr = getmap(-1)&0377;
375 esp->e_mode = S_USER;
377 esp->e_addr = (getmap(-1)&0377)<<8;
378 esp->e_addr |= (getmap(-1)&0377);
380 esp->e_addr = (getmap(-1)&0377);
381 esp->e_addr |= (getmap(-1)&0377)<<8;
385 if (c == '>' || c == '<') {
389 * evaluate msb/lsb directly
397 * let linker perform msb/lsb, lsb is default
399 esp->e_rlcf |= R_BYT2;
401 esp->e_rlcf |= R_MSB;
406 * Evaluate digit sequences as local symbols
407 * if followed by a '$' or as constants.
409 if (ctype[c] & DIGIT) {
410 esp->e_mode = S_USER;
412 while (ctype[(int)*jp] & RAD10) {
417 while ((v = digit(c, 10)) >= 0) {
423 if (n == tp->t_num) {
424 esp->e_base.e_ap = tp->t_area;
425 esp->e_addr = tp->t_addr;
466 while ((v = digit(c, r)) >= 0) {
475 * Evaluate '$' sequences as a temporary radix
476 * if followed by a '%', '&', '#', or '$'.
480 if (c == '%' || c == '&' || c == '#' || c == '$') {
499 while ((v = digit(c, r)) >= 0) {
504 esp->e_mode = S_USER;
512 * Evaluate symbols and labels
514 if (ctype[c] & LETTER) {
515 esp->e_mode = S_USER;
518 if (sp->s_type == S_NEW) {
520 if (sp->s_flag&S_GBL) {
522 esp->e_base.e_sp = sp;
527 esp->e_mode = sp->s_type;
528 esp->e_addr = sp->s_addr;
529 esp->e_base.e_ap = sp->s_area;
530 /* MB: abused bit 15 of s_addr to indicate bit-addressable bytes */
531 if ((sp->s_addr & 0x8000) && sp->s_area &&
532 (!strcmp(sp->s_area->a_id, "BSEG_BYTES") || !strcmp(sp->s_area->a_id, "BIT_BANK"))) {
533 esp->e_rlcf |= R_BIT | R_BYT2;
544 /*)Function int digit(c, r)
546 * int c digit character
547 * int r current radix
549 * The function digit() returns the value of c
550 * in the current radix r. If the c value is not
551 * a number of the current radix then a -1 is returned.
557 * char ctype[] array of character types, one per
568 digit(register int c, register int r)
571 if (ctype[c] & RAD16) {
572 if (c >= 'A' && c <= 'F')
573 return (c - 'A' + 10);
574 if (c >= 'a' && c <= 'f')
575 return (c - 'a' + 10);
580 if (ctype[c] & RAD10)
594 /*)Function VOID abscheck(esp)
596 * expr * esp pointer to an expr structure
598 * The function abscheck() tests the evaluation of an
599 * expression to verify it is absolute. If the evaluation
600 * is relocatable then an 'r' error is noted and the expression
603 * Note: The area type (i.e. ABS) is not checked because
604 * the linker can be told to explicitly relocate an
614 * VOID rerr() assubr.c
617 * The expression may be changed to absolute and the
622 abscheck(register struct expr *esp)
624 if (esp->e_flag || esp->e_base.e_ap) {
626 esp->e_base.e_ap = NULL;
631 /*)Function int is_abs(esp)
633 * expr * esp pointer to an expr structure
635 * The function is_abs() tests the evaluation of an
636 * expression to verify it is absolute. If the evaluation
637 * is absolute then 1 is returned, else 0 is returned.
639 * Note: The area type (i.e. ABS) is not checked because
640 * the linker can be told to explicitly relocate an
657 is_abs (register struct expr *esp)
659 if (esp->e_flag || esp->e_base.e_ap) {
665 /*)Function int oprio(c)
667 * int c operator character
669 * The function oprio() returns a relative priority
670 * for all valid unary and binary operators.
686 oprio(register int c)
690 if (c == '*' || c == '/' || c == '%')
692 if (c == '+' || c == '-')
694 if (c == '<' || c == '>')
705 /*)Function VOID clrexpr(esp)
707 * expr * esp pointer to expression structure
709 * The function clrexpr() clears the expression structure.
721 * expression structure cleared.
725 clrexpr(register struct expr *esp)
730 esp->e_base.e_ap = NULL;