ref: 52797b6f68bd470d538f5b12dff1c716eea4db09
parent: 5108c5643cbcab4463c831c44c83a18298edf4cc
author: Rangi <35663410+Rangi42@users.noreply.github.com>
date: Sat Apr 17 14:36:26 EDT 2021
Implement SIZEOF("Section") and STARTOF("Section") (#766) Updates the object file revision to 8 Fixes #765
--- a/include/asm/rpn.h
+++ b/include/asm/rpn.h
@@ -59,6 +59,8 @@
void rpn_BankSymbol(struct Expression *expr, char const *tzSym);
void rpn_BankSection(struct Expression *expr, char const *tzSectionName);
void rpn_BankSelf(struct Expression *expr);
+void rpn_SizeOfSection(struct Expression *expr, char const *tzSectionName);
+void rpn_StartOfSection(struct Expression *expr, char const *tzSectionName);
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);
--- a/include/linkdefs.h
+++ b/include/linkdefs.h
@@ -14,7 +14,7 @@
#define RGBDS_OBJECT_VERSION_STRING "RGB%1u"
#define RGBDS_OBJECT_VERSION_NUMBER 9U
-#define RGBDS_OBJECT_REV 7U
+#define RGBDS_OBJECT_REV 8U
enum AssertionType {
ASSERT_WARN,
@@ -23,42 +23,44 @@
};
enum RPNCommand {
- RPN_ADD = 0x00,
- RPN_SUB = 0x01,
- RPN_MUL = 0x02,
- RPN_DIV = 0x03,
- RPN_MOD = 0x04,
- RPN_UNSUB = 0x05,
- RPN_EXP = 0x06,
+ RPN_ADD = 0x00,
+ RPN_SUB = 0x01,
+ RPN_MUL = 0x02,
+ RPN_DIV = 0x03,
+ RPN_MOD = 0x04,
+ RPN_UNSUB = 0x05,
+ RPN_EXP = 0x06,
- RPN_OR = 0x10,
- RPN_AND = 0x11,
- RPN_XOR = 0x12,
- RPN_UNNOT = 0x13,
+ RPN_OR = 0x10,
+ RPN_AND = 0x11,
+ RPN_XOR = 0x12,
+ RPN_UNNOT = 0x13,
- RPN_LOGAND = 0x21,
- RPN_LOGOR = 0x22,
- RPN_LOGUNNOT = 0x23,
+ RPN_LOGAND = 0x21,
+ RPN_LOGOR = 0x22,
+ RPN_LOGUNNOT = 0x23,
- RPN_LOGEQ = 0x30,
- RPN_LOGNE = 0x31,
- RPN_LOGGT = 0x32,
- RPN_LOGLT = 0x33,
- RPN_LOGGE = 0x34,
- RPN_LOGLE = 0x35,
+ RPN_LOGEQ = 0x30,
+ RPN_LOGNE = 0x31,
+ RPN_LOGGT = 0x32,
+ RPN_LOGLT = 0x33,
+ RPN_LOGGE = 0x34,
+ RPN_LOGLE = 0x35,
- RPN_SHL = 0x40,
- RPN_SHR = 0x41,
+ RPN_SHL = 0x40,
+ RPN_SHR = 0x41,
- RPN_BANK_SYM = 0x50,
- RPN_BANK_SECT = 0x51,
- RPN_BANK_SELF = 0x52,
+ RPN_BANK_SYM = 0x50,
+ RPN_BANK_SECT = 0x51,
+ RPN_BANK_SELF = 0x52,
+ RPN_SIZEOF_SECT = 0x53,
+ RPN_STARTOF_SECT = 0x54,
- RPN_HRAM = 0x60,
- RPN_RST = 0x61,
+ RPN_HRAM = 0x60,
+ RPN_RST = 0x61,
- RPN_CONST = 0x80,
- RPN_SYM = 0x81
+ RPN_CONST = 0x80,
+ RPN_SYM = 0x81
};
enum SectionType {
--- a/src/asm/lexer.c
+++ b/src/asm/lexer.c
@@ -180,6 +180,9 @@
{"BANK", T_OP_BANK},
{"ALIGN", T_OP_ALIGN},
+ {"SIZEOF", T_OP_SIZEOF},
+ {"STARTOF", T_OP_STARTOF},
+
{"ROUND", T_OP_ROUND},
{"CEIL", T_OP_CEIL},
{"FLOOR", T_OP_FLOOR},
@@ -592,7 +595,7 @@
uint16_t children[0x60 - ' '];
struct KeywordMapping const *keyword;
/* Since the keyword structure is invariant, the min number of nodes is known at compile time */
-} keywordDict[357] = {0}; /* Make sure to keep this correct when adding keywords! */
+} keywordDict[365] = {0}; /* Make sure to keep this correct when adding keywords! */
/* Convert a char into its index into the dict */
static uint8_t dictIndex(char c)
--- a/src/asm/output.c
+++ b/src/asm/output.c
@@ -354,6 +354,22 @@
} while (b != 0);
break;
+ case RPN_SIZEOF_SECT:
+ writebyte(RPN_SIZEOF_SECT);
+ do {
+ b = popbyte();
+ writebyte(b);
+ } while (b != 0);
+ break;
+
+ case RPN_STARTOF_SECT:
+ writebyte(RPN_STARTOF_SECT);
+ do {
+ b = popbyte();
+ writebyte(b);
+ } while (b != 0);
+ break;
+
default:
writebyte(rpndata);
break;
--- a/src/asm/parser.y
+++ b/src/asm/parser.y
@@ -514,6 +514,7 @@
%token T_OP_DEF "DEF"
%token T_OP_BANK "BANK"
%token T_OP_ALIGN "ALIGN"
+%token T_OP_SIZEOF "SIZEOF" T_OP_STARTOF "STARTOF"
%token T_OP_SIN "SIN" T_OP_COS "COS" T_OP_TAN "TAN"
%token T_OP_ASIN "ASIN" T_OP_ACOS "ACOS" T_OP_ATAN "ATAN" T_OP_ATAN2 "ATAN2"
%token T_OP_FDIV "FDIV"
@@ -1419,6 +1420,8 @@
rpn_BankSymbol(&$$, $3);
}
| T_OP_BANK T_LPAREN string T_RPAREN { rpn_BankSection(&$$, $3); }
+ | T_OP_SIZEOF T_LPAREN string T_RPAREN { rpn_SizeOfSection(&$$, $3); }
+ | T_OP_STARTOF T_LPAREN string T_RPAREN { rpn_StartOfSection(&$$, $3); }
| T_OP_DEF {
lexer_ToggleStringExpansion(false);
} T_LPAREN scoped_anon_id T_RPAREN {
--- a/src/asm/rgbasm.5
+++ b/src/asm/rgbasm.5
@@ -461,6 +461,12 @@
The result may be constant if
.Nm
is able to compute it.
+.It Fn SIZEOF arg Ta Returns the size of the section named
+.Ar arg .
+The result is not constant, since only RGBLINK can compute its value.
+.It Fn STARTOF arg Ta Returns the starting address of the section named
+.Ar arg .
+The result is not constant, since only RGBLINK can compute its value.
.It Fn DEF symbol Ta Returns TRUE (1) if
.Ar symbol
has been defined, FALSE (0) otherwise.
--- a/src/asm/rpn.c
+++ b/src/asm/rpn.c
@@ -201,6 +201,34 @@
}
}
+void rpn_SizeOfSection(struct Expression *expr, char const *tzSectionName)
+{
+ rpn_Init(expr);
+
+ makeUnknown(expr, "Section \"%s\"'s size is not known", tzSectionName);
+
+ size_t nameLen = strlen(tzSectionName) + 1; /* Room for NUL! */
+ uint8_t *ptr = reserveSpace(expr, nameLen + 1);
+
+ expr->nRPNPatchSize += nameLen + 1;
+ *ptr++ = RPN_SIZEOF_SECT;
+ memcpy(ptr, tzSectionName, nameLen);
+}
+
+void rpn_StartOfSection(struct Expression *expr, char const *tzSectionName)
+{
+ rpn_Init(expr);
+
+ makeUnknown(expr, "Section \"%s\"'s start is not known", tzSectionName);
+
+ size_t nameLen = strlen(tzSectionName) + 1; /* Room for NUL! */
+ uint8_t *ptr = reserveSpace(expr, nameLen + 1);
+
+ expr->nRPNPatchSize += nameLen + 1;
+ *ptr++ = RPN_STARTOF_SECT;
+ memcpy(ptr, tzSectionName, nameLen);
+}
+
void rpn_CheckHRAM(struct Expression *expr, const struct Expression *src)
{
*expr = *src;
@@ -396,6 +424,8 @@
case RPN_BANK_SYM:
case RPN_BANK_SECT:
case RPN_BANK_SELF:
+ case RPN_SIZEOF_SECT:
+ case RPN_STARTOF_SECT:
case RPN_HRAM:
case RPN_RST:
case RPN_CONST:
--- a/src/link/patch.c
+++ b/src/link/patch.c
@@ -292,6 +292,11 @@
break;
case RPN_BANK_SECT:
+ /*
+ * `expression` is not guaranteed to be '\0'-terminated. If it is not,
+ * `getRPNByte` will have a fatal internal error.
+ * In either case, `getRPNByte` will not free `expression`.
+ */
name = (char const *)expression;
while (getRPNByte(&expression, &size, patch->src, patch->lineNo))
;
@@ -317,6 +322,44 @@
value = 1;
} else {
value = patch->pcSection->bank;
+ }
+ break;
+
+ case RPN_SIZEOF_SECT:
+ /* This has assumptions commented in the `RPN_BANK_SECT` case above. */
+ name = (char const *)expression;
+ while (getRPNByte(&expression, &size, patch->src, patch->lineNo))
+ ;
+
+ sect = sect_GetSection(name);
+
+ if (!sect) {
+ error(patch->src, patch->lineNo,
+ "Requested SIZEOF() of section \"%s\", which was not found",
+ name);
+ isError = true;
+ value = 1;
+ } else {
+ value = sect->size;
+ }
+ break;
+
+ case RPN_STARTOF_SECT:
+ /* This has assumptions commented in the `RPN_BANK_SECT` case above. */
+ name = (char const *)expression;
+ while (getRPNByte(&expression, &size, patch->src, patch->lineNo))
+ ;
+
+ sect = sect_GetSection(name);
+
+ if (!sect) {
+ error(patch->src, patch->lineNo,
+ "Requested STARTOF() of section \"%s\", which was not found",
+ name);
+ isError = true;
+ value = 1;
+ } else {
+ value = sect->org;
}
break;
--- a/src/rgbds.5
+++ b/src/rgbds.5
@@ -248,6 +248,10 @@
.It Li $51 Ta Li BANK(section_name) ,
a null-terminated string follows.
.It Li $52 Ta Li Current BANK()
+.It Li $53 Ta Li SIZEOF(section_name) ,
+a null-terminated string follows.
+.It Li $54 Ta Li STARTOF(section_name) ,
+a null-terminated string follows.
.It Li $60 Ta Li HRAMCheck .
Checks if the value is in HRAM, ANDs it with 0xFF.
.It Li $61 Ta Li RSTCheck .
--- /dev/null
+++ b/test/asm/section-sizeof-startof.asm
@@ -1,0 +1,8 @@
+SECTION "sect", ROMX[$4567], BANK[$23]
+ ds 42
+
+W = BANK("sect")
+X = SIZEOF("sect")
+Y = STARTOF("sect")
+
+ println "{W} {X} {Y}"
--- /dev/null
+++ b/test/asm/section-sizeof-startof.err
@@ -1,0 +1,5 @@
+ERROR: section-sizeof-startof.asm(5):
+ Expected constant expression: Section "sect"'s size is not known
+ERROR: section-sizeof-startof.asm(6):
+ Expected constant expression: Section "sect"'s start is not known
+error: Assembly aborted (2 errors)!
--- /dev/null
+++ b/test/asm/section-sizeof-startof.out
@@ -1,0 +1,1 @@
+$23 $0 $0
--- /dev/null
+++ b/test/link/sizeof-startof.asm
@@ -1,0 +1,7 @@
+SECTION "meta", ROM0[0]
+ db BANK("sect")
+ dw STARTOF("sect")
+ dw SIZEOF("sect")
+
+SECTION "sect", ROMX[$4567], BANK[$23]
+ ds 42
--- /dev/null
+++ b/test/link/sizeof-startof.out.bin
@@ -1,0 +1,1 @@
+#gE*
\ No newline at end of file