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