mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-21 02:32:06 +00:00
Merge pull request #470 from ISSOtm/rst
Allow using labels as argument to `rst`
This commit is contained in:
@@ -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 */
|
||||||
|
|||||||
@@ -13,7 +13,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define RGBDS_OBJECT_VERSION_STRING "RGB%1hhu"
|
#define RGBDS_OBJECT_VERSION_STRING "RGB%1hhu"
|
||||||
#define RGBDS_OBJECT_VERSION_NUMBER (uint8_t)6
|
#define RGBDS_OBJECT_VERSION_NUMBER (uint8_t)9
|
||||||
|
#define RGBDS_OBJECT_REV 0
|
||||||
|
|
||||||
enum RPNCommand {
|
enum RPNCommand {
|
||||||
RPN_ADD = 0x00,
|
RPN_ADD = 0x00,
|
||||||
@@ -47,6 +48,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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -542,6 +542,7 @@ void out_WriteObject(void)
|
|||||||
fatalerror("Couldn't write file '%s'\n", tzObjectname);
|
fatalerror("Couldn't write file '%s'\n", tzObjectname);
|
||||||
|
|
||||||
fprintf(f, RGBDS_OBJECT_VERSION_STRING, RGBDS_OBJECT_VERSION_NUMBER);
|
fprintf(f, RGBDS_OBJECT_VERSION_STRING, RGBDS_OBJECT_VERSION_NUMBER);
|
||||||
|
fputlong(RGBDS_OBJECT_REV, f);
|
||||||
|
|
||||||
fputlong(countsymbols(), f);
|
fputlong(countsymbols(), f);
|
||||||
fputlong(countsections(), f);
|
fputlong(countsections(), f);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -334,12 +334,39 @@ static void linkSymToSect(struct Symbol const *symbol, struct Section *section)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a RGB6 object file.
|
* Reads an object file of any supported format
|
||||||
* @param file The file to read from
|
* @param fileName The filename to report for errors
|
||||||
* @param fileName The filename to report in errors
|
|
||||||
*/
|
*/
|
||||||
static void readRGB6File(FILE *file, char const *fileName)
|
void obj_ReadFile(char const *fileName)
|
||||||
{
|
{
|
||||||
|
FILE *file = strcmp("-", fileName) ? fopen(fileName, "rb") : stdin;
|
||||||
|
|
||||||
|
if (!file)
|
||||||
|
err(1, "Could not open file %s", fileName);
|
||||||
|
|
||||||
|
/* Begin by reading the magic bytes and version number */
|
||||||
|
uint8_t versionNumber;
|
||||||
|
int matchedElems = fscanf(file, RGBDS_OBJECT_VERSION_STRING,
|
||||||
|
&versionNumber);
|
||||||
|
|
||||||
|
if (matchedElems != 1)
|
||||||
|
errx(1, "\"%s\" is not a RGBDS object file", fileName);
|
||||||
|
|
||||||
|
verbosePrint("Reading object file %s, version %hhu\n",
|
||||||
|
fileName, versionNumber);
|
||||||
|
|
||||||
|
if (versionNumber != RGBDS_OBJECT_VERSION_NUMBER)
|
||||||
|
errx(1, "\"%s\" is an incompatible version %hhu object file",
|
||||||
|
fileName, versionNumber);
|
||||||
|
|
||||||
|
uint32_t revNum;
|
||||||
|
|
||||||
|
tryReadlong(revNum, file, "%s: Cannot read revision number: %s",
|
||||||
|
fileName);
|
||||||
|
if (revNum != RGBDS_OBJECT_REV)
|
||||||
|
errx(1, "%s is a revision 0x%04x object file, only 0x%04x is supported",
|
||||||
|
fileName, revNum, RGBDS_OBJECT_REV);
|
||||||
|
|
||||||
uint32_t nbSymbols;
|
uint32_t nbSymbols;
|
||||||
uint32_t nbSections;
|
uint32_t nbSections;
|
||||||
|
|
||||||
@@ -424,37 +451,6 @@ static void readRGB6File(FILE *file, char const *fileName)
|
|||||||
linkSymToSect(fileSymbols[i], fileSections[sectionID]);
|
linkSymToSect(fileSymbols[i], fileSections[sectionID]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads an object file of any supported format
|
|
||||||
* @param fileName The filename to report for errors
|
|
||||||
*/
|
|
||||||
void obj_ReadFile(char const *fileName)
|
|
||||||
{
|
|
||||||
FILE *file = strcmp("-", fileName) ? fopen(fileName, "rb") : stdin;
|
|
||||||
|
|
||||||
if (!file) {
|
|
||||||
err(1, "Could not open file %s", fileName);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Begin by reading the magic bytes and version number */
|
|
||||||
uint8_t versionNumber;
|
|
||||||
int matchedElems = fscanf(file, RGBDS_OBJECT_VERSION_STRING,
|
|
||||||
&versionNumber);
|
|
||||||
|
|
||||||
if (matchedElems != 1)
|
|
||||||
errx(1, "\"%s\" is not a RGBDS object file", fileName);
|
|
||||||
/* TODO: support other versions? */
|
|
||||||
if (versionNumber != 6)
|
|
||||||
errx(1, "\"%s\" is an incompatible version %hhu object file",
|
|
||||||
fileName, versionNumber);
|
|
||||||
|
|
||||||
verbosePrint("Reading object file %s, version %hhu\n",
|
|
||||||
fileName, versionNumber);
|
|
||||||
|
|
||||||
readRGB6File(file, fileName);
|
|
||||||
|
|
||||||
fclose(file);
|
fclose(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)
|
||||||
|
|||||||
@@ -33,7 +33,8 @@ is a 0‐terminated string of
|
|||||||
.Bd -literal
|
.Bd -literal
|
||||||
; Header
|
; Header
|
||||||
|
|
||||||
BYTE ID[4] ; "RGB6"
|
BYTE ID[4] ; "RGB9"
|
||||||
|
LONG RevisionNumber ; The format's revision number this file uses
|
||||||
LONG NumberOfSymbols ; The number of symbols used in this file
|
LONG NumberOfSymbols ; The number of symbols used in this file
|
||||||
LONG NumberOfSections ; The number of sections used in this file
|
LONG NumberOfSections ; The number of sections used in this file
|
||||||
|
|
||||||
@@ -170,7 +171,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
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