X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=riscasm.c;h=5681f354e5a1d480d7a97783a9f9f138e663d058;hb=refs%2Ftags%2Fv2.1.11;hp=d595ebc96257f275a907febb33e63b9cebcf81d5;hpb=33bb2746fadd3501eccf6b1046cf8acdfb0f1e37;p=rmac diff --git a/riscasm.c b/riscasm.c index d595ebc..5681f35 100644 --- 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" @@ -24,6 +25,22 @@ #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,25 +193,40 @@ 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. + if (*tok >= KW_R0 && *tok <= KW_R31) + { + int reg = *tok - 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; } @@ -220,7 +238,6 @@ static int EvaluateRegisterFromTokenStream(uint32_t attr) return error(reg_err); } - // // Do RISC code generation // @@ -238,8 +255,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 +283,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 +294,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 +349,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 +367,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 +415,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 +433,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; @@ -468,7 +486,7 @@ int GenerateRISCCode(int state) if (!indexed) { - reg1 = EvaluateRegisterFromTokenStream(FU_REGONE); + EVAL_REG_RETURN_IF_ERROR(reg1, FU_REGONE); } else { @@ -500,7 +518,7 @@ int GenerateRISCCode(int state) if (indexed) { - reg1 = EvaluateRegisterFromTokenStream(FU_REGONE); + EVAL_REG_RETURN_IF_ERROR(reg1, FU_REGONE); } else { @@ -532,7 +550,7 @@ int GenerateRISCCode(int state) } else { - reg1 = EvaluateRegisterFromTokenStream(FU_REGONE); + EVAL_REG_RETURN_IF_ERROR(reg1, FU_REGONE); } } @@ -541,15 +559,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 != '(') @@ -584,7 +601,7 @@ int GenerateRISCCode(int state) if (!indexed) { - reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO); + EVAL_REG_RETURN_IF_ERROR(reg2, FU_REGTWO); } else { @@ -616,7 +633,7 @@ int GenerateRISCCode(int state) if (indexed) { - reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO); + EVAL_REG_RETURN_IF_ERROR(reg2, FU_REGTWO); } else { @@ -653,7 +670,7 @@ int GenerateRISCCode(int state) } else { - reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO); + EVAL_REG_RETURN_IF_ERROR(reg2, FU_REGTWO); } } @@ -661,7 +678,7 @@ int GenerateRISCCode(int state) return MalformedOpcode(MALF_RPAREN); tok++; - at_eol(); + CHECK_EOL; DepositRISCInstructionWord(parm, reg2, reg1); break; @@ -671,34 +688,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 +821,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 +841,3 @@ int GenerateRISCCode(int state) lastOpcode = type; return 0; } -