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