X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=expr.c;h=2361817784d7c0eccab31b9060de867613c1ff7d;hb=d21544da607af148b96a9d926d4564800892aa4e;hp=3a23e6e3cf68d4949ef1372ca98da1defecac7f6;hpb=c38505ee4b2a0de59926107e52fb8bb84041a0e4;p=rmac diff --git a/expr.c b/expr.c index 3a23e6e..2361817 100644 --- a/expr.c +++ b/expr.c @@ -1,7 +1,7 @@ // -// RMAC - Reboot's Macro Assembler for all Atari computers +// RMAC - Renamed Macro Assembler for all Atari computers // EXPR.C - Expression Analyzer -// Copyright (C) 199x Landon Dyer, 2011-2020 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2011-2021 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // @@ -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 @@ -169,7 +165,6 @@ int expr1(void) case CR_FILESIZE: if (*tok++ != STRING) return error("^^FILESIZE expects filename inside string"); - *evalTokenBuffer.u32++ = CONST; // @@copypasted from d_incbin, maybe factor this out somehow? // Attempt to open the include file in the current directory, then (if that @@ -180,20 +175,20 @@ int expr1(void) if ((fd = open(string[*tok], _OPEN_INC)) < 0) { - for(i=0; nthpath("RMACPATH", i, buf1)!= 0; i++) + for(i=0; nthpath("RMACPATH", i, buf1)!=0; i++) { fd = strlen(buf1); - + // Append path char if necessary if ((fd > 0) && (buf1[fd - 1] != SLASHCHAR)) strcat(buf1, SLASHSTRING); - + strcat(buf1, string[*tok]); - + if ((fd = open(buf1, _OPEN_INC)) >= 0) goto allright; } - + return error("cannot open: \"%s\"", string[tok[1]]); } @@ -265,7 +260,6 @@ getsym: return OK; } - // // Terminals (CONSTs) and parenthesis grouping // @@ -296,16 +290,6 @@ int expr2(void) if (sy == NULL) sy = NewSymbol(p, LABEL, j); - // Check register bank usage - if (sy->sattre & EQUATEDREG) - { - if ((regbank == BANK_0) && (sy->sattre & BANK_1) && !altbankok) - warn("equated symbol \'%s\' cannot be used in register bank 0", sy->sname); - - if ((regbank == BANK_1) && (sy->sattre & BANK_0) && !altbankok) - warn("equated symbol \'%s\' cannot be used in register bank 1", sy->sname); - } - *evalTokenBuffer.u32++ = SYMBOL; *evalTokenBuffer.u32++ = symbolNum; symbolPtr[symbolNum] = sy; @@ -349,7 +333,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 @@ -357,7 +341,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"); @@ -366,7 +351,6 @@ int expr2(void) return OK; } - // // Recursive-descent expression analyzer (with some simple speed hacks) // @@ -382,49 +366,24 @@ int expr(TOKEN * otk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym) PTR ptk; evalTokenBuffer.u32 = otk; // Set token pointer to 'exprbuf' (direct.c) - // Also set in various other places too (riscasm.c, - // e.g.) + // Also set in various other places too (riscasm.c, + // e.g.) -//printf("expr(): tokens 0-2: %i %i %i (%c %c %c); tc[2] = %i\n", tok[0], tok[1], tok[2], tok[0], tok[1], tok[2], tokenClass[tok[2]]); // Optimize for single constant or single symbol. - // Shamus: Subtle bug here. EOL token is 101; if you have a constant token - // followed by the value 101, it will trigger a bad evaluation here. - // This is probably a really bad assumption to be making here...! - // (assuming tok[1] == EOL is a single token that is) - // Seems that even other tokens (SUNARY type) can fuck this up too. -#if 0 -// if ((tok[1] == EOL) - if ((tok[1] == EOL && ((tok[0] != CONST || tok[0] != FCONST) && tokenClass[tok[0]] != SUNARY)) -// || (((*tok == CONST || *tok == FCONST || *tok == SYMBOL) || (*tok >= KW_R0 && *tok <= KW_R31)) -// && (tokenClass[tok[2]] < UNARY))) - || (((tok[0] == SYMBOL) || (tok[0] >= KW_R0 && tok[0] <= KW_R31)) - && (tokenClass[tok[2]] < UNARY)) - || ((tok[0] == CONST || tok[0] == FCONST) && (tokenClass[tok[3]] < UNARY)) - ) -#else -// 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) - || (tok[0] >= KW_R0 && tok[0] <= KW_R31)) + || ((tok[0] == SYMBOL) && (tokenClass[tok[2]] < UNARY)) || ((tok[0] == CONST) && (tokenClass[tok[3]] < UNARY)) ) -// Shamus: Yes, you can parse that out and make some kind of sense of it, but damn, it takes a while to get it and understand the subtle bugs that result from not being careful about what you're checking; especially vis-a-vis niavely checking tok[1] for an EOL. O_o -#endif +// Shamus: Yes, you can parse that out and make some kind of sense of it, but damn, it takes a while to get it and understand the subtle bugs that result from not being careful about what you're checking; especially vis-a-vis naively checking tok[1] for an EOL. O_o { - if (*tok >= KW_R0 && *tok <= KW_R31) - { - *evalTokenBuffer.u32++ = CONST; - *evalTokenBuffer.u64++ = *a_value = (*tok - KW_R0); - *a_attr = ABS | DEFINED; - - if (a_esym != NULL) - *a_esym = NULL; - - tok++; - } - else if (*tok == CONST) + if (*tok == CONST) { ptk.u32 = tok; *evalTokenBuffer.u32++ = *ptk.u32++; @@ -458,13 +417,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; @@ -476,11 +440,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); @@ -494,18 +453,6 @@ if (symbol) if ((symbol->sattre & UNDEF_EQUR) && !riscImmTokenSeen) { error("undefined register equate '%s'", symbol->sname); -//if we return right away, it returns some spurious errors... -// return ERROR; - } - - // Check register bank usage - if (symbol->sattre & EQUATEDREG) - { - if ((regbank == BANK_0) && (symbol->sattre & BANK_1) && !altbankok) - warn("equated symbol '%s' cannot be used in register bank 0", symbol->sname); - - if ((regbank == BANK_1) && (symbol->sattre & BANK_0) && !altbankok) - warn("equated symbol '%s' cannot be used in register bank 1", symbol->sname); } *evalTokenBuffer.u32++ = SYMBOL; @@ -522,19 +469,14 @@ be converted from a linked list into an array). symbolNum++; #endif - if (symbol->sattr & DEFINED) - *a_value = symbol->svalue; - else - *a_value = 0; + *a_value = (symbol->sattr & DEFINED ? symbol->svalue : 0); + *a_attr = (WORD)(symbol->sattr & ~GLOBAL); -/* -All that extra crap that was put into the svalue when doing the equr stuff is -thrown away right here. What the hell is it for? -*/ if (symbol->sattre & EQUATEDREG) - *a_value &= 0x1F; - - *a_attr = (WORD)(symbol->sattr & ~GLOBAL); + { + *a_attr |= RISCREG; // Mark it as a register, 'cause it is + *a_esym = symbol; + } if ((symbol->sattr & (GLOBAL | DEFINED)) == GLOBAL && a_esym != NULL) @@ -567,7 +509,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 @@ -590,7 +531,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 @@ -621,12 +561,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++; @@ -634,7 +572,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; @@ -652,10 +589,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; @@ -675,7 +610,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; @@ -685,10 +619,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; @@ -708,13 +640,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]; @@ -726,7 +654,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); @@ -745,7 +672,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); @@ -757,7 +683,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); @@ -769,7 +694,6 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); break; case '!': -//printf("evexpr(): !\n"); if (*sattr & TDB) return error(seg_error); @@ -781,7 +705,6 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); break; case '~': -//printf("evexpr(): ~\n"); if (*sattr & TDB) return error(seg_error); @@ -795,7 +718,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--; @@ -825,7 +747,6 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); break; case GE: -//printf("evexpr(): GE\n"); sattr--; sval--; @@ -855,7 +776,6 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); break; case '>': -//printf("evexpr(): >\n"); sattr--; sval--; @@ -885,7 +805,6 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); break; case '<': -//printf("evexpr(): <\n"); sattr--; sval--; @@ -915,7 +834,6 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); break; case NE: -//printf("evexpr(): NE\n"); sattr--; sval--; @@ -945,7 +863,6 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); break; case '=': -//printf("evexpr(): =\n"); sattr--; sval--; @@ -980,14 +897,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; @@ -1010,15 +925,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; @@ -1039,7 +951,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 @@ -1048,9 +959,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 '%': @@ -1064,7 +973,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: @@ -1075,7 +983,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: @@ -1086,7 +993,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 '&': @@ -1097,7 +1003,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 '^': @@ -1108,7 +1013,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 '|': @@ -1119,7 +1023,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: @@ -1142,7 +1045,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 @@ -1165,4 +1067,3 @@ uint16_t ExpressionLength(TOKEN * tk) return length; } -