* asranlib/asranlib.c, link/lkar.h, link/lkar.c:
[fw/sdcc] / as / mcs51 / asexpr.c
1 /* asexpr.c
2
3    Copyright (C) 1989-1995 Alan R. Baldwin
4    721 Berkeley St., Kent, Ohio 44240
5
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
9 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 #include <stdio.h>
20 #include <setjmp.h>
21 #include <string.h>
22 #include "asm.h"
23
24 /*)Module       asexpr.c
25  *
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.
34  *
35  *      asexpr.c contains the following functions:
36  *              VOID    abscheck()
37  *              Addr_T  absexpr()
38  *              VOID    clrexpr()
39  *              int     digit()
40  *              VOID    expr()
41  *              int     oprio()
42  *              VOID    term()
43  *
44  *      asexpr.c contains no local/static variables
45  */
46
47 /*)Function     VOID    expr(esp, n)
48  *
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.
53  *
54  *      The function expr() evaluates an expression and
55  *      stores its value and relocation information into
56  *      the expr structure supplied by the user.
57  *
58  *      local variables:
59  *              int     c               current assembler-source
60  *                                      text character
61  *              int     p               current operator priority
62  *              area *  ap              pointer to an area structure
63  *              exp     re              internal expr structure
64  *
65  *      global variables:
66  *              char    ctype[]         array of character types, one per
67  *                                      ASCII character
68  *
69  *      functions called:
70  *              VOID    abscheck()      asexpr.c
71  *              VOID    clrexpr()       asexpr.c
72  *              VOID    expr()          asexpr.c
73  *              int     getnb()         aslex.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
79  *
80  *
81  *      side effects:
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.
86  */
87
88 VOID
89 expr(register struct expr *esp, int n)
90 {
91         register int c, p;
92         struct area *ap;
93         struct expr re;
94
95         term(esp);
96         while (ctype[c = getnb()] & BINOP) {
97                 /*
98                  * Handle binary operators + - * / & | % ^ << >> [
99                  */
100                 if ((p = oprio(c)) <= n)
101                         break;
102                 if ((c == '>' || c == '<') && c != get())
103                         qerr();
104                 clrexpr(&re);
105                 expr(&re, p);
106                 esp->e_rlcf |= re.e_rlcf;
107                 if (c == '+') {
108                         /*
109                          * esp + re, at least one must be absolute
110                          */
111                         if (esp->e_base.e_ap == NULL) {
112                                 /*
113                                  * esp is absolute (constant),
114                                  * use area from re
115                                  */
116                                 esp->e_base.e_ap = re.e_base.e_ap;
117                         } else
118                         if (re.e_base.e_ap) {
119                                 /*
120                                  * re should be absolute (constant)
121                                  */
122                                 rerr();
123                         }
124                         if (esp->e_flag && re.e_flag)
125                                 rerr();
126                         if (re.e_flag)
127                                 esp->e_flag = 1;
128                         esp->e_addr += re.e_addr;
129                 } else
130                 if (c == '-') {
131                         /*
132                          * esp - re
133                          */
134                         if ((ap = re.e_base.e_ap) != NULL) {
135                                 if (esp->e_base.e_ap == ap) {
136                                         esp->e_base.e_ap = NULL;
137                                 } else {
138                                         rerr();
139                                 }
140                         }
141                         if (re.e_flag)
142                                 rerr();
143                         esp->e_addr -= re.e_addr;
144                 } else {
145                         /*
146                          * Both operands (esp and re) must be constants
147                          */
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 */
153                        switch (c) {
154
155                         case '*':
156                             abscheck(esp);
157                             abscheck(&re);
158                             esp->e_addr *= re.e_addr;
159                             break;
160
161                         case '/':
162                             abscheck(esp);
163                             abscheck(&re);
164                             esp->e_addr /= re.e_addr;
165                             break;
166
167                         case '&':
168                             abscheck(esp);
169                             abscheck(&re);
170                             esp->e_addr &= re.e_addr;
171                             break;
172
173                         case '|':
174                             abscheck(esp);
175                             abscheck(&re);
176                             esp->e_addr |= re.e_addr;
177                             break;
178
179                         case '%':
180                             abscheck(esp);
181                             abscheck(&re);
182                             esp->e_addr %= re.e_addr;
183                             break;
184
185                         case '^':
186                             abscheck(esp);
187                             abscheck(&re);
188                             esp->e_addr ^= re.e_addr;
189                             break;
190
191                         case '<':
192                             abscheck(esp);
193                             abscheck(&re);
194                             esp->e_addr <<= re.e_addr;
195                             break;
196
197                         case '>':
198                             /* SD change here */
199                             abscheck(&re);
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 ;
204                                 break;
205                             }
206                             else if (esp->e_base.e_ap && re.e_addr == 16)
207                             {
208 //                                if (flat24Mode)
209 //                                {
210                                     esp->e_rlcf |= R_HIB;
211 //                                }
212 //                                else
213 //                                {
214 //                                    warnBanner();
215 //                                    fprintf(stderr,
216 //                                            "(expr >> 16) is only meaningful in "
217 //                                            ".flat24 mode.\n");
218 //                                    qerr();
219 //                                }
220
221                                break;
222                             }
223                             /* else continue with the normal processing */
224                             abscheck(esp);
225                             esp->e_addr >>= re.e_addr;
226                             break;
227                         case '[':
228                             /* MB added [ for bit access in bdata */
229                             abscheck(&re);
230                             if (getnb() != ']')
231                                 qerr();
232
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;
236                                 break;
237                             }
238                             else if ((esp->e_addr & 0x87) == 0x80) {
239                                 esp->e_addr |= re.e_addr;
240                                 break;
241                             }
242
243                        default:
244                            qerr();
245                            break;
246                        }
247                 }
248         }
249         unget(c);
250 }
251
252 /*)Function     Addr_T  absexpr()
253  *
254  *      The function absexpr() evaluates an expression, verifies it
255  *      is absolute (i.e. not position dependent or relocatable), and
256  *      returns its value.
257  *
258  *      local variables:
259  *              expr    e               expr structure
260  *
261  *      global variables:
262  *              none
263  *
264  *      functions called:
265  *              VOID    abscheck()      asexpr.c
266  *              VOID    clrexpr()       asexpr.c
267  *              VOID    expr()          asexpr.c
268  *
269  *      side effects:
270  *              If the expression is not absolute then
271  *              a 'r' error is reported.
272  */
273
274 Addr_T
275 absexpr(void)
276 {
277         struct expr e;
278
279         clrexpr(&e);
280         expr(&e, 0);
281         abscheck(&e);
282         return (e.e_addr);
283 }
284
285 /*)Function     VOID    term(esp)
286  *
287  *              expr *  esp             pointer to an expr structure
288  *
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.
294  *
295  *      local variables:
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
304  *
305  *      global variables:
306  *              char    ctype[]         array of character types, one per
307  *                                      ASCII character
308  *              sym *   symp            pointer to a symbol structure
309  *
310  *      functions called:
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
316  *              int     get()           aslex.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
323  *
324  *      side effects:
325  *              An arithmetic term is evaluated, a symbol structure
326  *              may be created, term evaluation may be terminated
327  *              by a 'q' error.
328  */
329
330 VOID
331 term(register struct expr *esp)
332 {
333         register int c, n;
334         register const char *jp;
335         char id[NCPS];
336         struct sym  *sp;
337         struct tsym *tp;
338         int r=0, v;
339
340         c = getnb();
341         /*
342          * Discard the unary '+' at this point and
343          * also any reference to numerical arguments
344          * associated with the '#' prefix.
345          */
346         while (c == '+' || c == '#') { c = getnb(); }
347         /*
348          * Evaluate all binary operators
349          * by recursively calling expr().
350          */
351         if (c == LFTERM) {
352                 expr(esp, 0);
353                 if (getnb() != RTTERM)
354                         qerr();
355                 return;
356         }
357         if (c == '-') {
358                 expr(esp, 100);
359                 abscheck(esp);
360                 esp->e_addr = 0-esp->e_addr;
361                 return;
362         }
363         if (c == '~') {
364                 expr(esp, 100);
365                 abscheck(esp);
366                 esp->e_addr = ~esp->e_addr;
367                 return;
368         }
369         if (c == '\'') {
370                 esp->e_mode = S_USER;
371                 esp->e_addr = getmap(-1)&0377;
372                 return;
373         }
374         if (c == '\"') {
375                 esp->e_mode = S_USER;
376                 if (hilo) {
377                     esp->e_addr  = (getmap(-1)&0377)<<8;
378                     esp->e_addr |= (getmap(-1)&0377);
379                 } else {
380                     esp->e_addr  = (getmap(-1)&0377);
381                     esp->e_addr |= (getmap(-1)&0377)<<8;
382                 }
383                 return;
384         }
385         if (c == '>' || c == '<') {
386                 expr(esp, 100);
387                 if (is_abs (esp)) {
388                         /*
389                          * evaluate msb/lsb directly
390                          */
391                         if (c == '>')
392                                 esp->e_addr >>= 8;
393                         esp->e_addr &= 0377;
394                         return;
395                 } else {
396                         /*
397                          * let linker perform msb/lsb, lsb is default
398                          */
399                         esp->e_rlcf |= R_BYT2;
400                         if (c == '>')
401                                 esp->e_rlcf |= R_MSB;
402                         return;
403                 }
404         }
405         /*
406          * Evaluate digit sequences as local symbols
407          * if followed by a '$' or as constants.
408          */
409         if (ctype[c] & DIGIT) {
410                 esp->e_mode = S_USER;
411                 jp = ip;
412                 while (ctype[(int)*jp] & RAD10) {
413                         jp++;
414                 }
415                 if (*jp == '$') {
416                         n = 0;
417                         while ((v = digit(c, 10)) >= 0) {
418                                 n = 10*n + v;
419                                 c = get();
420                         }
421                         tp = symp->s_tsym;
422                         while (tp) {
423                                 if (n == tp->t_num) {
424                                         esp->e_base.e_ap = tp->t_area;
425                                         esp->e_addr = tp->t_addr;
426                                         return;
427                                 }
428                                 tp = tp->t_lnk;
429                         }
430                         err('u');
431                         return;
432                 }
433                 r = radix;
434                 if (c == '0') {
435                         c = get();
436                         switch (c) {
437                                 case 'b':
438                                 case 'B':
439                                         r = 2;
440                                         c = get();
441                                         break;
442                                 case 'o':
443                                 case 'O':
444                                 case 'q':
445                                 case 'Q':
446                                         r = 8;
447                                         c = get();
448                                         break;
449                                 case 'd':
450                                 case 'D':
451                                         r = 10;
452                                         c = get();
453                                         break;
454                                 case 'h':
455                                 case 'H':
456                                 case 'x':
457                                 case 'X':
458                                         r = 16;
459                                         c = get();
460                                         break;
461                                 default:
462                                         break;
463                         }
464                 }
465                 n = 0;
466                 while ((v = digit(c, r)) >= 0) {
467                         n = r*n + v;
468                         c = get();
469                 }
470                 unget(c);
471                 esp->e_addr = n;
472                 return;
473         }
474         /*
475          * Evaluate '$' sequences as a temporary radix
476          * if followed by a '%', '&', '#', or '$'.
477          */
478         if (c == '$') {
479                 c = get();
480                 if (c == '%' || c == '&' || c == '#' || c == '$') {
481                         switch (c) {
482                                 case '%':
483                                         r = 2;
484                                         break;
485                                 case '&':
486                                         r = 8;
487                                         break;
488                                 case '#':
489                                         r = 10;
490                                         break;
491                                 case '$':
492                                         r = 16;
493                                         break;
494                                 default:
495                                         break;
496                         }
497                         c = get();
498                         n = 0;
499                         while ((v = digit(c, r)) >= 0) {
500                                 n = r*n + v;
501                                 c = get();
502                         }
503                         unget(c);
504                         esp->e_mode = S_USER;
505                         esp->e_addr = n;
506                         return;
507                 }
508                 unget(c);
509                 c = '$';
510         }
511         /*
512          * Evaluate symbols and labels
513          */
514         if (ctype[c] & LETTER) {
515                 esp->e_mode = S_USER;
516                 getid(id, c);
517                 sp = lookup(id);
518                 if (sp->s_type == S_NEW) {
519                         esp->e_addr = 0;
520                         if (sp->s_flag&S_GBL) {
521                                 esp->e_flag = 1;
522                                 esp->e_base.e_sp = sp;
523                                 return;
524                         }
525                         /* err('u'); */
526                 } else {
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;
534                         }
535                 }
536                 return;
537         }
538         /*
539          * Else not a term.
540          */
541         qerr();
542 }
543
544 /*)Function     int     digit(c, r)
545  *
546  *              int     c               digit character
547  *              int     r               current radix
548  *
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.
552  *
553  *      local variables:
554  *              none
555  *
556  *      global variables:
557  *              char    ctype[]         array of character types, one per
558  *                                      ASCII character
559  *
560  *      functions called:
561  *              none
562  *
563  *      side effects:
564  *              none
565  */
566
567 int
568 digit(register int c, register int r)
569 {
570         if (r == 16) {
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);
576                         return (c - '0');
577                 }
578         } else
579         if (r == 10) {
580                 if (ctype[c] & RAD10)
581                         return (c - '0');
582         } else
583         if (r == 8) {
584                 if (ctype[c] & RAD8)
585                         return (c - '0');
586         } else
587         if (r == 2) {
588                 if (ctype[c] & RAD2)
589                         return (c - '0');
590         }
591         return (-1);
592 }
593
594 /*)Function     VOID    abscheck(esp)
595  *
596  *              expr *  esp             pointer to an expr structure
597  *
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
601  *      made absolute.
602  *
603  *      Note:   The area type (i.e. ABS) is not checked because
604  *              the linker can be told to explicitly relocate an
605  *              absolute area.
606  *
607  *      local variables:
608  *              none
609  *
610  *      global variables:
611  *              none
612  *
613  *      functions called:
614  *              VOID    rerr()          assubr.c
615  *
616  *      side effects:
617  *              The expression may be changed to absolute and the
618  *              'r' error invoked.
619  */
620
621 VOID
622 abscheck(register struct expr *esp)
623 {
624         if (esp->e_flag || esp->e_base.e_ap) {
625                 esp->e_flag = 0;
626                 esp->e_base.e_ap = NULL;
627                 rerr();
628         }
629 }
630
631 /*)Function     int     is_abs(esp)
632  *
633  *              expr *  esp             pointer to an expr structure
634  *
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.
638  *
639  *      Note:   The area type (i.e. ABS) is not checked because
640  *              the linker can be told to explicitly relocate an
641  *              absolute area.
642  *
643  *      local variables:
644  *              none
645  *
646  *      global variables:
647  *              none
648  *
649  *      functions called:
650  *              none
651  *
652  *      side effects:
653  *              none
654  */
655
656 int
657 is_abs (register struct expr *esp)
658 {
659         if (esp->e_flag || esp->e_base.e_ap) {
660                 return(0);
661         }
662         return(1);
663 }
664
665 /*)Function     int     oprio(c)
666  *
667  *              int     c               operator character
668  *
669  *      The function oprio() returns a relative priority
670  *      for all valid unary and binary operators.
671  *
672  *      local variables:
673  *              none
674  *
675  *      global variables:
676  *              none
677  *
678  *      functions called:
679  *              none
680  *
681  *      side effects:
682  *              none
683  */
684
685 int
686 oprio(register int c)
687 {
688         if (c == '[')
689                 return (12);
690         if (c == '*' || c == '/' || c == '%')
691                 return (10);
692         if (c == '+' || c == '-')
693                 return (7);
694         if (c == '<' || c == '>')
695                 return (5);
696         if (c == '^')
697                 return (4);
698         if (c == '&')
699                 return (3);
700         if (c == '|')
701                 return (1);
702         return (0);
703 }
704
705 /*)Function     VOID    clrexpr(esp)
706  *
707  *              expr *  esp             pointer to expression structure
708  *
709  *      The function clrexpr() clears the expression structure.
710  *
711  *      local variables:
712  *              none
713  *
714  *      global variables:
715  *              none
716  *
717  *      functions called:
718  *              none
719  *
720  *      side effects:
721  *              expression structure cleared.
722  */
723
724 VOID
725 clrexpr(register struct expr *esp)
726 {
727         esp->e_mode = 0;
728         esp->e_flag = 0;
729         esp->e_addr = 0;
730         esp->e_base.e_ap = NULL;
731         esp->e_rlcf = 0;
732 }