mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-24 12:02:08 +00:00
Merge pull request #430 from ISSOtm/known_selfbank
Make `BANK(@)` and `BANK("section")` known to RGBASM
This commit is contained in:
@@ -1394,6 +1394,14 @@ const : T_ID { constexpr_Symbol(&$$, $1); }
|
||||
| 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;
|
||||
|
||||
@@ -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"
|
||||
@@ -37,6 +38,42 @@ void constexpr_Symbol(struct ConstExpression *expr, char *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)
|
||||
{
|
||||
expr->u.nVal = i;
|
||||
|
||||
@@ -599,48 +599,52 @@ void out_SetFileName(char *s)
|
||||
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
|
||||
*/
|
||||
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 @@ struct Section *out_FindSection(char *pzName, uint32_t secttype, int32_t org,
|
||||
pSect->tData = NULL;
|
||||
}
|
||||
|
||||
return (pSect);
|
||||
/*
|
||||
* Add the new section to the list
|
||||
* at the beginning because order doesn't matter
|
||||
*/
|
||||
pSectionList = pSect;
|
||||
|
||||
return pSect;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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 @@ void rpn_BankSelf(struct Expression *expr)
|
||||
{
|
||||
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 @@ void rpn_BankSymbol(struct Expression *expr, char *tzSym)
|
||||
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 @@ void rpn_BankSection(struct Expression *expr, char *tzSectionName)
|
||||
{
|
||||
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++;
|
||||
|
||||
Reference in New Issue
Block a user