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