X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rmac;a=blobdiff_plain;f=riscasm.c;h=3092e6e7017d4c0e0a5145baf33d3ffd2d09663a;hp=82caf808d463e07d6b4cbbce9ce7076c2b6d7ae7;hb=HEAD;hpb=4205233c8397c581b4d27ab36ab81ec896ef3dd0 diff --git a/riscasm.c b/riscasm.c index 82caf80..3399b81 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-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 // @@ -20,11 +20,27 @@ #define DEF_MR // Declare keyword values #include "risckw.h" // Incl. generated risc keywords -#define DEF_KW // Declare keyword values -#include "kwtab.h" // Incl. generated keyword tables & defs +#define DEF_REGRISC +#include "riscregs.h" // Incl. generated keyword tables & defs #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 @@ -112,8 +128,8 @@ static const struct opcoderecord roptbl[] = { { MR_NORMI, RI_TWO, 56 }, { MR_NOP, RI_NONE, 57 }, { MR_SAT24, RI_ONE, 62 }, - { MR_UNPACK, RI_ONE, 63 + GPUONLY | (0 << 6) }, - { MR_PACK, RI_ONE, 63 + GPUONLY | (1 << 6) }, + { MR_UNPACK, RI_ONE, 63 + GPUONLY | (1 << 6) }, + { MR_PACK, RI_ONE, 63 + GPUONLY | (0 << 6) }, { MR_ADDQMOD, RI_NUM_32, 63 + DSPONLY }, { MR_MOVE, RI_MOVE, 0 }, { MR_LOAD, RI_LOAD, 0 }, @@ -134,7 +150,6 @@ static const char * malformErr[] = { malform1, malform2, malform3, malform4 }; - // // Function to return "malformed expression" error // This is done mainly to remove a bunch of GOTO statements in the parser @@ -144,17 +159,15 @@ 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 // static inline int IllegalIndexedRegister(int reg) { - return error("Attempted index reference with non-indexable register (r%d)", reg - KW_R0); + return error("Attempted index reference with non-indexable register (r%d)", reg - REGRISC_R0); } - // // Function to return "Illegal Indexed Register" error for EQUR scenarios // Trying to use register value within EQUR that isn't 14 or 15 @@ -164,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 // @@ -178,40 +190,53 @@ static void DepositRISCInstructionWord(uint16_t opcode, int reg1, int reg2) } int value = ((opcode & 0x3F) << 10) + ((reg1 & 0x1F) << 5) + (reg2 & 0x1F); + GENLINENOSYM(); 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 >= REGRISC_R0 && reg <= REGRISC_R31) + { + reg -= REGRISC_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; } - // If we got a register in range (0-31), return it - if (eval <= 31) - return (int)eval; - - // Otherwise, it's out of range & we flag an error - return error(reg_err); + // We shouldn't get here, that should not be legal + interror(9); + return 0; // Not that this will ever execute, but let's be nice and pacify gcc warnings } - // // Do RISC code generation // @@ -229,8 +254,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 @@ -257,8 +282,7 @@ int GenerateRISCCode(int state) // ABS, MIRROR, NEG, NOT, PACK, RESMAC, SAT8, SAT16, SAT16S, SAT24, SAT32S, // UNPACK case RI_ONE: - reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO); - ErrorIfNotAtEOL(); + EVAL_REG_RETURN_IF_ERROR_OR_NO_EOL(reg2, FU_REGTWO); DepositRISCInstructionWord(parm, parm >> 6, reg2); break; @@ -269,14 +293,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); - ErrorIfNotAtEOL(); + EVAL_REG_RETURN_IF_ERROR_OR_NO_EOL(reg2, FU_REGTWO); DepositRISCInstructionWord(parm, reg1, reg2); break; @@ -325,8 +348,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; @@ -337,8 +366,7 @@ int GenerateRISCCode(int state) } CHECK_COMMA; - reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO); - ErrorIfNotAtEOL(); + EVAL_REG_RETURN_IF_ERROR_OR_NO_EOL(reg2, FU_REGTWO); DepositRISCInstructionWord(parm, reg1, reg2); break; @@ -386,8 +414,7 @@ int GenerateRISCCode(int state) } CHECK_COMMA; - reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO); - ErrorIfNotAtEOL(); + EVAL_REG_RETURN_IF_ERROR_OR_NO_EOL(reg2, FU_REGTWO); DepositRISCInstructionWord(parm, 0, reg2); val = WORDSWAP32(eval); @@ -396,7 +423,7 @@ int GenerateRISCCode(int state) // PC,Rd or Rs,Rd case RI_MOVE: - if (*tok == KW_PC) + if (*tok == REGRISC_PC) { parm = 51; reg1 = 0; @@ -405,12 +432,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); - ErrorIfNotAtEOL(); + EVAL_REG_RETURN_IF_ERROR_OR_NO_EOL(reg2, FU_REGTWO); DepositRISCInstructionWord(parm, reg1, reg2); break; @@ -427,39 +453,15 @@ 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); + if ((*tok == REGRISC_R14) || (*tok == REGRISC_R15)) + indexed = (*tok - REGRISC_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 (!indexed) { - reg1 = EvaluateRegisterFromTokenStream(FU_REGONE); + EVAL_REG_RETURN_IF_ERROR(reg1, FU_REGONE); } else { @@ -472,7 +474,7 @@ int GenerateRISCCode(int state) parm = (WORD)(reg1 - 14 + 58); tok++; - if ((*tok >= KW_R0) && (*tok <= KW_R31)) + if ((*tok >= REGRISC_R0) && (*tok <= REGRISC_R31)) indexed = 1; if (*tok == SYMBOL) @@ -491,7 +493,7 @@ int GenerateRISCCode(int state) if (indexed) { - reg1 = EvaluateRegisterFromTokenStream(FU_REGONE); + EVAL_REG_RETURN_IF_ERROR(reg1, FU_REGONE); } else { @@ -523,7 +525,7 @@ int GenerateRISCCode(int state) } else { - reg1 = EvaluateRegisterFromTokenStream(FU_REGONE); + EVAL_REG_RETURN_IF_ERROR(reg1, FU_REGONE); } } @@ -532,15 +534,14 @@ int GenerateRISCCode(int state) tok++; CHECK_COMMA; - reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO); - ErrorIfNotAtEOL(); + 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 != '(') @@ -549,33 +550,12 @@ 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++; - } - } - } + if (((*tok == REGRISC_R14) || (*tok == REGRISC_R15)) && (tok[1] != ')')) + indexed = *tok - REGRISC_R0; if (!indexed) { - reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO); + EVAL_REG_RETURN_IF_ERROR(reg2, FU_REGTWO); } else { @@ -588,7 +568,7 @@ int GenerateRISCCode(int state) parm = (WORD)(reg2 - 14 + 60); tok++; - if ((*tok >= KW_R0) && (*tok <= KW_R31)) + if ((*tok >= REGRISC_R0) && (*tok <= REGRISC_R31)) indexed = 1; if (*tok == SYMBOL) @@ -607,7 +587,7 @@ int GenerateRISCCode(int state) if (indexed) { - reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO); + EVAL_REG_RETURN_IF_ERROR(reg2, FU_REGTWO); } else { @@ -644,7 +624,7 @@ int GenerateRISCCode(int state) } else { - reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO); + EVAL_REG_RETURN_IF_ERROR(reg2, FU_REGTWO); } } @@ -652,7 +632,7 @@ int GenerateRISCCode(int state) return MalformedOpcode(MALF_RPAREN); tok++; - ErrorIfNotAtEOL(); + CHECK_EOL; DepositRISCInstructionWord(parm, reg2, reg1); break; @@ -662,34 +642,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); - ErrorIfNotAtEOL(); + 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++; - ErrorIfNotAtEOL(); + CHECK_EOL; DepositRISCInstructionWord(parm, reg2, reg1); break; @@ -796,13 +775,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++; - ErrorIfNotAtEOL(); + CHECK_EOL; } DepositRISCInstructionWord(parm, reg2, reg1); @@ -816,4 +795,3 @@ int GenerateRISCCode(int state) lastOpcode = type; return 0; } -