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