-
-int evexpr(TOKEN *tk, VALUE *a_value, WORD *a_attr, SYM **a_esym) {
- WORD *sattr;
- VALUE *sval;
- WORD attr;
- SYM *sy;
- SYM *esym;
- WORD sym_seg;
-
- sval = evstk; // (Empty) initial stack
- sattr = evattr;
- esym = NULL; // No external symbol involved
- sym_seg = 0;
-
- while(*tk != ENDEXPR)
- switch((int)*tk++) {
- case SYMBOL:
- sy = (SYM *)*tk++;
- sy->sattr |= REFERENCED; // Set "referenced" bit
-
- if(!(sy->sattr & DEFINED)) {
- if(!(sy->sattr & GLOBAL)) { // Reference to undefined symbol
- *a_attr = 0;
- *a_value = 0;
- return(OK);
- }
- if(esym != NULL) // Check for multiple externals
- return(error(seg_error));
- esym = sy;
- }
-
- if(sy->sattr & DEFINED) {
- *++sval = sy->svalue; // Push symbol's value
- } else {
- *++sval = 0; // 0 for undefined symbols
- }
-
- *++sattr = (WORD)(sy->sattr & ~GLOBAL); // Push attribs
- sym_seg = (WORD)(sy->sattr & (TEXT|DATA|BSS));
- break;
- case CONST:
- *++sval = *tk++; // Push value
- *++sattr = ABS|DEFINED; // Push simple attribs
- break;
- case ACONST:
- *++sval = *tk++; // Push value
- *++sattr = (WORD)*tk++; // Push attribs
- break;
-
- // Binary "+" and "-" matrix:
- //
- // ABS Sect Other
- // ----------------------------
- // ABS | ABS | Sect | Other |
- // Sect | Sect | [1] | Error |
- // Other | Other | Error | [1] |
- // ----------------------------
- //
- // [1] + : Error
- // - : ABS
- case '+':
- --sval; // Pop value
- --sattr; // Pop attrib
- *sval += sval[1]; // Compute value
-
- if(!(*sattr & (TEXT|DATA|BSS)))
- *sattr = sattr[1];
- else if(sattr[1] & (TEXT|DATA|BSS))
- return(error(seg_error));
- break;
- case '-':
- --sval; // Pop value
- --sattr; // Pop attrib
- *sval -= sval[1]; // Compute value
-
- attr = (WORD)(*sattr & (TEXT|DATA|BSS));
- if(!attr)
- *sattr = sattr[1];
- else if(sattr[1] & (TEXT|DATA|BSS)) {
- if(!(attr & sattr[1])) {
- return(error(seg_error));
- } else {
- *sattr &= ~(TEXT|DATA|BSS);
- }
- }
- break;
- // Unary operators only work on ABS items
- case UNMINUS:
- if(*sattr & (TEXT|DATA|BSS))
- error(seg_error);
- *sval = -(int)*sval;
- *sattr = ABS|DEFINED; // Expr becomes absolute
- break;
- case '!':
- if(*sattr & (TEXT|DATA|BSS))
- error(seg_error);
- *sval = !*sval;
- *sattr = ABS|DEFINED; // Expr becomes absolute
- break;
- case '~':
- if(*sattr & (TEXT|DATA|BSS))
- error(seg_error);
- *sval = ~*sval;
- *sattr = ABS|DEFINED; // Expr becomes absolute
- break;
- // Comparison operators must have two values that
- // are in the same segment, but that's the only requirement.
- case LE:
- --sattr;
- --sval;
- if((*sattr & TDB) != (sattr[1] & TDB)) error(seg_error);
- *sattr = ABS|DEFINED;
- *sval = *sval <= sval[1];
- break;
- case GE:
- --sattr;
- --sval;
- if((*sattr & TDB) != (sattr[1] & TDB)) error(seg_error);
- *sattr = ABS|DEFINED;
- *sval = *sval >= sval[1];
- break;
- case '>':
- --sattr;
- --sval;
- if((*sattr & TDB) != (sattr[1] & TDB)) error(seg_error);
- *sattr = ABS|DEFINED;
- *sval = *sval > sval[1];
- break;
- case '<':
- --sattr;
- --sval;
- if((*sattr & TDB) != (sattr[1] & TDB)) error(seg_error);
- *sattr = ABS|DEFINED;
- *sval = *sval < sval[1];
- break;
- case NE:
- --sattr;
- --sval;
- if((*sattr & TDB) != (sattr[1] & TDB)) error(seg_error);
- *sattr = ABS|DEFINED;
- *sval = *sval != sval[1];
- break;
- case '=':
- --sattr;
- --sval;
- if((*sattr & TDB) != (sattr[1] & TDB)) error(seg_error);
- *sattr = ABS|DEFINED;
- *sval = *sval == sval[1];
- break;
- // All other binary operators must have two ABS items
- // to work with. They all produce an ABS value.
- default:
- // GH - Removed for v1.0.15 as part of the fix for indexed loads.
- //if((*sattr & (TEXT|DATA|BSS)) || (*--sattr & (TEXT|DATA|BSS)))
- //error(seg_error);
-
- *sattr = ABS|DEFINED; // Expr becomes absolute
- switch((int)tk[-1]) {
- case '*':
- --sval;
- --sattr; // Pop attrib
- *sval *= sval[1];
- break;
- case '/':
- --sval;
- --sattr; // Pop attrib
- if(sval[1] == 0)
- return(error("divide by zero"));
- *sval /= sval[1];
- break;
- case '%':
- --sval;
- --sattr; // Pop attrib
- if(sval[1] == 0)
- return(error("mod (%) by zero"));
- *sval %= sval[1];
- break;
- case SHL:
- --sval;
- --sattr; // Pop attrib
- *sval <<= sval[1];
- break;
- case SHR:
- --sval;
- --sattr; // Pop attrib
- *sval >>= sval[1];
- break;
- case '&':
- --sval;
- --sattr; // Pop attrib
- *sval &= sval[1];
- break;
- case '^':
- --sval;
- --sattr; // Pop attrib
- *sval ^= sval[1];
- break;
- case '|':
- --sval;
- --sattr; // Pop attrib
- *sval |= sval[1];
- break;
- default:
- interror(5); // Bad operator in expression stream
- }
- }
-
- if(esym != NULL) *sattr &= ~DEFINED;
- if(a_esym != NULL) *a_esym = esym;
-
- // sym_seg added in 1.0.16 to solve a problem with forward symbols in expressions where absolute
- // values also existed. The absolutes were overiding the symbol segments and not being included :(
- //*a_attr = *sattr | sym_seg; // Copy value + attrib
-
- *a_attr = *sattr; // Copy value + attrib
- *a_value = *sval;
-
- return(OK);
+int evexpr(TOKEN * tk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym)
+{
+ WORD attr;
+ SYM * sy;
+ uint64_t * sval = evstk; // (Empty) initial stack
+ WORD * sattr = evattr;
+ SYM * esym = NULL; // No external symbol involved
+ WORD sym_seg = 0;
+
+ while (*tk != ENDEXPR)
+ {
+ switch ((int)*tk++)
+ {
+ case SYMBOL:
+//printf("evexpr(): SYMBOL\n");
+ sy = symbolPtr[*tk++];
+ sy->sattr |= REFERENCED; // Set "referenced" bit
+
+ if (!(sy->sattr & DEFINED))
+ {
+ // Reference to undefined symbol
+ if (!(sy->sattr & GLOBAL))
+ {
+ *a_attr = 0;
+ *a_value = 0;
+ return OK;
+ }
+
+ if (esym != NULL) // Check for multiple externals
+ return error(seg_error);
+
+ esym = sy;
+ }
+
+ if (sy->sattr & DEFINED)
+ {
+ *++sval = sy->svalue; // Push symbol's value
+ }
+ else
+ {
+ *++sval = 0; // 0 for undefined symbols
+ }
+
+ *++sattr = (WORD)(sy->sattr & ~GLOBAL); // Push attribs
+ sym_seg = (WORD)(sy->sattr & TDB);
+ break;
+ case CONST:
+ *++sval = ((uint64_t)*tk++) << 32; // Push value
+ *sval |= *tk++; // & LO LONG (will this work???--should)
+//printf("evexpr(): CONST = %lX\n", *sval);
+ *++sattr = ABS | DEFINED; // Push simple attribs
+ break;
+ case ACONST:
+//printf("evexpr(): ACONST = %i\n", *tk);
+ *++sval = *tk++; // Push value
+ *++sattr = (WORD)*tk++; // Push attribs
+ break;
+
+ // Binary "+" and "-" matrix:
+ //
+ // ABS Sect Other
+ // ----------------------------
+ // ABS | ABS | Sect | Other |
+ // Sect | Sect | [1] | Error |
+ // Other | Other | Error | [1] |
+ // ----------------------------
+ //
+ // [1] + : Error
+ // - : ABS
+ case '+':
+//printf("evexpr(): +\n");
+ --sval; // Pop value
+ --sattr; // Pop attrib
+//printf("--> N+N: %i + %i = ", *sval, sval[1]);
+ *sval += sval[1]; // Compute value
+//printf("%i\n", *sval);
+
+ if (!(*sattr & TDB))
+ *sattr = sattr[1];
+ else if (sattr[1] & TDB)
+ return error(seg_error);
+
+ break;
+ case '-':
+//printf("evexpr(): -\n");
+ --sval; // Pop value
+ --sattr; // Pop attrib
+//printf("--> N-N: %i - %i = ", *sval, sval[1]);
+ *sval -= sval[1]; // Compute value
+//printf("%i\n", *sval);
+
+ attr = (WORD)(*sattr & TDB);
+#if 0
+printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
+#endif
+ // If symbol1 is ABS, take attributes from symbol2
+ if (!attr)
+ *sattr = sattr[1];
+ // Otherwise, they're both TDB and so attributes cancel out
+ else if (sattr[1] & TDB)
+ *sattr &= ~TDB;
+
+ break;
+ // Unary operators only work on ABS items
+ case UNMINUS:
+//printf("evexpr(): UNMINUS\n");
+ if (*sattr & TDB)
+ error(seg_error);
+
+ *sval = -(int)*sval;
+ *sattr = ABS | DEFINED; // Expr becomes absolute
+ break;
+ case '!':
+//printf("evexpr(): !\n");
+ if (*sattr & TDB)
+ error(seg_error);
+
+ *sval = !*sval;
+ *sattr = ABS | DEFINED; // Expr becomes absolute
+ break;
+ case '~':
+//printf("evexpr(): ~\n");
+ if (*sattr & TDB)
+ error(seg_error);
+
+ *sval = ~*sval;
+ *sattr = ABS | DEFINED; // Expr becomes absolute
+ break;
+ // Comparison operators must have two values that
+ // are in the same segment, but that's the only requirement.
+ case LE:
+//printf("evexpr(): LE\n");
+ sattr--;
+ sval--;
+
+ if ((*sattr & TDB) != (sattr[1] & TDB))
+ error(seg_error);
+
+ *sattr = ABS | DEFINED;
+ *sval = *sval <= sval[1];
+ break;
+ case GE:
+//printf("evexpr(): GE\n");
+ sattr--;
+ sval--;
+
+ if ((*sattr & TDB) != (sattr[1] & TDB))
+ error(seg_error);
+
+ *sattr = ABS | DEFINED;
+ *sval = *sval >= sval[1];
+ break;
+ case '>':
+//printf("evexpr(): >\n");
+ sattr--;
+ sval--;
+
+ if ((*sattr & TDB) != (sattr[1] & TDB))
+ error(seg_error);
+
+ *sattr = ABS | DEFINED;
+ *sval = *sval > sval[1];
+ break;
+ case '<':
+//printf("evexpr(): <\n");
+ sattr--;
+ sval--;
+
+ if ((*sattr & TDB) != (sattr[1] & TDB))
+ error(seg_error);
+
+ *sattr = ABS | DEFINED;
+ *sval = *sval < sval[1];
+ break;
+ case NE:
+//printf("evexpr(): NE\n");
+ sattr--;
+ sval--;
+
+ if ((*sattr & TDB) != (sattr[1] & TDB))
+ error(seg_error);
+
+ *sattr = ABS | DEFINED;
+ *sval = *sval != sval[1];
+ break;
+ case '=':
+//printf("evexpr(): =\n");
+ sattr--;
+ sval--;
+
+ if ((*sattr & TDB) != (sattr[1] & TDB))
+ error(seg_error);
+
+ *sattr = ABS | DEFINED;
+ *sval = *sval == sval[1];
+ break;
+ // All other binary operators must have two ABS items
+ // to work with. They all produce an ABS value.
+ default:
+//printf("evexpr(): default\n");
+ // GH - Removed for v1.0.15 as part of the fix for indexed loads.
+ //if ((*sattr & (TEXT|DATA|BSS)) || (*--sattr & (TEXT|DATA|BSS)))
+ //error(seg_error);
+ *sattr = ABS | DEFINED; // Expr becomes absolute
+
+ switch ((int)tk[-1])
+ {
+ case '*':
+ sval--;
+ sattr--; // Pop attrib
+//printf("--> NxN: %i x %i = ", *sval, sval[1]);
+ *sval *= sval[1];
+//printf("%i\n", *sval);
+ break;
+ case '/':
+ sval--;
+ sattr--; // Pop attrib
+
+ if (sval[1] == 0)
+ return error("division by zero");
+
+//printf("--> N/N: %i / %i = ", sval[0], sval[1]);
+ // Compiler is picky here: Without casting these, it discards
+ // the sign if dividing a negative # by a positive one,
+ // creating a bad result. :-/
+ // Definitely a side effect of using uint32_ts intead of ints.
+ *sval = (int32_t)sval[0] / (int32_t)sval[1];
+//printf("%i\n", *sval);
+ break;
+ case '%':
+ sval--;
+ sattr--; // Pop attrib
+
+ if (sval[1] == 0)
+ return error("mod (%) by zero");
+
+ *sval %= sval[1];
+ break;
+ case SHL:
+ sval--;
+ sattr--; // Pop attrib
+ *sval <<= sval[1];
+ break;
+ case SHR:
+ sval--;
+ sattr--; // Pop attrib
+ *sval >>= sval[1];
+ break;
+ case '&':
+ sval--;
+ sattr--; // Pop attrib
+ *sval &= sval[1];
+ break;
+ case '^':
+ sval--;
+ sattr--; // Pop attrib
+ *sval ^= sval[1];
+ break;
+ case '|':
+ sval--;
+ sattr--; // Pop attrib
+ *sval |= sval[1];
+ break;
+ default:
+ interror(5); // Bad operator in expression stream
+ }
+ }
+ }
+
+ if (esym != NULL)
+ *sattr &= ~DEFINED;
+
+ if (a_esym != NULL)
+ *a_esym = esym;
+
+ // sym_seg added in 1.0.16 to solve a problem with forward symbols in
+ // expressions where absolute values also existed. The absolutes were
+ // overiding the symbol segments and not being included :(
+ //*a_attr = *sattr | sym_seg; // Copy value + attrib
+
+ *a_attr = *sattr; // Copy value + attrib
+ *a_value = *sval;
+
+ return OK;