shithub: rgbds

Download patch

ref: 165bd8cb71c5ebe4f5cf79ed4179f9302834aa07
parent: e54e02dc77ae4e412905e168ff11e3017a481127
author: Rangi <remy.oukaour+rangi42@gmail.com>
date: Wed Dec 9 10:04:54 EST 2020

Allow 'dw' and 'dl' to apply to characters of strings

Fixes #568

The old behavior of `dw "string"` can be replicated with `dw ("string")`; likewise for dl

--- a/include/asm/section.h
+++ b/include/asm/section.h
@@ -56,6 +56,8 @@
 
 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);
--- a/src/asm/parser.y
+++ b/src/asm/parser.y
@@ -202,6 +202,7 @@
 %type	<sVal>		reloc_8bit
 %type	<sVal>		reloc_8bit_no_str
 %type	<sVal>		reloc_16bit
+%type	<sVal>		reloc_16bit_no_str
 %type	<nConstValue>	sectiontype
 
 %type	<tzString>	string
@@ -842,7 +843,14 @@
 			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 @@
 			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 {
@@ -873,6 +888,14 @@
 ;
 
 reloc_16bit	: relocexpr {
+			if (rpn_isKnown(&$1)
+			 && ($1.nVal < -32768 || $1.nVal > 65535))
+				warning(WARNING_TRUNCATION, "Expression must be 16-bit\n");
+			$$ = $1;
+		}
+;
+
+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");
--- a/src/asm/section.c
+++ b/src/asm/section.c
@@ -506,6 +506,24 @@
 		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
  */
--- /dev/null
+++ b/test/asm/db-dw-dl-string.asm
@@ -1,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
binary files /dev/null b/test/asm/db-dw-dl-string.out.bin differ