X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rmac;a=blobdiff_plain;f=expr.c;h=dea1de9c92d679461c90f3778e3257db01d58c7c;hp=4c4168f4a0c543eb45179a5ac376ff2337f8dc7c;hb=ff8188b7e279f99cf11ac8a283c4146af324d26f;hpb=a29cbeceeadc92ff48ffa70a51135b503c96cc6d diff --git a/expr.c b/expr.c index 4c4168f..dea1de9 100644 --- a/expr.c +++ b/expr.c @@ -1,7 +1,7 @@ // -// RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System +// RMAC - Reboot's Macro Assembler for all Atari computers // EXPR.C - Expression Analyzer -// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2011-2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // @@ -23,7 +23,7 @@ // N.B.: The size of tokenClass should be identical to the largest value of // a token; we're assuming 256 but not 100% sure! static char tokenClass[256]; // Generated table of token classes -static VALUE evstk[EVSTACKSIZE]; // Evaluator value stack +static uint64_t evstk[EVSTACKSIZE]; // Evaluator value stack static WORD evattr[EVSTACKSIZE]; // Evaluator attribute stack // Token-class initialization list @@ -61,9 +61,9 @@ static int symbolNum; // Pointer to the entry in symbolPtr[] // // Obtain a string value // -static VALUE str_value(char * p) +static uint32_t str_value(char * p) { - VALUE v; + uint32_t v; for(v=0; *p; p++) v = (v << 8) | (*p & 0xFF); @@ -154,14 +154,17 @@ int expr1(void) { case CR_ABSCOUNT: *evalTokenBuffer++ = CONST; + *evalTokenBuffer++ = 0; // Set HI LONG to zero *evalTokenBuffer++ = (LONG)sect[ABS].sloc; break; case CR_TIME: *evalTokenBuffer++ = CONST; + *evalTokenBuffer++ = 0; // Set HI LONG to zero *evalTokenBuffer++ = dos_time(); break; case CR_DATE: *evalTokenBuffer++ = CONST; + *evalTokenBuffer++ = 0; // Set HI LONG to zero *evalTokenBuffer++ = dos_date(); break; case CR_MACDEF: // ^^macdef @@ -171,6 +174,7 @@ int expr1(void) p = string[*tok++]; w = (lookup(p, MACRO, 0) == NULL ? 0 : 1); *evalTokenBuffer++ = CONST; + *evalTokenBuffer++ = 0; // Set HI LONG to zero *evalTokenBuffer++ = (TOKEN)w; break; case CR_DEFINED: @@ -186,6 +190,7 @@ getsym: j = (*p == '.' ? curenv : 0); w = ((sy = lookup(p, LABEL, j)) != NULL && (sy->sattr & w) ? 1 : 0); *evalTokenBuffer++ = CONST; + *evalTokenBuffer++ = 0; // Set HI LONG to zero *evalTokenBuffer++ = (TOKEN)w; break; case CR_STREQ: @@ -206,6 +211,7 @@ getsym: w = (WORD)(!strcmp(p, p2)); *evalTokenBuffer++ = CONST; + *evalTokenBuffer++ = 0; // Set HI LONG to zero *evalTokenBuffer++ = (TOKEN)w; break; } @@ -230,7 +236,8 @@ int expr2(void) { case CONST: *evalTokenBuffer++ = CONST; - *evalTokenBuffer++ = *tok++; + *evalTokenBuffer++ = *tok++; // HI LONG of constant + *evalTokenBuffer++ = *tok++; // LO LONG of constant break; case SYMBOL: p = string[*tok++]; @@ -244,10 +251,10 @@ int expr2(void) if (sy->sattre & EQUATEDREG) { if ((regbank == BANK_0) && (sy->sattre & BANK_1) && !altbankok) - warns("equated symbol \'%s\' cannot be used in register bank 0", sy->sname); + warn("equated symbol \'%s\' cannot be used in register bank 0", sy->sname); if ((regbank == BANK_1) && (sy->sattre & BANK_0) && !altbankok) - warns("equated symbol \'%s\' cannot be used in register bank 1", sy->sname); + warn("equated symbol \'%s\' cannot be used in register bank 1", sy->sname); } *evalTokenBuffer++ = SYMBOL; @@ -257,6 +264,7 @@ int expr2(void) break; case STRING: *evalTokenBuffer++ = CONST; + *evalTokenBuffer++ = 0; // Set HI LONG to zero *evalTokenBuffer++ = str_value(string[*tok++]); break; case '(': @@ -264,7 +272,7 @@ int expr2(void) return ERROR; if (*tok++ != ')') - return error("missing close parenthesis ')'"); + return error("missing closing parenthesis ')'"); break; case '[': @@ -272,7 +280,7 @@ int expr2(void) return ERROR; if (*tok++ != ']') - return error("missing close parenthesis ']'"); + return error("missing closing bracket ']'"); break; case '$': @@ -287,6 +295,20 @@ int expr2(void) *evalTokenBuffer++ = (orgactive ? orgaddr : pcloc); // '*' takes attributes of current section, not ABS! *evalTokenBuffer++ = cursect | DEFINED; + break; + case '{': + if (expr0() != OK) // Eat up first parameter (register or immediate) + return ERROR; + + if (*tok++ != ':') // Demand a ':' there + return error("missing colon ':'"); + + if (expr0() != OK) // Eat up second parameter (register or immediate) + return ERROR; + + if (*tok++ != '}') + return error("missing closing brace '}'"); + break; default: return error("bad expression"); @@ -299,7 +321,7 @@ int expr2(void) // // Recursive-descent expression analyzer (with some simple speed hacks) // -int expr(TOKEN * otk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) +int expr(TOKEN * otk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym) { // Passed in values (once derefenced, that is) can all be zero. They are // there so that the expression analyzer can fill them in as needed. The @@ -310,7 +332,8 @@ int expr(TOKEN * otk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) int j; evalTokenBuffer = 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. @@ -321,12 +344,17 @@ int expr(TOKEN * otk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) // Seems that even other tokens (SUNARY type) can fuck this up too. // if ((tok[1] == EOL) if ((tok[1] == EOL && (tok[0] != CONST && tokenClass[tok[0]] != SUNARY)) - || (((*tok == CONST || *tok == SYMBOL) || (*tok >= KW_R0 && *tok <= KW_R31)) - && (tokenClass[tok[2]] < UNARY))) +// || (((*tok == CONST || *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) && (tokenClass[tok[3]] < UNARY)) + ) { if (*tok >= KW_R0 && *tok <= KW_R31) { *evalTokenBuffer++ = CONST; + *evalTokenBuffer++ = 0; // Set HI LONG to zero *evalTokenBuffer++ = *a_value = (*tok - KW_R0); *a_attr = ABS | DEFINED; @@ -338,18 +366,21 @@ int expr(TOKEN * otk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) else if (*tok == CONST) { *evalTokenBuffer++ = CONST; - *evalTokenBuffer++ = *a_value = tok[1]; + *evalTokenBuffer++ = tok[1]; + *evalTokenBuffer++ = tok[2]; + *a_value = (((uint64_t)tok[1]) << 32) | tok[2]; *a_attr = ABS | DEFINED; if (a_esym != NULL) *a_esym = NULL; - tok += 2; + tok += 3; //printf("Quick eval in expr(): CONST = %i, tokenClass[tok[2]] = %i\n", *a_value, tokenClass[*tok]); } else if (*tok == '*') { *evalTokenBuffer++ = CONST; + *evalTokenBuffer++ = 0; // Set HI LONG to zero if (orgactive) *evalTokenBuffer++ = *a_value = orgaddr; @@ -386,7 +417,7 @@ if (symbol) // means it will be fixed up later, and thus, not an error. if ((symbol->sattre & UNDEF_EQUR) && !riscImmTokenSeen) { - errors("undefined register equate '%s'", symbol->sname); + error("undefined register equate '%s'", symbol->sname); //if we return right away, it returns some spurious errors... // return ERROR; } @@ -395,10 +426,10 @@ if (symbol) if (symbol->sattre & EQUATEDREG) { if ((regbank == BANK_0) && (symbol->sattre & BANK_1) && !altbankok) - warns("equated symbol '%s' cannot be used in register bank 0", symbol->sname); + warn("equated symbol '%s' cannot be used in register bank 0", symbol->sname); if ((regbank == BANK_1) && (symbol->sattre & BANK_0) && !altbankok) - warns("equated symbol '%s' cannot be used in register bank 1", symbol->sname); + warn("equated symbol '%s' cannot be used in register bank 1", symbol->sname); } *evalTokenBuffer++ = SYMBOL; @@ -462,11 +493,11 @@ thrown away right here. What the hell is it for? // UNDEFINED, but it's value includes everything but the symbol value, and // `a_esym' is set to the external symbol. // -int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) +int evexpr(TOKEN * tk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym) { WORD attr; SYM * sy; - VALUE * sval = evstk; // (Empty) initial stack + uint64_t * sval = evstk; // (Empty) initial stack WORD * sattr = evattr; SYM * esym = NULL; // No external symbol involved WORD sym_seg = 0; @@ -509,8 +540,9 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) sym_seg = (WORD)(sy->sattr & TDB); break; case CONST: -//printf("evexpr(): CONST = %i\n", *tk); - *++sval = *tk++; // Push value + *++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: @@ -680,14 +712,14 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); sattr--; // Pop attrib if (sval[1] == 0) - return error("divide by zero"); + 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. :-/ - // Probably a side effect of using VALUE intead of ints. - *sval = (int)sval[0] / (int)sval[1]; + // 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 '%':