ref: bba532193b80c8ccf2beff68a13d2786f0f31b72
parent: b4814b06b95ebc426b2f4c2783fe171d6adc52af
author: Rangi <remy.oukaour+rangi42@gmail.com>
date: Sun Apr 25 14:36:19 EDT 2021
Port some cleanup from PR #847 - Update some whitespace formatting - Factor out some functions - Free data after outputting to an object file
--- a/include/asm/rpn.h
+++ b/include/asm/rpn.h
@@ -30,7 +30,7 @@
/*
* 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;
}
@@ -64,5 +64,7 @@
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);
+void rpn_CheckNBit(struct Expression const *expr, uint8_t n);
+int32_t rpn_GetConstVal(struct Expression const *expr);
#endif /* RGBDS_ASM_RPN_H */
--- a/include/linkdefs.h
+++ b/include/linkdefs.h
@@ -28,17 +28,17 @@
RPN_MUL = 0x02,
RPN_DIV = 0x03,
RPN_MOD = 0x04,
- RPN_UNSUB = 0x05,
+ RPN_UNSUB = 0x05, // FIXME: should be renamed to "NEG" for consistency
RPN_EXP = 0x06,
RPN_OR = 0x10,
RPN_AND = 0x11,
RPN_XOR = 0x12,
- RPN_UNNOT = 0x13,
+ RPN_UNNOT = 0x13, // FIXME: should be renamed to "NOT" for consistency
RPN_LOGAND = 0x21,
RPN_LOGOR = 0x22,
- RPN_LOGUNNOT = 0x23,
+ RPN_LOGUNNOT = 0x23, // FIXME: should be renamed to "LOGNOT" for consistency
RPN_LOGEQ = 0x30,
RPN_LOGNE = 0x31,
--- a/src/asm/output.c
+++ b/src/asm/output.c
@@ -242,6 +242,21 @@
}
}
+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
*/
@@ -468,6 +483,13 @@
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)
{putlong(node->parent ? node->parent->ID : -1, f);
@@ -530,13 +552,21 @@
for (struct Symbol const *sym = objectSymbols; sym; sym = sym->next)
writesymbol(sym, f);
- for (struct Section *sect = sectionList; sect; sect = sect->next)
+ for (struct Section *sect = sectionList; sect; sect = sect->next) {writesection(sect, f);
+ freesection(sect);
+ }
putlong(countAsserts(), f);
- for (struct Assertion *assert = assertions; assert;
- assert = assert->next)
+ struct Assertion *assert = assertions;
+
+ while (assert != NULL) {+ struct Assertion *next = assert->next;
+
writeassert(assert, f);
+ freeassert(assert);
+ assert = next;
+ }
fclose(f);
}
--- a/src/asm/parser.y
+++ b/src/asm/parser.y
@@ -481,6 +481,7 @@
%type <expr> relocexpr_no_str
%type <constValue> const
%type <constValue> const_no_str
+%type <constValue> const_8bit
%type <constValue> uconst
%type <constValue> rs_uconst
%type <constValue> const_3bit
@@ -868,16 +869,16 @@
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 : 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 {@@ -925,35 +926,34 @@
| 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; }- | T_POP_WARN T_COMMA { $$ = ASSERT_WARN; }- | T_POP_FAIL T_COMMA { $$ = ASSERT_ERROR; }- | T_POP_FATAL T_COMMA { $$ = ASSERT_FATAL; }+assert_type : %empty { $$ = ASSERT_ERROR; }+ | T_POP_WARN T_COMMA { $$ = ASSERT_WARN; }+ | T_POP_FAIL T_COMMA { $$ = ASSERT_ERROR; }+ | 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 (!out_CreateAssert($2, &$3, "",
sect_GetOutputOffset()))
@@ -964,8 +964,7 @@
}
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 (!out_CreateAssert($2, &$3, $5,
sect_GetOutputOffset()))
@@ -976,26 +975,24 @@
}
rpn_Free(&$3);
}
- | T_POP_STATIC_ASSERT assert_type const
- {+ | T_POP_STATIC_ASSERT assert_type const {if ($3 == 0)
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)
failAssertMsg($2, $5);
}
;
-shift : T_POP_SHIFT { macro_ShiftCurrentArgs(1); }- | T_POP_SHIFT const { macro_ShiftCurrentArgs($2); }+shift : T_POP_SHIFT { macro_ShiftCurrentArgs(1); }+ | T_POP_SHIFT const { macro_ShiftCurrentArgs($2); };
load : T_POP_LOAD sectmod string T_COMMA sectiontype sectorg sectattrs {out_SetLoadSection($3, $5, $6, &$7, $2);
}
- | T_POP_ENDL { out_EndLoadSection(); }+ | T_POP_ENDL { out_EndLoadSection(); };
rept : T_POP_REPT uconst T_NEWLINE {@@ -1062,10 +1059,10 @@
}
;
-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 {@@ -1074,16 +1071,16 @@
| 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 {out_RelBytes($2, $4.args, $4.nbArgs);
freeDsArgList(&$4);
@@ -1104,15 +1101,15 @@
}
;
-db : T_POP_DB { out_Skip(1, false); }+db : T_POP_DB { out_Skip(1, false); }| 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
;
-dl : T_POP_DL { out_Skip(4, false); }+dl : T_POP_DL { out_Skip(4, false); }| T_POP_DL constlist_32bit trailing_comma
;
@@ -1168,7 +1165,7 @@
| 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
@@ -1178,7 +1175,7 @@
| 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 {@@ -1205,24 +1202,22 @@
}
;
-charmap : T_POP_CHARMAP string T_COMMA const {- if ($4 < INT8_MIN || $4 > UINT8_MAX)
- warning(WARNING_TRUNCATION, "Expression must be 8-bit\n");
+charmap : T_POP_CHARMAP string T_COMMA const_8bit {charmap_Add($2, (uint8_t)$4);
}
;
-newcharmap : T_POP_NEWCHARMAP T_ID { charmap_New($2, NULL); }- | T_POP_NEWCHARMAP T_ID T_COMMA T_ID { charmap_New($2, $4); }+newcharmap : T_POP_NEWCHARMAP T_ID { charmap_New($2, NULL); }+ | 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
@@ -1246,25 +1241,25 @@
| string { printf("%s", $1); };
-printt : T_POP_PRINTT string {+printt : T_POP_PRINTT string {warning(WARNING_OBSOLETE, "`PRINTT` is deprecated; use `PRINT`\n");
printf("%s", $2);}
;
-printv : T_POP_PRINTV const {+printv : T_POP_PRINTV const {warning(WARNING_OBSOLETE, "`PRINTV` is deprecated; use `PRINT`\n");
printf("$%" PRIX32, $2);}
;
-printi : T_POP_PRINTI const {+printi : T_POP_PRINTI const {warning(WARNING_OBSOLETE, "`PRINTI` is deprecated; use `PRINT` with `STRFMT`\n");
printf("%" PRId32, $2);}
;
-printf : T_POP_PRINTF const {+printf : T_POP_PRINTF const {warning(WARNING_OBSOLETE, "`PRINTF` is deprecated; use `PRINT` with `STRFMT`\n");
fix_Print($2);
}
@@ -1286,7 +1281,7 @@
| 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);
}
| string {@@ -1302,7 +1297,7 @@
| 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);
}
| string {@@ -1318,11 +1313,12 @@
| constlist_32bit T_COMMA constlist_32bit_entry
;
-constlist_32bit_entry :relocexpr_no_str {+constlist_32bit_entry : relocexpr_no_str {out_RelLong(&$1, 0);
}
| 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);
out_AbsLongGroup(output, length);
@@ -1331,33 +1327,25 @@
;
reloc_8bit : relocexpr {- if(rpn_isKnown(&$1)
- && ($1.val < -128 || $1.val > 255))
- warning(WARNING_TRUNCATION, "Expression must be 8-bit\n");
+ rpn_CheckNBit(&$1, 8);
$$ = $1;
}
;
reloc_8bit_no_str : relocexpr_no_str {- if(rpn_isKnown(&$1)
- && ($1.val < -128 || $1.val > 255))
- warning(WARNING_TRUNCATION, "Expression must be 8-bit\n");
+ rpn_CheckNBit(&$1, 8);
$$ = $1;
}
;
reloc_16bit : relocexpr {- if (rpn_isKnown(&$1)
- && ($1.val < -32768 || $1.val > 65535))
- warning(WARNING_TRUNCATION, "Expression must be 16-bit\n");
+ rpn_CheckNBit(&$1, 16);
$$ = $1;
}
;
reloc_16bit_no_str : relocexpr_no_str {- if (rpn_isKnown(&$1)
- && ($1.val < -32768 || $1.val > 65535))
- warning(WARNING_TRUNCATION, "Expression must be 16-bit\n");
+ rpn_CheckNBit(&$1, 16);
$$ = $1;
}
;
@@ -1365,7 +1353,8 @@
relocexpr : relocexpr_no_str
| 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);
uint32_t r = str2int2(output, length);
@@ -1374,8 +1363,8 @@
}
;
-relocexpr_no_str : scoped_anon_id { rpn_Symbol(&$$, $1); }- | T_NUMBER { rpn_Number(&$$, $1); }+relocexpr_no_str : scoped_anon_id { rpn_Symbol(&$$, $1); }+ | T_NUMBER { rpn_Number(&$$, $1); } | T_OP_LOGICNOT relocexpr %prec NEG {rpn_LOGNOT(&$$, &$2);
}
@@ -1436,19 +1425,19 @@
| relocexpr T_OP_EXP relocexpr {rpn_BinaryOp(RPN_EXP, &$$, &$1, &$3);
}
- | T_OP_ADD relocexpr %prec NEG { $$ = $2; }- | T_OP_SUB relocexpr %prec NEG { rpn_UNNEG(&$$, &$2); }- | T_OP_NOT relocexpr %prec NEG { rpn_UNNOT(&$$, &$2); }- | T_OP_HIGH T_LPAREN relocexpr T_RPAREN { rpn_HIGH(&$$, &$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_ADD relocexpr %prec NEG { $$ = $2; }+ | T_OP_SUB relocexpr %prec NEG { rpn_UNNEG(&$$, &$2); }+ | T_OP_NOT relocexpr %prec NEG { rpn_UNNOT(&$$, &$2); }+ | T_OP_HIGH T_LPAREN relocexpr T_RPAREN { rpn_HIGH(&$$, &$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_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);
}
- | 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_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 {@@ -1519,39 +1508,25 @@
| T_OP_CHARLEN T_LPAREN string T_RPAREN {rpn_Number(&$$, charlenUTF8($3));
}
- | T_LPAREN relocexpr T_RPAREN { $$ = $2; }+ | T_LPAREN relocexpr T_RPAREN { $$ = $2; };
uconst : const {$$ = $1;
if ($$ < 0)
- fatalerror("Constant mustn't be negative: %d\n",- $1);
+ fatalerror("Constant mustn't be negative: %d\n", $1);}
;
-const : relocexpr {- if (!rpn_isKnown(&$1)) {- error("Expected constant expression: %s\n",- $1.reason);
- $$ = 0;
- } else {- $$ = $1.val;
- }
- }
+const : relocexpr { $$ = rpn_GetConstVal(&$1); };
-const_no_str : relocexpr_no_str {- if (!rpn_isKnown(&$1)) {- error("Expected constant expression: %s\n",- $1.reason);
- $$ = 0;
- } else {- $$ = $1.val;
- }
- }
+const_no_str : relocexpr_no_str { $$ = rpn_GetConstVal(&$1); };
+const_8bit : reloc_8bit { $$ = rpn_GetConstVal(&$1); }+;
+
string : T_STRING
| T_OP_STRSUB T_LPAREN string T_COMMA const T_COMMA uconst T_RPAREN {size_t len = strlenUTF8($3);
@@ -1615,20 +1590,10 @@
strfmt_va_args : %empty {initStrFmtArgList(&$$);
}
- | strfmt_va_args T_COMMA relocexpr_no_str {- int32_t value;
-
- if (!rpn_isKnown(&$3)) {- error("Expected constant expression: %s\n",- $3.reason);
- value = 0;
- } else {- value = $3.val;
- }
-
+ | strfmt_va_args T_COMMA const_no_str {size_t i = nextStrFmtArgListIndex(&$1);
- $1.args[i].number = value;
+ $1.args[i].number = $3;
$1.args[i].isNumeric = true;
$$ = $1;
}
@@ -1646,19 +1611,19 @@
}
;
-sectmod : %empty { $$ = SECTION_NORMAL; }- | T_POP_UNION { $$ = SECTION_UNION; }- | T_POP_FRAGMENT{ $$ = SECTION_FRAGMENT; }+sectmod : %empty { $$ = SECTION_NORMAL; }+ | T_POP_UNION { $$ = SECTION_UNION; }+ | T_POP_FRAGMENT { $$ = SECTION_FRAGMENT; };
-sectiontype : T_SECT_WRAM0 { $$ = SECTTYPE_WRAM0; }- | T_SECT_VRAM { $$ = SECTTYPE_VRAM; }- | T_SECT_ROMX { $$ = SECTTYPE_ROMX; }- | T_SECT_ROM0 { $$ = SECTTYPE_ROM0; }- | T_SECT_HRAM { $$ = SECTTYPE_HRAM; }- | T_SECT_WRAMX { $$ = SECTTYPE_WRAMX; }- | T_SECT_SRAM { $$ = SECTTYPE_SRAM; }- | T_SECT_OAM { $$ = SECTTYPE_OAM; }+sectiontype : T_SECT_WRAM0 { $$ = SECTTYPE_WRAM0; }+ | T_SECT_VRAM { $$ = SECTTYPE_VRAM; }+ | T_SECT_ROMX { $$ = SECTTYPE_ROMX; }+ | T_SECT_ROM0 { $$ = SECTTYPE_ROM0; }+ | T_SECT_HRAM { $$ = SECTTYPE_HRAM; }+ | T_SECT_WRAMX { $$ = SECTTYPE_WRAMX; }+ | T_SECT_SRAM { $$ = SECTTYPE_SRAM; }+ | T_SECT_OAM { $$ = SECTTYPE_OAM; };
sectorg : %empty { $$ = -1; }@@ -1743,7 +1708,7 @@
out_AbsByte(0xCE);
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 {@@ -1750,8 +1715,8 @@
out_AbsByte(0xC6);
out_RelByte(&$2, 1);
}
- | 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 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_SP T_COMMA reloc_8bit {out_AbsByte(0xE8);
out_RelByte(&$4, 1);
@@ -1763,7 +1728,7 @@
out_AbsByte(0xE6);
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 {@@ -1782,7 +1747,7 @@
}
;
-z80_ccf : T_Z80_CCF { out_AbsByte(0x3F); }+z80_ccf : T_Z80_CCF { out_AbsByte(0x3F); };
z80_cp : T_Z80_CP op_a_n {@@ -1789,23 +1754,23 @@
out_AbsByte(0xFE);
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)); }- | T_Z80_DEC reg_ss { out_AbsByte(0x0B | ($2 << 4)); }+z80_dec : T_Z80_DEC reg_r { out_AbsByte(0x05 | ($2 << 3)); }+ | 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 {@@ -1815,8 +1780,8 @@
}
;
-z80_inc : T_Z80_INC reg_r { out_AbsByte(0x04 | ($2 << 3)); }- | T_Z80_INC reg_ss { out_AbsByte(0x03 | ($2 << 4)); }+z80_inc : T_Z80_INC reg_r { out_AbsByte(0x04 | ($2 << 3)); }+ | T_Z80_INC reg_ss { out_AbsByte(0x03 | ($2 << 4)); };
z80_jp : T_Z80_JP reloc_16bit {@@ -1902,7 +1867,7 @@
}
;
-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 {out_AbsByte(0x01 | (REG_SP << 4));
out_RelWord(&$4, 1);
@@ -1992,7 +1957,7 @@
*/
;
-z80_nop : T_Z80_NOP { out_AbsByte(0x00); }+z80_nop : T_Z80_NOP { out_AbsByte(0x00); };
z80_or : T_Z80_OR op_a_n {@@ -1999,13 +1964,13 @@
out_AbsByte(0xF6);
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 {@@ -2014,12 +1979,11 @@
}
;
-z80_ret : T_Z80_RET { out_AbsByte(0xC9);- }
- | T_Z80_RET ccode { out_AbsByte(0xC0 | ($2 << 3)); }+z80_ret : T_Z80_RET { out_AbsByte(0xC9); }+ | 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 {@@ -2028,7 +1992,7 @@
}
;
-z80_rla : T_Z80_RLA { out_AbsByte(0x17); }+z80_rla : T_Z80_RLA { out_AbsByte(0x17); };
z80_rlc : T_Z80_RLC reg_r {@@ -2037,7 +2001,7 @@
}
;
-z80_rlca : T_Z80_RLCA { out_AbsByte(0x07); }+z80_rlca : T_Z80_RLCA { out_AbsByte(0x07); };
z80_rr : T_Z80_RR reg_r {@@ -2046,7 +2010,7 @@
}
;
-z80_rra : T_Z80_RRA { out_AbsByte(0x1F); }+z80_rra : T_Z80_RRA { out_AbsByte(0x1F); };
z80_rrc : T_Z80_RRC reg_r {@@ -2055,7 +2019,7 @@
}
;
-z80_rrca : T_Z80_RRCA { out_AbsByte(0x0F); }+z80_rrca : T_Z80_RRCA { out_AbsByte(0x0F); };
z80_rst : T_Z80_RST reloc_8bit {@@ -2072,10 +2036,10 @@
out_AbsByte(0xDE);
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 {@@ -2116,8 +2080,7 @@
out_AbsByte(0xD6);
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 {@@ -2130,18 +2093,18 @@
out_AbsByte(0xEE);
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
- | T_MODE_A T_COMMA reg_r { $$ = $3; }+ | T_MODE_A T_COMMA reg_r { $$ = $3; };
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
@@ -2172,38 +2135,38 @@
| T_OP_LOW T_LPAREN T_MODE_HL T_RPAREN
;
-ccode : T_CC_NZ { $$ = CC_NZ; }- | T_CC_Z { $$ = CC_Z; }- | T_CC_NC { $$ = CC_NC; }- | T_TOKEN_C { $$ = CC_C; }+ccode : T_CC_NZ { $$ = CC_NZ; }+ | T_CC_Z { $$ = CC_Z; }+ | T_CC_NC { $$ = CC_NC; }+ | T_TOKEN_C { $$ = CC_C; };
-reg_r : T_MODE_B { $$ = REG_B; }- | T_MODE_C { $$ = REG_C; }- | T_MODE_D { $$ = REG_D; }- | T_MODE_E { $$ = REG_E; }- | T_MODE_H { $$ = REG_H; }- | T_MODE_L { $$ = REG_L; }- | T_LBRACK T_MODE_HL T_RBRACK { $$ = REG_HL_IND; }- | T_MODE_A { $$ = REG_A; }+reg_r : T_MODE_B { $$ = REG_B; }+ | T_MODE_C { $$ = REG_C; }+ | T_MODE_D { $$ = REG_D; }+ | T_MODE_E { $$ = REG_E; }+ | T_MODE_H { $$ = REG_H; }+ | T_MODE_L { $$ = REG_L; }+ | T_LBRACK T_MODE_HL T_RBRACK { $$ = REG_HL_IND; }+ | T_MODE_A { $$ = REG_A; };
-reg_tt : T_MODE_BC { $$ = REG_BC; }- | T_MODE_DE { $$ = REG_DE; }- | T_MODE_HL { $$ = REG_HL; }- | T_MODE_AF { $$ = REG_AF; }+reg_tt : T_MODE_BC { $$ = REG_BC; }+ | T_MODE_DE { $$ = REG_DE; }+ | T_MODE_HL { $$ = REG_HL; }+ | T_MODE_AF { $$ = REG_AF; };
-reg_ss : T_MODE_BC { $$ = REG_BC; }- | T_MODE_DE { $$ = REG_DE; }- | T_MODE_HL { $$ = REG_HL; }- | T_MODE_SP { $$ = REG_SP; }+reg_ss : T_MODE_BC { $$ = REG_BC; }+ | T_MODE_DE { $$ = REG_DE; }+ | T_MODE_HL { $$ = REG_HL; }+ | T_MODE_SP { $$ = REG_SP; };
-reg_rr : T_LBRACK T_MODE_BC T_RBRACK { $$ = REG_BC_IND; }- | T_LBRACK T_MODE_DE T_RBRACK { $$ = REG_DE_IND; }- | hl_ind_inc { $$ = REG_HL_INDINC; }- | hl_ind_dec { $$ = REG_HL_INDDEC; }+reg_rr : T_LBRACK T_MODE_BC T_RBRACK { $$ = REG_BC_IND; }+ | T_LBRACK T_MODE_DE T_RBRACK { $$ = REG_DE_IND; }+ | hl_ind_inc { $$ = REG_HL_INDINC; }+ | hl_ind_dec { $$ = REG_HL_INDDEC; };
hl_ind_inc : T_LBRACK T_MODE_HL_INC T_RBRACK
--- a/src/asm/rpn.c
+++ b/src/asm/rpn.c
@@ -13,6 +13,7 @@
#include <assert.h>
#include <errno.h>
#include <inttypes.h>
+#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -75,7 +76,7 @@
}
/*
- * Init the RPN expression
+ * Init a RPN expression
*/
static void rpn_Init(struct Expression *expr)
{@@ -258,6 +259,31 @@
expr->rpnPatchSize++;
*reserveSpace(expr, 1) = RPN_RST;
}
+}
+
+/*
+ * 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)
--
⑨