mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
Add link-time RST instruction
This allows using a label as the argument to a `rst` instruction Fixes rednex#448
This commit is contained in:
@@ -74,5 +74,6 @@ void rpn_BankSelf(struct Expression *expr);
|
||||
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 */
|
||||
|
||||
@@ -47,6 +47,7 @@ enum RPNCommand {
|
||||
RPN_BANK_SELF = 0x52,
|
||||
|
||||
RPN_HRAM = 0x60,
|
||||
RPN_RST = 0x61,
|
||||
|
||||
RPN_CONST = 0x80,
|
||||
RPN_SYM = 0x81
|
||||
|
||||
@@ -2065,9 +2065,10 @@ z80_rrca : T_Z80_RRCA
|
||||
|
||||
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);
|
||||
|
||||
@@ -242,6 +242,13 @@ void rpn_CheckHRAM(struct Expression *expr, const struct Expression *src)
|
||||
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;
|
||||
|
||||
@@ -284,6 +284,17 @@ static int32_t computeRPNExpr(struct Patch const *patch,
|
||||
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)
|
||||
|
||||
@@ -170,7 +170,9 @@ Symbol ID follows.
|
||||
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
|
||||
|
||||
35
test/asm/rst.asm
Normal file
35
test/asm/rst.asm
Normal file
@@ -0,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
|
||||
0
test/asm/rst.err
Normal file
0
test/asm/rst.err
Normal file
0
test/asm/rst.out
Normal file
0
test/asm/rst.out
Normal file
3
test/link/rst-bad.asm
Normal file
3
test/link/rst-bad.asm
Normal file
@@ -0,0 +1,3 @@
|
||||
SECTION "bad", ROM0[0]
|
||||
rst bad
|
||||
bad: ; This is not at a RST vector!
|
||||
1
test/link/rst-bad.out
Normal file
1
test/link/rst-bad.out
Normal file
@@ -0,0 +1 @@
|
||||
error: rst-bad.asm(2): Value 1 is not a RST vector
|
||||
31
test/link/rst.asm
Normal file
31
test/link/rst.asm
Normal file
@@ -0,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
|
||||
0
test/link/rst.out
Normal file
0
test/link/rst.out
Normal file
1
test/link/rst.out.bin
Normal file
1
test/link/rst.out.bin
Normal file
@@ -0,0 +1 @@
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
Reference in New Issue
Block a user