diff --git a/include/asm/rpn.h b/include/asm/rpn.h index 6fdb5ddc..24fed5cb 100644 --- a/include/asm/rpn.h +++ b/include/asm/rpn.h @@ -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 */ diff --git a/include/linkdefs.h b/include/linkdefs.h index d2fa00c7..f917ad81 100644 --- a/include/linkdefs.h +++ b/include/linkdefs.h @@ -13,7 +13,8 @@ #include #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 { RPN_ADD = 0x00, @@ -47,6 +48,7 @@ enum RPNCommand { RPN_BANK_SELF = 0x52, RPN_HRAM = 0x60, + RPN_RST = 0x61, RPN_CONST = 0x80, RPN_SYM = 0x81 diff --git a/src/asm/asmy.y b/src/asm/asmy.y index 5b5b06b7..d32873bb 100644 --- a/src/asm/asmy.y +++ b/src/asm/asmy.y @@ -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); diff --git a/src/asm/output.c b/src/asm/output.c index 80833db1..e1839d08 100644 --- a/src/asm/output.c +++ b/src/asm/output.c @@ -542,6 +542,7 @@ void out_WriteObject(void) fatalerror("Couldn't write file '%s'\n", tzObjectname); fprintf(f, RGBDS_OBJECT_VERSION_STRING, RGBDS_OBJECT_VERSION_NUMBER); + fputlong(RGBDS_OBJECT_REV, f); fputlong(countsymbols(), f); fputlong(countsections(), f); diff --git a/src/asm/rpn.c b/src/asm/rpn.c index b4f9ba33..8adff069 100644 --- a/src/asm/rpn.c +++ b/src/asm/rpn.c @@ -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; diff --git a/src/link/object.c b/src/link/object.c index 5082e695..7dcb2518 100644 --- a/src/link/object.c +++ b/src/link/object.c @@ -334,12 +334,39 @@ static void linkSymToSect(struct Symbol const *symbol, struct Section *section) } /** - * Reads a RGB6 object file. - * @param file The file to read from - * @param fileName The filename to report in errors + * Reads an object file of any supported format + * @param fileName The filename to report for 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 nbSections; @@ -424,37 +451,6 @@ static void readRGB6File(FILE *file, char const *fileName) 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); } diff --git a/src/link/patch.c b/src/link/patch.c index 2e8c76d5..50ae73ca 100644 --- a/src/link/patch.c +++ b/src/link/patch.c @@ -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) diff --git a/src/rgbds.5 b/src/rgbds.5 index bde7b013..0114138f 100644 --- a/src/rgbds.5 +++ b/src/rgbds.5 @@ -33,7 +33,8 @@ is a 0‐terminated string of .Bd -literal ; 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 NumberOfSections ; The number of sections used in this file @@ -170,7 +171,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 diff --git a/test/asm/rst.asm b/test/asm/rst.asm new file mode 100644 index 00000000..09dafe84 --- /dev/null +++ b/test/asm/rst.asm @@ -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 diff --git a/test/asm/rst.err b/test/asm/rst.err new file mode 100644 index 00000000..e69de29b diff --git a/test/asm/rst.out b/test/asm/rst.out new file mode 100644 index 00000000..e69de29b diff --git a/test/link/rst-bad.asm b/test/link/rst-bad.asm new file mode 100644 index 00000000..fe713c4c --- /dev/null +++ b/test/link/rst-bad.asm @@ -0,0 +1,3 @@ +SECTION "bad", ROM0[0] + rst bad +bad: ; This is not at a RST vector! diff --git a/test/link/rst-bad.out b/test/link/rst-bad.out new file mode 100644 index 00000000..6783e4d5 --- /dev/null +++ b/test/link/rst-bad.out @@ -0,0 +1 @@ +error: rst-bad.asm(2): Value 1 is not a RST vector diff --git a/test/link/rst.asm b/test/link/rst.asm new file mode 100644 index 00000000..14df973d --- /dev/null +++ b/test/link/rst.asm @@ -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 diff --git a/test/link/rst.out b/test/link/rst.out new file mode 100644 index 00000000..e69de29b diff --git a/test/link/rst.out.bin b/test/link/rst.out.bin new file mode 100644 index 00000000..1df237de --- /dev/null +++ b/test/link/rst.out.bin @@ -0,0 +1 @@ +ĒĻ×ßēļ÷’ \ No newline at end of file