mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Implement SIZEOF("Section") and STARTOF("Section") (#766)
Updates the object file revision to 8 Fixes #765
This commit is contained in:
@@ -59,6 +59,8 @@ void rpn_UNNOT(struct Expression *expr, const struct Expression *src);
|
||||
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);
|
||||
|
||||
@@ -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,
|
||||
@@ -53,6 +53,8 @@ enum RPNCommand {
|
||||
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,
|
||||
|
||||
@@ -180,6 +180,9 @@ static struct KeywordMapping {
|
||||
{"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 @@ struct KeywordDictNode {
|
||||
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)
|
||||
|
||||
@@ -354,6 +354,22 @@ static void writerpn(uint8_t *rpnexpr, uint32_t *rpnptr, uint8_t *rpn,
|
||||
} 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;
|
||||
|
||||
@@ -514,6 +514,7 @@ enum {
|
||||
%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 @@ relocexpr_no_str : scoped_anon_id { rpn_Symbol(&$$, $1); }
|
||||
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 {
|
||||
|
||||
@@ -461,6 +461,12 @@ is a label, it returns the bank number the label is in.
|
||||
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.
|
||||
|
||||
@@ -201,6 +201,34 @@ void rpn_BankSection(struct Expression *expr, char const *tzSectionName)
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr,
|
||||
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:
|
||||
|
||||
@@ -292,6 +292,11 @@ static int32_t computeRPNExpr(struct Patch const *patch,
|
||||
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))
|
||||
;
|
||||
@@ -320,6 +325,44 @@ static int32_t computeRPNExpr(struct Patch const *patch,
|
||||
}
|
||||
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;
|
||||
|
||||
case RPN_HRAM:
|
||||
value = popRPN();
|
||||
if (!isError && (value < 0
|
||||
|
||||
@@ -248,6 +248,10 @@ Symbol ID follows, where -1 means PC
|
||||
.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 .
|
||||
|
||||
8
test/asm/section-sizeof-startof.asm
Normal file
8
test/asm/section-sizeof-startof.asm
Normal file
@@ -0,0 +1,8 @@
|
||||
SECTION "sect", ROMX[$4567], BANK[$23]
|
||||
ds 42
|
||||
|
||||
W = BANK("sect")
|
||||
X = SIZEOF("sect")
|
||||
Y = STARTOF("sect")
|
||||
|
||||
println "{W} {X} {Y}"
|
||||
5
test/asm/section-sizeof-startof.err
Normal file
5
test/asm/section-sizeof-startof.err
Normal file
@@ -0,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)!
|
||||
1
test/asm/section-sizeof-startof.out
Normal file
1
test/asm/section-sizeof-startof.out
Normal file
@@ -0,0 +1 @@
|
||||
$23 $0 $0
|
||||
7
test/link/sizeof-startof.asm
Normal file
7
test/link/sizeof-startof.asm
Normal file
@@ -0,0 +1,7 @@
|
||||
SECTION "meta", ROM0[0]
|
||||
db BANK("sect")
|
||||
dw STARTOF("sect")
|
||||
dw SIZEOF("sect")
|
||||
|
||||
SECTION "sect", ROMX[$4567], BANK[$23]
|
||||
ds 42
|
||||
BIN
test/link/sizeof-startof.out.bin
Normal file
BIN
test/link/sizeof-startof.out.bin
Normal file
Binary file not shown.
Reference in New Issue
Block a user