struct / union in initializer, RFE #901.
[sdcc.git] / sdcc / sdas / asxxsrc / asexpr.c
blob6348a8786fb90991a4843c82c4238563b7e53bde
1 /* asexpr.c */
3 /*
4 * Copyright (C) 1989-2021 Alan R. Baldwin
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
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/>.
20 * Alan R. Baldwin
21 * 721 Berkeley St.
22 * Kent, Ohio 44240
24 * With enhancements from
26 * Bill McKinnon (BM)
27 * w_mckinnon at conknet dot com
30 #include "sdas.h"
31 #include "asxxxx.h"
33 /*)Module asexpr.c
35 * The module asexpr.c contains the routines to evaluate
36 * arithmetic/numerical expressions. The functions in
37 * asexpr.c perform a recursive evaluation of the arithmetic
38 * expression read from the assembler-source text line.
39 * The expression may include binary/unary operators, brackets,
40 * symbols, labels, and constants in hexadecimal, decimal, octal
41 * and binary. Arithmetic operations are prioritized and
42 * evaluated by normal arithmetic conventions.
44 * asexpr.c contains the following functions:
45 * VOID abscheck()
46 * a_uint absexpr()
47 * int is_abs()
48 * VOID clrexpr()
49 * int digit()
50 * VOID expr()
51 * VOID exprmasks()
52 * int oprio()
53 * VOID term()
54 * a_uint rngchk()
56 * asexpr.c contains no local/static variables
59 /*)Function VOID expr(esp, n)
61 * expr * esp pointer to an expr structure
62 * int n a firewall priority; all top
63 * level calls (from the user)
64 * should be made with n set to 0.
66 * The function expr() evaluates an expression and
67 * stores its value and relocation information into
68 * the expr structure supplied by the user.
70 * Notes about the arithmetic:
71 * The coding emulates N-Bit unsigned
72 * arithmetic operations. This allows
73 * program compilation without regard to the
74 * intrinsic integer length of the host
75 * machine.
77 * local variables:
78 * a_uint ae value from expr esp
79 * a_uint ar value from expr re
80 * int c current assembler-source
81 * text character
82 * int p current operator priority
83 * area * ap pointer to an area structure
84 * exp re internal expr structure
86 * global variables:
87 * char ctype[] array of character types, one per
88 * ASCII character
90 * functions called:
91 * VOID abscheck() asexpr.c
92 * VOID clrexpr() asexpr.c
93 * VOID err() assubr.c
94 * VOID expr() asexpr.c
95 * int get() aslex.c
96 * int getnb() aslex.c
97 * int oprio() asexpr.c
98 * VOID xerr() assubr.c
99 * VOID term() asexpr.c
100 * VOID unget() aslex.c
103 * side effects:
104 * An expression is evaluated modifying the user supplied
105 * expr structure, a sym structure maybe created for an
106 * undefined symbol, and the parse of the expression may
107 * terminate if a 'q' error occurs.
110 VOID
111 expr(struct expr *esp, int n)
113 a_uint ae, ar;
114 int c, p;
115 struct area *ap;
116 struct expr re;
118 term(esp);
119 while (ctype[c = getnb()] & BINOP) {
121 * Handle binary operators + - * / & | % ^ << >> [
123 if ((p = oprio(c)) <= n)
124 break;
125 if ((c == '>' || c == '<') && c != get())
126 xerr('q', "Binary operator >> or << expected.");
127 clrexpr(&re);
128 expr(&re, p);
129 esp->e_rlcf |= re.e_rlcf;
131 ae = esp->e_addr;
132 ar = re.e_addr;
134 if (c == '+') {
136 * esp + re, at least one must be absolute
138 if (esp->e_base.e_ap == NULL) {
140 * esp is absolute (constant),
141 * use area from re
143 esp->e_base.e_ap = re.e_base.e_ap;
144 } else
145 if (re.e_base.e_ap) {
147 * re should be absolute (constant)
149 xerr('r', "Arg1 + Arg2, Arg2 must be a constant.");
151 if (esp->e_flag && re.e_flag)
152 xerr('r', "Arg1 + Arg2, Both arguments cannot be external.");
153 if (re.e_flag)
154 esp->e_flag = 1;
155 ae += ar;
156 } else
157 if (c == '-') {
159 * esp - re
161 if ((ap = re.e_base.e_ap) != NULL) {
162 if (esp->e_base.e_ap == ap) {
163 esp->e_base.e_ap = NULL;
164 } else {
165 xerr('r', "Arg1 - Arg2, Arg2 must be in same area.");
168 if (re.e_flag)
169 xerr('r', "Arg1 - Arg2, Arg2 cannot be external.");
170 ae -= ar;
171 } else {
173 * Both operands (esp and re) must be constants
175 /* SD/MB :- postpone the abscheck to cases '>' and '['
176 and change the right shift operator.. if
177 right shift by 8/16/24 bits of a relocatable address then
178 the user wants the higher order byte. set the R_MSB
179 for the expression */
180 if (c != '>' && c != '[')
181 abscheck(esp);
182 abscheck(&re);
183 switch (c) {
185 * The (int) /, %, and >> operations
186 * are truncated to a_bytes.
188 case '*':
189 ae *= ar;
190 break;
192 case '/':
193 if (ar == 0) {
194 ae = 0;
195 err('z');
196 } else {
197 ae /= ar;
199 break;
201 case '&':
202 ae &= ar;
203 break;
205 case '|':
206 ae |= ar;
207 break;
209 case '%':
210 if (ar == 0) {
211 ae = 0;
212 err('z');
213 } else {
214 ae %= ar;
216 break;
218 case '^':
219 ae ^= ar;
220 break;
222 case '<':
223 ae <<= ar;
224 break;
226 case '>':
227 /* SD change here */
228 /* if the left is a relative address &
229 the right side is 8/16/24 then */
230 if (esp->e_base.e_ap && ar == 8) {
231 esp->e_rlcf |= R_MSB;
232 break;
234 else if (esp->e_base.e_ap && ar == 16) {
235 esp->e_rlcf |= R_HIB;
236 break;
238 else if (esp->e_base.e_ap && ar == 24) {
239 esp->e_rlcf |= R_MSB | R_HIB;
240 break;
242 /* else continue with the normal processing */
243 abscheck(esp);
244 ae >>= ar;
245 break;
247 case '[':
248 if (is_sdas() && is_sdas_target_8051_like()) {
249 /* MB added [ for bit access in bdata */
250 if (getnb() != ']')
251 qerr();
253 /* if the left is a relative address then */
254 if (esp->e_base.e_ap) {
255 ae |= (ar | 0x80) << 8;
256 break;
258 else if ((ae & 0x87) == 0x80) {
259 ae |= ar;
260 break;
263 /* fall through */
265 default:
266 qerr();
267 break;
270 esp->e_addr = rngchk(ae);
272 unget(c);
275 /*)Function a_uint absexpr()
277 * The function absexpr() evaluates an expression, verifies it
278 * is absolute (i.e. not position dependent or relocatable), and
279 * returns its value.
281 * local variables:
282 * expr e expr structure
284 * global variables:
285 * none
287 * functions called:
288 * VOID abscheck() asexpr.c
289 * VOID clrexpr() asexpr.c
290 * VOID expr() asexpr.c
292 * side effects:
293 * If the expression is not absolute then
294 * a 'r' error is reported.
297 a_uint
298 absexpr(void)
300 struct expr e;
302 clrexpr(&e);
303 expr(&e, 0);
304 abscheck(&e);
305 return (e.e_addr);
308 /*)Function VOID term(esp)
310 * expr * esp pointer to an expr structure
312 * The function term() evaluates a single constant
313 * or symbol value prefaced by any unary operator
314 * ( +, -, ~, ', ", >, or < ). This routine is also
315 * responsible for setting the relocation type to symbol
316 * based (e.flag != 0) on global references.
318 * local variables:
319 * int c current character
320 * char id[] symbol name
321 * char * jp pointer to assembler-source text
322 * a_uint n constant evaluation running sum
323 * int r current evaluation radix
324 * sym * sp pointer to a sym structure
325 * tsym * tp pointer to a tsym structure
326 * int v current digit evaluation
328 * global variables:
329 * char ctype[] array of character types, one per
330 * ASCII character
331 * int nflag don't resolve global assigned value symbols flag
332 * sym * symp pointer to a symbol structure
334 * functions called:
335 * VOID abscheck() asexpr.c
336 * int digit() asexpr.c
337 * VOID err() assubr.c
338 * VOID expr() asexpr.c
339 * int is_abs() asexpr.c
340 * int get() aslex.c
341 * VOID getid() aslex.c
342 * int getmap() aslex.c
343 * int getnb() aslex.c
344 * sym * lookup() assym.c
345 * VOID qerr() assubr.c
346 * VOID unget() aslex.c
348 * side effects:
349 * An arithmetic term is evaluated, a symbol structure
350 * may be created, term evaluation may be terminated
351 * by a 'q' error.
354 VOID
355 term(struct expr *esp)
357 int c;
358 const char *jp;
359 char id[NCPS];
360 struct sym *sp;
361 struct tsym *tp;
362 int r, v;
363 a_uint n;
365 r = radix;
366 c = getnb();
368 * Discard the unary '+' at this point and
369 * also any reference to numerical arguments
370 * associated with the '#' prefix.
372 while (c == '+' || c == '#') { c = getnb(); }
374 * Evaluate all binary operators
375 * by recursively calling expr().
377 if (c == LFTERM) {
378 expr(esp, 0);
379 if (getnb() != RTTERM)
380 qerr();
381 return;
383 if (c == '-') {
384 expr(esp, 100);
385 abscheck(esp);
386 esp->e_addr = ~esp->e_addr + 1;
387 return;
389 if (c == '~') {
390 expr(esp, 100);
391 abscheck(esp);
392 esp->e_addr = ~esp->e_addr;
393 return;
395 if (c == '\'') {
396 esp->e_mode = S_USER;
397 esp->e_addr = getmap(-1)&0377;
398 /* MB: accept a closing ' */
399 c = get();
400 if (c != '\'')
401 unget(c);
402 return;
404 if (c == '\"') {
405 esp->e_mode = S_USER;
406 if ((int) hilo) {
407 esp->e_addr = (getmap(-1)&0377)<<8;
408 esp->e_addr |= (getmap(-1)&0377);
409 } else {
410 esp->e_addr = (getmap(-1)&0377);
411 esp->e_addr |= (getmap(-1)&0377)<<8;
413 /* MB: accept a closing " */
414 c = get();
415 if (c != '\"')
416 unget(c);
417 return;
419 if (c == '>' || c == '<') {
420 if (is_sdas_target_pdk()) {
421 waddrmode = 1;
423 expr(esp, 100);
424 if (is_sdas_target_pdk()) {
425 waddrmode = 0;
427 if (is_abs (esp)) {
429 * evaluate byte selection directly
431 if (c == '>')
432 esp->e_addr >>= 8;
433 esp->e_addr &= 0377;
434 return;
435 } else {
437 * let linker perform byte selection
439 esp->e_rlcf |= R_BYTX;
440 if (c == '>')
441 esp->e_rlcf |= R_MSB;
442 return;
446 * Evaluate digit sequences as reusable symbols
447 * if followed by a '$' or as constants.
449 if (ctype[c] & DIGIT) {
450 esp->e_mode = S_USER;
451 jp = ip;
452 while (ctype[*jp & 0x007F] & RAD10) {
453 jp++;
455 if (*jp == '$') {
456 n = 0;
457 while ((v = digit(c, 10)) >= 0) {
458 n = 10*n + v;
459 c = get();
461 n = rngchk(n);
462 tp = symp->s_tsym;
463 while (tp) {
464 if (n == tp->t_num) {
465 esp->e_base.e_ap = tp->t_area;
466 esp->e_addr = tp->t_addr;
467 return;
469 tp = tp->t_lnk;
471 err('u');
472 return;
474 if (c == '0') {
475 c = get();
476 switch (c) {
477 case 'b':
478 case 'B':
479 r = 2;
480 c = get();
481 break;
482 case 'o':
483 case 'O':
484 case 'q':
485 case 'Q':
486 r = 8;
487 c = get();
488 break;
489 case 'd':
490 case 'D':
491 r = 10;
492 c = get();
493 break;
494 case 'h':
495 case 'H':
496 case 'x':
497 case 'X':
498 r = 16;
499 c = get();
500 break;
501 default:
502 break;
505 n = 0;
506 while ((v = digit(c, r)) >= 0) {
507 n = r*n + v;
508 c = get();
510 unget(c);
511 if (is_sdas_target_pdk() && waddrmode) {
512 n *= 2;
514 esp->e_addr = rngchk(n);
515 return;
518 * Evaluate '$' sequences as a temporary radix
519 * if followed by a '%', '&', '#', or '$'.
521 if (c == '$') {
522 c = get();
523 if (c == '%' || c == '&' || c == '#' || c == '$') {
524 switch (c) {
525 case '%':
526 r = 2;
527 break;
528 case '&':
529 r = 8;
530 break;
531 case '#':
532 r = 10;
533 break;
534 case '$':
535 r = 16;
536 break;
537 default:
538 break;
540 c = get();
541 n = 0;
542 while ((v = digit(c, r)) >= 0) {
543 n = r*n + v;
544 c = get();
546 unget(c);
547 esp->e_mode = S_USER;
548 esp->e_addr = rngchk(n);
549 return;
551 unget(c);
552 c = '$';
555 * Evaluate symbols and labels
557 if (ctype[c] & LETTER) {
558 getid(id, c);
559 esp->e_mode = S_USER;
560 sp = lookup(id);
561 /* Handle if the symbol or label is not yet defined.
563 Also leave unevaluated if it's a global with an assigned value
564 and the don't resolve global symbol assigns flag is set.
565 This allows the value to get resolved at link time instead
566 of during compile time. */
567 if ((sp->s_type == S_NEW) || ((sp->s_flag & S_GBL) && (sp->s_flag & S_ASG) && (nflag))) {
568 esp->e_addr = 0;
570 * Flag the expression symbol as external if it's global
572 if (sp->s_flag&S_GBL) {
573 esp->e_flag = 1;
574 esp->e_base.e_sp = sp;
575 return;
578 * Otherwise it's an undefined symbol
580 err('u');
581 } else {
582 esp->e_mode = sp->s_type;
583 esp->e_addr = sp->s_addr;
584 esp->e_base.e_ap = sp->s_area;
585 /* MB: abused bit 15 of s_addr to indicate bit-addressable bytes */
586 if ((sp->s_addr & 0x8000) && sp->s_area &&
587 (!strcmp(sp->s_area->a_id, "BSEG_BYTES") || !strcmp(sp->s_area->a_id, "BIT_BANK"))) {
588 esp->e_rlcf |= R_BIT | R_BYTX;
591 return;
594 * Else not a term.
596 qerr();
599 /*)Function int digit(c, r)
601 * int c digit character
602 * int r current radix
604 * The function digit() returns the value of c
605 * in the current radix r. If the c value is not
606 * a number of the current radix then a -1 is returned.
608 * local variables:
609 * none
611 * global variables:
612 * char ctype[] array of character types, one per
613 * ASCII character
615 * functions called:
616 * none
618 * side effects:
619 * none
623 digit(int c, int r)
625 if (r == 16) {
626 if (ctype[c] & RAD16) {
627 if (c >= 'A' && c <= 'F')
628 return (c - 'A' + 10);
629 if (c >= 'a' && c <= 'f')
630 return (c - 'a' + 10);
631 return (c - '0');
633 } else
634 if (r == 10) {
635 if (ctype[c] & RAD10)
636 return (c - '0');
637 } else
638 if (r == 8) {
639 if (ctype[c] & RAD8)
640 return (c - '0');
641 } else
642 if (r == 2) {
643 if (ctype[c] & RAD2)
644 return (c - '0');
646 return (-1);
649 /*)Function VOID abscheck(esp)
651 * expr * esp pointer to an expr structure
653 * The function abscheck() tests the evaluation of an
654 * expression to verify it is absolute. If the evaluation
655 * is relocatable then an 'r' error is noted and the expression
656 * made absolute.
658 * Note: The area type (i.e. ABS) is not checked because
659 * the linker can be told to explicitly relocate an
660 * absolute area.
662 * local variables:
663 * none
665 * global variables:
666 * none
668 * functions called:
669 * VOID rerr() assubr.c
671 * side effects:
672 * The expression may be changed to absolute and the
673 * 'r' error invoked.
676 VOID
677 abscheck(struct expr *esp)
679 if (esp->e_flag || esp->e_base.e_ap) {
680 esp->e_flag = 0;
681 esp->e_base.e_ap = NULL;
682 rerr();
686 /*)Function int is_abs(esp)
688 * expr * esp pointer to an expr structure
690 * The function is_abs() tests the evaluation of an
691 * expression to verify it is absolute. If the evaluation
692 * is absolute then 1 is returned, else 0 is returned.
694 * Note: The area type (i.e. ABS) is not checked because
695 * the linker can be told to explicitly relocate an
696 * absolute area.
698 * local variables:
699 * none
701 * global variables:
702 * none
704 * functions called:
705 * none
707 * side effects:
708 * none
712 is_abs (struct expr *esp)
714 if (esp->e_flag || esp->e_base.e_ap) {
715 return(0);
717 return(1);
720 /*)Function int oprio(c)
722 * int c operator character
724 * The function oprio() returns a relative priority
725 * for all valid unary and binary operators.
727 * local variables:
728 * none
730 * global variables:
731 * none
733 * functions called:
734 * none
736 * side effects:
737 * none
741 oprio(int c)
743 if (c == '*' || c == '/' || c == '%')
744 return (10);
745 if (c == '+' || c == '-')
746 return (7);
747 if (c == '<' || c == '>')
748 return (5);
749 if (c == '^')
750 return (4);
751 if (c == '&')
752 return (3);
753 if (c == '|')
754 return (1);
755 if (is_sdas() && is_sdas_target_8051_like() && c == '[')
756 return (12);
757 return (0);
760 /*)Function VOID clrexpr(esp)
762 * expr * esp pointer to expression structure
764 * The function clrexpr() clears the expression structure.
766 * local variables:
767 * none
769 * global variables:
770 * none
772 * functions called:
773 * none
775 * side effects:
776 * expression structure cleared.
779 VOID
780 clrexpr(struct expr *esp)
782 esp->e_mode = 0;
783 esp->e_flag = 0;
784 esp->e_addr = 0;
785 esp->e_base.e_ap = NULL;
786 esp->e_rlcf = 0;
789 /*)Function a_uint rngchk(n)
791 * a_uint n a signed /unsigned value
793 * The function rngchk() verifies that the
794 * value of n is a signed or unsigned value
795 * within the range of the current exprmasks()
796 * settings and returns the value masked to
797 * the current exprmasks() settings.
799 * local variables:
800 * none
802 * global variables:
803 * a_uint a_mask Address mask
804 * int vflag Enable flag
805 * a_aint v_mask Value mask
807 * functions called:
808 * VOID err() assubr.c
810 * side effects:
811 * a 'v' error message may be generated.
813 * Note:
814 * When the default arithmetic size is the
815 * same as the default sizeof(int) then the
816 * arithmetic overflow cannot be determined.
817 * This ambiguity is caused by the inability
818 * to distinguish signed and unsigned values
819 * at the instrinsic sizeof(int) size.
822 a_uint
823 rngchk(a_uint n)
825 if (vflag) {
826 if ((n & ~a_mask) && ((n & ~a_mask) != ~a_mask)) {
827 err('v');
830 return((n & s_mask) ? (n | ~v_mask) : (n & v_mask));
833 /*)Function VOID exprmasks(esp)
835 * int n T Line Bytes in Address
837 * The function exprmasks() configures the assembler
838 * for 16, 24, or 32-Bit Data/Addresses.
840 * local variables:
841 * none
843 * global variables:
844 * int a_bytes T Line Bytes in Address
845 * a_uint a_mask Address mask
846 * a_uint s_mask Sign mask
847 * a_uint v_mask Value mask
849 * functions called:
850 * none
852 * side effects:
853 * The arithmetic precision parameters are set.
856 VOID
857 exprmasks(int n)
859 a_bytes = n;
861 #ifdef LONGINT
862 switch(a_bytes) {
863 default:
864 a_bytes = 2;
865 case 2:
866 a_mask = (a_uint) 0x0000FFFFl;
867 s_mask = (a_uint) 0x00008000l;
868 v_mask = (a_uint) 0x00007FFFl;
869 break;
871 case 3:
872 a_mask = (a_uint) 0x00FFFFFFl;
873 s_mask = (a_uint) 0x00800000l;
874 v_mask = (a_uint) 0x007FFFFFl;
875 break;
877 case 4:
878 a_mask = (a_uint) 0xFFFFFFFFl;
879 s_mask = (a_uint) 0x80000000l;
880 v_mask = (a_uint) 0x7FFFFFFFl;
881 break;
883 #else
884 switch(a_bytes) {
885 default:
886 a_bytes = 2;
887 case 2:
888 a_mask = (a_uint) 0x0000FFFF;
889 s_mask = (a_uint) 0x00008000;
890 v_mask = (a_uint) 0x00007FFF;
891 break;
893 case 3:
894 a_mask = (a_uint) 0x00FFFFFF;
895 s_mask = (a_uint) 0x00800000;
896 v_mask = (a_uint) 0x007FFFFF;
897 break;
899 case 4:
900 a_mask = (a_uint) 0xFFFFFFFF;
901 s_mask = (a_uint) 0x80000000;
902 v_mask = (a_uint) 0x7FFFFFFF;
903 break;
905 #endif