diff --git a/include/asm/section.h b/include/asm/section.h index 4b433728..85d94833 100644 --- a/include/asm/section.h +++ b/include/asm/section.h @@ -56,6 +56,8 @@ void sect_CheckUnionClosed(void); void out_AbsByte(uint8_t b); void out_AbsByteGroup(uint8_t const *s, int32_t length); +void out_AbsWordGroup(uint8_t const *s, int32_t length); +void out_AbsLongGroup(uint8_t const *s, int32_t length); void out_Skip(int32_t skip, bool ds); void out_String(char const *s); void out_RelByte(struct Expression *expr); diff --git a/src/asm/parser.y b/src/asm/parser.y index f9bdc00f..34e10fa5 100644 --- a/src/asm/parser.y +++ b/src/asm/parser.y @@ -202,6 +202,7 @@ static inline void failAssertMsg(enum AssertionType type, char const *msg) %type reloc_8bit %type reloc_8bit_no_str %type reloc_16bit +%type reloc_16bit_no_str %type sectiontype %type string @@ -842,7 +843,14 @@ constlist_16bit_entry : /* empty */ { out_Skip(2, false); nListCountEmpty++; } - | reloc_16bit { out_RelWord(&$1); } + | reloc_16bit_no_str { out_RelWord(&$1); } + | string { + uint8_t *output = malloc(strlen($1)); /* Cannot be larger than that */ + int32_t length = charmap_Convert($1, output); + + out_AbsWordGroup(output, length); + free(output); + } ; constlist_32bit : constlist_32bit_entry @@ -853,7 +861,14 @@ constlist_32bit_entry : /* empty */ { out_Skip(4, false); nListCountEmpty++; } - | relocexpr { out_RelLong(&$1); } + | relocexpr_no_str { out_RelLong(&$1); } + | string { + uint8_t *output = malloc(strlen($1)); /* Cannot be larger than that */ + int32_t length = charmap_Convert($1, output); + + out_AbsLongGroup(output, length); + free(output); + } ; reloc_8bit : relocexpr { @@ -880,6 +895,14 @@ reloc_16bit : relocexpr { } ; +reloc_16bit_no_str : relocexpr_no_str { + if (rpn_isKnown(&$1) + && ($1.nVal < -32768 || $1.nVal > 65535)) + warning(WARNING_TRUNCATION, "Expression must be 16-bit\n"); + $$ = $1; + } +; + relocexpr : relocexpr_no_str | string { diff --git a/src/asm/section.c b/src/asm/section.c index b7dcab5a..2776efe1 100644 --- a/src/asm/section.c +++ b/src/asm/section.c @@ -506,6 +506,24 @@ void out_AbsByteGroup(uint8_t const *s, int32_t length) writebyte(*s++); } +void out_AbsWordGroup(uint8_t const *s, int32_t length) +{ + checkcodesection(); + reserveSpace(length * 2); + + while (length--) + writeword(*s++); +} + +void out_AbsLongGroup(uint8_t const *s, int32_t length) +{ + checkcodesection(); + reserveSpace(length * 4); + + while (length--) + writelong(*s++); +} + /* * Skip this many bytes */ diff --git a/test/asm/db-dw-dl-string.asm b/test/asm/db-dw-dl-string.asm new file mode 100644 index 00000000..7a72ca45 --- /dev/null +++ b/test/asm/db-dw-dl-string.asm @@ -0,0 +1,17 @@ +SECTION "Test", ROM0 + + db "ABC" + dw "ABC" + dl "ABC" + + db 0, "DEF", -1 + dw 0, "DEF", -1 + dl 0, "DEF", -1 + + db "A" + 1 + dw "A" + 1 + dl "A" + 1 + + db 1, ("UVWXYZ") & $ff, -1 + dw 1, ("UVWXYZ") & $ffff, -1 + dl 1, ("UVWXYZ"), -1 diff --git a/test/asm/db-dw-dl-string.err b/test/asm/db-dw-dl-string.err new file mode 100644 index 00000000..e69de29b diff --git a/test/asm/db-dw-dl-string.out b/test/asm/db-dw-dl-string.out new file mode 100644 index 00000000..e69de29b diff --git a/test/asm/db-dw-dl-string.out.bin b/test/asm/db-dw-dl-string.out.bin new file mode 100644 index 00000000..e66cd191 Binary files /dev/null and b/test/asm/db-dw-dl-string.out.bin differ