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