4 * Copyright (C) 1989-2021 Alan R. Baldwin
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
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.
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/>.
24 * With enhancements from
27 * w_mckinnon at conknet dot com
35 * The module asexpr.c contains the routines to evaluate
36 * arithmetic/numerical expressions. The functions in
37 * asexpr.c perform a recursive evaluation of the arithmetic
38 * expression read from the assembler-source text line.
39 * The expression may include binary/unary operators, brackets,
40 * symbols, labels, and constants in hexadecimal, decimal, octal
41 * and binary. Arithmetic operations are prioritized and
42 * evaluated by normal arithmetic conventions.
44 * asexpr.c contains the following functions:
56 * asexpr.c contains no local/static variables
59 /*)Function VOID expr(esp, n)
61 * expr * esp pointer to an expr structure
62 * int n a firewall priority; all top
63 * level calls (from the user)
64 * should be made with n set to 0.
66 * The function expr() evaluates an expression and
67 * stores its value and relocation information into
68 * the expr structure supplied by the user.
70 * Notes about the arithmetic:
71 * The coding emulates N-Bit unsigned
72 * arithmetic operations. This allows
73 * program compilation without regard to the
74 * intrinsic integer length of the host
78 * a_uint ae value from expr esp
79 * a_uint ar value from expr re
80 * int c current assembler-source
82 * int p current operator priority
83 * area * ap pointer to an area structure
84 * exp re internal expr structure
87 * char ctype[] array of character types, one per
91 * VOID abscheck() asexpr.c
92 * VOID clrexpr() asexpr.c
94 * VOID expr() asexpr.c
97 * int oprio() asexpr.c
98 * VOID xerr() assubr.c
99 * VOID term() asexpr.c
100 * VOID unget() aslex.c
104 * An expression is evaluated modifying the user supplied
105 * expr structure, a sym structure maybe created for an
106 * undefined symbol, and the parse of the expression may
107 * terminate if a 'q' error occurs.
111 expr(struct expr
*esp
, int n
)
119 while (ctype
[c
= getnb()] & BINOP
) {
121 * Handle binary operators + - * / & | % ^ << >> [
123 if ((p
= oprio(c
)) <= n
)
125 if ((c
== '>' || c
== '<') && c
!= get())
126 xerr('q', "Binary operator >> or << expected.");
129 esp
->e_rlcf
|= re
.e_rlcf
;
136 * esp + re, at least one must be absolute
138 if (esp
->e_base
.e_ap
== NULL
) {
140 * esp is absolute (constant),
143 esp
->e_base
.e_ap
= re
.e_base
.e_ap
;
145 if (re
.e_base
.e_ap
) {
147 * re should be absolute (constant)
149 xerr('r', "Arg1 + Arg2, Arg2 must be a constant.");
151 if (esp
->e_flag
&& re
.e_flag
)
152 xerr('r', "Arg1 + Arg2, Both arguments cannot be external.");
161 if ((ap
= re
.e_base
.e_ap
) != NULL
) {
162 if (esp
->e_base
.e_ap
== ap
) {
163 esp
->e_base
.e_ap
= NULL
;
165 xerr('r', "Arg1 - Arg2, Arg2 must be in same area.");
169 xerr('r', "Arg1 - Arg2, Arg2 cannot be external.");
173 * Both operands (esp and re) must be constants
175 /* SD/MB :- postpone the abscheck to cases '>' and '['
176 and change the right shift operator.. if
177 right shift by 8/16/24 bits of a relocatable address then
178 the user wants the higher order byte. set the R_MSB
179 for the expression */
180 if (c
!= '>' && c
!= '[')
185 * The (int) /, %, and >> operations
186 * are truncated to a_bytes.
228 /* if the left is a relative address &
229 the right side is 8/16/24 then */
230 if (esp
->e_base
.e_ap
&& ar
== 8) {
231 esp
->e_rlcf
|= R_MSB
;
234 else if (esp
->e_base
.e_ap
&& ar
== 16) {
235 esp
->e_rlcf
|= R_HIB
;
238 else if (esp
->e_base
.e_ap
&& ar
== 24) {
239 esp
->e_rlcf
|= R_MSB
| R_HIB
;
242 /* else continue with the normal processing */
248 if (is_sdas() && is_sdas_target_8051_like()) {
249 /* MB added [ for bit access in bdata */
253 /* if the left is a relative address then */
254 if (esp
->e_base
.e_ap
) {
255 ae
|= (ar
| 0x80) << 8;
258 else if ((ae
& 0x87) == 0x80) {
270 esp
->e_addr
= rngchk(ae
);
275 /*)Function a_uint absexpr()
277 * The function absexpr() evaluates an expression, verifies it
278 * is absolute (i.e. not position dependent or relocatable), and
282 * expr e expr structure
288 * VOID abscheck() asexpr.c
289 * VOID clrexpr() asexpr.c
290 * VOID expr() asexpr.c
293 * If the expression is not absolute then
294 * a 'r' error is reported.
308 /*)Function VOID term(esp)
310 * expr * esp pointer to an expr structure
312 * The function term() evaluates a single constant
313 * or symbol value prefaced by any unary operator
314 * ( +, -, ~, ', ", >, or < ). This routine is also
315 * responsible for setting the relocation type to symbol
316 * based (e.flag != 0) on global references.
319 * int c current character
320 * char id[] symbol name
321 * char * jp pointer to assembler-source text
322 * a_uint n constant evaluation running sum
323 * int r current evaluation radix
324 * sym * sp pointer to a sym structure
325 * tsym * tp pointer to a tsym structure
326 * int v current digit evaluation
329 * char ctype[] array of character types, one per
331 * int nflag don't resolve global assigned value symbols flag
332 * sym * symp pointer to a symbol structure
335 * VOID abscheck() asexpr.c
336 * int digit() asexpr.c
337 * VOID err() assubr.c
338 * VOID expr() asexpr.c
339 * int is_abs() asexpr.c
341 * VOID getid() aslex.c
342 * int getmap() aslex.c
343 * int getnb() aslex.c
344 * sym * lookup() assym.c
345 * VOID qerr() assubr.c
346 * VOID unget() aslex.c
349 * An arithmetic term is evaluated, a symbol structure
350 * may be created, term evaluation may be terminated
355 term(struct expr
*esp
)
368 * Discard the unary '+' at this point and
369 * also any reference to numerical arguments
370 * associated with the '#' prefix.
372 while (c
== '+' || c
== '#') { c
= getnb(); }
374 * Evaluate all binary operators
375 * by recursively calling expr().
379 if (getnb() != RTTERM
)
386 esp
->e_addr
= ~esp
->e_addr
+ 1;
392 esp
->e_addr
= ~esp
->e_addr
;
396 esp
->e_mode
= S_USER
;
397 esp
->e_addr
= getmap(-1)&0377;
398 /* MB: accept a closing ' */
405 esp
->e_mode
= S_USER
;
407 esp
->e_addr
= (getmap(-1)&0377)<<8;
408 esp
->e_addr
|= (getmap(-1)&0377);
410 esp
->e_addr
= (getmap(-1)&0377);
411 esp
->e_addr
|= (getmap(-1)&0377)<<8;
413 /* MB: accept a closing " */
419 if (c
== '>' || c
== '<') {
420 if (is_sdas_target_pdk()) {
424 if (is_sdas_target_pdk()) {
429 * evaluate byte selection directly
437 * let linker perform byte selection
439 esp
->e_rlcf
|= R_BYTX
;
441 esp
->e_rlcf
|= R_MSB
;
446 * Evaluate digit sequences as reusable symbols
447 * if followed by a '$' or as constants.
449 if (ctype
[c
] & DIGIT
) {
450 esp
->e_mode
= S_USER
;
452 while (ctype
[*jp
& 0x007F] & RAD10
) {
457 while ((v
= digit(c
, 10)) >= 0) {
464 if (n
== tp
->t_num
) {
465 esp
->e_base
.e_ap
= tp
->t_area
;
466 esp
->e_addr
= tp
->t_addr
;
506 while ((v
= digit(c
, r
)) >= 0) {
511 if (is_sdas_target_pdk() && waddrmode
) {
514 esp
->e_addr
= rngchk(n
);
518 * Evaluate '$' sequences as a temporary radix
519 * if followed by a '%', '&', '#', or '$'.
523 if (c
== '%' || c
== '&' || c
== '#' || c
== '$') {
542 while ((v
= digit(c
, r
)) >= 0) {
547 esp
->e_mode
= S_USER
;
548 esp
->e_addr
= rngchk(n
);
555 * Evaluate symbols and labels
557 if (ctype
[c
] & LETTER
) {
559 esp
->e_mode
= S_USER
;
561 /* Handle if the symbol or label is not yet defined.
563 Also leave unevaluated if it's a global with an assigned value
564 and the don't resolve global symbol assigns flag is set.
565 This allows the value to get resolved at link time instead
566 of during compile time. */
567 if ((sp
->s_type
== S_NEW
) || ((sp
->s_flag
& S_GBL
) && (sp
->s_flag
& S_ASG
) && (nflag
))) {
570 * Flag the expression symbol as external if it's global
572 if (sp
->s_flag
&S_GBL
) {
574 esp
->e_base
.e_sp
= sp
;
578 * Otherwise it's an undefined symbol
582 esp
->e_mode
= sp
->s_type
;
583 esp
->e_addr
= sp
->s_addr
;
584 esp
->e_base
.e_ap
= sp
->s_area
;
585 /* MB: abused bit 15 of s_addr to indicate bit-addressable bytes */
586 if ((sp
->s_addr
& 0x8000) && sp
->s_area
&&
587 (!strcmp(sp
->s_area
->a_id
, "BSEG_BYTES") || !strcmp(sp
->s_area
->a_id
, "BIT_BANK"))) {
588 esp
->e_rlcf
|= R_BIT
| R_BYTX
;
599 /*)Function int digit(c, r)
601 * int c digit character
602 * int r current radix
604 * The function digit() returns the value of c
605 * in the current radix r. If the c value is not
606 * a number of the current radix then a -1 is returned.
612 * char ctype[] array of character types, one per
626 if (ctype
[c
] & RAD16
) {
627 if (c
>= 'A' && c
<= 'F')
628 return (c
- 'A' + 10);
629 if (c
>= 'a' && c
<= 'f')
630 return (c
- 'a' + 10);
635 if (ctype
[c
] & RAD10
)
649 /*)Function VOID abscheck(esp)
651 * expr * esp pointer to an expr structure
653 * The function abscheck() tests the evaluation of an
654 * expression to verify it is absolute. If the evaluation
655 * is relocatable then an 'r' error is noted and the expression
658 * Note: The area type (i.e. ABS) is not checked because
659 * the linker can be told to explicitly relocate an
669 * VOID rerr() assubr.c
672 * The expression may be changed to absolute and the
677 abscheck(struct expr
*esp
)
679 if (esp
->e_flag
|| esp
->e_base
.e_ap
) {
681 esp
->e_base
.e_ap
= NULL
;
686 /*)Function int is_abs(esp)
688 * expr * esp pointer to an expr structure
690 * The function is_abs() tests the evaluation of an
691 * expression to verify it is absolute. If the evaluation
692 * is absolute then 1 is returned, else 0 is returned.
694 * Note: The area type (i.e. ABS) is not checked because
695 * the linker can be told to explicitly relocate an
712 is_abs (struct expr
*esp
)
714 if (esp
->e_flag
|| esp
->e_base
.e_ap
) {
720 /*)Function int oprio(c)
722 * int c operator character
724 * The function oprio() returns a relative priority
725 * for all valid unary and binary operators.
743 if (c
== '*' || c
== '/' || c
== '%')
745 if (c
== '+' || c
== '-')
747 if (c
== '<' || c
== '>')
755 if (is_sdas() && is_sdas_target_8051_like() && c
== '[')
760 /*)Function VOID clrexpr(esp)
762 * expr * esp pointer to expression structure
764 * The function clrexpr() clears the expression structure.
776 * expression structure cleared.
780 clrexpr(struct expr
*esp
)
785 esp
->e_base
.e_ap
= NULL
;
789 /*)Function a_uint rngchk(n)
791 * a_uint n a signed /unsigned value
793 * The function rngchk() verifies that the
794 * value of n is a signed or unsigned value
795 * within the range of the current exprmasks()
796 * settings and returns the value masked to
797 * the current exprmasks() settings.
803 * a_uint a_mask Address mask
804 * int vflag Enable flag
805 * a_aint v_mask Value mask
808 * VOID err() assubr.c
811 * a 'v' error message may be generated.
814 * When the default arithmetic size is the
815 * same as the default sizeof(int) then the
816 * arithmetic overflow cannot be determined.
817 * This ambiguity is caused by the inability
818 * to distinguish signed and unsigned values
819 * at the instrinsic sizeof(int) size.
826 if ((n
& ~a_mask
) && ((n
& ~a_mask
) != ~a_mask
)) {
830 return((n
& s_mask
) ? (n
| ~v_mask
) : (n
& v_mask
));
833 /*)Function VOID exprmasks(esp)
835 * int n T Line Bytes in Address
837 * The function exprmasks() configures the assembler
838 * for 16, 24, or 32-Bit Data/Addresses.
844 * int a_bytes T Line Bytes in Address
845 * a_uint a_mask Address mask
846 * a_uint s_mask Sign mask
847 * a_uint v_mask Value mask
853 * The arithmetic precision parameters are set.
866 a_mask
= (a_uint
) 0x0000FFFFl
;
867 s_mask
= (a_uint
) 0x00008000l
;
868 v_mask
= (a_uint
) 0x00007FFFl
;
872 a_mask
= (a_uint
) 0x00FFFFFFl
;
873 s_mask
= (a_uint
) 0x00800000l
;
874 v_mask
= (a_uint
) 0x007FFFFFl
;
878 a_mask
= (a_uint
) 0xFFFFFFFFl
;
879 s_mask
= (a_uint
) 0x80000000l
;
880 v_mask
= (a_uint
) 0x7FFFFFFFl
;
888 a_mask
= (a_uint
) 0x0000FFFF;
889 s_mask
= (a_uint
) 0x00008000;
890 v_mask
= (a_uint
) 0x00007FFF;
894 a_mask
= (a_uint
) 0x00FFFFFF;
895 s_mask
= (a_uint
) 0x00800000;
896 v_mask
= (a_uint
) 0x007FFFFF;
900 a_mask
= (a_uint
) 0xFFFFFFFF;
901 s_mask
= (a_uint
) 0x80000000;
902 v_mask
= (a_uint
) 0x7FFFFFFF;