]> Shamusworld >> Repos - rmac/blobdiff - riscasm.c
.equr overhaul part 3: store and handle banks in .equr evaluation
[rmac] / riscasm.c
index d595ebc96257f275a907febb33e63b9cebcf81d5..f16abe0f30d201ffda4e5c424442bac1f784399b 100644 (file)
--- a/riscasm.c
+++ b/riscasm.c
@@ -1,7 +1,7 @@
 //
-// RMAC - Reboot's Macro Assembler for all Atari computers
+// RMAC - Renamed Macro Assembler for all Atari computers
 // RISCA.C - GPU/DSP Assembler
-// Copyright (C) 199x Landon Dyer, 2011-2018 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
 //
@@ -13,6 +13,7 @@
 #include "expr.h"
 #include "mark.h"
 #include "procln.h"
+#include "rmac.h"
 #include "sect.h"
 #include "token.h"
 
 
 #define MAXINTERNCC 26         // Maximum internal condition codes
 
+// Useful macros
+#define EVAL_REG_RETURN_IF_ERROR(x, y) \
+x = EvaluateRegisterFromTokenStream(y); \
+\
+if (x == ERROR) \
+       return ERROR;
+
+#define EVAL_REG_RETURN_IF_ERROR_OR_NO_EOL(x, y) \
+x = EvaluateRegisterFromTokenStream(y); \
+\
+if ((x == ERROR) || (ErrorIfNotAtEOL() == ERROR)) \
+       return ERROR;
+
+#define CHECK_EOL \
+if (ErrorIfNotAtEOL() == ERROR) \
+       return ERROR;
 
 unsigned altbankok = 0;                // Ok to use alternate register bank
 unsigned orgactive = 0;                // RISC/6502 org directive active
@@ -133,17 +150,6 @@ static const char * malformErr[] = {
        malform1, malform2, malform3, malform4
 };
 
-
-//
-// Convert a string to uppercase
-//
-static void strtoupper(char * s)
-{
-       while (*s)
-               *s++ &= 0xDF;
-}
-
-
 //
 // Function to return "malformed expression" error
 // This is done mainly to remove a bunch of GOTO statements in the parser
@@ -153,7 +159,6 @@ static inline int MalformedOpcode(int signal)
        return error("Malformed opcode, %s", malformErr[signal]);
 }
 
-
 //
 // Function to return "Illegal Indexed Register" error
 // Anyone trying to index something other than R14 or R15
@@ -163,7 +168,6 @@ static inline int IllegalIndexedRegister(int reg)
        return error("Attempted index reference with non-indexable register (r%d)", reg - KW_R0);
 }
 
-
 //
 // Function to return "Illegal Indexed Register" error for EQUR scenarios
 // Trying to use register value within EQUR that isn't 14 or 15
@@ -173,7 +177,6 @@ static inline int IllegalIndexedRegisterEqur(SYM * sy)
        return error("Attempted index reference with non-indexable register within EQUR (%s = r%d)", sy->sname, sy->svalue);
 }
 
-
 //
 // Build up & deposit RISC instruction word
 //
@@ -190,37 +193,68 @@ static void DepositRISCInstructionWord(uint16_t opcode, int reg1, int reg2)
        D_word(value);
 }
 
-
 //
 // Evaluate the RISC register from the token stream. Passed in value is the
 // FIXUP attribute to use if the expression comes back as undefined.
 //
-static int EvaluateRegisterFromTokenStream(uint32_t attr)
+static int EvaluateRegisterFromTokenStream(uint32_t fixup)
 {
+       // Firstly, check to see if it's a register token and return that.  No
+       // need to invoke expr() for easy cases like this.
+       int reg = *tok & 255;
+       if (reg >= KW_R0 && reg <= KW_R31)
+       {
+               // Check register bank usage in the case of .equr register
+               // (encoded as bits 30 and 31 in *tok).
+               // (I still think that this is superfluous and should be taken out, see my note in token.c)
+               if (*tok & 0x80000000)
+               {
+                       // Oops, with all the evaluation in token.c we now lost the equated symbol reference, so we
+                       // don't know its name or anything else. Oh well...
+                       if ((regbank == BANK_0) && (*tok & 0x40000000) && !altbankok)
+                               return error("equated symbol cannot be used in register bank 0");
+
+                       if ((regbank == BANK_1) && !(*tok & 0x40000000) && !altbankok)
+                               return error("equated symbol cannot be used in register bank 1");
+               }
+               reg -= KW_R0;
+               tok++;
+               return reg;
+       }
+
+       if (*tok != SYMBOL)
+       {
+               // If at this point we don't have a symbol then it's garbage.  Punt.
+               return error("Expected register number or EQUREG");
+       }
+
        uint64_t eval;                          // Expression value
        WORD eattr;                                     // Expression attributes
        SYM * esym;                                     // External symbol involved in expr.
        TOKEN r_expr[EXPRSIZE];         // Expression token list
 
        // Evaluate what's in the global "tok" buffer
+       // N.B.: We should either get a fixup or a register name from EQUR
        if (expr(r_expr, &eval, &eattr, &esym) != OK)
                return ERROR;
 
        if (!(eattr & DEFINED))
        {
-               AddFixup(FU_WORD | attr, sloc, r_expr);
+               AddFixup(FU_WORD | fixup, sloc, r_expr);
                return 0;
        }
 
+       // We shouldn't get here, that should not be legal
+       interror(9);
+
        // If we got a register in range (0-31), return it
-       if (eval <= 31)
-               return (int)eval;
+       //if (eattr & RISCREG)
+       //      return (int)eval - KW_R0;
 
-       // Otherwise, it's out of range & we flag an error
-       return error(reg_err);
+       //// Otherwise, it's out of range & we flag an error
+       //return error(reg_err);
 }
 
-
 //
 // Do RISC code generation
 //
@@ -238,8 +272,8 @@ int GenerateRISCCode(int state)
        int indexed;                            // Indexed register flag
 
        uint64_t eval;                          // Expression value
-       uint16_t eattr;                                 // Expression attributes
-       SYM * esym;                                     // External symbol involved in expr.
+       uint16_t eattr;                         // Expression attributes
+       SYM * esym = NULL;                      // External symbol involved in expr.
        TOKEN r_expr[EXPRSIZE];         // Expression token list
 
        // Get opcode parameter and type
@@ -266,8 +300,7 @@ int GenerateRISCCode(int state)
        // ABS, MIRROR, NEG, NOT, PACK, RESMAC, SAT8, SAT16, SAT16S, SAT24, SAT32S,
        // UNPACK
        case RI_ONE:
-               reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
-               at_eol();
+               EVAL_REG_RETURN_IF_ERROR_OR_NO_EOL(reg2, FU_REGTWO);
                DepositRISCInstructionWord(parm, parm >> 6, reg2);
                break;
 
@@ -278,14 +311,13 @@ int GenerateRISCCode(int state)
                if (parm == 37)
                        altbankok = 1;                      // MOVEFA
 
-               reg1 = EvaluateRegisterFromTokenStream(FU_REGONE);
+               EVAL_REG_RETURN_IF_ERROR(reg1, FU_REGONE);
                CHECK_COMMA;
 
                if (parm == 36)
                        altbankok = 1;                      // MOVETA
 
-               reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
-               at_eol();
+               EVAL_REG_RETURN_IF_ERROR_OR_NO_EOL(reg2, FU_REGTWO);
                DepositRISCInstructionWord(parm, reg1, reg2);
                break;
 
@@ -334,8 +366,14 @@ int GenerateRISCCode(int state)
                }
                else
                {
+                       if (esym && (esym->sattre & EQUATEDREG))
+                               return error("equated register seen for immediate value");
+
+                       if (eattr & RISCREG)
+                               return error("register seen for immediate value");
+
                        if (((int)eval < reg1) || ((int)eval > reg2))
-                               return error("constant out of range (%d to %d", reg1, reg2);
+                               return error("constant out of range (%d to %d)", reg1, reg2);
 
                        if (parm & SUB32)
                                reg1 = 32 - (int)eval;
@@ -346,8 +384,7 @@ int GenerateRISCCode(int state)
                }
 
                CHECK_COMMA;
-               reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
-               at_eol();
+               EVAL_REG_RETURN_IF_ERROR_OR_NO_EOL(reg2, FU_REGTWO);
                DepositRISCInstructionWord(parm, reg1, reg2);
                break;
 
@@ -395,8 +432,7 @@ int GenerateRISCCode(int state)
                }
 
                CHECK_COMMA;
-               reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
-               at_eol();
+               EVAL_REG_RETURN_IF_ERROR_OR_NO_EOL(reg2, FU_REGTWO);
 
                DepositRISCInstructionWord(parm, 0, reg2);
                val = WORDSWAP32(eval);
@@ -414,12 +450,11 @@ int GenerateRISCCode(int state)
                else
                {
                        parm = 34;
-                       reg1 = EvaluateRegisterFromTokenStream(FU_REGONE);
+                       EVAL_REG_RETURN_IF_ERROR(reg1, FU_REGONE);
                }
 
                CHECK_COMMA;
-               reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
-               at_eol();
+               EVAL_REG_RETURN_IF_ERROR_OR_NO_EOL(reg2, FU_REGTWO);
                DepositRISCInstructionWord(parm, reg1, reg2);
                break;
 
@@ -436,39 +471,42 @@ int GenerateRISCCode(int state)
         if ((tok[1] == '+') || (tok[1] == '-'))
                {
                        // Trying to make indexed call
-                       if ((*tok == KW_R14) || (*tok == KW_R15))
-                               indexed = (*tok - KW_R0);
+                       // Note: no bank check for .equr symbol here, but the original code for .equr
+                       //       below also didn't check for banks. Even more reasons to throw away
+                       //       bank checks.
+                       if (((*tok & 0xff) == KW_R14) || ((*tok &0xff) == KW_R15))
+                               indexed = ((*tok & 0xff) - KW_R0);
                        else
                                return IllegalIndexedRegister(*tok);
                }
 
-               if (*tok == SYMBOL)
-               {
-                       sy = lookup(string[tok[1]], LABEL, 0);
-
-                       if (!sy)
-                       {
-                               error(reg_err);
-                               return ERROR;
-                       }
-
-                       if (sy->sattre & EQUATEDREG)
-                       {
-                               if ((tok[2] == '+') || (tok[2] == '-'))
-                               {
-                                       if ((sy->svalue & 0x1F) == 14 || (sy->svalue & 0x1F) == 15) {
-                                               indexed = (sy->svalue & 0x1F);
-                                               tok++;
-                                       }
-                                       else
-                                               return IllegalIndexedRegisterEqur(sy);
-                               }
-                       }
-               }
+               //if (*tok == SYMBOL)
+               //{
+               //      sy = lookup(string[tok[1]], LABEL, 0);
+               //
+               //      if (!sy)
+               //      {
+               //              error(reg_err);
+               //              return ERROR;
+               //      }
+               //
+               //      if (sy->sattre & EQUATEDREG)
+               //      {
+               //              if ((tok[2] == '+') || (tok[2] == '-'))
+               //              {
+               //                      if ((sy->svalue - KW_R0) == 14 || (sy->svalue - KW_R0) == 15) {
+               //                              indexed = (sy->svalue - KW_R0);
+               //                              tok++;
+               //                      }
+               //                      else
+               //                              return IllegalIndexedRegisterEqur(sy);
+               //              }
+               //      }
+               //}
 
                if (!indexed)
                {
-                       reg1 = EvaluateRegisterFromTokenStream(FU_REGONE);
+                       EVAL_REG_RETURN_IF_ERROR(reg1, FU_REGONE);
                }
                else
                {
@@ -481,7 +519,7 @@ int GenerateRISCCode(int state)
                                parm = (WORD)(reg1 - 14 + 58);
                                tok++;
 
-                               if ((*tok >= KW_R0) && (*tok <= KW_R31))
+                               if (((*tok & 0xff) >= KW_R0) && ((*tok & 0xff) <= KW_R31))
                                        indexed = 1;
 
                                if (*tok == SYMBOL)
@@ -500,7 +538,7 @@ int GenerateRISCCode(int state)
 
                                if (indexed)
                                {
-                                       reg1 = EvaluateRegisterFromTokenStream(FU_REGONE);
+                                       EVAL_REG_RETURN_IF_ERROR(reg1, FU_REGONE);
                                }
                                else
                                {
@@ -532,7 +570,7 @@ int GenerateRISCCode(int state)
                        }
                        else
                        {
-                               reg1 = EvaluateRegisterFromTokenStream(FU_REGONE);
+                               EVAL_REG_RETURN_IF_ERROR(reg1, FU_REGONE);
                        }
                }
 
@@ -541,15 +579,14 @@ int GenerateRISCCode(int state)
 
                tok++;
                CHECK_COMMA;
-               reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
-               at_eol();
+               EVAL_REG_RETURN_IF_ERROR_OR_NO_EOL(reg2, FU_REGTWO);
                DepositRISCInstructionWord(parm, reg1, reg2);
                break;
 
        // Rn,(Rn) = 47 / Rn,(R14/R15+n) = 49/50 / Rn,(R14/R15+Rn) = 60/61
        case RI_STORE:
                parm = 47;
-               reg1 = EvaluateRegisterFromTokenStream(FU_REGONE);
+               EVAL_REG_RETURN_IF_ERROR(reg1, FU_REGONE);
                CHECK_COMMA;
 
                if (*tok != '(')
@@ -558,33 +595,35 @@ int GenerateRISCCode(int state)
                tok++;
                indexed = 0;
 
-               if (((*tok == KW_R14) || (*tok == KW_R15)) && (tok[1] != ')'))
-                       indexed = *tok - KW_R0;
-
-               if (*tok == SYMBOL)
-               {
-                       sy = lookup(string[tok[1]], LABEL, 0);
-
-                       if (!sy)
-                       {
-                               error(reg_err);
-                               return ERROR;
-                       }
-
-                       if (sy->sattre & EQUATEDREG)
-                       {
-                               if (((sy->svalue & 0x1F) == 14 || (sy->svalue & 0x1F) == 15)
-                                       && (tok[2] != ')'))
-                               {
-                                       indexed = (sy->svalue & 0x1F);
-                                       tok++;
-                               }
-                       }
-               }
+               // Again, no bank checks here or in the original code.
+               // This check has more holes than a very hole-y thing.
+               if ((((*tok & 0xff) == KW_R14) || ((*tok & 0xff) == KW_R15)) && (tok[1] != ')'))
+                       indexed = (*tok & 0xff) - KW_R0;
+
+               //if (*tok == SYMBOL)
+               //{
+               //      sy = lookup(string[tok[1]], LABEL, 0);
+               //
+               //      if (!sy)
+               //      {
+               //              error(reg_err);
+               //              return ERROR;
+               //      }
+               //
+               //      if (sy->sattre & EQUATEDREG)
+               //      {
+               //              if (((sy->svalue - KW_R0) == 14 || (sy->svalue - KW_R0) == 15)
+               //                      && (tok[2] != ')'))
+               //              {
+               //                      indexed = (sy->svalue - KW_R0);
+               //                      tok++;
+               //              }
+               //      }
+               //}
 
                if (!indexed)
                {
-                       reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
+                       EVAL_REG_RETURN_IF_ERROR(reg2, FU_REGTWO);
                }
                else
                {
@@ -597,7 +636,7 @@ int GenerateRISCCode(int state)
                                parm = (WORD)(reg2 - 14 + 60);
                                tok++;
 
-                               if ((*tok >= KW_R0) && (*tok <= KW_R31))
+                               if (((*tok & 0xff) >= KW_R0) && ((*tok & 0xff) <= KW_R31))
                                        indexed = 1;
 
                                if (*tok == SYMBOL)
@@ -616,7 +655,7 @@ int GenerateRISCCode(int state)
 
                                if (indexed)
                                {
-                                       reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
+                                       EVAL_REG_RETURN_IF_ERROR(reg2, FU_REGTWO);
                                }
                                else
                                {
@@ -653,7 +692,7 @@ int GenerateRISCCode(int state)
                        }
                        else
                        {
-                               reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
+                               EVAL_REG_RETURN_IF_ERROR(reg2, FU_REGTWO);
                        }
                }
 
@@ -661,7 +700,7 @@ int GenerateRISCCode(int state)
                        return MalformedOpcode(MALF_RPAREN);
 
                tok++;
-               at_eol();
+               CHECK_EOL;
                DepositRISCInstructionWord(parm, reg2, reg1);
                break;
 
@@ -671,34 +710,33 @@ int GenerateRISCCode(int state)
                        return MalformedOpcode(MALF_LPAREN);
 
                tok++;
-               reg1 = EvaluateRegisterFromTokenStream(FU_REGONE);
+               EVAL_REG_RETURN_IF_ERROR(reg1, FU_REGONE);
 
                if (*tok != ')')
                        return MalformedOpcode(MALF_RPAREN);
 
                tok++;
                CHECK_COMMA;
-               reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
-               at_eol();
+               EVAL_REG_RETURN_IF_ERROR_OR_NO_EOL(reg2, FU_REGTWO);
                DepositRISCInstructionWord(parm, reg1, reg2);
                break;
 
        // STOREB/STOREP/STOREW Rn,(Rn)
        case RI_STOREN:
-               reg1 = EvaluateRegisterFromTokenStream(FU_REGONE);
+               EVAL_REG_RETURN_IF_ERROR(reg1, FU_REGONE);
                CHECK_COMMA;
 
                if (*tok != '(')
                        return MalformedOpcode(MALF_LPAREN);
 
                tok++;
-               reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
+               EVAL_REG_RETURN_IF_ERROR(reg2, FU_REGTWO);
 
                if (*tok != ')')
                        return MalformedOpcode(MALF_RPAREN);
 
                tok++;
-               at_eol();
+               CHECK_EOL;
                DepositRISCInstructionWord(parm, reg2, reg1);
                break;
 
@@ -805,13 +843,13 @@ int GenerateRISCCode(int state)
                                return MalformedOpcode(MALF_LPAREN);
 
                        tok++;
-                       reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
+                       EVAL_REG_RETURN_IF_ERROR(reg2, FU_REGTWO);
 
                        if (*tok != ')')
                                return MalformedOpcode(MALF_RPAREN);
 
                        tok++;
-                       at_eol();
+                       CHECK_EOL;
                }
 
                DepositRISCInstructionWord(parm, reg2, reg1);
@@ -825,4 +863,3 @@ int GenerateRISCCode(int state)
        lastOpcode = type;
        return 0;
 }
-