shithub: rgbds

Download patch

ref: 676800476d47695fc90de2b7b5316b7320e7a9a3
parent: 4dfa3157e568137e71b4351f16fb7fc0927d740e
parent: d23401316e460336400d7c7bc0e302ca924bfa02
author: Eldred Habert <[email protected]>
date: Wed Jan 8 13:56:28 EST 2020

Merge pull request #430 from ISSOtm/known_selfbank

Make `BANK(@)` and `BANK("section")` known to RGBASM

--- a/include/asm/constexpr.h
+++ b/include/asm/constexpr.h
@@ -20,6 +20,8 @@
 };
 
 void constexpr_Symbol(struct ConstExpression *expr, char *tzSym);
+void constexpr_BanksSymbol(struct ConstExpression *expr, char *tzSym);
+void constexpr_BankSection(struct ConstExpression *expr, char *tzSym);
 void constexpr_Number(struct ConstExpression *expr, int32_t i);
 void constexpr_UnaryOp(struct ConstExpression *expr,
 		       int32_t op,
--- a/include/asm/output.h
+++ b/include/asm/output.h
@@ -29,6 +29,7 @@
 
 void out_PrepPass2(void);
 void out_SetFileName(char *s);
+struct Section *out_FindSectionByName(const char *pzName);
 void out_NewSection(char *pzName, uint32_t secttype);
 void out_NewAbsSection(char *pzName, uint32_t secttype, int32_t org,
 		       int32_t bank);
--- a/src/asm/asmy.y
+++ b/src/asm/asmy.y
@@ -1394,6 +1394,14 @@
 		| T_NUMBER				{ constexpr_Number(&$$, $1); }
 		| T_OP_HIGH '(' const ')'		{ constexpr_UnaryOp(&$$, $1, &$3); }
 		| T_OP_LOW '(' const ')'		{ constexpr_UnaryOp(&$$, $1, &$3); }
+		| T_OP_BANK '(' T_ID ')'
+		{
+			constexpr_BankSymbol(&$$, $3);
+		}
+		| T_OP_BANK '(' string ')'
+		{
+			constexpr_BankSection(&$$, $3);
+		}
 		| string
 		{
 			char *s = $1;
--- a/src/asm/constexpr.c
+++ b/src/asm/constexpr.c
@@ -15,6 +15,7 @@
 #include "asm/lexer.h"
 #include "asm/main.h"
 #include "asm/mymath.h"
+#include "asm/output.h"
 #include "asm/rpn.h"
 #include "asm/symbol.h"
 #include "asm/warning.h"
@@ -35,6 +36,42 @@
 	} else {
 		constexpr_Number(expr, sym_GetConstantValue(tzSym));
 	}
+}
+
+void constexpr_BankSymbol(struct ConstExpression *expr, char *tzSym)
+{
+	if (sym_FindSymbol(tzSym) == pPCSymbol) {
+		if (pCurrentSection->nBank == -1)
+			yyerror("%s's bank is not known yet", tzSym);
+		else
+			constexpr_Number(expr, pCurrentSection->nBank);
+		return;
+	}
+
+	if (sym_isConstant(tzSym)) {
+		yyerror("BANK argument must be a relocatable identifier");
+	} else {
+		struct sSymbol *pSymbol = sym_FindSymbol(tzSym);
+
+		if (!pSymbol)
+			yyerror("BANK argument doesn't exist");
+		else if (!pSymbol->pSection || pSymbol->pSection->nBank == -1)
+			yyerror("BANK argument must be a relocatable identifier");
+		else
+			constexpr_Number(expr, pSymbol->pSection->nBank);
+	}
+}
+
+void constexpr_BankSection(struct ConstExpression *expr, char *tzSectionName)
+{
+	struct Section *pSection = out_FindSectionByName(tzSectionName);
+
+	if (!pSection)
+		yyerror("Section \"%s\" doesn't exist");
+	else if (pSection->nBank == -1)
+		yyerror("Section \"%s\"'s bank is not known yet");
+	else
+		constexpr_Number(expr, pSection->nBank);
 }
 
 void constexpr_Number(struct ConstExpression *expr, int32_t i)
--- a/src/asm/output.c
+++ b/src/asm/output.c
@@ -599,6 +599,20 @@
 		printf("Output filename %s\n", s);
 }
 
+struct Section *out_FindSectionByName(const char *pzName)
+{
+	struct Section *pSect = pSectionList;
+
+	while (pSect) {
+		if (strcmp(pzName, pSect->pzName) == 0)
+			return pSect;
+
+		pSect = pSect->pNext;
+	}
+
+	return NULL;
+}
+
 /*
  * Find a section by name and type. If it doesn't exist, create it
  */
@@ -605,42 +619,32 @@
 struct Section *out_FindSection(char *pzName, uint32_t secttype, int32_t org,
 				int32_t bank, int32_t alignment)
 {
-	struct Section *pSect, **ppSect;
+	struct Section *pSect = out_FindSectionByName(pzName);
 
-	ppSect = &pSectionList;
-	pSect = pSectionList;
-
-	while (pSect) {
-		if (strcmp(pzName, pSect->pzName) == 0) {
-			if (secttype == pSect->nType
-			    && ((uint32_t)org) == pSect->nOrg
-			    && ((uint32_t)bank) == pSect->nBank
-			    && ((uint32_t)alignment == pSect->nAlign)) {
-				return pSect;
-			}
-
-			fatalerror("Section already exists but with a different type");
+	if (pSect) {
+		if (secttype == pSect->nType
+			&& ((uint32_t)org) == pSect->nOrg
+			&& ((uint32_t)bank) == pSect->nBank
+			&& ((uint32_t)alignment == pSect->nAlign)) {
+			return pSect;
 		}
-		ppSect = &(pSect->pNext);
-		pSect = pSect->pNext;
+		fatalerror("Section already exists but with a different type");
 	}
 
 	pSect = malloc(sizeof(struct Section));
-	*ppSect = pSect;
 	if (pSect == NULL)
 		fatalerror("Not enough memory for section");
 
-	pSect->pzName = malloc(strlen(pzName) + 1);
+	pSect->pzName = strdup(pzName);
 	if (pSect->pzName == NULL)
 		fatalerror("Not enough memory for sectionname");
 
-	strcpy(pSect->pzName, pzName);
 	pSect->nType = secttype;
 	pSect->nPC = 0;
 	pSect->nOrg = org;
 	pSect->nBank = bank;
 	pSect->nAlign = alignment;
-	pSect->pNext = NULL;
+	pSect->pNext = pSectionList;
 	pSect->pPatches = NULL;
 
 	/* It is only needed to allocate memory for ROM sections. */
@@ -655,7 +659,13 @@
 		pSect->tData = NULL;
 	}
 
-	return (pSect);
+	/*
+	 * Add the new section to the list
+	 * at the beginning because order doesn't matter
+	 */
+	pSectionList = pSect;
+
+	return pSect;
 }
 
 /*
--- a/src/asm/rpn.c
+++ b/src/asm/rpn.c
@@ -19,6 +19,7 @@
 #include "asm/main.h"
 #include "asm/rpn.h"
 #include "asm/symbol.h"
+#include "asm/output.h"
 #include "asm/warning.h"
 
 #include "linkdefs.h"
@@ -160,11 +161,14 @@
 {
 	rpn_Init(expr);
 
-	/*
-	 * This symbol is not really relocatable, but this makes the assembler
-	 * write this expression as a RPN patch to the object file.
-	 */
-	expr->isReloc = 1;
+	if (pCurrentSection->nBank == -1)
+		/*
+		 * This is not really relocatable, but this makes the assembler
+		 * write this expression as a RPN patch to the object file.
+		 */
+		expr->isReloc = 1;
+	else
+		expr->nVal = pCurrentSection->nBank;
 
 	pushbyte(expr, RPN_BANK_SELF);
 	expr->nRPNPatchSize++;
@@ -178,17 +182,25 @@
 		return;
 	}
 
-	if (!sym_isConstant(tzSym)) {
+	if (sym_isConstant(tzSym)) {
+		yyerror("BANK argument must be a relocatable identifier");
+	} else {
 		rpn_Init(expr);
 		sym_Ref(tzSym);
-		expr->isReloc = 1;
 		pushbyte(expr, RPN_BANK_SYM);
-		while (*tzSym)
-			pushbyte(expr, *tzSym++);
+		for (unsigned int i = 0; tzSym[i]; i++)
+			pushbyte(expr, tzSym[i]);
 		pushbyte(expr, 0);
 		expr->nRPNPatchSize += 5;
-	} else {
-		yyerror("BANK argument must be a relocatable identifier");
+
+		/* If the symbol didn't exist, `sym_Ref` created it */
+		struct sSymbol *pSymbol = sym_FindSymbol(tzSym);
+
+		if (pSymbol->pSection && pSymbol->pSection->nBank != -1)
+			/* Symbol's section is known and bank's fixed */
+			expr->nVal = pSymbol->pSection->nBank;
+		else
+			expr->isReloc = 1;
 	}
 }
 
@@ -196,11 +208,16 @@
 {
 	rpn_Init(expr);
 
-	/*
-	 * This symbol is not really relocatable, but this makes the assembler
-	 * write this expression as a RPN patch to the object file.
-	 */
-	expr->isReloc = 1;
+	struct Section *pSection = out_FindSectionByName(tzSectionName);
+
+	if (pSection && pSection->nBank != -1)
+		expr->nVal = pSection->nBank;
+	else
+		/*
+		 * This is not really relocatable, but this makes the assembler
+		 * write this expression as a RPN patch to the object file.
+		 */
+		expr->isReloc = 1;
 
 	pushbyte(expr, RPN_BANK_SECT);
 	expr->nRPNPatchSize++;
--- /dev/null
+++ b/test/asm/pc-bank.asm
@@ -1,0 +1,11 @@
+SECTION "Fixed bank", ROMX,BANK[42]
+	ldh a, [BANK(@) * 256] ; This should be complained about at assembly time
+
+X = BANK(@)
+
+SECTION "Something else", ROMX
+Y = BANK("Fixed bank")
+
+    PRINTT "@: {X}\nStr: {Y}\n"
+
+ERR = BANK(@)
--- /dev/null
+++ b/test/asm/pc-bank.out
@@ -1,0 +1,8 @@
+ERROR: pc-bank.asm(2):
+    Source address $2a00 not in $FF00 to $FFFF
+ERROR: pc-bank.asm(11):
+    @'s bank is not known yet
+ERROR: pc-bank.asm(11):
+    Non-constant expression
+@: $2A
+Str: $2A