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:
ISSOtm
2020-01-14 00:02:22 +01:00
parent 359a048b6e
commit b1cd730db2
14 changed files with 98 additions and 4 deletions

View File

@@ -74,5 +74,6 @@ void rpn_BankSelf(struct Expression *expr);
void rpn_Init(struct Expression *expr); void rpn_Init(struct Expression *expr);
void rpn_Free(struct Expression *expr); void rpn_Free(struct Expression *expr);
void rpn_CheckHRAM(struct Expression *expr, const struct Expression *src); 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 */ #endif /* RGBDS_ASM_RPN_H */

View File

@@ -47,6 +47,7 @@ enum RPNCommand {
RPN_BANK_SELF = 0x52, RPN_BANK_SELF = 0x52,
RPN_HRAM = 0x60, RPN_HRAM = 0x60,
RPN_RST = 0x61,
RPN_CONST = 0x80, RPN_CONST = 0x80,
RPN_SYM = 0x81 RPN_SYM = 0x81

View File

@@ -2065,9 +2065,10 @@ 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_isReloc(&$2)) {
yyerror("Address for RST must be absolute"); rpn_CheckRST(&$2, &$2);
else if (($2.nVal & 0x38) != $2.nVal) out_RelByte(&$2);
} 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);

View File

@@ -242,6 +242,13 @@ void rpn_CheckHRAM(struct Expression *expr, const struct Expression *src)
expr->nRPNPatchSize++; 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) void rpn_LOGNOT(struct Expression *expr, const struct Expression *src)
{ {
*expr = *src; *expr = *src;

View File

@@ -284,6 +284,17 @@ static int32_t computeRPNExpr(struct Patch const *patch,
value &= 0xFF; value &= 0xFF;
break; 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: case RPN_CONST:
value = 0; value = 0;
for (uint8_t shift = 0; shift < 32; shift += 8) for (uint8_t shift = 0; shift < 32; shift += 8)

View File

@@ -170,7 +170,9 @@ Symbol ID follows.
a null-terminated string follows. a null-terminated string follows.
.It Li $52 Ta Li Current BANK() .It Li $52 Ta Li Current BANK()
.It Li $60 Ta Li HRAMCheck . .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 .It Li $80 Ta Ar LONG
integer follows. integer follows.
.It Li $81 Ta Ar LONG .It Li $81 Ta Ar LONG

35
test/asm/rst.asm Normal file
View 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
View File

0
test/asm/rst.out Normal file
View File

3
test/link/rst-bad.asm Normal file
View 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
View File

@@ -0,0 +1 @@
error: rst-bad.asm(2): Value 1 is not a RST vector

31
test/link/rst.asm Normal file
View 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
View File

1
test/link/rst.out.bin Normal file
View File

@@ -0,0 +1 @@
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>