Implement SIZEOF("Section") and STARTOF("Section") (#766)

Updates the object file revision to 8

Fixes #765
This commit is contained in:
Rangi
2021-04-17 18:36:26 -04:00
committed by GitHub
parent 5108c5643c
commit 52797b6f68
14 changed files with 161 additions and 31 deletions

View File

@@ -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);

View File

@@ -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,

View File

@@ -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)

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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.

View File

@@ -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:

View File

@@ -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

View File

@@ -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 .

View 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}"

View 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)!

View File

@@ -0,0 +1 @@
$23 $0 $0

View 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

Binary file not shown.