shithub: rgbds

Download patch

ref: 97c326942f7f558fc994b19e21920bee719c3fc0
parent: b037d54f64917b1df175f33226ef21f20f94b0f7
author: ISSOtm <eldredhabert0@gmail.com>
date: Sat May 21 17:49:07 EDT 2022

Warn about automatic instruction alterations

Step 1 of #986

--- a/include/asm/main.h
+++ b/include/asm/main.h
@@ -16,7 +16,9 @@
 #include "helpers.h"
 
 extern bool haltnop;
+extern bool warnOnHaltNop;
 extern bool optimizeLoads;
+extern bool warnOnLdOpt;
 extern bool verbose;
 extern bool warnings; /* True to enable warnings, false to disable them. */
 
--- a/src/asm/main.c
+++ b/src/asm/main.c
@@ -59,7 +59,9 @@
 char *targetFileName;
 
 bool haltnop;
+bool warnOnHaltNop;
 bool optimizeLoads;
+bool warnOnLdOpt;
 bool verbose;
 bool warnings; /* True to enable warnings, false to disable them. */
 
@@ -84,7 +86,7 @@
 }
 
 /* Short options */
-static const char *optstring = "b:D:Eg:hi:LM:o:p:r:VvW:w";
+static const char *optstring = "b:D:Eg:Hhi:LlM:o:p:r:VvW:w";
 
 /* Variables for the long-only options */
 static int depType; /* Variants of `-M` */
@@ -104,9 +106,11 @@
 	{ "define",           required_argument, NULL,     'D' },
 	{ "export-all",       no_argument,       NULL,     'E' },
 	{ "gfx-chars",        required_argument, NULL,     'g' },
+	{ "nop-after-halt",   no_argument,       NULL,     'H' },
 	{ "halt-without-nop", no_argument,       NULL,     'h' },
 	{ "include",          required_argument, NULL,     'i' },
 	{ "preserve-ld",      no_argument,       NULL,     'L' },
+	{ "auto-ldh",         no_argument,       NULL,     'l' },
 	{ "dependfile",       required_argument, NULL,     'M' },
 	{ "MG",               no_argument,       &depType, 'G' },
 	{ "MP",               no_argument,       &depType, 'P' },
@@ -170,8 +174,10 @@
 	opt_B("01");
 	opt_G("0123");
 	opt_P(0);
-	optimizeLoads = true;
 	haltnop = true;
+	warnOnHaltNop = true;
+	optimizeLoads = true;
+	warnOnLdOpt = true;
 	verbose = false;
 	warnings = true;
 	sym_SetExportAll(false);
@@ -209,7 +215,14 @@
 				errx("Must specify exactly 4 characters for option 'g'");
 			break;
 
+		case 'H':
+			if (!haltnop)
+				errx("`-H` and `-h` don't make sense together");
+			warnOnHaltNop = false;
+			break;
 		case 'h':
+			if (!warnOnHaltNop)
+				errx("`-H` and `-h` don't make sense together");
 			haltnop = false;
 			break;
 
@@ -218,7 +231,14 @@
 			break;
 
 		case 'L':
+			if (!warnOnLdOpt)
+				errx("`-L` and `-l` don't make sense together");
 			optimizeLoads = false;
+			break;
+		case 'l':
+			if (!optimizeLoads)
+				errx("`-L` and `-l` don't make sense together");
+			warnOnLdOpt = false;
 			break;
 
 		case 'M':
--- a/src/asm/opt.c
+++ b/src/asm/opt.c
@@ -17,7 +17,9 @@
 	char gbgfx[4];
 	int32_t fillByte;
 	bool haltnop;
+	bool warnOnHaltNop;
 	bool optimizeLoads;
+	bool warnOnLdOpt;
 	bool warningsAreErrors;
 	size_t maxRecursionDepth;
 	// Don't be confused: we use the size of the **global variable** `warningStates`!
@@ -48,6 +50,11 @@
 	lexer_CheckRecursionDepth();
 }
 
+void opt_H(bool warn)
+{
+	warnOnHaltNop = warn;
+}
+
 void opt_h(bool halt)
 {
 	haltnop = halt;
@@ -58,6 +65,11 @@
 	optimizeLoads = optimize;
 }
 
+void opt_l(bool warn)
+{
+	warnOnLdOpt = warn;
+}
+
 void opt_W(char *flag)
 {
 	processWarningFlag(flag);
@@ -118,6 +130,13 @@
 		break;
 	}
 
+	case 'H':
+		if (s[1] == '\0')
+			opt_H(false);
+		else
+			error("Option 'H' does not take an argument\n");
+		break;
+
 	case 'h':
 		if (s[1] == '\0')
 			opt_h(false);
@@ -132,6 +151,13 @@
 			error("Option 'L' does not take an argument\n");
 		break;
 
+	case 'l':
+		if (s[1] == '\0')
+			opt_l(false);
+		else
+			error("Option 'l' does not take an argument\n");
+		break;
+
 	case 'W':
 		if (strlen(&s[1]) > 0)
 			opt_W(&s[1]);
@@ -186,8 +212,10 @@
 	entry->fillByte = fillByte; // Pulled from section.h
 
 	entry->haltnop = haltnop; // Pulled from main.h
+	entry->warnOnHaltNop = warnOnHaltNop;
 
 	entry->optimizeLoads = optimizeLoads; // Pulled from main.h
+	entry->warnOnLdOpt = warnOnLdOpt;
 
 	// Both of these pulled from warning.h
 	entry->warningsAreErrors = warningsAreErrors;
@@ -209,8 +237,10 @@
 	opt_B(entry->binary);
 	opt_G(entry->gbgfx);
 	opt_P(entry->fillByte);
+	opt_H(entry->warnOnHaltNop);
 	opt_h(entry->haltnop);
 	opt_L(entry->optimizeLoads);
+	opt_l(entry->warnOnLdOpt);
 
 	// opt_W does not apply a whole warning state; it processes one flag string
 	warningsAreErrors = entry->warningsAreErrors;
--- a/src/asm/parser.y
+++ b/src/asm/parser.y
@@ -1801,8 +1801,13 @@
 
 z80_halt	: T_Z80_HALT {
 			sect_AbsByte(0x76);
-			if (haltnop)
+			if (haltnop) {
+				if (warnOnHaltNop) {
+					warnOnHaltNop = false;
+					warning(WARNING_OBSOLETE, "`nop` after `halt` will stop being the default; pass `-H` to opt into it\n");
+				}
 				sect_AbsByte(0x00);
+			}
 		}
 ;
 
@@ -1910,6 +1915,10 @@
 		| T_Z80_LD op_mem_ind T_COMMA T_MODE_A {
 			if (optimizeLoads && rpn_isKnown(&$2)
 			 && $2.val >= 0xFF00) {
+				if (warnOnLdOpt) {
+					warnOnLdOpt = false;
+					warning(WARNING_OBSOLETE, "ld optimization will stop being the default; pass `-l` to opt into it\n");
+				}
 				sect_AbsByte(0xE0);
 				sect_AbsByte($2.val & 0xFF);
 				rpn_Free(&$2);
@@ -1958,6 +1967,10 @@
 			if ($2 == REG_A) {
 				if (optimizeLoads && rpn_isKnown(&$4)
 				 && $4.val >= 0xFF00) {
+					if (warnOnLdOpt) {
+						warnOnLdOpt = false;
+						warning(WARNING_OBSOLETE, "ld optimization will stop being the default; pass `-l` to opt into it\n");
+					}
 					sect_AbsByte(0xF0);
 					sect_AbsByte($4.val & 0xFF);
 					rpn_Free(&$4);
--- a/test/asm/opt.asm
+++ b/test/asm/opt.asm
@@ -10,6 +10,8 @@
 	println $8000_0000 / -1
 popo
 
+	opt H, l
+
 	ds 1
 	ld [$ff88], a
 	halt
--- a/test/asm/opt.err
+++ b/test/asm/opt.err
@@ -1,2 +1,2 @@
-warning: opt.asm(16): [-Wdiv]
+warning: opt.asm(18): [-Wdiv]
     Division of -2147483648 by -1 yields -2147483648