1 /* asexpr.c */
2
3 /*
4 * Copyright (C) 1989-2010 Alan R. Baldwin
5 *
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.
10 *
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.
15 *
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/>.
18 *
19 *
20 * Alan R. Baldwin
21 * 721 Berkeley St.
22 * Kent, Ohio 44240
23 *
24 * With enhancements from
25 *
26 * Bill McKinnon (BM)
27 * w_mckinnon at conknet dot com
28 */
29
30 #include "sdas.h"
31 #include "asxxxx.h"
32
33 /*)Module asexpr.c
34 *
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.
43 *
44 * asexpr.c contains the following functions:
45 * VOID abscheck()
46 * a_uint absexpr()
47 * VOID clrexpr()
48 * int digit()
49 * VOID expr()
50 * VOID exprmasks()
51 * int oprio()
52 * VOID term()
53 * a_uint rngchk()
54 *
55 * asexpr.c contains no local/static variables
56 */
57
58 /*)Function VOID expr(esp, n)
59 *
60 * expr * esp pointer to an expr structure
61 * int n a firewall priority; all top
62 * level calls (from the user)
63 * should be made with n set to 0.
64 *
65 * The function expr() evaluates an expression and
66 * stores its value and relocation information into
67 * the expr structure supplied by the user.
68 *
69 * local variables:
70 * a_uint ae value from expr esp
71 * a_uint ar value from expr re
72 * int c current assembler-source
73 * text character
74 * int p current operator priority
75 * area * ap pointer to an area structure
76 * exp re internal expr structure
77 *
78 * global variables:
79 * char ctype[] array of character types, one per
80 * ASCII character
81 *
82 * functions called:
83 * VOID abscheck() asexpr.c
84 * VOID clrexpr() asexpr.c
85 * VOID expr() asexpr.c
86 * int get() aslex.c
87 * int getnb() aslex.c
88 * int oprio() asexpr.c
89 * VOID qerr() assubr.c
90 * VOID rerr() assubr.c
91 * VOID term() asexpr.c
92 * VOID unget() aslex.c
93 *
94 *
95 * side effects:
96 * An expression is evaluated modifying the user supplied
97 * expr structure, a sym structure maybe created for an
98 * undefined symbol, and the parse of the expression may
99 * terminate if a 'q' error occurs.
100 */
101
102 VOID
expr(struct expr * esp,int n)103 expr(struct expr *esp, int n)
104 {
105 a_uint ae, ar;
106 int c, p;
107 struct area *ap;
108 struct expr re;
109
110 term(esp);
111 while (ctype[c = getnb()] & BINOP) {
112 /*
113 * Handle binary operators + - * / & | % ^ << >> [
114 */
115 if ((p = oprio(c)) <= n)
116 break;
117 if ((c == '>' || c == '<') && c != get())
118 qerr();
119 clrexpr(&re);
120 expr(&re, p);
121 esp->e_rlcf |= re.e_rlcf;
122
123 ae = esp->e_addr;
124 ar = re.e_addr;
125
126 if (c == '+') {
127 /*
128 * esp + re, at least one must be absolute
129 */
130 if (esp->e_base.e_ap == NULL) {
131 /*
132 * esp is absolute (constant),
133 * use area from re
134 */
135 esp->e_base.e_ap = re.e_base.e_ap;
136 } else
137 if (re.e_base.e_ap) {
138 /*
139 * re should be absolute (constant)
140 */
141 rerr();
142 }
143 if (esp->e_flag && re.e_flag)
144 rerr();
145 if (re.e_flag)
146 esp->e_flag = 1;
147 ae += ar;
148 } else
149 if (c == '-') {
150 /*
151 * esp - re
152 */
153 if ((ap = re.e_base.e_ap) != NULL) {
154 if (esp->e_base.e_ap == ap) {
155 esp->e_base.e_ap = NULL;
156 } else {
157 rerr();
158 }
159 }
160 if (re.e_flag)
161 rerr();
162 ae -= ar;
163 } else {
164 /*
165 * Both operands (esp and re) must be constants
166 */
167 /* SD/MB :- postpone the abscheck to cases '>' and '['
168 and change the right shift operator.. if
169 right shift by 8/16/24 bits of a relocatable address then
170 the user wants the higher order byte. set the R_MSB
171 for the expression */
172 if (c != '>' && c != '[')
173 abscheck(esp);
174 abscheck(&re);
175 switch (c) {
176 /*
177 * The (int) /, %, and >> operations
178 * are truncated to a_bytes.
179 */
180 case '*':
181 ae *= ar;
182 break;
183
184 case '/':
185 if (ar == 0) {
186 ae = 0;
187 err('z');
188 } else {
189 ae /= ar;
190 }
191 break;
192
193 case '&':
194 ae &= ar;
195 break;
196
197 case '|':
198 ae |= ar;
199 break;
200
201 case '%':
202 if (ar == 0) {
203 ae = 0;
204 err('z');
205 } else {
206 ae %= ar;
207 }
208 break;
209
210 case '^':
211 ae ^= ar;
212 break;
213
214 case '<':
215 ae <<= ar;
216 break;
217
218 case '>':
219 /* SD change here */
220 /* if the left is a relative address &
221 the right side is 8/16/24 then */
222 if (esp->e_base.e_ap && ar == 8) {
223 esp->e_rlcf |= R_MSB;
224 break;
225 }
226 else if (esp->e_base.e_ap && ar == 16) {
227 esp->e_rlcf |= R_HIB;
228 break;
229 }
230 else if (esp->e_base.e_ap && ar == 24) {
231 esp->e_rlcf |= R_MSB | R_HIB;
232 break;
233 }
234 /* else continue with the normal processing */
235 abscheck(esp);
236 ae >>= ar;
237 break;
238
239 case '[':
240 if (is_sdas() && is_sdas_target_8051_like()) {
241 /* MB added [ for bit access in bdata */
242 if (getnb() != ']')
243 qerr();
244
245 /* if the left is a relative address then */
246 if (esp->e_base.e_ap) {
247 ae |= (ar | 0x80) << 8;
248 break;
249 }
250 else if ((ae & 0x87) == 0x80) {
251 ae |= ar;
252 break;
253 }
254 }
255 /* fall through */
256
257 default:
258 qerr();
259 break;
260 }
261 }
262 esp->e_addr = rngchk(ae);
263 }
264 unget(c);
265 }
266
267 /*)Function a_uint absexpr()
268 *
269 * The function absexpr() evaluates an expression, verifies it
270 * is absolute (i.e. not position dependent or relocatable), and
271 * returns its value.
272 *
273 * local variables:
274 * expr e expr structure
275 *
276 * global variables:
277 * none
278 *
279 * functions called:
280 * VOID abscheck() asexpr.c
281 * VOID clrexpr() asexpr.c
282 * VOID expr() asexpr.c
283 *
284 * side effects:
285 * If the expression is not absolute then
286 * a 'r' error is reported.
287 */
288
289 a_uint
absexpr(void)290 absexpr(void)
291 {
292 struct expr e;
293
294 clrexpr(&e);
295 expr(&e, 0);
296 abscheck(&e);
297 return (e.e_addr);
298 }
299
300 /*)Function VOID term(esp)
301 *
302 * expr * esp pointer to an expr structure
303 *
304 * The function term() evaluates a single constant
305 * or symbol value prefaced by any unary operator
306 * ( +, -, ~, ', ", >, or < ). This routine is also
307 * responsible for setting the relocation type to symbol
308 * based (e.flag != 0) on global references.
309 *
310 * local variables:
311 * int c current character
312 * char id[] symbol name
313 * char * jp pointer to assembler-source text
314 * a_uint n constant evaluation running sum
315 * int r current evaluation radix
316 * sym * sp pointer to a sym structure
317 * tsym * tp pointer to a tsym structure
318 * int v current digit evaluation
319 *
320 * global variables:
321 * char ctype[] array of character types, one per
322 * ASCII character
323 * sym * symp pointer to a symbol structure
324 *
325 * functions called:
326 * VOID abscheck() asexpr.c
327 * int digit() asexpr.c
328 * VOID err() assubr.c
329 * VOID expr() asexpr.c
330 * int is_abs() asexpr.c
331 * int get() aslex.c
332 * VOID getid() aslex.c
333 * int getmap() aslex.c
334 * int getnb() aslex.c
335 * sym * lookup() assym.c
336 * VOID qerr() assubr.c
337 * VOID unget() aslex.c
338 *
339 * side effects:
340 * An arithmetic term is evaluated, a symbol structure
341 * may be created, term evaluation may be terminated
342 * by a 'q' error.
343 */
344
345 VOID
term(struct expr * esp)346 term(struct expr *esp)
347 {
348 int c;
349 const char *jp;
350 char id[NCPS];
351 struct sym *sp;
352 struct tsym *tp;
353 int r, v;
354 a_uint n;
355
356 r = radix;
357 c = getnb();
358 /*
359 * Discard the unary '+' at this point and
360 * also any reference to numerical arguments
361 * associated with the '#' prefix.
362 */
363 while (c == '+' || c == '#') { c = getnb(); }
364 /*
365 * Evaluate all binary operators
366 * by recursively calling expr().
367 */
368 if (c == LFTERM) {
369 expr(esp, 0);
370 if (getnb() != RTTERM)
371 qerr();
372 return;
373 }
374 if (c == '-') {
375 expr(esp, 100);
376 abscheck(esp);
377 esp->e_addr = ~esp->e_addr + 1;
378 return;
379 }
380 if (c == '~') {
381 expr(esp, 100);
382 abscheck(esp);
383 esp->e_addr = ~esp->e_addr;
384 return;
385 }
386 if (c == '\'') {
387 esp->e_mode = S_USER;
388 esp->e_addr = getmap(-1)&0377;
389 /* MB: accept a closing ' */
390 c = get();
391 if (c != '\'')
392 unget(c);
393 return;
394 }
395 if (c == '\"') {
396 esp->e_mode = S_USER;
397 if ((int) hilo) {
398 esp->e_addr = (getmap(-1)&0377)<<8;
399 esp->e_addr |= (getmap(-1)&0377);
400 } else {
401 esp->e_addr = (getmap(-1)&0377);
402 esp->e_addr |= (getmap(-1)&0377)<<8;
403 }
404 /* MB: accept a closing " */
405 c = get();
406 if (c != '\"')
407 unget(c);
408 return;
409 }
410 if (c == '>' || c == '<') {
411 if (is_sdas_target_pdk()) {
412 waddrmode = 1;
413 }
414 expr(esp, 100);
415 if (is_sdas_target_pdk()) {
416 waddrmode = 0;
417 }
418 if (is_abs (esp)) {
419 /*
420 * evaluate byte selection directly
421 */
422 if (c == '>')
423 esp->e_addr >>= 8;
424 esp->e_addr &= 0377;
425 return;
426 } else {
427 /*
428 * let linker perform byte selection
429 */
430 esp->e_rlcf |= R_BYTX;
431 if (c == '>')
432 esp->e_rlcf |= R_MSB;
433 return;
434 }
435 }
436 /*
437 * Evaluate digit sequences as reusable symbols
438 * if followed by a '$' or as constants.
439 */
440 if (ctype[c] & DIGIT) {
441 esp->e_mode = S_USER;
442 jp = ip;
443 while (ctype[*jp & 0x007F] & RAD10) {
444 jp++;
445 }
446 if (*jp == '$') {
447 n = 0;
448 while ((v = digit(c, 10)) >= 0) {
449 n = 10*n + v;
450 c = get();
451 }
452 n = rngchk(n);
453 tp = symp->s_tsym;
454 while (tp) {
455 if (n == tp->t_num) {
456 esp->e_base.e_ap = tp->t_area;
457 esp->e_addr = tp->t_addr;
458 return;
459 }
460 tp = tp->t_lnk;
461 }
462 err('u');
463 return;
464 }
465 if (c == '0') {
466 c = get();
467 switch (c) {
468 case 'b':
469 case 'B':
470 r = 2;
471 c = get();
472 break;
473 case 'o':
474 case 'O':
475 case 'q':
476 case 'Q':
477 r = 8;
478 c = get();
479 break;
480 case 'd':
481 case 'D':
482 r = 10;
483 c = get();
484 break;
485 case 'h':
486 case 'H':
487 case 'x':
488 case 'X':
489 r = 16;
490 c = get();
491 break;
492 default:
493 break;
494 }
495 }
496 n = 0;
497 while ((v = digit(c, r)) >= 0) {
498 n = r*n + v;
499 c = get();
500 }
501 unget(c);
502 if (is_sdas_target_pdk() && waddrmode) {
503 n *= 2;
504 }
505 esp->e_addr = rngchk(n);
506 return;
507 }
508 /*
509 * Evaluate '$' sequences as a temporary radix
510 * if followed by a '%', '&', '#', or '$'.
511 */
512 if (c == '$') {
513 c = get();
514 if (c == '%' || c == '&' || c == '#' || c == '$') {
515 switch (c) {
516 case '%':
517 r = 2;
518 break;
519 case '&':
520 r = 8;
521 break;
522 case '#':
523 r = 10;
524 break;
525 case '$':
526 r = 16;
527 break;
528 default:
529 break;
530 }
531 c = get();
532 n = 0;
533 while ((v = digit(c, r)) >= 0) {
534 n = r*n + v;
535 c = get();
536 }
537 unget(c);
538 esp->e_mode = S_USER;
539 esp->e_addr = rngchk(n);
540 return;
541 }
542 unget(c);
543 c = '$';
544 }
545 /*
546 * Evaluate symbols and labels
547 */
548 if (ctype[c] & LETTER) {
549 getid(id, c);
550 esp->e_mode = S_USER;
551 sp = lookup(id);
552 if (sp->s_type == S_NEW) {
553 esp->e_addr = 0;
554 if (sp->s_flag&S_GBL) {
555 esp->e_flag = 1;
556 esp->e_base.e_sp = sp;
557 return;
558 }
559 err('u');
560 } else {
561 esp->e_mode = sp->s_type;
562 esp->e_addr = sp->s_addr;
563 esp->e_base.e_ap = sp->s_area;
564 /* MB: abused bit 15 of s_addr to indicate bit-addressable bytes */
565 if ((sp->s_addr & 0x8000) && sp->s_area &&
566 (!strcmp(sp->s_area->a_id, "BSEG_BYTES") || !strcmp(sp->s_area->a_id, "BIT_BANK"))) {
567 esp->e_rlcf |= R_BIT | R_BYTX;
568 }
569 }
570 return;
571 }
572 /*
573 * Else not a term.
574 */
575 qerr();
576 }
577
578 /*)Function int digit(c, r)
579 *
580 * int c digit character
581 * int r current radix
582 *
583 * The function digit() returns the value of c
584 * in the current radix r. If the c value is not
585 * a number of the current radix then a -1 is returned.
586 *
587 * local variables:
588 * none
589 *
590 * global variables:
591 * char ctype[] array of character types, one per
592 * ASCII character
593 *
594 * functions called:
595 * none
596 *
597 * side effects:
598 * none
599 */
600
601 int
digit(int c,int r)602 digit(int c, int r)
603 {
604 if (r == 16) {
605 if (ctype[c] & RAD16) {
606 if (c >= 'A' && c <= 'F')
607 return (c - 'A' + 10);
608 if (c >= 'a' && c <= 'f')
609 return (c - 'a' + 10);
610 return (c - '0');
611 }
612 } else
613 if (r == 10) {
614 if (ctype[c] & RAD10)
615 return (c - '0');
616 } else
617 if (r == 8) {
618 if (ctype[c] & RAD8)
619 return (c - '0');
620 } else
621 if (r == 2) {
622 if (ctype[c] & RAD2)
623 return (c - '0');
624 }
625 return (-1);
626 }
627
628 /*)Function VOID abscheck(esp)
629 *
630 * expr * esp pointer to an expr structure
631 *
632 * The function abscheck() tests the evaluation of an
633 * expression to verify it is absolute. If the evaluation
634 * is relocatable then an 'r' error is noted and the expression
635 * made absolute.
636 *
637 * Note: The area type (i.e. ABS) is not checked because
638 * the linker can be told to explicitly relocate an
639 * absolute area.
640 *
641 * local variables:
642 * none
643 *
644 * global variables:
645 * none
646 *
647 * functions called:
648 * VOID rerr() assubr.c
649 *
650 * side effects:
651 * The expression may be changed to absolute and the
652 * 'r' error invoked.
653 */
654
655 VOID
abscheck(struct expr * esp)656 abscheck(struct expr *esp)
657 {
658 if (esp->e_flag || esp->e_base.e_ap) {
659 esp->e_flag = 0;
660 esp->e_base.e_ap = NULL;
661 rerr();
662 }
663 }
664
665 /*)Function int is_abs(esp)
666 *
667 * expr * esp pointer to an expr structure
668 *
669 * The function is_abs() tests the evaluation of an
670 * expression to verify it is absolute. If the evaluation
671 * is absolute then 1 is returned, else 0 is returned.
672 *
673 * Note: The area type (i.e. ABS) is not checked because
674 * the linker can be told to explicitly relocate an
675 * absolute area.
676 *
677 * local variables:
678 * none
679 *
680 * global variables:
681 * none
682 *
683 * functions called:
684 * none
685 *
686 * side effects:
687 * none
688 */
689
690 int
is_abs(struct expr * esp)691 is_abs (struct expr *esp)
692 {
693 if (esp->e_flag || esp->e_base.e_ap) {
694 return(0);
695 }
696 return(1);
697 }
698
699 /*)Function int oprio(c)
700 *
701 * int c operator character
702 *
703 * The function oprio() returns a relative priority
704 * for all valid unary and binary operators.
705 *
706 * local variables:
707 * none
708 *
709 * global variables:
710 * none
711 *
712 * functions called:
713 * none
714 *
715 * side effects:
716 * none
717 */
718
719 int
oprio(int c)720 oprio(int c)
721 {
722 if (c == '*' || c == '/' || c == '%')
723 return (10);
724 if (c == '+' || c == '-')
725 return (7);
726 if (c == '<' || c == '>')
727 return (5);
728 if (c == '^')
729 return (4);
730 if (c == '&')
731 return (3);
732 if (c == '|')
733 return (1);
734 if (is_sdas() && is_sdas_target_8051_like() && c == '[')
735 return (12);
736 return (0);
737 }
738
739 /*)Function VOID clrexpr(esp)
740 *
741 * expr * esp pointer to expression structure
742 *
743 * The function clrexpr() clears the expression structure.
744 *
745 * local variables:
746 * none
747 *
748 * global variables:
749 * none
750 *
751 * functions called:
752 * none
753 *
754 * side effects:
755 * expression structure cleared.
756 */
757
758 VOID
clrexpr(struct expr * esp)759 clrexpr(struct expr *esp)
760 {
761 esp->e_mode = 0;
762 esp->e_flag = 0;
763 esp->e_addr = 0;
764 esp->e_base.e_ap = NULL;
765 esp->e_rlcf = 0;
766 }
767
768 /*)Function a_uint rngchk(n)
769 *
770 * a_uint n a signed /unsigned value
771 *
772 *
773 * local variables:
774 * none
775 *
776 * global variables:
777 * none
778 *
779 * functions called:
780 * none
781 *
782 * side effects:
783 * none
784 */
785
786 a_uint
rngchk(a_uint n)787 rngchk(a_uint n)
788 {
789 return n;
790 }
791
792 /*)Function VOID exprmasks(esp)
793 *
794 * int n T Line Bytes in Address
795 *
796 * The function exprmasks() configures the assembler
797 * for 16, 24, or 32-Bit Data/Addresses.
798 *
799 * local variables:
800 * none
801 *
802 * global variables:
803 * int a_bytes T Line Bytes in Address
804 * a_uint a_mask Address mask
805 * a_uint s_mask Sign mask
806 * a_uint v_mask Value mask
807 *
808 * functions called:
809 * none
810 *
811 * side effects:
812 * The arithmetic precision parameters are set.
813 */
814
815 VOID
exprmasks(int n)816 exprmasks(int n)
817 {
818 a_bytes = n;
819
820 #ifdef LONGINT
821 switch(a_bytes) {
822 default:
823 a_bytes = 2;
824 case 2:
825 a_mask = (a_uint) 0x0000FFFFl;
826 s_mask = (a_uint) 0x00008000l;
827 v_mask = (a_uint) 0x00007FFFl;
828 break;
829
830 case 3:
831 a_mask = (a_uint) 0x00FFFFFFl;
832 s_mask = (a_uint) 0x00800000l;
833 v_mask = (a_uint) 0x007FFFFFl;
834 break;
835
836 case 4:
837 a_mask = (a_uint) 0xFFFFFFFFl;
838 s_mask = (a_uint) 0x80000000l;
839 v_mask = (a_uint) 0x7FFFFFFFl;
840 break;
841 }
842 #else
843 switch(a_bytes) {
844 default:
845 a_bytes = 2;
846 case 2:
847 a_mask = (a_uint) 0x0000FFFF;
848 s_mask = (a_uint) 0x00008000;
849 v_mask = (a_uint) 0x00007FFF;
850 break;
851
852 case 3:
853 a_mask = (a_uint) 0x00FFFFFF;
854 s_mask = (a_uint) 0x00800000;
855 v_mask = (a_uint) 0x007FFFFF;
856 break;
857
858 case 4:
859 a_mask = (a_uint) 0xFFFFFFFF;
860 s_mask = (a_uint) 0x80000000;
861 v_mask = (a_uint) 0x7FFFFFFF;
862 break;
863 }
864 #endif
865 }
866