Cleanup the RPN evaluator somewhat

Make the bool field an actual bool
Rename `iReloc` to a more exact `isKnown` (as was already pointed out by some
comments)
Make the value of `BANK(symbol)` consistent when the argument is invalid
This commit is contained in:
ISSOtm
2020-01-20 14:04:14 +01:00
parent 0a04904b75
commit cc59730c5b
4 changed files with 44 additions and 46 deletions

View File

@@ -10,6 +10,7 @@
#define RGBDS_ASM_RPN_H #define RGBDS_ASM_RPN_H
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include "linkdefs.h" #include "linkdefs.h"
@@ -22,13 +23,13 @@ struct Expression {
uint32_t nRPNLength; uint32_t nRPNLength;
uint32_t nRPNPatchSize; uint32_t nRPNPatchSize;
uint32_t nRPNOut; uint32_t nRPNOut;
uint32_t isReloc; bool isKnown;
}; };
/* FIXME: Should be defined in `asmy.h`, but impossible with POSIX Yacc */ /* FIXME: Should be defined in `asmy.h`, but impossible with POSIX Yacc */
extern int32_t nPCOffset; extern int32_t nPCOffset;
uint32_t rpn_isReloc(const struct Expression *expr); bool rpn_isKnown(const struct Expression *expr);
void rpn_Symbol(struct Expression *expr, char *tzSym); void rpn_Symbol(struct Expression *expr, char *tzSym);
void rpn_Number(struct Expression *expr, uint32_t i); void rpn_Number(struct Expression *expr, uint32_t i);
void rpn_LOGNOT(struct Expression *expr, const struct Expression *src); void rpn_LOGNOT(struct Expression *expr, const struct Expression *src);

View File

@@ -1190,7 +1190,7 @@ constlist_32bit_entry : /* empty */
const_8bit : relocconst const_8bit : relocconst
{ {
if( (!rpn_isReloc(&$1)) && (($1.nVal < -128) || ($1.nVal > 255)) ) if( (rpn_isKnown(&$1)) && (($1.nVal < -128) || ($1.nVal > 255)) )
warning(WARNING_TRUNCATION, "Expression must be 8-bit"); warning(WARNING_TRUNCATION, "Expression must be 8-bit");
$$ = $1; $$ = $1;
} }
@@ -1198,7 +1198,7 @@ const_8bit : relocconst
const_16bit : relocconst const_16bit : relocconst
{ {
if ((!rpn_isReloc(&$1)) && (($1.nVal < -32768) || ($1.nVal > 65535))) if ((rpn_isKnown(&$1)) && (($1.nVal < -32768) || ($1.nVal > 65535)))
warning(WARNING_TRUNCATION, "Expression must be 16-bit"); warning(WARNING_TRUNCATION, "Expression must be 16-bit");
$$ = $1; $$ = $1;
} }
@@ -1769,7 +1769,7 @@ z80_ldio : T_Z80_LDIO T_MODE_A comma op_mem_ind
{ {
rpn_CheckHRAM(&$4, &$4); rpn_CheckHRAM(&$4, &$4);
if ((!rpn_isReloc(&$4)) && ($4.nVal < 0 || ($4.nVal > 0xFF && $4.nVal < 0xFF00) || $4.nVal > 0xFFFF)) if ((rpn_isKnown(&$4)) && ($4.nVal < 0 || ($4.nVal > 0xFF && $4.nVal < 0xFF00) || $4.nVal > 0xFFFF))
yyerror("Source address $%x not in $FF00 to $FFFF", $4.nVal); yyerror("Source address $%x not in $FF00 to $FFFF", $4.nVal);
out_AbsByte(0xF0); out_AbsByte(0xF0);
@@ -1780,7 +1780,7 @@ z80_ldio : T_Z80_LDIO T_MODE_A comma op_mem_ind
{ {
rpn_CheckHRAM(&$2, &$2); rpn_CheckHRAM(&$2, &$2);
if ((!rpn_isReloc(&$2)) && ($2.nVal < 0 || ($2.nVal > 0xFF && $2.nVal < 0xFF00) || $2.nVal > 0xFFFF)) if ((rpn_isKnown(&$2)) && ($2.nVal < 0 || ($2.nVal > 0xFF && $2.nVal < 0xFF00) || $2.nVal > 0xFFFF))
yyerror("Destination address $%x not in $FF00 to $FFFF", $2.nVal); yyerror("Destination address $%x not in $FF00 to $FFFF", $2.nVal);
out_AbsByte(0xE0); out_AbsByte(0xE0);
@@ -1844,7 +1844,7 @@ z80_ld_mem : T_Z80_LD op_mem_ind comma T_MODE_SP
| T_Z80_LD op_mem_ind comma T_MODE_A | T_Z80_LD op_mem_ind comma T_MODE_A
{ {
if (CurrentOptions.optimizeloads && if (CurrentOptions.optimizeloads &&
(!rpn_isReloc(&$2)) && ($2.nVal >= 0xFF00)) { (rpn_isKnown(&$2)) && ($2.nVal >= 0xFF00)) {
out_AbsByte(0xE0); out_AbsByte(0xE0);
out_AbsByte($2.nVal & 0xFF); out_AbsByte($2.nVal & 0xFF);
rpn_Free(&$2); rpn_Free(&$2);
@@ -1899,7 +1899,7 @@ z80_ld_a : T_Z80_LD reg_r comma T_MODE_C_IND
{ {
if ($2 == REG_A) { if ($2 == REG_A) {
if (CurrentOptions.optimizeloads && if (CurrentOptions.optimizeloads &&
(!rpn_isReloc(&$4)) && ($4.nVal >= 0xFF00)) { (rpn_isKnown(&$4)) && ($4.nVal >= 0xFF00)) {
out_AbsByte(0xF0); out_AbsByte(0xF0);
out_AbsByte($4.nVal & 0xFF); out_AbsByte($4.nVal & 0xFF);
rpn_Free(&$4); rpn_Free(&$4);
@@ -2036,13 +2036,14 @@ z80_rrca : T_Z80_RRCA
z80_rst : T_Z80_RST const_8bit z80_rst : T_Z80_RST const_8bit
{ {
if (rpn_isReloc(&$2)) { if (!rpn_isKnown(&$2)) {
rpn_CheckRST(&$2, &$2); rpn_CheckRST(&$2, &$2);
out_RelByte(&$2); out_RelByte(&$2);
} else if (($2.nVal & 0x38) != $2.nVal) } else if (($2.nVal & 0x38) != $2.nVal) {
yyerror("Invalid address $%x for RST", $2.nVal); yyerror("Invalid address $%x for RST", $2.nVal);
else } else {
out_AbsByte(0xC7 | $2.nVal); out_AbsByte(0xC7 | $2.nVal);
}
rpn_Free(&$2); rpn_Free(&$2);
} }
; ;

View File

@@ -766,7 +766,7 @@ void out_RelByte(struct Expression *expr)
{ {
checkcodesection(); checkcodesection();
checksectionoverflow(1); checksectionoverflow(1);
if (rpn_isReloc(expr)) { if (!rpn_isKnown(expr)) {
pCurrentSection->tData[nPC] = 0; pCurrentSection->tData[nPC] = 0;
createpatch(PATCHTYPE_BYTE, expr); createpatch(PATCHTYPE_BYTE, expr);
pCurrentSection->nPC++; pCurrentSection->nPC++;
@@ -801,7 +801,7 @@ void out_RelWord(struct Expression *expr)
{ {
checkcodesection(); checkcodesection();
checksectionoverflow(2); checksectionoverflow(2);
if (rpn_isReloc(expr)) { if (!rpn_isKnown(expr)) {
pCurrentSection->tData[nPC] = 0; pCurrentSection->tData[nPC] = 0;
pCurrentSection->tData[nPC + 1] = 0; pCurrentSection->tData[nPC + 1] = 0;
createpatch(PATCHTYPE_WORD, expr); createpatch(PATCHTYPE_WORD, expr);
@@ -838,7 +838,7 @@ void out_RelLong(struct Expression *expr)
{ {
checkcodesection(); checkcodesection();
checksectionoverflow(4); checksectionoverflow(4);
if (rpn_isReloc(expr)) { if (!rpn_isKnown(expr)) {
pCurrentSection->tData[nPC] = 0; pCurrentSection->tData[nPC] = 0;
pCurrentSection->tData[nPC + 1] = 0; pCurrentSection->tData[nPC + 1] = 0;
pCurrentSection->tData[nPC + 2] = 0; pCurrentSection->tData[nPC + 2] = 0;

View File

@@ -25,7 +25,7 @@
/* /*
* Add a byte to the RPN expression * Add a byte to the RPN expression
*/ */
void pushbyte(struct Expression *expr, uint8_t b) static void pushbyte(struct Expression *expr, uint8_t b)
{ {
if (expr->nRPNLength == expr->nRPNCapacity) { if (expr->nRPNLength == expr->nRPNCapacity) {
if (expr->nRPNCapacity == 0) if (expr->nRPNCapacity == 0)
@@ -55,7 +55,7 @@ void rpn_Init(struct Expression *expr)
expr->nRPNLength = 0; expr->nRPNLength = 0;
expr->nRPNPatchSize = 0; expr->nRPNPatchSize = 0;
expr->nRPNOut = 0; expr->nRPNOut = 0;
expr->isReloc = 0; expr->isKnown = true;
} }
/* /*
@@ -79,11 +79,11 @@ uint16_t rpn_PopByte(struct Expression *expr)
} }
/* /*
* Determine if the current expression is relocatable * Determine if the current expression is known at assembly time
*/ */
uint32_t rpn_isReloc(const struct Expression *expr) bool rpn_isKnown(const struct Expression *expr)
{ {
return expr->isReloc; return expr->isKnown;
} }
/* /*
@@ -108,7 +108,7 @@ void rpn_Symbol(struct Expression *expr, char *tzSym)
if (!sym || !sym_IsConstant(sym)) { if (!sym || !sym_IsConstant(sym)) {
rpn_Init(expr); rpn_Init(expr);
sym_Ref(tzSym); sym_Ref(tzSym);
expr->isReloc = 1; expr->isKnown = false;
pushbyte(expr, RPN_SYM); pushbyte(expr, RPN_SYM);
while (*tzSym) while (*tzSym)
pushbyte(expr, *tzSym++); pushbyte(expr, *tzSym++);
@@ -132,11 +132,7 @@ void rpn_BankSelf(struct Expression *expr)
rpn_Init(expr); rpn_Init(expr);
if (pCurrentSection->nBank == -1) if (pCurrentSection->nBank == -1)
/* expr->isKnown = false;
* This is not really relocatable, but this makes the assembler
* write this expression as a RPN patch to the object file.
*/
expr->isReloc = 1;
else else
expr->nVal = pCurrentSection->nBank; expr->nVal = pCurrentSection->nBank;
@@ -154,10 +150,10 @@ void rpn_BankSymbol(struct Expression *expr, char *tzSym)
return; return;
} }
rpn_Init(expr);
if (sym && sym_IsConstant(sym)) { if (sym && sym_IsConstant(sym)) {
yyerror("BANK argument must be a relocatable identifier"); yyerror("BANK argument must be a relocatable identifier");
} else { } else {
rpn_Init(expr);
sym_Ref(tzSym); sym_Ref(tzSym);
pushbyte(expr, RPN_BANK_SYM); pushbyte(expr, RPN_BANK_SYM);
for (unsigned int i = 0; tzSym[i]; i++) for (unsigned int i = 0; tzSym[i]; i++)
@@ -172,7 +168,7 @@ void rpn_BankSymbol(struct Expression *expr, char *tzSym)
/* Symbol's section is known and bank's fixed */ /* Symbol's section is known and bank's fixed */
expr->nVal = pSymbol->pSection->nBank; expr->nVal = pSymbol->pSection->nBank;
else else
expr->isReloc = 1; expr->isKnown = false;
} }
} }
@@ -185,11 +181,7 @@ void rpn_BankSection(struct Expression *expr, char *tzSectionName)
if (pSection && pSection->nBank != -1) if (pSection && pSection->nBank != -1)
expr->nVal = pSection->nBank; expr->nVal = pSection->nBank;
else else
/* expr->isKnown = false;
* This is not really relocatable, but this makes the assembler
* write this expression as a RPN patch to the object file.
*/
expr->isReloc = 1;
pushbyte(expr, RPN_BANK_SECT); pushbyte(expr, RPN_BANK_SECT);
expr->nRPNPatchSize++; expr->nRPNPatchSize++;
@@ -272,11 +264,11 @@ void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr,
{ {
assert(src1->tRPN != NULL && src2->tRPN != NULL); assert(src1->tRPN != NULL && src2->tRPN != NULL);
if (src1->nRPNLength + src2->nRPNLength > MAXRPNLEN)
fatalerror("RPN expression is too large");
uint32_t len = src1->nRPNLength + src2->nRPNLength; uint32_t len = src1->nRPNLength + src2->nRPNLength;
if (len > MAXRPNLEN)
fatalerror("RPN expression is too large");
expr->nVal = 0; expr->nVal = 0;
expr->tRPN = src1->tRPN; expr->tRPN = src1->tRPN;
@@ -302,7 +294,7 @@ void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr,
expr->nRPNLength = len; expr->nRPNLength = len;
expr->nRPNPatchSize = src1->nRPNPatchSize + src2->nRPNPatchSize; expr->nRPNPatchSize = src1->nRPNPatchSize + src2->nRPNPatchSize;
expr->nRPNOut = 0; expr->nRPNOut = 0;
expr->isReloc = src1->isReloc || src2->isReloc; expr->isKnown = src1->isKnown && src2->isKnown;
switch (op) { switch (op) {
case RPN_LOGOR: case RPN_LOGOR:
@@ -345,24 +337,28 @@ void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr,
expr->nVal = src1->nVal & src2->nVal; expr->nVal = src1->nVal & src2->nVal;
break; break;
case RPN_SHL: case RPN_SHL:
if (src2->nVal < 0) if (expr->isKnown) {
warning(WARNING_SHIFT_AMOUNT, "Shifting left by negative value: %d", if (src2->nVal < 0)
src2->nVal); warning(WARNING_SHIFT_AMOUNT, "Shifting left by negative value: %d",
src2->nVal);
expr->nVal = shift(src1->nVal, src2->nVal); expr->nVal = shift(src1->nVal, src2->nVal);
}
break; break;
case RPN_SHR: case RPN_SHR:
if (src2->nVal < 0) if (expr->isKnown) {
warning(WARNING_SHIFT_AMOUNT, "Shifting right by negative value: %d", if (src2->nVal < 0)
src2->nVal); warning(WARNING_SHIFT_AMOUNT, "Shifting right by negative value: %d",
src2->nVal);
expr->nVal = shift(src1->nVal, -src2->nVal); expr->nVal = shift(src1->nVal, -src2->nVal);
}
break; break;
case RPN_MUL: case RPN_MUL:
expr->nVal = (uint32_t)src1->nVal * (uint32_t)src2->nVal; expr->nVal = (uint32_t)src1->nVal * (uint32_t)src2->nVal;
break; break;
case RPN_DIV: case RPN_DIV:
if (!expr->isReloc) { if (expr->isKnown) {
if (src2->nVal == 0) if (src2->nVal == 0)
fatalerror("Division by zero"); fatalerror("Division by zero");
@@ -375,7 +371,7 @@ void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr,
} }
break; break;
case RPN_MOD: case RPN_MOD:
if (!expr->isReloc) { if (expr->isKnown) {
if (src2->nVal == 0) if (src2->nVal == 0)
fatalerror("Division by zero"); fatalerror("Division by zero");