#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
malform1, malform2, malform3, malform4
};
-
//
// Function to return "malformed expression" error
// This is done mainly to remove a bunch of GOTO statements in the parser
return error("Malformed opcode, %s", malformErr[signal]);
}
-
//
// Function to return "Illegal Indexed Register" error
// Anyone trying to index something other than R14 or R15
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
return error("Attempted index reference with non-indexable register within EQUR (%s = r%d)", sy->sname, sy->svalue);
}
-
//
// Build up & deposit RISC instruction word
//
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;
}
return error(reg_err);
}
-
//
// Do RISC code generation
//
// 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;
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;
}
CHECK_COMMA;
- reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
- ErrorIfNotAtEOL();
+ EVAL_REG_RETURN_IF_ERROR_OR_NO_EOL(reg2, FU_REGTWO);
DepositRISCInstructionWord(parm, reg1, reg2);
break;
}
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);
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;
if (!indexed)
{
- reg1 = EvaluateRegisterFromTokenStream(FU_REGONE);
+ EVAL_REG_RETURN_IF_ERROR(reg1, FU_REGONE);
}
else
{
if (indexed)
{
- reg1 = EvaluateRegisterFromTokenStream(FU_REGONE);
+ EVAL_REG_RETURN_IF_ERROR(reg1, FU_REGONE);
}
else
{
}
else
{
- reg1 = EvaluateRegisterFromTokenStream(FU_REGONE);
+ EVAL_REG_RETURN_IF_ERROR(reg1, FU_REGONE);
}
}
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 != '(')
if (!indexed)
{
- reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
+ EVAL_REG_RETURN_IF_ERROR(reg2, FU_REGTWO);
}
else
{
if (indexed)
{
- reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
+ EVAL_REG_RETURN_IF_ERROR(reg2, FU_REGTWO);
}
else
{
}
else
{
- reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
+ EVAL_REG_RETURN_IF_ERROR(reg2, FU_REGTWO);
}
}
return MalformedOpcode(MALF_RPAREN);
tok++;
- ErrorIfNotAtEOL();
+ CHECK_EOL;
DepositRISCInstructionWord(parm, reg2, reg1);
break;
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;
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);
lastOpcode = type;
return 0;
}
-