]> Shamusworld >> Repos - rmac/blobdiff - expr.c
Add support for 64-bit evaluations.
[rmac] / expr.c
diff --git a/expr.c b/expr.c
index b7bf4b1a95b1237a244a8ae12ff619255b4cdaa1..dea1de9c92d679461c90f3778e3257db01d58c7c 100644 (file)
--- 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);
@@ -77,14 +77,13 @@ static VALUE str_value(char * p)
 //
 void InitExpression(void)
 {
-       int i;
-       char * p;
-
        // Initialize token-class table (all set to END)
-       for(i=0; i<256; i++)
+       for(int i=0; i<256; i++)
                tokenClass[i] = END;
 
-       for(i=0, p=itokcl; *p!=1; p++)
+       int i = 0;
+
+       for(char * p=itokcl; *p!=1; p++)
        {
                if (*p == 0)
                        i++;
@@ -155,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 <macro-name>
@@ -172,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:
@@ -187,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:
@@ -207,6 +211,7 @@ getsym:
 
                        w = (WORD)(!strcmp(p, p2));
                        *evalTokenBuffer++ = CONST;
+                       *evalTokenBuffer++ = 0;         // Set HI LONG to zero
                        *evalTokenBuffer++ = (TOKEN)w;
                        break;
                }
@@ -231,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++];
@@ -245,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;
@@ -258,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 '(':
@@ -265,7 +272,7 @@ int expr2(void)
                        return ERROR;
 
                if (*tok++ != ')')
-                       return error("missing close parenthesis ')'");
+                       return error("missing closing parenthesis ')'");
 
                break;
        case '[':
@@ -273,7 +280,7 @@ int expr2(void)
                        return ERROR;
 
                if (*tok++ != ']')
-                       return error("missing close parenthesis ']'");
+                       return error("missing closing bracket ']'");
 
                break;
        case '$':
@@ -288,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");
@@ -300,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
@@ -311,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.
@@ -322,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;
 
@@ -339,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;
@@ -387,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;
                        }
@@ -396,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;
@@ -463,19 +493,14 @@ 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 * 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;
+       uint64_t * sval = evstk;                                // (Empty) initial stack
+       WORD * sattr = evattr;
+       SYM * esym = NULL;                                              // No external symbol involved
+       WORD sym_seg = 0;
 
        while (*tk != ENDEXPR)
        {
@@ -515,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:
@@ -686,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 '%':
@@ -745,7 +771,7 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
        // 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 | sym_seg;           // Copy value + attrib
 
        *a_attr = *sattr;                                               // Copy value + attrib
        *a_value = *sval;