mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
Fix @
The symbol's evaluation by the assembler and linker was very inconsistent
This commit is contained in:
@@ -23,6 +23,9 @@ struct Expression {
|
||||
uint32_t isReloc;
|
||||
};
|
||||
|
||||
/* FIXME: Should be defined in `asmy.h`, but impossible with POSIX Yacc */
|
||||
extern int32_t nPCOffset;
|
||||
|
||||
uint32_t rpn_isReloc(const struct Expression *expr);
|
||||
void rpn_Symbol(struct Expression *expr, char *tzSym);
|
||||
void rpn_Number(struct Expression *expr, uint32_t i);
|
||||
|
||||
@@ -1206,37 +1206,7 @@ const_16bit : relocconst
|
||||
|
||||
relocconst : T_ID
|
||||
{
|
||||
/*
|
||||
* The value of @ needs to be evaluated by the linker,
|
||||
* it can only be calculated by the assembler in very
|
||||
* few cases (when the base address of a section is
|
||||
* known).
|
||||
*
|
||||
* '@' is a bit special in that it means different
|
||||
* things depending on when it is used:
|
||||
*
|
||||
* - JR/LD/ADD/etc: It refers to the first byte of the
|
||||
* instruction (1 byte offset relative to the value
|
||||
* stored in the ROM).
|
||||
* - DB/DW/DL: It refers to the address of the value
|
||||
* that is being saved (0 byte offset relative to the
|
||||
* value stored in the ROM.
|
||||
*
|
||||
* This offset must be added whenever '@' is added to a
|
||||
* RPN expression so that the linker can calculate the
|
||||
* correct result of any expression that uses '@'.
|
||||
*/
|
||||
if ((strcmp($1, "@") == 0) && (nPCOffset != 0)) {
|
||||
struct Expression sTemp, sOffset;
|
||||
|
||||
rpn_Symbol(&sTemp, $1);
|
||||
|
||||
rpn_Number(&sOffset, nPCOffset);
|
||||
|
||||
rpn_SUB(&$$, &sTemp, &sOffset);
|
||||
} else {
|
||||
rpn_Symbol(&$$, $1);
|
||||
}
|
||||
rpn_Symbol(&$$, $1);
|
||||
}
|
||||
| T_NUMBER
|
||||
{
|
||||
|
||||
@@ -154,6 +154,14 @@ void rpn_Symbol(struct Expression *expr, char *tzSym)
|
||||
pushbyte(expr, *tzSym++);
|
||||
pushbyte(expr, 0);
|
||||
expr->nRPNPatchSize += 5;
|
||||
|
||||
/* RGBLINK assumes PC is at the byte being computed... */
|
||||
if (sym == pPCSymbol && nPCOffset) {
|
||||
struct Expression pc = *expr, offset;
|
||||
|
||||
rpn_Number(&offset, nPCOffset);
|
||||
rpn_SUB(expr, &pc, &offset);
|
||||
}
|
||||
} else {
|
||||
rpn_Number(expr, sym_GetConstantValue(tzSym));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user