X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=as%2Fmcs51%2Fasexpr.c;h=a424d144b45eb38dbb8e30f90090cd297dbb09ec;hb=d08e6df2202ed3f19b681221b502dedb3c6c8a28;hp=26aea4b0a015f474d23a3f33ae7e8533c999e942;hpb=0678d63e45c69dfe0da26fc39942936578724432;p=fw%2Fsdcc diff --git a/as/mcs51/asexpr.c b/as/mcs51/asexpr.c index 26aea4b0..a424d144 100644 --- a/as/mcs51/asexpr.c +++ b/as/mcs51/asexpr.c @@ -1,4 +1,4 @@ - /* asexpr.c */ +/* asexpr.c */ /* * (C) Copyright 1989-1995 @@ -14,74 +14,72 @@ #include #include "asm.h" -/*)Module asexpr.c - * - * The module asexpr.c contains the routines to evaluate - * arithmetic/numerical expressions. The functions in - * asexpr.c perform a recursive evaluation of the arithmetic - * expression read from the assembler-source text line. - * The expression may include binary/unary operators, brackets, - * symbols, labels, and constants in hexadecimal, decimal, octal - * and binary. Arithmetic operations are prioritized and - * evaluated by normal arithmetic conventions. - * - * asexpr.c contains the following functions: - * VOID abscheck() - * Addr_T absexpr() - * VOID clrexpr() - * int digit() - * VOID expr() - * int oprio() - * VOID term() - * - * asexpr.c contains no local/static variables +/*)Module asexpr.c + * + * The module asexpr.c contains the routines to evaluate + * arithmetic/numerical expressions. The functions in + * asexpr.c perform a recursive evaluation of the arithmetic + * expression read from the assembler-source text line. + * The expression may include binary/unary operators, brackets, + * symbols, labels, and constants in hexadecimal, decimal, octal + * and binary. Arithmetic operations are prioritized and + * evaluated by normal arithmetic conventions. + * + * asexpr.c contains the following functions: + * VOID abscheck() + * Addr_T absexpr() + * VOID clrexpr() + * int digit() + * VOID expr() + * int oprio() + * VOID term() + * + * asexpr.c contains no local/static variables */ -/*)Function VOID expr(esp, n) - * - * expr * esp pointer to an expr structure - * int n a firewall priority; all top - * level calls (from the user) - * should be made with n set to 0. - * - * The function expr() evaluates an expression and - * stores its value and relocation information into - * the expr structure supplied by the user. - * - * local variables: - * int c current assembler-source - * text character - * int p current operator priority - * area * ap pointer to an area structure - * exp re internal expr structure - * - * global variables: - * char ctype[] array of character types, one per - * ASCII character - * - * functions called: - * VOID abscheck() asexpr.c - * VOID clrexpr() asexpr.c - * VOID expr() asexpr.c - * int getnb() aslex.c - * int oprio() asexpr.c - * VOID qerr() assubr.c - * VOID rerr() assubr.c - * VOID term() asexpr.c - * VOID unget() aslex.c - * - * - * side effects: - * An expression is evaluated modifying the user supplied - * expr structure, a sym structure maybe created for an - * undefined symbol, and the parse of the expression may - * terminate if a 'q' error occurs. +/*)Function VOID expr(esp, n) + * + * expr * esp pointer to an expr structure + * int n a firewall priority; all top + * level calls (from the user) + * should be made with n set to 0. + * + * The function expr() evaluates an expression and + * stores its value and relocation information into + * the expr structure supplied by the user. + * + * local variables: + * int c current assembler-source + * text character + * int p current operator priority + * area * ap pointer to an area structure + * exp re internal expr structure + * + * global variables: + * char ctype[] array of character types, one per + * ASCII character + * + * functions called: + * VOID abscheck() asexpr.c + * VOID clrexpr() asexpr.c + * VOID expr() asexpr.c + * int getnb() aslex.c + * int oprio() asexpr.c + * VOID qerr() assubr.c + * VOID rerr() assubr.c + * VOID term() asexpr.c + * VOID unget() aslex.c + * + * + * side effects: + * An expression is evaluated modifying the user supplied + * expr structure, a sym structure maybe created for an + * undefined symbol, and the parse of the expression may + * terminate if a 'q' error occurs. */ VOID -expr(esp, n) -register struct expr *esp; -int n; +expr(register struct expr *esp, int n) { register int c, p; struct area *ap; @@ -89,31 +87,31 @@ int n; term(esp); while (ctype[c = getnb()] & BINOP) { - /* - * Handle binary operators + - * / & | % ^ << >> - */ + /* + * Handle binary operators + - * / & | % ^ << >> [ + */ if ((p = oprio(c)) <= n) break; if ((c == '>' || c == '<') && c != get()) qerr(); - clrexpr(&re); + clrexpr(&re); expr(&re, p); - esp->e_rlcf |= re.e_rlcf; + esp->e_rlcf |= re.e_rlcf; if (c == '+') { - /* - * esp + re, at least one must be absolute - */ + /* + * esp + re, at least one must be absolute + */ if (esp->e_base.e_ap == NULL) { - /* - * esp is absolute (constant), - * use area from re - */ + /* + * esp is absolute (constant), + * use area from re + */ esp->e_base.e_ap = re.e_base.e_ap; } else if (re.e_base.e_ap) { - /* - * re should be absolute (constant) - */ + /* + * re should be absolute (constant) + */ rerr(); } if (esp->e_flag && re.e_flag) @@ -123,9 +121,9 @@ int n; esp->e_addr += re.e_addr; } else if (c == '-') { - /* - * esp - re - */ + /* + * esp - re + */ if ((ap = re.e_base.e_ap) != NULL) { if (esp->e_base.e_ap == ap) { esp->e_base.e_ap = NULL; @@ -137,198 +135,212 @@ int n; rerr(); esp->e_addr -= re.e_addr; } else { - /* - * Both operands (esp and re) must be constants - */ - /* SD :- moved the abscheck to each case - case and change the right shift operator.. if - right shift by 8 bits of a relocatable address then - the user wants the higher order byte. set the R_MSB - for the expression */ + /* + * Both operands (esp and re) must be constants + */ + /* SD :- moved the abscheck to each case + case and change the right shift operator.. if + right shift by 8 bits of a relocatable address then + the user wants the higher order byte. set the R_MSB + for the expression */ switch (c) { case '*': - abscheck(esp); - abscheck(&re); - esp->e_addr *= re.e_addr; - break; + abscheck(esp); + abscheck(&re); + esp->e_addr *= re.e_addr; + break; case '/': - abscheck(esp); - abscheck(&re); - esp->e_addr /= re.e_addr; - break; + abscheck(esp); + abscheck(&re); + esp->e_addr /= re.e_addr; + break; case '&': - abscheck(esp); - abscheck(&re); - esp->e_addr &= re.e_addr; - break; + abscheck(esp); + abscheck(&re); + esp->e_addr &= re.e_addr; + break; case '|': - abscheck(esp); - abscheck(&re); - esp->e_addr |= re.e_addr; - break; + abscheck(esp); + abscheck(&re); + esp->e_addr |= re.e_addr; + break; case '%': - abscheck(esp); - abscheck(&re); - esp->e_addr %= re.e_addr; - break; + abscheck(esp); + abscheck(&re); + esp->e_addr %= re.e_addr; + break; case '^': - abscheck(esp); - abscheck(&re); - esp->e_addr ^= re.e_addr; - break; + abscheck(esp); + abscheck(&re); + esp->e_addr ^= re.e_addr; + break; case '<': - abscheck(esp); - abscheck(&re); - esp->e_addr <<= re.e_addr; - break; + abscheck(esp); + abscheck(&re); + esp->e_addr <<= re.e_addr; + break; case '>': - /* SD change here */ - abscheck(&re); - /* if the left is a relative address & - the right side is == 8 then */ - if (esp->e_base.e_ap && re.e_addr == 8) { - esp->e_rlcf |= R_MSB ; - break; - } - else if (esp->e_base.e_ap && re.e_addr == 16) - { - if (flat24Mode) - { - esp->e_rlcf |= R_HIB; - } - else - { - warnBanner(); - fprintf(stderr, - "(expr >> 16) is only meaningful in " - ".flat24 mode.\n"); - qerr(); - } - - break; - } - /* else continue with the normal processing */ - abscheck(esp); - esp->e_addr >>= re.e_addr; - break; - - default: - qerr(); - break; - } + /* SD change here */ + abscheck(&re); + /* if the left is a relative address & + the right side is == 8 then */ + if (esp->e_base.e_ap && re.e_addr == 8) { + esp->e_rlcf |= R_MSB ; + break; + } + else if (esp->e_base.e_ap && re.e_addr == 16) + { +// if (flat24Mode) +// { + esp->e_rlcf |= R_HIB; +// } +// else +// { +// warnBanner(); +// fprintf(stderr, +// "(expr >> 16) is only meaningful in " +// ".flat24 mode.\n"); +// qerr(); +// } + + break; + } + /* else continue with the normal processing */ + abscheck(esp); + esp->e_addr >>= re.e_addr; + break; + case '[': + /* MB added [ for bit access in bdata */ + abscheck(&re); + if (getnb() != ']') + qerr(); + + /* if the left is a relative address then */ + if (esp->e_base.e_ap) { + esp->e_addr |= (re.e_addr | 0x80) << 8; + break; + } + else if ((esp->e_addr & 0x87) == 0x80) { + esp->e_addr |= re.e_addr; + break; + } + + default: + qerr(); + break; + } } } unget(c); } -/*)Function Addr_T absexpr() +/*)Function Addr_T absexpr() * - * The function absexpr() evaluates an expression, verifies it - * is absolute (i.e. not position dependent or relocatable), and - * returns its value. + * The function absexpr() evaluates an expression, verifies it + * is absolute (i.e. not position dependent or relocatable), and + * returns its value. * - * local variables: - * expr e expr structure + * local variables: + * expr e expr structure * - * global variables: - * none + * global variables: + * none * - * functions called: - * VOID abscheck() asexpr.c - * VOID clrexpr() asexpr.c - * VOID expr() asexpr.c + * functions called: + * VOID abscheck() asexpr.c + * VOID clrexpr() asexpr.c + * VOID expr() asexpr.c * - * side effects: - * If the expression is not absolute then - * a 'r' error is reported. + * side effects: + * If the expression is not absolute then + * a 'r' error is reported. */ Addr_T -absexpr() +absexpr(void) { struct expr e; - clrexpr(&e); - expr(&e, 0); - abscheck(&e); - return (e.e_addr); + clrexpr(&e); + expr(&e, 0); + abscheck(&e); + return (e.e_addr); } -/*)Function VOID term(esp) - * - * expr * esp pointer to an expr structure - * - * The function term() evaluates a single constant - * or symbol value prefaced by any unary operator - * ( +, -, ~, ', ", >, or < ). This routine is also - * responsible for setting the relocation type to symbol - * based (e.flag != 0) on global references. - * - * local variables: - * int c current character - * char id[] symbol name - * char * jp pointer to assembler-source text - * int n constant evaluation running sum - * int r current evaluation radix - * sym * sp pointer to a sym structure - * tsym * tp pointer to a tsym structure - * int v current digit evaluation - * - * global variables: - * char ctype[] array of character types, one per - * ASCII character - * sym * symp pointer to a symbol structure - * - * functions called: - * VOID abscheck() asexpr.c - * int digit() asexpr.c - * VOID err() assubr.c - * VOID expr() asexpr.c - * int is_abs() asexpr.c - * int get() aslex.c - * VOID getid() aslex.c - * int getmap() aslex.c - * int getnb() aslex.c - * sym * lookup() assym.c - * VOID qerr() assubr.c - * VOID unget() aslex.c - * - * side effects: - * An arithmetic term is evaluated, a symbol structure - * may be created, term evaluation may be terminated - * by a 'q' error. +/*)Function VOID term(esp) + * + * expr * esp pointer to an expr structure + * + * The function term() evaluates a single constant + * or symbol value prefaced by any unary operator + * ( +, -, ~, ', ", >, or < ). This routine is also + * responsible for setting the relocation type to symbol + * based (e.flag != 0) on global references. + * + * local variables: + * int c current character + * char id[] symbol name + * char * jp pointer to assembler-source text + * int n constant evaluation running sum + * int r current evaluation radix + * sym * sp pointer to a sym structure + * tsym * tp pointer to a tsym structure + * int v current digit evaluation + * + * global variables: + * char ctype[] array of character types, one per + * ASCII character + * sym * symp pointer to a symbol structure + * + * functions called: + * VOID abscheck() asexpr.c + * int digit() asexpr.c + * VOID err() assubr.c + * VOID expr() asexpr.c + * int is_abs() asexpr.c + * int get() aslex.c + * VOID getid() aslex.c + * int getmap() aslex.c + * int getnb() aslex.c + * sym * lookup() assym.c + * VOID qerr() assubr.c + * VOID unget() aslex.c + * + * side effects: + * An arithmetic term is evaluated, a symbol structure + * may be created, term evaluation may be terminated + * by a 'q' error. */ VOID -term(esp) -register struct expr *esp; +term(register struct expr *esp) { register int c, n; - register char *jp; + register const char *jp; char id[NCPS]; struct sym *sp; struct tsym *tp; int r=0, v; c = getnb(); - /* - * Discard the unary '+' at this point and - * also any reference to numerical arguments - * associated with the '#' prefix. - */ + /* + * Discard the unary '+' at this point and + * also any reference to numerical arguments + * associated with the '#' prefix. + */ while (c == '+' || c == '#') { c = getnb(); } - /* - * Evaluate all binary operators - * by recursively calling expr(). - */ + /* + * Evaluate all binary operators + * by recursively calling expr(). + */ if (c == LFTERM) { expr(esp, 0); if (getnb() != RTTERM) @@ -365,28 +377,28 @@ register struct expr *esp; } if (c == '>' || c == '<') { expr(esp, 100); - if (is_abs (esp)) { - /* - * evaluate msb/lsb directly - */ - if (c == '>') - esp->e_addr >>= 8; - esp->e_addr &= 0377; - return; - } else { - /* - * let linker perform msb/lsb, lsb is default - */ - esp->e_rlcf |= R_BYT2; - if (c == '>') - esp->e_rlcf |= R_MSB; - return; - } + if (is_abs (esp)) { + /* + * evaluate msb/lsb directly + */ + if (c == '>') + esp->e_addr >>= 8; + esp->e_addr &= 0377; + return; + } else { + /* + * let linker perform msb/lsb, lsb is default + */ + esp->e_rlcf |= R_BYT2; + if (c == '>') + esp->e_rlcf |= R_MSB; + return; + } } - /* - * Evaluate digit sequences as local symbols - * if followed by a '$' or as constants. - */ + /* + * Evaluate digit sequences as local symbols + * if followed by a '$' or as constants. + */ if (ctype[c] & DIGIT) { esp->e_mode = S_USER; jp = ip; @@ -408,7 +420,7 @@ register struct expr *esp; } tp = tp->t_lnk; } - /* err('u'); */ + err('u'); return; } r = radix; @@ -452,97 +464,101 @@ register struct expr *esp; esp->e_addr = n; return; } - /* - * Evaluate '$' sequences as a temporary radix - * if followed by a '%', '&', '#', or '$'. - */ + /* + * Evaluate '$' sequences as a temporary radix + * if followed by a '%', '&', '#', or '$'. + */ if (c == '$') { c = get(); if (c == '%' || c == '&' || c == '#' || c == '$') { - switch (c) { - case '%': - r = 2; - break; - case '&': - r = 8; - break; - case '#': - r = 10; - break; - case '$': - r = 16; - break; - default: - break; - } - c = get(); - n = 0; - while ((v = digit(c, r)) >= 0) { - n = r*n + v; - c = get(); - } - unget(c); - esp->e_mode = S_USER; - esp->e_addr = n; - return; - } - unget(c); - c = '$'; + switch (c) { + case '%': + r = 2; + break; + case '&': + r = 8; + break; + case '#': + r = 10; + break; + case '$': + r = 16; + break; + default: + break; + } + c = get(); + n = 0; + while ((v = digit(c, r)) >= 0) { + n = r*n + v; + c = get(); + } + unget(c); + esp->e_mode = S_USER; + esp->e_addr = n; + return; + } + unget(c); + c = '$'; } - /* - * Evaluate symbols and labels - */ + /* + * Evaluate symbols and labels + */ if (ctype[c] & LETTER) { esp->e_mode = S_USER; getid(id, c); sp = lookup(id); if (sp->s_type == S_NEW) { esp->e_addr = 0; - if (sp->s_flag&S_GBL) { - esp->e_flag = 1; - esp->e_base.e_sp = sp; - return; - } - /* err('u'); */ + if (sp->s_flag&S_GBL) { + esp->e_flag = 1; + esp->e_base.e_sp = sp; + return; + } + /* err('u'); */ } else { esp->e_mode = sp->s_type; esp->e_addr = sp->s_addr; esp->e_base.e_ap = sp->s_area; + /* MB: abused bit 15 of s_addr to indicate bit-addressable bytes */ + if ((sp->s_addr & 0x8000) && sp->s_area && + (!strcmp(sp->s_area->a_id, "BSEG_BYTES") || !strcmp(sp->s_area->a_id, "BIT_BANK"))) { + esp->e_rlcf |= R_BIT | R_BYT2; + } } return; } - /* - * Else not a term. - */ + /* + * Else not a term. + */ qerr(); } -/*)Function int digit(c, r) +/*)Function int digit(c, r) * - * int c digit character - * int r current radix + * int c digit character + * int r current radix * - * The function digit() returns the value of c - * in the current radix r. If the c value is not - * a number of the current radix then a -1 is returned. + * The function digit() returns the value of c + * in the current radix r. If the c value is not + * a number of the current radix then a -1 is returned. * - * local variables: - * none + * local variables: + * none * - * global variables: - * char ctype[] array of character types, one per - * ASCII character + * global variables: + * char ctype[] array of character types, one per + * ASCII character * - * functions called: - * none + * functions called: + * none * - * side effects: - * none + * side effects: + * none */ int -digit(c, r) -register int c, r; +digit(register int c, register int r) { if (r == 16) { if (ctype[c] & RAD16) { @@ -568,36 +584,35 @@ register int c, r; return (-1); } -/*)Function VOID abscheck(esp) +/*)Function VOID abscheck(esp) * - * expr * esp pointer to an expr structure + * expr * esp pointer to an expr structure * - * The function abscheck() tests the evaluation of an - * expression to verify it is absolute. If the evaluation - * is relocatable then an 'r' error is noted and the expression - * made absolute. + * The function abscheck() tests the evaluation of an + * expression to verify it is absolute. If the evaluation + * is relocatable then an 'r' error is noted and the expression + * made absolute. * - * Note: The area type (i.e. ABS) is not checked because - * the linker can be told to explicitly relocate an - * absolute area. + * Note: The area type (i.e. ABS) is not checked because + * the linker can be told to explicitly relocate an + * absolute area. * - * local variables: - * none + * local variables: + * none * - * global variables: - * none + * global variables: + * none * - * functions called: - * VOID rerr() assubr.c + * functions called: + * VOID rerr() assubr.c * - * side effects: - * The expression may be changed to absolute and the - * 'r' error invoked. + * side effects: + * The expression may be changed to absolute and the + * 'r' error invoked. */ VOID -abscheck(esp) -register struct expr *esp; +abscheck(register struct expr *esp) { if (esp->e_flag || esp->e_base.e_ap) { esp->e_flag = 0; @@ -606,65 +621,65 @@ register struct expr *esp; } } -/*)Function int is_abs(esp) +/*)Function int is_abs(esp) * - * expr * esp pointer to an expr structure + * expr * esp pointer to an expr structure * - * The function is_abs() tests the evaluation of an - * expression to verify it is absolute. If the evaluation - * is absolute then 1 is returned, else 0 is returned. + * The function is_abs() tests the evaluation of an + * expression to verify it is absolute. If the evaluation + * is absolute then 1 is returned, else 0 is returned. * - * Note: The area type (i.e. ABS) is not checked because - * the linker can be told to explicitly relocate an - * absolute area. + * Note: The area type (i.e. ABS) is not checked because + * the linker can be told to explicitly relocate an + * absolute area. * - * local variables: - * none + * local variables: + * none * - * global variables: - * none + * global variables: + * none * - * functions called: - * none + * functions called: + * none * - * side effects: - * none + * side effects: + * none */ int -is_abs (esp) -register struct expr *esp; +is_abs (register struct expr *esp) { if (esp->e_flag || esp->e_base.e_ap) { - return(0); + return(0); } - return(1); + return(1); } -/*)Function int oprio(c) +/*)Function int oprio(c) * - * int c operator character + * int c operator character * - * The function oprio() returns a relative priority - * for all valid unary and binary operators. + * The function oprio() returns a relative priority + * for all valid unary and binary operators. * - * local variables: - * none + * local variables: + * none * - * global variables: - * none + * global variables: + * none * - * functions called: - * none + * functions called: + * none * - * side effects: - * none + * side effects: + * none */ - + int -oprio(c) -register int c; +oprio(register int c) { + if (c == '[') + return (12); if (c == '*' || c == '/' || c == '%') return (10); if (c == '+' || c == '-') @@ -680,32 +695,31 @@ register int c; return (0); } -/*)Function VOID clrexpr(esp) +/*)Function VOID clrexpr(esp) * - * expr * esp pointer to expression structure + * expr * esp pointer to expression structure * - * The function clrexpr() clears the expression structure. + * The function clrexpr() clears the expression structure. * - * local variables: - * none + * local variables: + * none * - * global variables: - * none + * global variables: + * none * - * functions called: - * none + * functions called: + * none * - * side effects: - * expression structure cleared. + * side effects: + * expression structure cleared. */ - + VOID -clrexpr(esp) -register struct expr *esp; +clrexpr(register struct expr *esp) { - esp->e_mode = 0; - esp->e_flag = 0; - esp->e_addr = 0; - esp->e_base.e_ap = NULL; - esp->e_rlcf = 0; + esp->e_mode = 0; + esp->e_flag = 0; + esp->e_addr = 0; + esp->e_base.e_ap = NULL; + esp->e_rlcf = 0; }