mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +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_BankSymbol(struct Expression *expr, char const *tzSym);
|
||||||
void rpn_BankSection(struct Expression *expr, char const *tzSectionName);
|
void rpn_BankSection(struct Expression *expr, char const *tzSectionName);
|
||||||
void rpn_BankSelf(struct Expression *expr);
|
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_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);
|
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_STRING "RGB%1u"
|
||||||
#define RGBDS_OBJECT_VERSION_NUMBER 9U
|
#define RGBDS_OBJECT_VERSION_NUMBER 9U
|
||||||
#define RGBDS_OBJECT_REV 7U
|
#define RGBDS_OBJECT_REV 8U
|
||||||
|
|
||||||
enum AssertionType {
|
enum AssertionType {
|
||||||
ASSERT_WARN,
|
ASSERT_WARN,
|
||||||
@@ -53,6 +53,8 @@ enum RPNCommand {
|
|||||||
RPN_BANK_SYM = 0x50,
|
RPN_BANK_SYM = 0x50,
|
||||||
RPN_BANK_SECT = 0x51,
|
RPN_BANK_SECT = 0x51,
|
||||||
RPN_BANK_SELF = 0x52,
|
RPN_BANK_SELF = 0x52,
|
||||||
|
RPN_SIZEOF_SECT = 0x53,
|
||||||
|
RPN_STARTOF_SECT = 0x54,
|
||||||
|
|
||||||
RPN_HRAM = 0x60,
|
RPN_HRAM = 0x60,
|
||||||
RPN_RST = 0x61,
|
RPN_RST = 0x61,
|
||||||
|
|||||||
@@ -180,6 +180,9 @@ static struct KeywordMapping {
|
|||||||
{"BANK", T_OP_BANK},
|
{"BANK", T_OP_BANK},
|
||||||
{"ALIGN", T_OP_ALIGN},
|
{"ALIGN", T_OP_ALIGN},
|
||||||
|
|
||||||
|
{"SIZEOF", T_OP_SIZEOF},
|
||||||
|
{"STARTOF", T_OP_STARTOF},
|
||||||
|
|
||||||
{"ROUND", T_OP_ROUND},
|
{"ROUND", T_OP_ROUND},
|
||||||
{"CEIL", T_OP_CEIL},
|
{"CEIL", T_OP_CEIL},
|
||||||
{"FLOOR", T_OP_FLOOR},
|
{"FLOOR", T_OP_FLOOR},
|
||||||
@@ -592,7 +595,7 @@ struct KeywordDictNode {
|
|||||||
uint16_t children[0x60 - ' '];
|
uint16_t children[0x60 - ' '];
|
||||||
struct KeywordMapping const *keyword;
|
struct KeywordMapping const *keyword;
|
||||||
/* Since the keyword structure is invariant, the min number of nodes is known at compile time */
|
/* 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 */
|
/* Convert a char into its index into the dict */
|
||||||
static uint8_t dictIndex(char c)
|
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);
|
} while (b != 0);
|
||||||
break;
|
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:
|
default:
|
||||||
writebyte(rpndata);
|
writebyte(rpndata);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -514,6 +514,7 @@ enum {
|
|||||||
%token T_OP_DEF "DEF"
|
%token T_OP_DEF "DEF"
|
||||||
%token T_OP_BANK "BANK"
|
%token T_OP_BANK "BANK"
|
||||||
%token T_OP_ALIGN "ALIGN"
|
%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_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_ASIN "ASIN" T_OP_ACOS "ACOS" T_OP_ATAN "ATAN" T_OP_ATAN2 "ATAN2"
|
||||||
%token T_OP_FDIV "FDIV"
|
%token T_OP_FDIV "FDIV"
|
||||||
@@ -1419,6 +1420,8 @@ relocexpr_no_str : scoped_anon_id { rpn_Symbol(&$$, $1); }
|
|||||||
rpn_BankSymbol(&$$, $3);
|
rpn_BankSymbol(&$$, $3);
|
||||||
}
|
}
|
||||||
| T_OP_BANK T_LPAREN string T_RPAREN { rpn_BankSection(&$$, $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 {
|
| T_OP_DEF {
|
||||||
lexer_ToggleStringExpansion(false);
|
lexer_ToggleStringExpansion(false);
|
||||||
} T_LPAREN scoped_anon_id T_RPAREN {
|
} 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
|
The result may be constant if
|
||||||
.Nm
|
.Nm
|
||||||
is able to compute it.
|
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
|
.It Fn DEF symbol Ta Returns TRUE (1) if
|
||||||
.Ar symbol
|
.Ar symbol
|
||||||
has been defined, FALSE (0) otherwise.
|
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)
|
void rpn_CheckHRAM(struct Expression *expr, const struct Expression *src)
|
||||||
{
|
{
|
||||||
*expr = *src;
|
*expr = *src;
|
||||||
@@ -396,6 +424,8 @@ void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr,
|
|||||||
case RPN_BANK_SYM:
|
case RPN_BANK_SYM:
|
||||||
case RPN_BANK_SECT:
|
case RPN_BANK_SECT:
|
||||||
case RPN_BANK_SELF:
|
case RPN_BANK_SELF:
|
||||||
|
case RPN_SIZEOF_SECT:
|
||||||
|
case RPN_STARTOF_SECT:
|
||||||
case RPN_HRAM:
|
case RPN_HRAM:
|
||||||
case RPN_RST:
|
case RPN_RST:
|
||||||
case RPN_CONST:
|
case RPN_CONST:
|
||||||
|
|||||||
@@ -292,6 +292,11 @@ static int32_t computeRPNExpr(struct Patch const *patch,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case RPN_BANK_SECT:
|
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;
|
name = (char const *)expression;
|
||||||
while (getRPNByte(&expression, &size, patch->src, patch->lineNo))
|
while (getRPNByte(&expression, &size, patch->src, patch->lineNo))
|
||||||
;
|
;
|
||||||
@@ -320,6 +325,44 @@ static int32_t computeRPNExpr(struct Patch const *patch,
|
|||||||
}
|
}
|
||||||
break;
|
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:
|
case RPN_HRAM:
|
||||||
value = popRPN();
|
value = popRPN();
|
||||||
if (!isError && (value < 0
|
if (!isError && (value < 0
|
||||||
|
|||||||
@@ -248,6 +248,10 @@ Symbol ID follows, where -1 means PC
|
|||||||
.It Li $51 Ta Li BANK(section_name) ,
|
.It Li $51 Ta Li BANK(section_name) ,
|
||||||
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 $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 .
|
.It Li $60 Ta Li HRAMCheck .
|
||||||
Checks if the value is in HRAM, ANDs it with 0xFF.
|
Checks if the value is in HRAM, ANDs it with 0xFF.
|
||||||
.It Li $61 Ta Li RSTCheck .
|
.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