Allow ds to take multiple values to repeat for a count (#725)

Fixes #722
This commit is contained in:
Rangi
2021-02-16 19:01:23 -08:00
committed by GitHub
parent 76d6ef8695
commit 8c0275480c
9 changed files with 74 additions and 14 deletions

View File

@@ -83,4 +83,11 @@ int yylex(void);
void lexer_CaptureRept(struct CaptureBody *capture); void lexer_CaptureRept(struct CaptureBody *capture);
void lexer_CaptureMacroBody(struct CaptureBody *capture); void lexer_CaptureMacroBody(struct CaptureBody *capture);
#define INITIAL_DS_ARG_SIZE 2
struct DsArgList {
size_t nbArgs;
size_t capacity;
struct Expression *args;
};
#endif /* RGBDS_ASM_LEXER_H */ #endif /* RGBDS_ASM_LEXER_H */

View File

@@ -64,7 +64,7 @@ void out_AbsLongGroup(uint8_t const *s, int32_t length);
void out_Skip(int32_t skip, bool ds); void out_Skip(int32_t skip, bool ds);
void out_String(char const *s); void out_String(char const *s);
void out_RelByte(struct Expression *expr, uint32_t pcShift); void out_RelByte(struct Expression *expr, uint32_t pcShift);
void out_RelBytes(struct Expression *expr, uint32_t n); void out_RelBytes(uint32_t n, struct Expression *exprs, size_t size);
void out_RelWord(struct Expression *expr, uint32_t pcShift); void out_RelWord(struct Expression *expr, uint32_t pcShift);
void out_RelLong(struct Expression *expr, uint32_t pcShift); void out_RelLong(struct Expression *expr, uint32_t pcShift);
void out_PCRelByte(struct Expression *expr, uint32_t pcShift); void out_PCRelByte(struct Expression *expr, uint32_t pcShift);

View File

@@ -310,6 +310,33 @@ static void strfmt(char *dest, size_t destLen, char const *fmt, size_t nbArgs, s
dest[i] = '\0'; dest[i] = '\0';
} }
static void initDsArgList(struct DsArgList *args)
{
args->nbArgs = 0;
args->capacity = INITIAL_DS_ARG_SIZE;
args->args = malloc(args->capacity * sizeof(*args->args));
if (!args->args)
fatalerror("Failed to allocate memory for ds arg list: %s\n",
strerror(errno));
}
static size_t nextDsArgListIndex(struct DsArgList *args)
{
if (args->nbArgs == args->capacity) {
args->capacity = (args->capacity + 1) * 2;
args->args = realloc(args->args, args->capacity * sizeof(*args->args));
if (!args->args)
fatalerror("realloc error while resizing ds arg list: %s\n",
strerror(errno));
}
return args->nbArgs++;
}
static void freeDsArgList(struct DsArgList *args)
{
free(args->args);
}
static inline void failAssert(enum AssertionType type) static inline void failAssert(enum AssertionType type)
{ {
switch (type) { switch (type) {
@@ -397,6 +424,7 @@ enum {
struct SectionSpec sectSpec; struct SectionSpec sectSpec;
struct MacroArgs *macroArg; struct MacroArgs *macroArg;
enum AssertionType assertType; enum AssertionType assertType;
struct DsArgList dsArgs;
struct { struct {
int32_t start; int32_t start;
int32_t stop; int32_t stop;
@@ -537,6 +565,8 @@ enum {
%type <sectMod> sectmod %type <sectMod> sectmod
%type <macroArg> macroargs %type <macroArg> macroargs
%type <dsArgs> ds_args
%type <forArgs> for_args %type <forArgs> for_args
%token T_Z80_ADC "adc" T_Z80_ADD "add" T_Z80_AND "and" %token T_Z80_ADC "adc" T_Z80_ADD "add" T_Z80_AND "and"
@@ -946,8 +976,23 @@ 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 reloc_8bit { | T_POP_DS uconst T_COMMA ds_args {
out_RelBytes(&$4, $2); out_RelBytes($2, $4.args, $4.nbArgs);
freeDsArgList(&$4);
}
;
ds_args : reloc_8bit {
initDsArgList(&$$);
size_t i = nextDsArgListIndex(&$$);
$$.args[i] = $1;
}
| ds_args T_COMMA reloc_8bit {
size_t i = nextDsArgListIndex(&$1);
$1.args[i] = $3;
$$ = $1;
} }
; ;
@@ -1265,7 +1310,7 @@ relocexpr_no_str : scoped_anon_id { rpn_Symbol(&$$, $1); }
| relocexpr T_OP_XOR relocexpr { | relocexpr T_OP_XOR relocexpr {
rpn_BinaryOp(RPN_XOR, &$$, &$1, &$3); rpn_BinaryOp(RPN_XOR, &$$, &$1, &$3);
} }
| relocexpr T_OP_OR relocexpr { | relocexpr T_OP_OR relocexpr {
rpn_BinaryOp(RPN_OR, &$$, &$1, &$3); rpn_BinaryOp(RPN_OR, &$$, &$1, &$3);
} }
| relocexpr T_OP_AND relocexpr { | relocexpr T_OP_AND relocexpr {

View File

@@ -1239,10 +1239,13 @@ DW "H", "e", "l", "l", "o", "!"
If you do not want this special handling, enclose the string in parentheses. If you do not want this special handling, enclose the string in parentheses.
.Pp .Pp
.Ic DS .Ic DS
can also be used to fill a region of memory with some value. can also be used to fill a region of memory with some repeated values.
The following produces 42 times the byte $FF: For example:
.Bd -literal -offset indent .Bd -literal -offset indent
DS 42, $FF ; outputs 3 bytes: $AA, $AA, $AA
DS 3, $AA
; outputs 7 bytes: $BB, $CC, $BB, $CC, $BB, $CC, $BB
DS 7, $BB, $CC
.Ed .Ed
.Pp .Pp
You can also use You can also use

View File

@@ -637,12 +637,14 @@ void out_RelByte(struct Expression *expr, uint32_t pcShift)
* Output several copies of a relocatable byte. Checking will be done to see if * Output several copies of a relocatable byte. Checking will be done to see if
* it is an absolute value in disguise. * it is an absolute value in disguise.
*/ */
void out_RelBytes(struct Expression *expr, uint32_t n) void out_RelBytes(uint32_t n, struct Expression *exprs, size_t size)
{ {
checkcodesection(); checkcodesection();
reserveSpace(n); reserveSpace(n);
for (uint32_t i = 0; i < n; i++) { for (uint32_t i = 0; i < n; i++) {
struct Expression *expr = &exprs[i % size];
if (!rpn_isKnown(expr)) { if (!rpn_isKnown(expr)) {
createPatch(PATCHTYPE_BYTE, expr, i); createPatch(PATCHTYPE_BYTE, expr, i);
writebyte(0); writebyte(0);
@@ -650,7 +652,9 @@ void out_RelBytes(struct Expression *expr, uint32_t n)
writebyte(expr->nVal); writebyte(expr->nVal);
} }
} }
rpn_Free(expr);
for (size_t i = 0; i < size; i++)
rpn_Free(&exprs[i]);
} }
/* /*

View File

@@ -1,14 +1,14 @@
SECTION "test fixed", ROM0[0] SECTION "test fixed", ROM0[0]
FixedStart: FixedStart:
ds 8, (@ - FixedStart) * 2 + zero ds 6, (@ - FixedStart) * 2 + zero
ds 8, (@ - FixedStart) * 2 + zero ds 10, (@ - FixedStart) + zero, (@ - FixedStart) * 3 + zero, (@ - FixedStart) * 4 + zero
SECTION "test floating", ROM0 SECTION "test floating", ROM0
FloatingStart: FloatingStart:
ds 8, (@ - FloatingStart) * 2 + zero ds 6, (@ - FloatingStart) * 2 + zero
ds 8, (@ - FloatingStart) * 2 + zero ds 10, (@ - FloatingStart) + zero, (@ - FloatingStart) * 3 + zero, (@ - FloatingStart) * 4 + zero
SECTION "zero", ROM0[0] SECTION "zero", ROM0[0]
zero: zero:

Binary file not shown.

View File

@@ -6,3 +6,4 @@ Label:
ds 5, .other - Label - 5 ; Expressions should work... ds 5, .other - Label - 5 ; Expressions should work...
ds 60, .last - Label ; ...even if not constant ds 60, .last - Label ; ...even if not constant
.last .last
ds 11, $67, $89

View File

@@ -1 +1 @@
****<2A><><EFBFBD><EFBFBD><EFBFBD>EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE ****<2A><><EFBFBD><EFBFBD><EFBFBD>EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEg<EFBFBD>g<EFBFBD>g<EFBFBD>g<EFBFBD>g<EFBFBD>g