Port some cleanup from PR #847

- Update some whitespace formatting
- Factor out some functions
- Free data after outputting to an object file
This commit is contained in:
Rangi
2021-04-25 18:36:19 -04:00
committed by Rangi
parent b4814b06b9
commit bba532193b
5 changed files with 209 additions and 188 deletions

View File

@@ -30,7 +30,7 @@ struct Expression {
/* /*
* Determines if an expression is known at assembly time * Determines if an expression is known at assembly time
*/ */
static inline bool rpn_isKnown(const struct Expression *expr) static inline bool rpn_isKnown(struct Expression const *expr)
{ {
return expr->isKnown; return expr->isKnown;
} }
@@ -64,5 +64,7 @@ void rpn_StartOfSection(struct Expression *expr, char const *sectionName);
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);
void rpn_CheckNBit(struct Expression const *expr, uint8_t n);
int32_t rpn_GetConstVal(struct Expression const *expr);
#endif /* RGBDS_ASM_RPN_H */ #endif /* RGBDS_ASM_RPN_H */

View File

@@ -28,17 +28,17 @@ enum RPNCommand {
RPN_MUL = 0x02, RPN_MUL = 0x02,
RPN_DIV = 0x03, RPN_DIV = 0x03,
RPN_MOD = 0x04, RPN_MOD = 0x04,
RPN_UNSUB = 0x05, RPN_UNSUB = 0x05, // FIXME: should be renamed to "NEG" for consistency
RPN_EXP = 0x06, RPN_EXP = 0x06,
RPN_OR = 0x10, RPN_OR = 0x10,
RPN_AND = 0x11, RPN_AND = 0x11,
RPN_XOR = 0x12, RPN_XOR = 0x12,
RPN_UNNOT = 0x13, RPN_UNNOT = 0x13, // FIXME: should be renamed to "NOT" for consistency
RPN_LOGAND = 0x21, RPN_LOGAND = 0x21,
RPN_LOGOR = 0x22, RPN_LOGOR = 0x22,
RPN_LOGUNNOT = 0x23, RPN_LOGUNNOT = 0x23, // FIXME: should be renamed to "LOGNOT" for consistency
RPN_LOGEQ = 0x30, RPN_LOGEQ = 0x30,
RPN_LOGNE = 0x31, RPN_LOGNE = 0x31,

View File

@@ -242,6 +242,21 @@ static void writesection(struct Section const *sect, FILE *f)
} }
} }
static void freesection(struct Section const *sect)
{
if (sect_HasData(sect->type)) {
struct Patch *patch = sect->patches;
while (patch != NULL) {
struct Patch *next = patch->next;
free(patch->rpn);
free(patch);
patch = next;
}
}
}
/* /*
* Write a symbol to a file * Write a symbol to a file
*/ */
@@ -468,6 +483,13 @@ static void writeassert(struct Assertion *assert, FILE *f)
putstring(assert->message, f); putstring(assert->message, f);
} }
static void freeassert(struct Assertion *assert)
{
free(assert->patch->rpn);
free(assert->patch);
free(assert);
}
static void writeFileStackNode(struct FileStackNode const *node, FILE *f) static void writeFileStackNode(struct FileStackNode const *node, FILE *f)
{ {
putlong(node->parent ? node->parent->ID : -1, f); putlong(node->parent ? node->parent->ID : -1, f);
@@ -530,13 +552,21 @@ void out_WriteObject(void)
for (struct Symbol const *sym = objectSymbols; sym; sym = sym->next) for (struct Symbol const *sym = objectSymbols; sym; sym = sym->next)
writesymbol(sym, f); writesymbol(sym, f);
for (struct Section *sect = sectionList; sect; sect = sect->next) for (struct Section *sect = sectionList; sect; sect = sect->next) {
writesection(sect, f); writesection(sect, f);
freesection(sect);
}
putlong(countAsserts(), f); putlong(countAsserts(), f);
for (struct Assertion *assert = assertions; assert; struct Assertion *assert = assertions;
assert = assert->next)
while (assert != NULL) {
struct Assertion *next = assert->next;
writeassert(assert, f); writeassert(assert, f);
freeassert(assert);
assert = next;
}
fclose(f); fclose(f);
} }

View File

@@ -481,6 +481,7 @@ enum {
%type <expr> relocexpr_no_str %type <expr> relocexpr_no_str
%type <constValue> const %type <constValue> const
%type <constValue> const_no_str %type <constValue> const_no_str
%type <constValue> const_8bit
%type <constValue> uconst %type <constValue> uconst
%type <constValue> rs_uconst %type <constValue> rs_uconst
%type <constValue> const_3bit %type <constValue> const_3bit
@@ -868,16 +869,16 @@ directive : endc
trailing_comma : %empty | T_COMMA trailing_comma : %empty | T_COMMA
; ;
equ : T_LABEL T_POP_EQU const { sym_AddEqu($1, $3); } equ : T_LABEL T_POP_EQU const { sym_AddEqu($1, $3); }
; ;
set_or_equal : T_POP_SET | T_POP_EQUAL set_or_equal : T_POP_SET | T_POP_EQUAL
; ;
set : T_LABEL set_or_equal const { sym_AddSet($1, $3); } set : T_LABEL set_or_equal const { sym_AddSet($1, $3); }
; ;
equs : T_LABEL T_POP_EQUS string { sym_AddString($1, $3); } equs : T_LABEL T_POP_EQUS string { sym_AddString($1, $3); }
; ;
rb : T_LABEL T_POP_RB rs_uconst { rb : T_LABEL T_POP_RB rs_uconst {
@@ -925,35 +926,34 @@ opt_list : opt_list_entry
| opt_list opt_list_entry | opt_list opt_list_entry
; ;
opt_list_entry : T_STRING { opt_Parse($1); } opt_list_entry : T_STRING { opt_Parse($1); }
; ;
popo : T_POP_POPO { opt_Pop(); } popo : T_POP_POPO { opt_Pop(); }
; ;
pusho : T_POP_PUSHO { opt_Push(); } pusho : T_POP_PUSHO { opt_Push(); }
; ;
pops : T_POP_POPS { out_PopSection(); } pops : T_POP_POPS { out_PopSection(); }
; ;
pushs : T_POP_PUSHS { out_PushSection(); } pushs : T_POP_PUSHS { out_PushSection(); }
; ;
fail : T_POP_FAIL string { fatalerror("%s\n", $2); } fail : T_POP_FAIL string { fatalerror("%s\n", $2); }
; ;
warn : T_POP_WARN string { warning(WARNING_USER, "%s\n", $2); } warn : T_POP_WARN string { warning(WARNING_USER, "%s\n", $2); }
; ;
assert_type : %empty { $$ = ASSERT_ERROR; } assert_type : %empty { $$ = ASSERT_ERROR; }
| T_POP_WARN T_COMMA { $$ = ASSERT_WARN; } | T_POP_WARN T_COMMA { $$ = ASSERT_WARN; }
| T_POP_FAIL T_COMMA { $$ = ASSERT_ERROR; } | T_POP_FAIL T_COMMA { $$ = ASSERT_ERROR; }
| T_POP_FATAL T_COMMA { $$ = ASSERT_FATAL; } | T_POP_FATAL T_COMMA { $$ = ASSERT_FATAL; }
; ;
assert : T_POP_ASSERT assert_type relocexpr assert : T_POP_ASSERT assert_type relocexpr {
{
if (!rpn_isKnown(&$3)) { if (!rpn_isKnown(&$3)) {
if (!out_CreateAssert($2, &$3, "", if (!out_CreateAssert($2, &$3, "",
sect_GetOutputOffset())) sect_GetOutputOffset()))
@@ -964,8 +964,7 @@ assert : T_POP_ASSERT assert_type relocexpr
} }
rpn_Free(&$3); rpn_Free(&$3);
} }
| T_POP_ASSERT assert_type relocexpr T_COMMA string | T_POP_ASSERT assert_type relocexpr T_COMMA string {
{
if (!rpn_isKnown(&$3)) { if (!rpn_isKnown(&$3)) {
if (!out_CreateAssert($2, &$3, $5, if (!out_CreateAssert($2, &$3, $5,
sect_GetOutputOffset())) sect_GetOutputOffset()))
@@ -976,26 +975,24 @@ assert : T_POP_ASSERT assert_type relocexpr
} }
rpn_Free(&$3); rpn_Free(&$3);
} }
| T_POP_STATIC_ASSERT assert_type const | T_POP_STATIC_ASSERT assert_type const {
{
if ($3 == 0) if ($3 == 0)
failAssert($2); failAssert($2);
} }
| T_POP_STATIC_ASSERT assert_type const T_COMMA string | T_POP_STATIC_ASSERT assert_type const T_COMMA string {
{
if ($3 == 0) if ($3 == 0)
failAssertMsg($2, $5); failAssertMsg($2, $5);
} }
; ;
shift : T_POP_SHIFT { macro_ShiftCurrentArgs(1); } shift : T_POP_SHIFT { macro_ShiftCurrentArgs(1); }
| T_POP_SHIFT const { macro_ShiftCurrentArgs($2); } | T_POP_SHIFT const { macro_ShiftCurrentArgs($2); }
; ;
load : T_POP_LOAD sectmod string T_COMMA sectiontype sectorg sectattrs { load : T_POP_LOAD sectmod string T_COMMA sectiontype sectorg sectattrs {
out_SetLoadSection($3, $5, $6, &$7, $2); out_SetLoadSection($3, $5, $6, &$7, $2);
} }
| T_POP_ENDL { out_EndLoadSection(); } | T_POP_ENDL { out_EndLoadSection(); }
; ;
rept : T_POP_REPT uconst T_NEWLINE { rept : T_POP_REPT uconst T_NEWLINE {
@@ -1062,10 +1059,10 @@ macrodef : T_POP_MACRO {
} }
; ;
rsset : T_POP_RSSET uconst { sym_AddSet("_RS", $2); } rsset : T_POP_RSSET uconst { sym_AddSet("_RS", $2); }
; ;
rsreset : T_POP_RSRESET { sym_AddSet("_RS", 0); } rsreset : T_POP_RSRESET { sym_AddSet("_RS", 0); }
; ;
rs_uconst : %empty { rs_uconst : %empty {
@@ -1074,16 +1071,16 @@ rs_uconst : %empty {
| uconst | uconst
; ;
union : T_POP_UNION { sect_StartUnion(); } union : T_POP_UNION { sect_StartUnion(); }
; ;
nextu : T_POP_NEXTU { sect_NextUnionMember(); } nextu : T_POP_NEXTU { sect_NextUnionMember(); }
; ;
endu : T_POP_ENDU { sect_EndUnion(); } endu : T_POP_ENDU { sect_EndUnion(); }
; ;
ds : T_POP_DS uconst { out_Skip($2, true); } ds : T_POP_DS uconst { out_Skip($2, true); }
| T_POP_DS uconst T_COMMA ds_args trailing_comma { | T_POP_DS uconst T_COMMA ds_args trailing_comma {
out_RelBytes($2, $4.args, $4.nbArgs); out_RelBytes($2, $4.args, $4.nbArgs);
freeDsArgList(&$4); freeDsArgList(&$4);
@@ -1104,15 +1101,15 @@ ds_args : reloc_8bit {
} }
; ;
db : T_POP_DB { out_Skip(1, false); } db : T_POP_DB { out_Skip(1, false); }
| T_POP_DB constlist_8bit trailing_comma | T_POP_DB constlist_8bit trailing_comma
; ;
dw : T_POP_DW { out_Skip(2, false); } dw : T_POP_DW { out_Skip(2, false); }
| T_POP_DW constlist_16bit trailing_comma | T_POP_DW constlist_16bit trailing_comma
; ;
dl : T_POP_DL { out_Skip(4, false); } dl : T_POP_DL { out_Skip(4, false); }
| T_POP_DL constlist_32bit trailing_comma | T_POP_DL constlist_32bit trailing_comma
; ;
@@ -1168,7 +1165,7 @@ purge_list : purge_list_entry
| purge_list T_COMMA purge_list_entry | purge_list T_COMMA purge_list_entry
; ;
purge_list_entry : scoped_id { sym_Purge($1); } purge_list_entry : scoped_id { sym_Purge($1); }
; ;
export : T_POP_EXPORT export_list trailing_comma export : T_POP_EXPORT export_list trailing_comma
@@ -1178,7 +1175,7 @@ export_list : export_list_entry
| export_list T_COMMA export_list_entry | export_list T_COMMA export_list_entry
; ;
export_list_entry : scoped_id { sym_Export($1); } export_list_entry : scoped_id { sym_Export($1); }
; ;
include : label T_POP_INCLUDE string endofline { include : label T_POP_INCLUDE string endofline {
@@ -1205,24 +1202,22 @@ incbin : T_POP_INCBIN string {
} }
; ;
charmap : T_POP_CHARMAP string T_COMMA const { charmap : T_POP_CHARMAP string T_COMMA const_8bit {
if ($4 < INT8_MIN || $4 > UINT8_MAX)
warning(WARNING_TRUNCATION, "Expression must be 8-bit\n");
charmap_Add($2, (uint8_t)$4); charmap_Add($2, (uint8_t)$4);
} }
; ;
newcharmap : T_POP_NEWCHARMAP T_ID { charmap_New($2, NULL); } newcharmap : T_POP_NEWCHARMAP T_ID { charmap_New($2, NULL); }
| T_POP_NEWCHARMAP T_ID T_COMMA T_ID { charmap_New($2, $4); } | T_POP_NEWCHARMAP T_ID T_COMMA T_ID { charmap_New($2, $4); }
; ;
setcharmap : T_POP_SETCHARMAP T_ID { charmap_Set($2); } setcharmap : T_POP_SETCHARMAP T_ID { charmap_Set($2); }
; ;
pushc : T_POP_PUSHC { charmap_Push(); } pushc : T_POP_PUSHC { charmap_Push(); }
; ;
popc : T_POP_POPC { charmap_Pop(); } popc : T_POP_POPC { charmap_Pop(); }
; ;
print : T_POP_PRINT print_exprs trailing_comma print : T_POP_PRINT print_exprs trailing_comma
@@ -1246,25 +1241,25 @@ print_expr : const_no_str { printf("$%" PRIX32, $1); }
| string { printf("%s", $1); } | string { printf("%s", $1); }
; ;
printt : T_POP_PRINTT string { printt : T_POP_PRINTT string {
warning(WARNING_OBSOLETE, "`PRINTT` is deprecated; use `PRINT`\n"); warning(WARNING_OBSOLETE, "`PRINTT` is deprecated; use `PRINT`\n");
printf("%s", $2); printf("%s", $2);
} }
; ;
printv : T_POP_PRINTV const { printv : T_POP_PRINTV const {
warning(WARNING_OBSOLETE, "`PRINTV` is deprecated; use `PRINT`\n"); warning(WARNING_OBSOLETE, "`PRINTV` is deprecated; use `PRINT`\n");
printf("$%" PRIX32, $2); printf("$%" PRIX32, $2);
} }
; ;
printi : T_POP_PRINTI const { printi : T_POP_PRINTI const {
warning(WARNING_OBSOLETE, "`PRINTI` is deprecated; use `PRINT` with `STRFMT`\n"); warning(WARNING_OBSOLETE, "`PRINTI` is deprecated; use `PRINT` with `STRFMT`\n");
printf("%" PRId32, $2); printf("%" PRId32, $2);
} }
; ;
printf : T_POP_PRINTF const { printf : T_POP_PRINTF const {
warning(WARNING_OBSOLETE, "`PRINTF` is deprecated; use `PRINT` with `STRFMT`\n"); warning(WARNING_OBSOLETE, "`PRINTF` is deprecated; use `PRINT` with `STRFMT`\n");
fix_Print($2); fix_Print($2);
} }
@@ -1286,7 +1281,7 @@ constlist_8bit : constlist_8bit_entry
| constlist_8bit T_COMMA constlist_8bit_entry | constlist_8bit T_COMMA constlist_8bit_entry
; ;
constlist_8bit_entry : reloc_8bit_no_str { constlist_8bit_entry : reloc_8bit_no_str {
out_RelByte(&$1, 0); out_RelByte(&$1, 0);
} }
| string { | string {
@@ -1302,7 +1297,7 @@ constlist_16bit : constlist_16bit_entry
| constlist_16bit T_COMMA constlist_16bit_entry | constlist_16bit T_COMMA constlist_16bit_entry
; ;
constlist_16bit_entry : reloc_16bit_no_str { constlist_16bit_entry : reloc_16bit_no_str {
out_RelWord(&$1, 0); out_RelWord(&$1, 0);
} }
| string { | string {
@@ -1318,11 +1313,12 @@ constlist_32bit : constlist_32bit_entry
| constlist_32bit T_COMMA constlist_32bit_entry | constlist_32bit T_COMMA constlist_32bit_entry
; ;
constlist_32bit_entry :relocexpr_no_str { constlist_32bit_entry : relocexpr_no_str {
out_RelLong(&$1, 0); out_RelLong(&$1, 0);
} }
| string { | string {
uint8_t *output = malloc(strlen($1)); /* Cannot be larger than that */ // Charmaps cannot increase the length of a string
uint8_t *output = malloc(strlen($1));
int32_t length = charmap_Convert($1, output); int32_t length = charmap_Convert($1, output);
out_AbsLongGroup(output, length); out_AbsLongGroup(output, length);
@@ -1331,33 +1327,25 @@ constlist_32bit_entry :relocexpr_no_str {
; ;
reloc_8bit : relocexpr { reloc_8bit : relocexpr {
if(rpn_isKnown(&$1) rpn_CheckNBit(&$1, 8);
&& ($1.val < -128 || $1.val > 255))
warning(WARNING_TRUNCATION, "Expression must be 8-bit\n");
$$ = $1; $$ = $1;
} }
; ;
reloc_8bit_no_str : relocexpr_no_str { reloc_8bit_no_str : relocexpr_no_str {
if(rpn_isKnown(&$1) rpn_CheckNBit(&$1, 8);
&& ($1.val < -128 || $1.val > 255))
warning(WARNING_TRUNCATION, "Expression must be 8-bit\n");
$$ = $1; $$ = $1;
} }
; ;
reloc_16bit : relocexpr { reloc_16bit : relocexpr {
if (rpn_isKnown(&$1) rpn_CheckNBit(&$1, 16);
&& ($1.val < -32768 || $1.val > 65535))
warning(WARNING_TRUNCATION, "Expression must be 16-bit\n");
$$ = $1; $$ = $1;
} }
; ;
reloc_16bit_no_str : relocexpr_no_str { reloc_16bit_no_str : relocexpr_no_str {
if (rpn_isKnown(&$1) rpn_CheckNBit(&$1, 16);
&& ($1.val < -32768 || $1.val > 65535))
warning(WARNING_TRUNCATION, "Expression must be 16-bit\n");
$$ = $1; $$ = $1;
} }
; ;
@@ -1365,7 +1353,8 @@ reloc_16bit_no_str : relocexpr_no_str {
relocexpr : relocexpr_no_str relocexpr : relocexpr_no_str
| string { | string {
uint8_t *output = malloc(strlen($1)); /* Cannot be longer than that */ // Charmaps cannot increase the length of a string
uint8_t *output = malloc(strlen($1));
int32_t length = charmap_Convert($1, output); int32_t length = charmap_Convert($1, output);
uint32_t r = str2int2(output, length); uint32_t r = str2int2(output, length);
@@ -1374,8 +1363,8 @@ relocexpr : relocexpr_no_str
} }
; ;
relocexpr_no_str : scoped_anon_id { rpn_Symbol(&$$, $1); } relocexpr_no_str : scoped_anon_id { rpn_Symbol(&$$, $1); }
| T_NUMBER { rpn_Number(&$$, $1); } | T_NUMBER { rpn_Number(&$$, $1); }
| T_OP_LOGICNOT relocexpr %prec NEG { | T_OP_LOGICNOT relocexpr %prec NEG {
rpn_LOGNOT(&$$, &$2); rpn_LOGNOT(&$$, &$2);
} }
@@ -1436,19 +1425,19 @@ relocexpr_no_str : scoped_anon_id { rpn_Symbol(&$$, $1); }
| relocexpr T_OP_EXP relocexpr { | relocexpr T_OP_EXP relocexpr {
rpn_BinaryOp(RPN_EXP, &$$, &$1, &$3); rpn_BinaryOp(RPN_EXP, &$$, &$1, &$3);
} }
| T_OP_ADD relocexpr %prec NEG { $$ = $2; } | T_OP_ADD relocexpr %prec NEG { $$ = $2; }
| T_OP_SUB relocexpr %prec NEG { rpn_UNNEG(&$$, &$2); } | T_OP_SUB relocexpr %prec NEG { rpn_UNNEG(&$$, &$2); }
| T_OP_NOT relocexpr %prec NEG { rpn_UNNOT(&$$, &$2); } | T_OP_NOT relocexpr %prec NEG { rpn_UNNOT(&$$, &$2); }
| T_OP_HIGH T_LPAREN relocexpr T_RPAREN { rpn_HIGH(&$$, &$3); } | T_OP_HIGH T_LPAREN relocexpr T_RPAREN { rpn_HIGH(&$$, &$3); }
| T_OP_LOW T_LPAREN relocexpr T_RPAREN { rpn_LOW(&$$, &$3); } | T_OP_LOW T_LPAREN relocexpr T_RPAREN { rpn_LOW(&$$, &$3); }
| T_OP_ISCONST T_LPAREN relocexpr T_RPAREN{ rpn_ISCONST(&$$, &$3); } | T_OP_ISCONST T_LPAREN relocexpr T_RPAREN { rpn_ISCONST(&$$, &$3); }
| T_OP_BANK T_LPAREN scoped_anon_id T_RPAREN { | T_OP_BANK T_LPAREN scoped_anon_id T_RPAREN {
/* '@' is also a T_ID, it is handled here. */ // '@' is also a T_ID; it is handled here
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_SIZEOF T_LPAREN string T_RPAREN { rpn_SizeOfSection(&$$, $3); }
| T_OP_STARTOF T_LPAREN string T_RPAREN { rpn_StartOfSection(&$$, $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 {
@@ -1519,37 +1508,23 @@ relocexpr_no_str : scoped_anon_id { rpn_Symbol(&$$, $1); }
| T_OP_CHARLEN T_LPAREN string T_RPAREN { | T_OP_CHARLEN T_LPAREN string T_RPAREN {
rpn_Number(&$$, charlenUTF8($3)); rpn_Number(&$$, charlenUTF8($3));
} }
| T_LPAREN relocexpr T_RPAREN { $$ = $2; } | T_LPAREN relocexpr T_RPAREN { $$ = $2; }
; ;
uconst : const { uconst : const {
$$ = $1; $$ = $1;
if ($$ < 0) if ($$ < 0)
fatalerror("Constant mustn't be negative: %d\n", fatalerror("Constant mustn't be negative: %d\n", $1);
$1);
} }
; ;
const : relocexpr { const : relocexpr { $$ = rpn_GetConstVal(&$1); }
if (!rpn_isKnown(&$1)) {
error("Expected constant expression: %s\n",
$1.reason);
$$ = 0;
} else {
$$ = $1.val;
}
}
; ;
const_no_str : relocexpr_no_str { const_no_str : relocexpr_no_str { $$ = rpn_GetConstVal(&$1); }
if (!rpn_isKnown(&$1)) { ;
error("Expected constant expression: %s\n",
$1.reason); const_8bit : reloc_8bit { $$ = rpn_GetConstVal(&$1); }
$$ = 0;
} else {
$$ = $1.val;
}
}
; ;
string : T_STRING string : T_STRING
@@ -1615,20 +1590,10 @@ strfmt_args : string strfmt_va_args {
strfmt_va_args : %empty { strfmt_va_args : %empty {
initStrFmtArgList(&$$); initStrFmtArgList(&$$);
} }
| strfmt_va_args T_COMMA relocexpr_no_str { | strfmt_va_args T_COMMA const_no_str {
int32_t value;
if (!rpn_isKnown(&$3)) {
error("Expected constant expression: %s\n",
$3.reason);
value = 0;
} else {
value = $3.val;
}
size_t i = nextStrFmtArgListIndex(&$1); size_t i = nextStrFmtArgListIndex(&$1);
$1.args[i].number = value; $1.args[i].number = $3;
$1.args[i].isNumeric = true; $1.args[i].isNumeric = true;
$$ = $1; $$ = $1;
} }
@@ -1646,19 +1611,19 @@ section : T_POP_SECTION sectmod string T_COMMA sectiontype sectorg sectattrs {
} }
; ;
sectmod : %empty { $$ = SECTION_NORMAL; } sectmod : %empty { $$ = SECTION_NORMAL; }
| T_POP_UNION { $$ = SECTION_UNION; } | T_POP_UNION { $$ = SECTION_UNION; }
| T_POP_FRAGMENT{ $$ = SECTION_FRAGMENT; } | T_POP_FRAGMENT { $$ = SECTION_FRAGMENT; }
; ;
sectiontype : T_SECT_WRAM0 { $$ = SECTTYPE_WRAM0; } sectiontype : T_SECT_WRAM0 { $$ = SECTTYPE_WRAM0; }
| T_SECT_VRAM { $$ = SECTTYPE_VRAM; } | T_SECT_VRAM { $$ = SECTTYPE_VRAM; }
| T_SECT_ROMX { $$ = SECTTYPE_ROMX; } | T_SECT_ROMX { $$ = SECTTYPE_ROMX; }
| T_SECT_ROM0 { $$ = SECTTYPE_ROM0; } | T_SECT_ROM0 { $$ = SECTTYPE_ROM0; }
| T_SECT_HRAM { $$ = SECTTYPE_HRAM; } | T_SECT_HRAM { $$ = SECTTYPE_HRAM; }
| T_SECT_WRAMX { $$ = SECTTYPE_WRAMX; } | T_SECT_WRAMX { $$ = SECTTYPE_WRAMX; }
| T_SECT_SRAM { $$ = SECTTYPE_SRAM; } | T_SECT_SRAM { $$ = SECTTYPE_SRAM; }
| T_SECT_OAM { $$ = SECTTYPE_OAM; } | T_SECT_OAM { $$ = SECTTYPE_OAM; }
; ;
sectorg : %empty { $$ = -1; } sectorg : %empty { $$ = -1; }
@@ -1743,15 +1708,15 @@ z80_adc : T_Z80_ADC op_a_n {
out_AbsByte(0xCE); out_AbsByte(0xCE);
out_RelByte(&$2, 1); out_RelByte(&$2, 1);
} }
| T_Z80_ADC op_a_r { out_AbsByte(0x88 | $2); } | T_Z80_ADC op_a_r { out_AbsByte(0x88 | $2); }
; ;
z80_add : T_Z80_ADD op_a_n { z80_add : T_Z80_ADD op_a_n {
out_AbsByte(0xC6); out_AbsByte(0xC6);
out_RelByte(&$2, 1); out_RelByte(&$2, 1);
} }
| T_Z80_ADD op_a_r { out_AbsByte(0x80 | $2); } | T_Z80_ADD op_a_r { out_AbsByte(0x80 | $2); }
| T_Z80_ADD T_MODE_HL T_COMMA reg_ss { out_AbsByte(0x09 | ($4 << 4)); } | T_Z80_ADD T_MODE_HL T_COMMA reg_ss { out_AbsByte(0x09 | ($4 << 4)); }
| T_Z80_ADD T_MODE_SP T_COMMA reloc_8bit { | T_Z80_ADD T_MODE_SP T_COMMA reloc_8bit {
out_AbsByte(0xE8); out_AbsByte(0xE8);
out_RelByte(&$4, 1); out_RelByte(&$4, 1);
@@ -1763,7 +1728,7 @@ z80_and : T_Z80_AND op_a_n {
out_AbsByte(0xE6); out_AbsByte(0xE6);
out_RelByte(&$2, 1); out_RelByte(&$2, 1);
} }
| T_Z80_AND op_a_r { out_AbsByte(0xA0 | $2); } | T_Z80_AND op_a_r { out_AbsByte(0xA0 | $2); }
; ;
z80_bit : T_Z80_BIT const_3bit T_COMMA reg_r { z80_bit : T_Z80_BIT const_3bit T_COMMA reg_r {
@@ -1782,30 +1747,30 @@ z80_call : T_Z80_CALL reloc_16bit {
} }
; ;
z80_ccf : T_Z80_CCF { out_AbsByte(0x3F); } z80_ccf : T_Z80_CCF { out_AbsByte(0x3F); }
; ;
z80_cp : T_Z80_CP op_a_n { z80_cp : T_Z80_CP op_a_n {
out_AbsByte(0xFE); out_AbsByte(0xFE);
out_RelByte(&$2, 1); out_RelByte(&$2, 1);
} }
| T_Z80_CP op_a_r { out_AbsByte(0xB8 | $2); } | T_Z80_CP op_a_r { out_AbsByte(0xB8 | $2); }
; ;
z80_cpl : T_Z80_CPL { out_AbsByte(0x2F); } z80_cpl : T_Z80_CPL { out_AbsByte(0x2F); }
; ;
z80_daa : T_Z80_DAA { out_AbsByte(0x27); } z80_daa : T_Z80_DAA { out_AbsByte(0x27); }
; ;
z80_dec : T_Z80_DEC reg_r { out_AbsByte(0x05 | ($2 << 3)); } z80_dec : T_Z80_DEC reg_r { out_AbsByte(0x05 | ($2 << 3)); }
| T_Z80_DEC reg_ss { out_AbsByte(0x0B | ($2 << 4)); } | T_Z80_DEC reg_ss { out_AbsByte(0x0B | ($2 << 4)); }
; ;
z80_di : T_Z80_DI { out_AbsByte(0xF3); } z80_di : T_Z80_DI { out_AbsByte(0xF3); }
; ;
z80_ei : T_Z80_EI { out_AbsByte(0xFB); } z80_ei : T_Z80_EI { out_AbsByte(0xFB); }
; ;
z80_halt : T_Z80_HALT { z80_halt : T_Z80_HALT {
@@ -1815,8 +1780,8 @@ z80_halt : T_Z80_HALT {
} }
; ;
z80_inc : T_Z80_INC reg_r { out_AbsByte(0x04 | ($2 << 3)); } z80_inc : T_Z80_INC reg_r { out_AbsByte(0x04 | ($2 << 3)); }
| T_Z80_INC reg_ss { out_AbsByte(0x03 | ($2 << 4)); } | T_Z80_INC reg_ss { out_AbsByte(0x03 | ($2 << 4)); }
; ;
z80_jp : T_Z80_JP reloc_16bit { z80_jp : T_Z80_JP reloc_16bit {
@@ -1902,7 +1867,7 @@ z80_ld_hl : T_Z80_LD T_MODE_HL T_COMMA T_MODE_SP T_OP_ADD reloc_8bit {
} }
; ;
z80_ld_sp : T_Z80_LD T_MODE_SP T_COMMA T_MODE_HL { out_AbsByte(0xF9); } z80_ld_sp : T_Z80_LD T_MODE_SP T_COMMA T_MODE_HL { out_AbsByte(0xF9); }
| T_Z80_LD T_MODE_SP T_COMMA reloc_16bit { | T_Z80_LD T_MODE_SP T_COMMA reloc_16bit {
out_AbsByte(0x01 | (REG_SP << 4)); out_AbsByte(0x01 | (REG_SP << 4));
out_RelWord(&$4, 1); out_RelWord(&$4, 1);
@@ -1992,20 +1957,20 @@ z80_ld_ss : T_Z80_LD T_MODE_BC T_COMMA reloc_16bit {
*/ */
; ;
z80_nop : T_Z80_NOP { out_AbsByte(0x00); } z80_nop : T_Z80_NOP { out_AbsByte(0x00); }
; ;
z80_or : T_Z80_OR op_a_n { z80_or : T_Z80_OR op_a_n {
out_AbsByte(0xF6); out_AbsByte(0xF6);
out_RelByte(&$2, 1); out_RelByte(&$2, 1);
} }
| T_Z80_OR op_a_r { out_AbsByte(0xB0 | $2); } | T_Z80_OR op_a_r { out_AbsByte(0xB0 | $2); }
; ;
z80_pop : T_Z80_POP reg_tt { out_AbsByte(0xC1 | ($2 << 4)); } z80_pop : T_Z80_POP reg_tt { out_AbsByte(0xC1 | ($2 << 4)); }
; ;
z80_push : T_Z80_PUSH reg_tt { out_AbsByte(0xC5 | ($2 << 4)); } z80_push : T_Z80_PUSH reg_tt { out_AbsByte(0xC5 | ($2 << 4)); }
; ;
z80_res : T_Z80_RES const_3bit T_COMMA reg_r { z80_res : T_Z80_RES const_3bit T_COMMA reg_r {
@@ -2014,12 +1979,11 @@ z80_res : T_Z80_RES const_3bit T_COMMA reg_r {
} }
; ;
z80_ret : T_Z80_RET { out_AbsByte(0xC9); z80_ret : T_Z80_RET { out_AbsByte(0xC9); }
} | T_Z80_RET ccode { out_AbsByte(0xC0 | ($2 << 3)); }
| T_Z80_RET ccode { out_AbsByte(0xC0 | ($2 << 3)); }
; ;
z80_reti : T_Z80_RETI { out_AbsByte(0xD9); } z80_reti : T_Z80_RETI { out_AbsByte(0xD9); }
; ;
z80_rl : T_Z80_RL reg_r { z80_rl : T_Z80_RL reg_r {
@@ -2028,7 +1992,7 @@ z80_rl : T_Z80_RL reg_r {
} }
; ;
z80_rla : T_Z80_RLA { out_AbsByte(0x17); } z80_rla : T_Z80_RLA { out_AbsByte(0x17); }
; ;
z80_rlc : T_Z80_RLC reg_r { z80_rlc : T_Z80_RLC reg_r {
@@ -2037,7 +2001,7 @@ z80_rlc : T_Z80_RLC reg_r {
} }
; ;
z80_rlca : T_Z80_RLCA { out_AbsByte(0x07); } z80_rlca : T_Z80_RLCA { out_AbsByte(0x07); }
; ;
z80_rr : T_Z80_RR reg_r { z80_rr : T_Z80_RR reg_r {
@@ -2046,7 +2010,7 @@ z80_rr : T_Z80_RR reg_r {
} }
; ;
z80_rra : T_Z80_RRA { out_AbsByte(0x1F); } z80_rra : T_Z80_RRA { out_AbsByte(0x1F); }
; ;
z80_rrc : T_Z80_RRC reg_r { z80_rrc : T_Z80_RRC reg_r {
@@ -2055,7 +2019,7 @@ z80_rrc : T_Z80_RRC reg_r {
} }
; ;
z80_rrca : T_Z80_RRCA { out_AbsByte(0x0F); } z80_rrca : T_Z80_RRCA { out_AbsByte(0x0F); }
; ;
z80_rst : T_Z80_RST reloc_8bit { z80_rst : T_Z80_RST reloc_8bit {
@@ -2072,10 +2036,10 @@ z80_sbc : T_Z80_SBC op_a_n {
out_AbsByte(0xDE); out_AbsByte(0xDE);
out_RelByte(&$2, 1); out_RelByte(&$2, 1);
} }
| T_Z80_SBC op_a_r { out_AbsByte(0x98 | $2); } | T_Z80_SBC op_a_r { out_AbsByte(0x98 | $2); }
; ;
z80_scf : T_Z80_SCF { out_AbsByte(0x37); } z80_scf : T_Z80_SCF { out_AbsByte(0x37); }
; ;
z80_set : T_POP_SET const_3bit T_COMMA reg_r { z80_set : T_POP_SET const_3bit T_COMMA reg_r {
@@ -2116,8 +2080,7 @@ z80_sub : T_Z80_SUB op_a_n {
out_AbsByte(0xD6); out_AbsByte(0xD6);
out_RelByte(&$2, 1); out_RelByte(&$2, 1);
} }
| T_Z80_SUB op_a_r { out_AbsByte(0x90 | $2); | T_Z80_SUB op_a_r { out_AbsByte(0x90 | $2); }
}
; ;
z80_swap : T_Z80_SWAP reg_r { z80_swap : T_Z80_SWAP reg_r {
@@ -2130,18 +2093,18 @@ z80_xor : T_Z80_XOR op_a_n {
out_AbsByte(0xEE); out_AbsByte(0xEE);
out_RelByte(&$2, 1); out_RelByte(&$2, 1);
} }
| T_Z80_XOR op_a_r { out_AbsByte(0xA8 | $2); } | T_Z80_XOR op_a_r { out_AbsByte(0xA8 | $2); }
; ;
op_mem_ind : T_LBRACK reloc_16bit T_RBRACK { $$ = $2; } op_mem_ind : T_LBRACK reloc_16bit T_RBRACK { $$ = $2; }
; ;
op_a_r : reg_r op_a_r : reg_r
| T_MODE_A T_COMMA reg_r { $$ = $3; } | T_MODE_A T_COMMA reg_r { $$ = $3; }
; ;
op_a_n : reloc_8bit op_a_n : reloc_8bit
| T_MODE_A T_COMMA reloc_8bit { $$ = $3; } | T_MODE_A T_COMMA reloc_8bit { $$ = $3; }
; ;
T_MODE_A : T_TOKEN_A T_MODE_A : T_TOKEN_A
@@ -2172,38 +2135,38 @@ T_MODE_L : T_TOKEN_L
| T_OP_LOW T_LPAREN T_MODE_HL T_RPAREN | T_OP_LOW T_LPAREN T_MODE_HL T_RPAREN
; ;
ccode : T_CC_NZ { $$ = CC_NZ; } ccode : T_CC_NZ { $$ = CC_NZ; }
| T_CC_Z { $$ = CC_Z; } | T_CC_Z { $$ = CC_Z; }
| T_CC_NC { $$ = CC_NC; } | T_CC_NC { $$ = CC_NC; }
| T_TOKEN_C { $$ = CC_C; } | T_TOKEN_C { $$ = CC_C; }
; ;
reg_r : T_MODE_B { $$ = REG_B; } reg_r : T_MODE_B { $$ = REG_B; }
| T_MODE_C { $$ = REG_C; } | T_MODE_C { $$ = REG_C; }
| T_MODE_D { $$ = REG_D; } | T_MODE_D { $$ = REG_D; }
| T_MODE_E { $$ = REG_E; } | T_MODE_E { $$ = REG_E; }
| T_MODE_H { $$ = REG_H; } | T_MODE_H { $$ = REG_H; }
| T_MODE_L { $$ = REG_L; } | T_MODE_L { $$ = REG_L; }
| T_LBRACK T_MODE_HL T_RBRACK { $$ = REG_HL_IND; } | T_LBRACK T_MODE_HL T_RBRACK { $$ = REG_HL_IND; }
| T_MODE_A { $$ = REG_A; } | T_MODE_A { $$ = REG_A; }
; ;
reg_tt : T_MODE_BC { $$ = REG_BC; } reg_tt : T_MODE_BC { $$ = REG_BC; }
| T_MODE_DE { $$ = REG_DE; } | T_MODE_DE { $$ = REG_DE; }
| T_MODE_HL { $$ = REG_HL; } | T_MODE_HL { $$ = REG_HL; }
| T_MODE_AF { $$ = REG_AF; } | T_MODE_AF { $$ = REG_AF; }
; ;
reg_ss : T_MODE_BC { $$ = REG_BC; } reg_ss : T_MODE_BC { $$ = REG_BC; }
| T_MODE_DE { $$ = REG_DE; } | T_MODE_DE { $$ = REG_DE; }
| T_MODE_HL { $$ = REG_HL; } | T_MODE_HL { $$ = REG_HL; }
| T_MODE_SP { $$ = REG_SP; } | T_MODE_SP { $$ = REG_SP; }
; ;
reg_rr : T_LBRACK T_MODE_BC T_RBRACK { $$ = REG_BC_IND; } reg_rr : T_LBRACK T_MODE_BC T_RBRACK { $$ = REG_BC_IND; }
| T_LBRACK T_MODE_DE T_RBRACK { $$ = REG_DE_IND; } | T_LBRACK T_MODE_DE T_RBRACK { $$ = REG_DE_IND; }
| hl_ind_inc { $$ = REG_HL_INDINC; } | hl_ind_inc { $$ = REG_HL_INDINC; }
| hl_ind_dec { $$ = REG_HL_INDDEC; } | hl_ind_dec { $$ = REG_HL_INDDEC; }
; ;
hl_ind_inc : T_LBRACK T_MODE_HL_INC T_RBRACK hl_ind_inc : T_LBRACK T_MODE_HL_INC T_RBRACK

View File

@@ -13,6 +13,7 @@
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <inttypes.h> #include <inttypes.h>
#include <limits.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@@ -75,7 +76,7 @@ static uint8_t *reserveSpace(struct Expression *expr, uint32_t size)
} }
/* /*
* Init the RPN expression * Init a RPN expression
*/ */
static void rpn_Init(struct Expression *expr) static void rpn_Init(struct Expression *expr)
{ {
@@ -260,6 +261,31 @@ void rpn_CheckRST(struct Expression *expr, const struct Expression *src)
} }
} }
/*
* Checks that an RPN expression's value fits within N bits (signed or unsigned)
*/
void rpn_CheckNBit(struct Expression const *expr, uint8_t n)
{
assert(n != 0); // That doesn't make sense
assert(n < CHAR_BIT * sizeof(int)); // Otherwise `1 << n` is UB
if (rpn_isKnown(expr)) {
int32_t val = expr->val;
if (val < -(1 << (n - 1)) || val >= 1 << n)
warning(WARNING_TRUNCATION, "Expression must be %u-bit\n", n);
}
}
int32_t rpn_GetConstVal(struct Expression const *expr)
{
if (!rpn_isKnown(expr)) {
error("Expected constant expression: %s\n", expr->reason);
return 0;
}
return expr->val;
}
void rpn_LOGNOT(struct Expression *expr, const struct Expression *src) void rpn_LOGNOT(struct Expression *expr, const struct Expression *src)
{ {
*expr = *src; *expr = *src;