Skip to content

Commit

Permalink
Implement SIZEOF("Section") and STARTOF("Section") (gbdev#766)
Browse files Browse the repository at this point in the history
Updates the object file revision to 8

Fixes gbdev#765
  • Loading branch information
Rangi42 authored Apr 17, 2021
1 parent 5108c56 commit 52797b6
Show file tree
Hide file tree
Showing 14 changed files with 168 additions and 38 deletions.
2 changes: 2 additions & 0 deletions include/asm/rpn.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
76 changes: 39 additions & 37 deletions include/linkdefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -23,42 +23,44 @@ enum AssertionType {
};

enum RPNCommand {
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_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_SHL = 0x40,
RPN_SHR = 0x41,

RPN_BANK_SYM = 0x50,
RPN_BANK_SECT = 0x51,
RPN_BANK_SELF = 0x52,

RPN_HRAM = 0x60,
RPN_RST = 0x61,

RPN_CONST = 0x80,
RPN_SYM = 0x81
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_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_SHL = 0x40,
RPN_SHR = 0x41,

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_CONST = 0x80,
RPN_SYM = 0x81
};

enum SectionType {
Expand Down
5 changes: 4 additions & 1 deletion src/asm/lexer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -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)
Expand Down
16 changes: 16 additions & 0 deletions src/asm/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions src/asm/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 {
Expand Down
6 changes: 6 additions & 0 deletions src/asm/rgbasm.5
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
30 changes: 30 additions & 0 deletions src/asm/rpn.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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:
Expand Down
43 changes: 43 additions & 0 deletions src/link/patch.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
;
Expand Down Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions src/rgbds.5
Original file line number Diff line number Diff line change
Expand Up @@ -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 .
Expand Down
8 changes: 8 additions & 0 deletions test/asm/section-sizeof-startof.asm
Original file line number Diff line number Diff line change
@@ -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 changes: 5 additions & 0 deletions test/asm/section-sizeof-startof.err
Original file line number Diff line number Diff line change
@@ -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 change: 1 addition & 0 deletions test/asm/section-sizeof-startof.out
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
$23 $0 $0
7 changes: 7 additions & 0 deletions test/link/sizeof-startof.asm
Original file line number Diff line number Diff line change
@@ -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 added test/link/sizeof-startof.out.bin
Binary file not shown.

0 comments on commit 52797b6

Please sign in to comment.