fixed warnings and errors
[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                         case '[':
221                             /* MB added [ for bit access in bdata */
222                             abscheck(&re);
223                             if (getnb() != ']')
224                                 qerr();
225
226                             /* if the left is a relative address then */
227                             if (esp->e_base.e_ap) {
228                                 esp->e_addr |= (re.e_addr | 0x80) << 8;
229                                 break;
230                             }
231                             else if ((esp->e_addr & 0x87) == 0x80) {
232                                 esp->e_addr |= re.e_addr;
233                                 break;
234                             }
235
236                        default:
237                            qerr();
238                            break;
239                        }
240                 }
241         }
242         unget(c);
243 }
244
245 /*)Function     Addr_T  absexpr()
246  *
247  *      The function absexpr() evaluates an expression, verifies it
248  *      is absolute (i.e. not position dependent or relocatable), and
249  *      returns its value.
250  *
251  *      local variables:
252  *              expr    e               expr structure
253  *
254  *      global variables:
255  *              none
256  *
257  *      functions called:
258  *              VOID    abscheck()      asexpr.c
259  *              VOID    clrexpr()       asexpr.c
260  *              VOID    expr()          asexpr.c
261  *
262  *      side effects:
263  *              If the expression is not absolute then
264  *              a 'r' error is reported.
265  */
266
267 Addr_T
268 absexpr(void)
269 {
270         struct expr e;
271
272         clrexpr(&e);
273         expr(&e, 0);
274         abscheck(&e);
275         return (e.e_addr);
276 }
277
278 /*)Function     VOID    term(esp)
279  *
280  *              expr *  esp             pointer to an expr structure
281  *
282  *      The function term() evaluates a single constant
283  *      or symbol value prefaced by any unary operator
284  *      ( +, -, ~, ', ", >, or < ).  This routine is also
285  *      responsible for setting the relocation type to symbol
286  *      based (e.flag != 0) on global references.
287  *
288  *      local variables:
289  *              int     c               current character
290  *              char    id[]            symbol name
291  *              char *  jp              pointer to assembler-source text
292  *              int     n               constant evaluation running sum
293  *              int     r               current evaluation radix
294  *              sym *   sp              pointer to a sym structure
295  *              tsym *  tp              pointer to a tsym structure
296  *              int     v               current digit evaluation
297  *
298  *      global variables:
299  *              char    ctype[]         array of character types, one per
300  *                                      ASCII character
301  *              sym *   symp            pointer to a symbol structure
302  *
303  *      functions called:
304  *              VOID    abscheck()      asexpr.c
305  *              int     digit()         asexpr.c
306  *              VOID    err()           assubr.c
307  *              VOID    expr()          asexpr.c
308  *              int     is_abs()        asexpr.c
309  *              int     get()           aslex.c
310  *              VOID    getid()         aslex.c
311  *              int     getmap()        aslex.c
312  *              int     getnb()         aslex.c
313  *              sym *   lookup()        assym.c
314  *              VOID    qerr()          assubr.c
315  *              VOID    unget()         aslex.c
316  *
317  *      side effects:
318  *              An arithmetic term is evaluated, a symbol structure
319  *              may be created, term evaluation may be terminated
320  *              by a 'q' error.
321  */
322
323 VOID
324 term(register struct expr *esp)
325 {
326         register int c, n;
327         register const char *jp;
328         char id[NCPS];
329         struct sym  *sp;
330         struct tsym *tp;
331         int r=0, v;
332
333         c = getnb();
334         /*
335          * Discard the unary '+' at this point and
336          * also any reference to numerical arguments
337          * associated with the '#' prefix.
338          */
339         while (c == '+' || c == '#') { c = getnb(); }
340         /*
341          * Evaluate all binary operators
342          * by recursively calling expr().
343          */
344         if (c == LFTERM) {
345                 expr(esp, 0);
346                 if (getnb() != RTTERM)
347                         qerr();
348                 return;
349         }
350         if (c == '-') {
351                 expr(esp, 100);
352                 abscheck(esp);
353                 esp->e_addr = 0-esp->e_addr;
354                 return;
355         }
356         if (c == '~') {
357                 expr(esp, 100);
358                 abscheck(esp);
359                 esp->e_addr = ~esp->e_addr;
360                 return;
361         }
362         if (c == '\'') {
363                 esp->e_mode = S_USER;
364                 esp->e_addr = getmap(-1)&0377;
365                 return;
366         }
367         if (c == '\"') {
368                 esp->e_mode = S_USER;
369                 if (hilo) {
370                     esp->e_addr  = (getmap(-1)&0377)<<8;
371                     esp->e_addr |= (getmap(-1)&0377);
372                 } else {
373                     esp->e_addr  = (getmap(-1)&0377);
374                     esp->e_addr |= (getmap(-1)&0377)<<8;
375                 }
376                 return;
377         }
378         if (c == '>' || c == '<') {
379                 expr(esp, 100);
380                 if (is_abs (esp)) {
381                         /*
382                          * evaluate msb/lsb directly
383                          */
384                         if (c == '>')
385                                 esp->e_addr >>= 8;
386                         esp->e_addr &= 0377;
387                         return;
388                 } else {
389                         /*
390                          * let linker perform msb/lsb, lsb is default
391                          */
392                         esp->e_rlcf |= R_BYT2;
393                         if (c == '>')
394                                 esp->e_rlcf |= R_MSB;
395                         return;
396                 }
397         }
398         /*
399          * Evaluate digit sequences as local symbols
400          * if followed by a '$' or as constants.
401          */
402         if (ctype[c] & DIGIT) {
403                 esp->e_mode = S_USER;
404                 jp = ip;
405                 while (ctype[(int)*jp] & RAD10) {
406                         jp++;
407                 }
408                 if (*jp == '$') {
409                         n = 0;
410                         while ((v = digit(c, 10)) >= 0) {
411                                 n = 10*n + v;
412                                 c = get();
413                         }
414                         tp = symp->s_tsym;
415                         while (tp) {
416                                 if (n == tp->t_num) {
417                                         esp->e_base.e_ap = tp->t_area;
418                                         esp->e_addr = tp->t_addr;
419                                         return;
420                                 }
421                                 tp = tp->t_lnk;
422                         }
423                         err('u');
424                         return;
425                 }
426                 r = radix;
427                 if (c == '0') {
428                         c = get();
429                         switch (c) {
430                                 case 'b':
431                                 case 'B':
432                                         r = 2;
433                                         c = get();
434                                         break;
435                                 case 'o':
436                                 case 'O':
437                                 case 'q':
438                                 case 'Q':
439                                         r = 8;
440                                         c = get();
441                                         break;
442                                 case 'd':
443                                 case 'D':
444                                         r = 10;
445                                         c = get();
446                                         break;
447                                 case 'h':
448                                 case 'H':
449                                 case 'x':
450                                 case 'X':
451                                         r = 16;
452                                         c = get();
453                                         break;
454                                 default:
455                                         break;
456                         }
457                 }
458                 n = 0;
459                 while ((v = digit(c, r)) >= 0) {
460                         n = r*n + v;
461                         c = get();
462                 }
463                 unget(c);
464                 esp->e_addr = n;
465                 return;
466         }
467         /*
468          * Evaluate '$' sequences as a temporary radix
469          * if followed by a '%', '&', '#', or '$'.
470          */
471         if (c == '$') {
472                 c = get();
473                 if (c == '%' || c == '&' || c == '#' || c == '$') {
474                         switch (c) {
475                                 case '%':
476                                         r = 2;
477                                         break;
478                                 case '&':
479                                         r = 8;
480                                         break;
481                                 case '#':
482                                         r = 10;
483                                         break;
484                                 case '$':
485                                         r = 16;
486                                         break;
487                                 default:
488                                         break;
489                         }
490                         c = get();
491                         n = 0;
492                         while ((v = digit(c, r)) >= 0) {
493                                 n = r*n + v;
494                                 c = get();
495                         }
496                         unget(c);
497                         esp->e_mode = S_USER;
498                         esp->e_addr = n;
499                         return;
500                 }
501                 unget(c);
502                 c = '$';
503         }
504         /*
505          * Evaluate symbols and labels
506          */
507         if (ctype[c] & LETTER) {
508                 esp->e_mode = S_USER;
509                 getid(id, c);
510                 sp = lookup(id);
511                 if (sp->s_type == S_NEW) {
512                         esp->e_addr = 0;
513                         if (sp->s_flag&S_GBL) {
514                                 esp->e_flag = 1;
515                                 esp->e_base.e_sp = sp;
516                                 return;
517                         }
518                         /* err('u'); */
519                 } else {
520                         esp->e_mode = sp->s_type;
521                         esp->e_addr = sp->s_addr;
522                         esp->e_base.e_ap = sp->s_area;
523                         /* MB: abused bit 15 of s_addr to indicate bit-addressable bytes */
524                         if ((sp->s_addr & 0x8000) && sp->s_area &&
525                             (!strcmp(sp->s_area->a_id, "BSEG_BYTES") || !strcmp(sp->s_area->a_id, "BIT_BANK"))) {
526                                 esp->e_rlcf |= R_BIT | R_BYT2;
527                         }
528                 }
529                 return;
530         }
531         /*
532          * Else not a term.
533          */
534         qerr();
535 }
536
537 /*)Function     int     digit(c, r)
538  *
539  *              int     c               digit character
540  *              int     r               current radix
541  *
542  *      The function digit() returns the value of c
543  *      in the current radix r.  If the c value is not
544  *      a number of the current radix then a -1 is returned.
545  *
546  *      local variables:
547  *              none
548  *
549  *      global variables:
550  *              char    ctype[]         array of character types, one per
551  *                                      ASCII character
552  *
553  *      functions called:
554  *              none
555  *
556  *      side effects:
557  *              none
558  */
559
560 int
561 digit(register int c, register int r)
562 {
563         if (r == 16) {
564                 if (ctype[c] & RAD16) {
565                         if (c >= 'A' && c <= 'F')
566                                 return (c - 'A' + 10);
567                         if (c >= 'a' && c <= 'f')
568                                 return (c - 'a' + 10);
569                         return (c - '0');
570                 }
571         } else
572         if (r == 10) {
573                 if (ctype[c] & RAD10)
574                         return (c - '0');
575         } else
576         if (r == 8) {
577                 if (ctype[c] & RAD8)
578                         return (c - '0');
579         } else
580         if (r == 2) {
581                 if (ctype[c] & RAD2)
582                         return (c - '0');
583         }
584         return (-1);
585 }
586
587 /*)Function     VOID    abscheck(esp)
588  *
589  *              expr *  esp             pointer to an expr structure
590  *
591  *      The function abscheck() tests the evaluation of an
592  *      expression to verify it is absolute.  If the evaluation
593  *      is relocatable then an 'r' error is noted and the expression
594  *      made absolute.
595  *
596  *      Note:   The area type (i.e. ABS) is not checked because
597  *              the linker can be told to explicitly relocate an
598  *              absolute area.
599  *
600  *      local variables:
601  *              none
602  *
603  *      global variables:
604  *              none
605  *
606  *      functions called:
607  *              VOID    rerr()          assubr.c
608  *
609  *      side effects:
610  *              The expression may be changed to absolute and the
611  *              'r' error invoked.
612  */
613
614 VOID
615 abscheck(register struct expr *esp)
616 {
617         if (esp->e_flag || esp->e_base.e_ap) {
618                 esp->e_flag = 0;
619                 esp->e_base.e_ap = NULL;
620                 rerr();
621         }
622 }
623
624 /*)Function     int     is_abs(esp)
625  *
626  *              expr *  esp             pointer to an expr structure
627  *
628  *      The function is_abs() tests the evaluation of an
629  *      expression to verify it is absolute.  If the evaluation
630  *      is absolute then 1 is returned, else 0 is returned.
631  *
632  *      Note:   The area type (i.e. ABS) is not checked because
633  *              the linker can be told to explicitly relocate an
634  *              absolute area.
635  *
636  *      local variables:
637  *              none
638  *
639  *      global variables:
640  *              none
641  *
642  *      functions called:
643  *              none
644  *
645  *      side effects:
646  *              none
647  */
648
649 int
650 is_abs (register struct expr *esp)
651 {
652         if (esp->e_flag || esp->e_base.e_ap) {
653                 return(0);
654         }
655         return(1);
656 }
657
658 /*)Function     int     oprio(c)
659  *
660  *              int     c               operator character
661  *
662  *      The function oprio() returns a relative priority
663  *      for all valid unary and binary operators.
664  *
665  *      local variables:
666  *              none
667  *
668  *      global variables:
669  *              none
670  *
671  *      functions called:
672  *              none
673  *
674  *      side effects:
675  *              none
676  */
677
678 int
679 oprio(register int c)
680 {
681         if (c == '[')
682                 return (12);
683         if (c == '*' || c == '/' || c == '%')
684                 return (10);
685         if (c == '+' || c == '-')
686                 return (7);
687         if (c == '<' || c == '>')
688                 return (5);
689         if (c == '^')
690                 return (4);
691         if (c == '&')
692                 return (3);
693         if (c == '|')
694                 return (1);
695         return (0);
696 }
697
698 /*)Function     VOID    clrexpr(esp)
699  *
700  *              expr *  esp             pointer to expression structure
701  *
702  *      The function clrexpr() clears the expression structure.
703  *
704  *      local variables:
705  *              none
706  *
707  *      global variables:
708  *              none
709  *
710  *      functions called:
711  *              none
712  *
713  *      side effects:
714  *              expression structure cleared.
715  */
716
717 VOID
718 clrexpr(register struct expr *esp)
719 {
720         esp->e_mode = 0;
721         esp->e_flag = 0;
722         esp->e_addr = 0;
723         esp->e_base.e_ap = NULL;
724         esp->e_rlcf = 0;
725 }