mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
Fix RPN patches for all commands (#1819)
This commit is contained in:
@@ -405,9 +405,6 @@ Checks if the value is a valid bit index
|
|||||||
.Pq see e.g. Do BIT u3, r8 Dc in Xr gbz80 7 ,
|
.Pq see e.g. Do BIT u3, r8 Dc in Xr gbz80 7 ,
|
||||||
that is, from 0 to 7.
|
that is, from 0 to 7.
|
||||||
The value is then ORed with the instruction's mask.
|
The value is then ORed with the instruction's mask.
|
||||||
.It Li $80 Ta Integer literal; followed by the
|
|
||||||
.Cm LONG
|
|
||||||
integer.
|
|
||||||
.It Li $70 Ta Cm HIGH
|
.It Li $70 Ta Cm HIGH
|
||||||
byte.
|
byte.
|
||||||
.It Li $71 Ta Cm LOW
|
.It Li $71 Ta Cm LOW
|
||||||
@@ -416,6 +413,9 @@ byte.
|
|||||||
value.
|
value.
|
||||||
.It Li $73 Ta Cm TZCOUNT
|
.It Li $73 Ta Cm TZCOUNT
|
||||||
value.
|
value.
|
||||||
|
.It Li $80 Ta Integer literal; followed by the
|
||||||
|
.Cm LONG
|
||||||
|
integer.
|
||||||
.It Li $81 Ta A symbol's value; followed by the symbol's
|
.It Li $81 Ta A symbol's value; followed by the symbol's
|
||||||
.Cm LONG
|
.Cm LONG
|
||||||
ID.
|
ID.
|
||||||
|
|||||||
@@ -132,90 +132,6 @@ static void registerUnregisteredSymbol(Symbol &sym) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeRpn(std::vector<uint8_t> &rpnexpr, std::vector<uint8_t> const &rpn) {
|
|
||||||
size_t rpnptr = 0;
|
|
||||||
|
|
||||||
for (size_t offset = 0; offset < rpn.size();) {
|
|
||||||
uint8_t rpndata = rpn[offset++];
|
|
||||||
|
|
||||||
auto getSymName = [&]() {
|
|
||||||
std::string symName;
|
|
||||||
for (uint8_t c; (c = rpn[offset++]) != 0;) {
|
|
||||||
symName += c;
|
|
||||||
}
|
|
||||||
return symName;
|
|
||||||
};
|
|
||||||
|
|
||||||
switch (rpndata) {
|
|
||||||
Symbol *sym;
|
|
||||||
uint32_t value;
|
|
||||||
uint8_t b;
|
|
||||||
|
|
||||||
case RPN_CONST:
|
|
||||||
rpnexpr[rpnptr++] = RPN_CONST;
|
|
||||||
rpnexpr[rpnptr++] = rpn[offset++];
|
|
||||||
rpnexpr[rpnptr++] = rpn[offset++];
|
|
||||||
rpnexpr[rpnptr++] = rpn[offset++];
|
|
||||||
rpnexpr[rpnptr++] = rpn[offset++];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RPN_SYM:
|
|
||||||
// The symbol name is always written expanded
|
|
||||||
sym = sym_FindExactSymbol(getSymName());
|
|
||||||
registerUnregisteredSymbol(*sym); // Ensure that `sym->ID` is set
|
|
||||||
value = sym->ID;
|
|
||||||
|
|
||||||
rpnexpr[rpnptr++] = RPN_SYM;
|
|
||||||
rpnexpr[rpnptr++] = value & 0xFF;
|
|
||||||
rpnexpr[rpnptr++] = value >> 8;
|
|
||||||
rpnexpr[rpnptr++] = value >> 16;
|
|
||||||
rpnexpr[rpnptr++] = value >> 24;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RPN_BANK_SYM:
|
|
||||||
// The symbol name is always written expanded
|
|
||||||
sym = sym_FindExactSymbol(getSymName());
|
|
||||||
registerUnregisteredSymbol(*sym); // Ensure that `sym->ID` is set
|
|
||||||
value = sym->ID;
|
|
||||||
|
|
||||||
rpnexpr[rpnptr++] = RPN_BANK_SYM;
|
|
||||||
rpnexpr[rpnptr++] = value & 0xFF;
|
|
||||||
rpnexpr[rpnptr++] = value >> 8;
|
|
||||||
rpnexpr[rpnptr++] = value >> 16;
|
|
||||||
rpnexpr[rpnptr++] = value >> 24;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RPN_BANK_SECT:
|
|
||||||
rpnexpr[rpnptr++] = RPN_BANK_SECT;
|
|
||||||
do {
|
|
||||||
b = rpn[offset++];
|
|
||||||
rpnexpr[rpnptr++] = b;
|
|
||||||
} while (b != 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RPN_SIZEOF_SECT:
|
|
||||||
rpnexpr[rpnptr++] = RPN_SIZEOF_SECT;
|
|
||||||
do {
|
|
||||||
b = rpn[offset++];
|
|
||||||
rpnexpr[rpnptr++] = b;
|
|
||||||
} while (b != 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RPN_STARTOF_SECT:
|
|
||||||
rpnexpr[rpnptr++] = RPN_STARTOF_SECT;
|
|
||||||
do {
|
|
||||||
b = rpn[offset++];
|
|
||||||
rpnexpr[rpnptr++] = b;
|
|
||||||
} while (b != 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
rpnexpr[rpnptr++] = rpndata;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void initPatch(Patch &patch, uint32_t type, Expression const &expr, uint32_t ofs) {
|
static void initPatch(Patch &patch, uint32_t type, Expression const &expr, uint32_t ofs) {
|
||||||
patch.type = type;
|
patch.type = type;
|
||||||
patch.src = fstk_GetFileStack();
|
patch.src = fstk_GetFileStack();
|
||||||
@@ -235,9 +151,77 @@ static void initPatch(Patch &patch, uint32_t type, Expression const &expr, uint3
|
|||||||
patch.rpn[2] = val >> 8;
|
patch.rpn[2] = val >> 8;
|
||||||
patch.rpn[3] = val >> 16;
|
patch.rpn[3] = val >> 16;
|
||||||
patch.rpn[4] = val >> 24;
|
patch.rpn[4] = val >> 24;
|
||||||
} else {
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the RPN expr's value is not known, its RPN patch buffer size is known
|
||||||
patch.rpn.resize(expr.rpnPatchSize);
|
patch.rpn.resize(expr.rpnPatchSize);
|
||||||
writeRpn(patch.rpn, expr.rpn);
|
|
||||||
|
for (size_t exprIdx = 0, patchIdx = 0; exprIdx < expr.rpn.size();) {
|
||||||
|
// Every command starts with its own ID
|
||||||
|
assume(patchIdx < patch.rpn.size());
|
||||||
|
uint8_t cmd = expr.rpn[exprIdx++];
|
||||||
|
patch.rpn[patchIdx++] = cmd;
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case RPN_CONST:
|
||||||
|
// The command ID is followed by a four-byte integer
|
||||||
|
assume(exprIdx + 3 < expr.rpn.size());
|
||||||
|
assume(patchIdx + 3 < patch.rpn.size());
|
||||||
|
patch.rpn[patchIdx++] = expr.rpn[exprIdx++];
|
||||||
|
patch.rpn[patchIdx++] = expr.rpn[exprIdx++];
|
||||||
|
patch.rpn[patchIdx++] = expr.rpn[exprIdx++];
|
||||||
|
patch.rpn[patchIdx++] = expr.rpn[exprIdx++];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RPN_SYM:
|
||||||
|
case RPN_BANK_SYM: {
|
||||||
|
// The command ID is followed by a four-byte symbol ID
|
||||||
|
std::string symName;
|
||||||
|
for (;;) {
|
||||||
|
assume(exprIdx < expr.rpn.size());
|
||||||
|
uint8_t c = expr.rpn[exprIdx++];
|
||||||
|
if (!c) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
symName += c;
|
||||||
|
}
|
||||||
|
// The symbol name is always written expanded
|
||||||
|
Symbol *sym = sym_FindExactSymbol(symName);
|
||||||
|
registerUnregisteredSymbol(*sym); // Ensure that `sym->ID` is set
|
||||||
|
assume(patchIdx + 3 < patch.rpn.size());
|
||||||
|
patch.rpn[patchIdx++] = sym->ID & 0xFF;
|
||||||
|
patch.rpn[patchIdx++] = sym->ID >> 8;
|
||||||
|
patch.rpn[patchIdx++] = sym->ID >> 16;
|
||||||
|
patch.rpn[patchIdx++] = sym->ID >> 24;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case RPN_BANK_SECT:
|
||||||
|
case RPN_SIZEOF_SECT:
|
||||||
|
case RPN_STARTOF_SECT: {
|
||||||
|
// The command ID is followed by a NUL-terminated section name string
|
||||||
|
for (;;) {
|
||||||
|
assume(exprIdx < expr.rpn.size());
|
||||||
|
assume(patchIdx < patch.rpn.size());
|
||||||
|
uint8_t b = expr.rpn[exprIdx++];
|
||||||
|
patch.rpn[patchIdx++] = b;
|
||||||
|
if (!b) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case RPN_SIZEOF_SECTTYPE:
|
||||||
|
case RPN_STARTOF_SECTTYPE:
|
||||||
|
case RPN_BIT_INDEX:
|
||||||
|
// The command ID is followed by a byte value
|
||||||
|
assume(exprIdx < expr.rpn.size());
|
||||||
|
assume(patchIdx < patch.rpn.size());
|
||||||
|
patch.rpn[patchIdx++] = expr.rpn[exprIdx++];
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
4
test/asm/rpn-undefined.asm
Normal file
4
test/asm/rpn-undefined.asm
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
section "test", rom0
|
||||||
|
db UNDEFINED ; 4-byte ID
|
||||||
|
db BANK("Undefined") ; N-byte string
|
||||||
|
bit UNDEFINED, a ; 1-byte value
|
||||||
Reference in New Issue
Block a user