ref: b1cd730db2dc3719e451b5eb6fb91c26b3715d4d
parent: 359a048b6e235aab6e330fc6f85b118da0e9e046
author: ISSOtm <[email protected]>
date: Mon Jan 13 19:02:22 EST 2020
Add link-time RST instruction This allows using a label as the argument to a `rst` instruction Fixes rednex#448
--- a/include/asm/rpn.h
+++ b/include/asm/rpn.h
@@ -74,5 +74,6 @@
void rpn_Init(struct Expression *expr);
void rpn_Free(struct Expression *expr);
void rpn_CheckHRAM(struct Expression *expr, const struct Expression *src);
+void rpn_CheckRST(struct Expression *expr, const struct Expression *src);
#endif /* RGBDS_ASM_RPN_H */
--- a/include/linkdefs.h
+++ b/include/linkdefs.h
@@ -47,6 +47,7 @@
RPN_BANK_SELF = 0x52,
RPN_HRAM = 0x60,
+ RPN_RST = 0x61,
RPN_CONST = 0x80,
RPN_SYM = 0x81
--- a/src/asm/asmy.y
+++ b/src/asm/asmy.y
@@ -2065,9 +2065,10 @@
z80_rst : T_Z80_RST const_8bit
{
- if (rpn_isReloc(&$2))
- yyerror("Address for RST must be absolute");
- else if (($2.nVal & 0x38) != $2.nVal)
+ if (rpn_isReloc(&$2)) {
+ rpn_CheckRST(&$2, &$2);
+ out_RelByte(&$2);
+ } else if (($2.nVal & 0x38) != $2.nVal)
yyerror("Invalid address $%x for RST", $2.nVal);
else
out_AbsByte(0xC7 | $2.nVal);
--- a/src/asm/rpn.c
+++ b/src/asm/rpn.c
@@ -242,6 +242,13 @@
expr->nRPNPatchSize++;
}
+void rpn_CheckRST(struct Expression *expr, const struct Expression *src)
+{
+ *expr = *src;
+ pushbyte(expr, RPN_RST);
+ expr->nRPNPatchSize++;
+}
+
void rpn_LOGNOT(struct Expression *expr, const struct Expression *src)
{
*expr = *src;
--- a/src/link/patch.c
+++ b/src/link/patch.c
@@ -284,6 +284,17 @@
value &= 0xFF;
break;
+ case RPN_RST:
+ value = popRPN();
+ /* Acceptable values are 0x00, 0x08, 0x10, ..., 0x38
+ * They can be easily checked with a bitmask
+ */
+ if (value & ~0x38)
+ errx(1, "%s(%d): Value %d is not a RST vector",
+ patch->fileName, patch->lineNo, value);
+ value |= 0xC7;
+ break;
+
case RPN_CONST:
value = 0;
for (uint8_t shift = 0; shift < 32; shift += 8)
--- a/src/rgbds.5
+++ b/src/rgbds.5
@@ -170,7 +170,9 @@
a null-terminated string follows.
.It Li $52 Ta Li Current BANK()
.It Li $60 Ta Li HRAMCheck .
-Checks if the value is in HRAM, AND it with 0xFF.
+Checks if the value is in HRAM, ANDs it with 0xFF.
+.It Li $61 Ta Li RSTCheck .
+Checks if the value is a RST vector, ORs it with 0xC7.
.It Li $80 Ta Ar LONG
integer follows.
.It Li $81 Ta Ar LONG
--- /dev/null
+++ b/test/asm/rst.asm
@@ -1,0 +1,35 @@
+
+SECTION "calls", ROM0[0]
+
+; The values are not known at this point, forcing the assembler to emit an
+; expression
+ rst rst00
+ rst rst08
+ rst rst10
+ rst rst18
+ rst rst20
+ rst rst28
+ rst rst30
+ rst rst38
+
+ rst rst2A
+
+
+defRST: MACRO
+; FIXME: This is required, otherwise the lexer does not paste the two tokens
+ADDR equs "$\1"
+SECTION "rst\1", ROM0[ADDR]
+
+rst\1:
+ PURGE ADDR
+ENDM
+ defRST 00
+ defRST 08
+ defRST 10
+ defRST 18
+ defRST 20
+ defRST 28
+ defRST 30
+ defRST 38
+
+ defRST 2A ; Define a nonsensical RST, because RGBASM cannot catch it
--- /dev/null
+++ b/test/link/rst-bad.asm
@@ -1,0 +1,3 @@
+SECTION "bad", ROM0[0]
+ rst bad
+bad: ; This is not at a RST vector!
--- /dev/null
+++ b/test/link/rst-bad.out
@@ -1,0 +1,1 @@
+error: rst-bad.asm(2): Value 1 is not a RST vector
--- /dev/null
+++ b/test/link/rst.asm
@@ -1,0 +1,31 @@
+
+SECTION "calls", ROM0[0]
+
+; The values are not known at this point, forcing the assembler to emit an
+; expression
+ rst rst00
+ rst rst08
+ rst rst10
+ rst rst18
+ rst rst20
+ rst rst28
+ rst rst30
+ rst rst38
+
+
+defRST: MACRO
+; FIXME: This is required, otherwise the lexer does not paste the two tokens
+ADDR equs "$\1"
+SECTION "rst\1", ROM0[ADDR]
+
+rst\1:
+ PURGE ADDR
+ENDM
+ defRST 00
+ defRST 08
+ defRST 10
+ defRST 18
+ defRST 20
+ defRST 28
+ defRST 30
+ defRST 38
--- /dev/null
+++ b/test/link/rst.out.bin
@@ -1,0 +1,1 @@
+������
\ No newline at end of file