From 5d066fc78602b4263aa1f37cd5dd60cc6fd9d302 Mon Sep 17 00:00:00 2001 From: ggn Date: Tue, 1 Sep 2020 09:44:56 +0300 Subject: [PATCH] Fix for bug #173 - expressions that contain "*" are treated as absolute when ORG is active. Also small cleanup of expr.c and doc update --- expr.c | 74 +++++++++++++--------------------------------------------- 1 file changed, 16 insertions(+), 58 deletions(-) diff --git a/expr.c b/expr.c index 65b4a11..527cb2a 100644 --- a/expr.c +++ b/expr.c @@ -58,7 +58,6 @@ static PTR evalTokenBuffer; // Deposit tokens here (this is really a // riscasm.c) static int symbolNum; // Pointer to the entry in symbolPtr[] - // // Obtain a string value // @@ -72,7 +71,6 @@ static uint32_t str_value(char * p) return v; } - // // Initialize expression analyzer // @@ -95,7 +93,6 @@ void InitExpression(void) symbolNum = 0; } - // // Binary operators (all the same precedence) // @@ -117,7 +114,6 @@ int expr0(void) return OK; } - // // Unary operators (detect unary '-') // ggn: If expression starts with a plus then also eat it up. For some reason @@ -264,7 +260,6 @@ getsym: return OK; } - // // Terminals (CONSTs) and parenthesis grouping // @@ -348,7 +343,7 @@ int expr2(void) case '$': *evalTokenBuffer.u32++ = ACONST; // Attributed const *evalTokenBuffer.u32++ = sloc; // Current location - *evalTokenBuffer.u32++ = cursect | DEFINED; // Store attribs + *evalTokenBuffer.u32++ = DEFINED | ((orgactive | org68k_active) ? 0 : cursect); // Store attribs break; case '*': *evalTokenBuffer.u32++ = ACONST; // Attributed const @@ -356,7 +351,8 @@ int expr2(void) // pcloc == location at start of line *evalTokenBuffer.u32++ = (orgactive ? orgaddr : pcloc); // '*' takes attributes of current section, not ABS! - *evalTokenBuffer.u32++ = cursect | DEFINED; + // Also, if we're ORG'd, the symbol is absolute + *evalTokenBuffer.u32++ = DEFINED | ((orgactive | org68k_active) ? 0 : cursect); break; default: return error("bad expression"); @@ -365,7 +361,6 @@ int expr2(void) return OK; } - // // Recursive-descent expression analyzer (with some simple speed hacks) // @@ -385,7 +380,11 @@ int expr(TOKEN * otk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym) // e.g.) // Optimize for single constant or single symbol. -// Shamus: Seems to me that this could be greatly simplified by 1st checking if the first token is a multibyte token, *then* checking if there's an EOL after it depending on the actual length of the token (multiple vs. single). Otherwise, we have the horror show that is the following: + // Shamus: Seems to me that this could be greatly simplified by 1st + // checking if the first token is a multibyte token, *then* + // checking if there's an EOL after it depending on the actual + // length of the token (multiple vs. single). Otherwise, we have + // the horror show that is the following: if ((tok[1] == EOL && (tok[0] != CONST && tokenClass[tok[0]] != SUNARY)) || ((tok[0] == SYMBOL) @@ -428,13 +427,18 @@ int expr(TOKEN * otk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym) { *evalTokenBuffer.u32++ = CONST; - if (orgactive) + if (orgactive | org68k_active) + { *evalTokenBuffer.u64++ = *a_value = orgaddr; + *a_attr = DEFINED; // We have ORG active, it doesn't belong in a section! + } else + { *evalTokenBuffer.u64++ = *a_value = pcloc; + // '*' takes attributes of current section, not ABS! + *a_attr = cursect | DEFINED; + } - // '*' takes attributes of current section, not ABS! - *a_attr = cursect | DEFINED; if (a_esym != NULL) *a_esym = NULL; @@ -446,11 +450,6 @@ int expr(TOKEN * otk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym) p = string[tok[1]]; j = (*p == '.' ? curenv : 0); symbol = lookup(p, LABEL, j); -#if 0 -printf("eval: Looking up symbol (%s) [=%08X]\n", p, symbol); -if (symbol) - printf(" attr=%04X, attre=%08X, val=%i, name=%s\n", symbol->sattr, symbol->sattre, symbol->svalue, symbol->sname); -#endif if (symbol == NULL) symbol = NewSymbol(p, LABEL, j); @@ -537,7 +536,6 @@ thrown away right here. What the hell is it for? return evexpr(otk, a_value, a_attr, a_esym); } - // // Evaluate expression. // If the expression involves only ONE external symbol, the expression is @@ -560,7 +558,6 @@ int evexpr(TOKEN * _tk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym) switch ((int)*tk.u32++) { case SYMBOL: -//printf("evexpr(): SYMBOL\n"); sy = symbolPtr[*tk.u32++]; sy->sattr |= REFERENCED; // Set "referenced" bit @@ -591,12 +588,10 @@ int evexpr(TOKEN * _tk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym) case CONST: *++sval = *tk.u64++; -//printf("evexpr(): CONST = %lX\n", *sval); *++sattr = ABS | DEFINED; // Push simple attribs break; case FCONST: -//printf("evexpr(): FCONST = %lf\n", *tk.dp); // Even though it's a double, we can treat it like a uint64_t since // we're just moving the bits around. *++sval = *tk.u64++; @@ -604,7 +599,6 @@ int evexpr(TOKEN * _tk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym) break; case ACONST: -//printf("evexpr(): ACONST = %i\n", *tk.u32); *++sval = *tk.u32++; // Push value *++sattr = (WORD)*tk.u32++; // Push attribs break; @@ -622,10 +616,8 @@ int evexpr(TOKEN * _tk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym) // - : ABS case '+': -//printf("evexpr(): +\n"); --sval; // Pop value --sattr; // Pop attrib -//printf("--> N+N: %i + %i = ", *sval, sval[1]); // Get FLOAT attribute, if any attr = (sattr[0] | sattr[1]) & FLOAT; @@ -645,7 +637,6 @@ int evexpr(TOKEN * _tk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym) { *sval += sval[1]; // Compute value } -//printf("%i\n", *sval); if (!(*sattr & TDB)) *sattr = sattr[1] | attr; @@ -655,10 +646,8 @@ int evexpr(TOKEN * _tk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym) break; case '-': -//printf("evexpr(): -\n"); --sval; // Pop value --sattr; // Pop attrib -//printf("--> N-N: %i - %i = ", *sval, sval[1]); // Get FLOAT attribute, if any attr = (sattr[0] | sattr[1]) & FLOAT; @@ -678,13 +667,9 @@ int evexpr(TOKEN * _tk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym) { *sval -= sval[1]; } -//printf("%i\n", *sval); *sattr |= attr; // Inherit FLOAT attribute 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]; @@ -696,7 +681,6 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); // Unary operators only work on ABS items case UNMINUS: -//printf("evexpr(): UNMINUS\n"); if (*sattr & TDB) return error(seg_error); @@ -715,7 +699,6 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); break; case UNLT: // Unary < (get the low byte of a word) -//printf("evexpr(): UNLT\n"); if (*sattr & TDB) return error(seg_error); @@ -727,7 +710,6 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); break; case UNGT: // Unary > (get the high byte of a word) -//printf("evexpr(): UNGT\n"); if (*sattr & TDB) return error(seg_error); @@ -739,7 +721,6 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); break; case '!': -//printf("evexpr(): !\n"); if (*sattr & TDB) return error(seg_error); @@ -751,7 +732,6 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); break; case '~': -//printf("evexpr(): ~\n"); if (*sattr & TDB) return error(seg_error); @@ -765,7 +745,6 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); // 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--; @@ -795,7 +774,6 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); break; case GE: -//printf("evexpr(): GE\n"); sattr--; sval--; @@ -825,7 +803,6 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); break; case '>': -//printf("evexpr(): >\n"); sattr--; sval--; @@ -855,7 +832,6 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); break; case '<': -//printf("evexpr(): <\n"); sattr--; sval--; @@ -885,7 +861,6 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); break; case NE: -//printf("evexpr(): NE\n"); sattr--; sval--; @@ -915,7 +890,6 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); break; case '=': -//printf("evexpr(): =\n"); sattr--; sval--; @@ -950,14 +924,12 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); // Shamus: Is this true? There's at least one counterexample of legit // code where this assumption fails to produce correct code. default: -//printf("evexpr(): default\n"); switch ((int)tk.u32[-1]) { case '*': sval--; sattr--; -//printf("--> NxN: %i x %i = ", *sval, sval[1]); // Get FLOAT attribute, if any attr = (sattr[0] | sattr[1]) & FLOAT; @@ -980,15 +952,12 @@ An open question here is do we promote ints to floats as signed or unsigned? It { *sval *= sval[1]; } -//printf("%i\n", *sval); -//no *sattr = ABS | DEFINED | attr; // Expr becomes absolute break; case '/': sval--; sattr--; -//printf("--> N/N: %i / %i = ", sval[0], sval[1]); // Get FLOAT attribute, if any attr = (sattr[0] | sattr[1]) & FLOAT; @@ -1009,7 +978,6 @@ An open question here is do we promote ints to floats as signed or unsigned? It { if (sval[1] == 0) return error("divide 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 @@ -1018,9 +986,7 @@ An open question here is do we promote ints to floats as signed or unsigned? It // ints. *sval = (int32_t)sval[0] / (int32_t)sval[1]; } -//printf("%i\n", *sval); -//no *sattr = ABS | DEFINED | attr; // Expr becomes absolute break; case '%': @@ -1034,7 +1000,6 @@ An open question here is do we promote ints to floats as signed or unsigned? It return error("mod (%) by zero"); *sval %= sval[1]; -//no *sattr = ABS | DEFINED; // Expr becomes absolute break; case SHL: @@ -1045,7 +1010,6 @@ An open question here is do we promote ints to floats as signed or unsigned? It return error("floating point numbers not allowed with operator '<<'."); *sval <<= sval[1]; -//no *sattr = ABS | DEFINED; // Expr becomes absolute break; case SHR: @@ -1056,7 +1020,6 @@ An open question here is do we promote ints to floats as signed or unsigned? It return error("floating point numbers not allowed with operator '>>'."); *sval >>= sval[1]; -//no *sattr = ABS | DEFINED; // Expr becomes absolute break; case '&': @@ -1067,7 +1030,6 @@ An open question here is do we promote ints to floats as signed or unsigned? It return error("floating point numbers not allowed with operator '&'."); *sval &= sval[1]; -//no *sattr = ABS | DEFINED; // Expr becomes absolute break; case '^': @@ -1078,7 +1040,6 @@ An open question here is do we promote ints to floats as signed or unsigned? It return error("floating point numbers not allowed with operator '^'."); *sval ^= sval[1]; -//no *sattr = ABS | DEFINED; // Expr becomes absolute break; case '|': @@ -1089,7 +1050,6 @@ An open question here is do we promote ints to floats as signed or unsigned? It return error("floating point numbers not allowed with operator '|'."); *sval |= sval[1]; -//no *sattr = ABS | DEFINED; // Expr becomes absolute break; default: @@ -1112,7 +1072,6 @@ An open question here is do we promote ints to floats as signed or unsigned? It return OK; } - // // Count the # of tokens in the passed in expression // N.B.: 64-bit constants count as two tokens each @@ -1135,4 +1094,3 @@ uint16_t ExpressionLength(TOKEN * tk) return length; } - -- 2.37.2