Allow to request BANK() of sections and PC

The bank of a section can be requested with `BANK("Section Name")`, and
the bank of the current section with `BANK(@)`. In both cases, the bank
number is resolved by the linker.

New commands have been added to the list of RPN commands of object
files, and the rest has been moved so that new additions don't force a
new change in the number of the enumerations.

Increase object file version, as it is now incompatible with the old
format.

Update manpages to reflect the new ways of using `BANK()` and the new
format of the object files.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
This commit is contained in:
Antonio Niño Díaz
2018-01-07 02:05:05 +00:00
parent d24cf11ad4
commit 959bfe2a9d
11 changed files with 216 additions and 92 deletions

View File

@@ -58,7 +58,9 @@ void rpn_LOW(struct Expression *expr, const struct Expression *src);
void rpn_UNNEG(struct Expression *expr, const struct Expression *src);
void rpn_UNNOT(struct Expression *expr, const struct Expression *src);
uint16_t rpn_PopByte(struct Expression *expr);
void rpn_Bank(struct Expression *expr, char *tzSym);
void rpn_BankSymbol(struct Expression *expr, char *tzSym);
void rpn_BankSection(struct Expression *expr, char *tzSectionName);
void rpn_BankSelf(struct Expression *expr);
void rpn_Reset(struct Expression *expr);
void rpn_CheckHRAM(struct Expression *expr, const struct Expression *src);

View File

@@ -1,6 +1,6 @@
#ifndef RGBDS_COMMON_H
#define RGBDS_COMMON_H
#define RGBDS_OBJECT_VERSION_STRING "RGB5"
#define RGBDS_OBJECT_VERSION_STRING "RGB6"
#endif /* RGBDS_COMMON_H */

View File

@@ -38,6 +38,7 @@ extern int32_t MaxAvail[MAXBANKS];
int32_t area_Avail(int32_t bank);
void AssignSections(void);
void CreateSymbolTable(void);
struct sSection *GetSectionByName(const char *name);
int32_t IsSectionNameInUse(const char *name);
void SetLinkerscriptName(char *tzLinkerscriptFile);
int32_t IsSectionSameTypeBankAndFloating(const char *name,

View File

@@ -2,61 +2,63 @@
#define RGBDS_LINKDEFS_H
enum eRpnData {
RPN_ADD = 0,
RPN_SUB,
RPN_MUL,
RPN_DIV,
RPN_MOD,
RPN_UNSUB,
RPN_ADD = 0x00,
RPN_SUB = 0x01,
RPN_MUL = 0x02,
RPN_DIV = 0x03,
RPN_MOD = 0x04,
RPN_UNSUB = 0x05,
RPN_OR,
RPN_AND,
RPN_XOR,
RPN_UNNOT,
RPN_OR = 0x10,
RPN_AND = 0x11,
RPN_XOR = 0x12,
RPN_UNNOT = 0x13,
RPN_LOGAND,
RPN_LOGOR,
RPN_LOGUNNOT,
RPN_LOGAND = 0x21,
RPN_LOGOR = 0x22,
RPN_LOGUNNOT = 0x23,
RPN_LOGEQ,
RPN_LOGNE,
RPN_LOGGT,
RPN_LOGLT,
RPN_LOGGE,
RPN_LOGLE,
RPN_LOGEQ = 0x30,
RPN_LOGNE = 0x31,
RPN_LOGGT = 0x32,
RPN_LOGLT = 0x33,
RPN_LOGGE = 0x34,
RPN_LOGLE = 0x35,
RPN_SHL,
RPN_SHR,
RPN_SHL = 0x40,
RPN_SHR = 0x41,
RPN_BANK,
RPN_BANK_SYM = 0x50,
RPN_BANK_SECT = 0x51,
RPN_BANK_SELF = 0x52,
RPN_HRAM,
RPN_HRAM = 0x60,
RPN_CONST = 0x80,
RPN_SYM = 0x81
RPN_CONST = 0x80,
RPN_SYM = 0x81
};
enum eSectionType {
SECT_WRAM0 = 0,
SECT_VRAM,
SECT_ROMX,
SECT_ROM0,
SECT_HRAM,
SECT_WRAMX,
SECT_SRAM,
SECT_OAM
SECT_WRAM0 = 0x00,
SECT_VRAM = 0x01,
SECT_ROMX = 0x02,
SECT_ROM0 = 0x03,
SECT_HRAM = 0x04,
SECT_WRAMX = 0x05,
SECT_SRAM = 0x06,
SECT_OAM = 0x07
};
enum eSymbolType {
SYM_LOCAL = 0,
SYM_IMPORT,
SYM_EXPORT
SYM_LOCAL = 0x00,
SYM_IMPORT = 0x01,
SYM_EXPORT = 0x02
};
enum ePatchType {
PATCH_BYTE = 0,
PATCH_WORD_L,
PATCH_LONG_L
PATCH_BYTE = 0x00,
PATCH_WORD_L = 0x01,
PATCH_LONG_L = 0x02
};
#endif /* RGBDS_LINKDEFS_H */

View File

@@ -1173,7 +1173,13 @@ relocconst : T_ID
| T_OP_LOW '(' relocconst ')' { rpn_LOW(&$$, &$3); }
| T_OP_BANK '(' T_ID ')'
{
rpn_Bank(&$$, $3);
/* '@' is also a T_ID, it is handled here. */
rpn_BankSymbol(&$$, $3);
$$.nVal = 0;
}
| T_OP_BANK '(' string ')'
{
rpn_BankSection(&$$, $3);
$$.nVal = 0;
}
| T_OP_DEF {

View File

@@ -419,7 +419,7 @@ void createpatch(uint32_t type, struct Expression *expr)
rpnexpr[rpnptr++] = symptr >> 24;
}
break;
case RPN_BANK:
case RPN_BANK_SYM:
{
struct sSymbol *sym;
@@ -432,13 +432,25 @@ void createpatch(uint32_t type, struct Expression *expr)
break;
symptr = addsymbol(sym);
rpnexpr[rpnptr++] = RPN_BANK;
rpnexpr[rpnptr++] = RPN_BANK_SYM;
rpnexpr[rpnptr++] = symptr & 0xFF;
rpnexpr[rpnptr++] = symptr >> 8;
rpnexpr[rpnptr++] = symptr >> 16;
rpnexpr[rpnptr++] = symptr >> 24;
break;
}
case RPN_BANK_SECT:
{
uint16_t b;
rpnexpr[rpnptr++] = RPN_BANK_SECT;
do {
b = rpn_PopByte(expr);
rpnexpr[rpnptr++] = b & 0xFF;
} while (b != 0);
break;
}
default:
rpnexpr[rpnptr++] = rpndata;
break;

View File

@@ -1,4 +1,4 @@
.\" Copyright (c) 2017 Antonio Nino Diaz <antonio_nd@outlook.com>
.\" Copyright (c) 2017-2018 Antonio Nino Diaz <antonio_nd@outlook.com>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
@@ -12,7 +12,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd July 22, 2017
.Dd January 7, 2018
.Dt RGBASM 5
.Os RGBDS Manual
.Sh NAME
@@ -969,9 +969,15 @@ There are a few other functions that do various useful things:
.Pp
.Bl -column ".Sy String" ".Sy String"
.It Sy Name Ta Ta Ta Sy Operation
.It Li BANK(label) Ta Returns the bank number label is in.
The linker will have to resolve this so it can't be used when the expression has
to be constant.
.It Li BANK(\@/str/lbl) Ta Returns a bank number.
If the argument is the symbol
.Ic \@,
this function returns the bank of the current section.
If the argument is a string, it returns the bank of the section that has that
name.
If the argument is a label, it returns the bank number the label is in.
For labels, as the linker has to resolve this, it can't be used when the
expression has to be constant.
.It Li DEF(label) Ta Returns TRUE if label has been defined.
.It Li HIGH(r16/cnst/lbl) Ta Returns the top 8 bits of the operand if it is a
label or constant, or the top 8-bit register if it is a 16-bit register.

View File

@@ -108,8 +108,27 @@ void rpn_Symbol(struct Expression *expr, char *tzSym)
}
}
void rpn_Bank(struct Expression *expr, char *tzSym)
void rpn_BankSelf(struct Expression *expr)
{
rpn_Reset(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;
pushbyte(expr, RPN_BANK_SELF);
}
void rpn_BankSymbol(struct Expression *expr, char *tzSym)
{
/* The @ symbol is treated differently. */
if (sym_FindSymbol(tzSym) == pPCSymbol) {
rpn_BankSelf(expr);
return;
}
if (!sym_isConstant(tzSym)) {
rpn_Reset(expr);
@@ -120,7 +139,7 @@ void rpn_Bank(struct Expression *expr, char *tzSym)
sym_GetValue(tzSym);
expr->isReloc = 1;
pushbyte(expr, RPN_BANK);
pushbyte(expr, RPN_BANK_SYM);
while (*tzSym)
pushbyte(expr, *tzSym++);
pushbyte(expr, 0);
@@ -129,6 +148,22 @@ void rpn_Bank(struct Expression *expr, char *tzSym)
}
}
void rpn_BankSection(struct Expression *expr, char *tzSectionName)
{
rpn_Reset(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;
pushbyte(expr, RPN_BANK_SECT);
while (*tzSectionName)
pushbyte(expr, *tzSectionName++);
pushbyte(expr, 0);
}
void rpn_CheckHRAM(struct Expression *expr, const struct Expression *src)
{
*expr = *src;

View File

@@ -247,6 +247,20 @@ int32_t IsSectionNameInUse(const char *name)
return 0;
}
struct sSection *GetSectionByName(const char *name)
{
struct sSection *pSection = pSections;
while (pSection) {
if (strcmp(pSection->pzName, name) == 0)
return pSection;
pSection = pSection->pNext;
}
return NULL;
}
int32_t IsSectionSameTypeBankAndFloating(const char *name,
enum eSectionType type, int32_t bank)
{

View File

@@ -27,7 +27,7 @@ static int32_t rpnpop(void)
return rpnstack[rpnp];
}
int32_t getsymvalue(int32_t symid)
static int32_t getsymvalue(int32_t symid)
{
const struct sSymbol *tSymbol = pCurrentSection->tSymbols[symid];
@@ -49,26 +49,14 @@ int32_t getsymvalue(int32_t symid)
errx(1, "%s: Unknown symbol type", __func__);
}
int32_t getsymbank(int32_t symid)
static int32_t getrealbankfrominternalbank(int32_t n)
{
int32_t n;
const struct sSymbol *tSymbol = pCurrentSection->tSymbols[symid];
switch (tSymbol->Type) {
case SYM_IMPORT:
n = sym_GetBank(tSymbol->pzName);
break;
case SYM_EXPORT:
case SYM_LOCAL:
n = tSymbol->pSection->nBank;
break;
default:
errx(1, "%s: Unknown symbol type", __func__);
}
if ((n == BANK_WRAM0) || (n == BANK_ROM0) || (n == BANK_OAM) ||
(n == BANK_HRAM)) {
return 0;
} else if ((n >= BANK_ROMX) && (n < (BANK_ROMX + BANK_COUNT_ROMX))) {
return n - BANK_ROMX + 1;
} else if ((n >= BANK_WRAMX) && (n < (BANK_WRAMX + BANK_COUNT_WRAMX))) {
return n - BANK_WRAMX + 1;
} else if ((n >= BANK_VRAM) && (n < (BANK_VRAM + BANK_COUNT_VRAM))) {
@@ -77,13 +65,37 @@ int32_t getsymbank(int32_t symid)
return n - BANK_SRAM;
}
errx(1, "%s: Unknown bank %d", __func__, n);
return n;
}
static int32_t getsymbank(int32_t symid)
{
int32_t nBank;
const struct sSymbol *tSymbol = pCurrentSection->tSymbols[symid];
switch (tSymbol->Type) {
case SYM_IMPORT:
nBank = sym_GetBank(tSymbol->pzName);
break;
case SYM_EXPORT:
case SYM_LOCAL:
nBank = tSymbol->pSection->nBank;
break;
default:
errx(1, "%s: Unknown symbol type", __func__);
}
return getrealbankfrominternalbank(nBank);
}
int32_t calcrpn(struct sPatch *pPatch)
{
int32_t t, size;
uint8_t *rpn;
uint8_t rpn_cmd;
int32_t nBank;
rpnp = 0;
@@ -93,7 +105,9 @@ int32_t calcrpn(struct sPatch *pPatch)
while (size > 0) {
size -= 1;
switch (*rpn++) {
rpn_cmd = *rpn++;
switch (rpn_cmd) {
case RPN_ADD:
rpnpush(rpnpop() + rpnpop());
break;
@@ -194,7 +208,7 @@ int32_t calcrpn(struct sPatch *pPatch)
pPatch->oRelocPatch |= (getsymbank(t) != -1);
size -= 4;
break;
case RPN_BANK:
case RPN_BANK_SYM:
/* symbol */
t = (*rpn++);
t |= (*rpn++) << 8;
@@ -203,6 +217,34 @@ int32_t calcrpn(struct sPatch *pPatch)
rpnpush(getsymbank(t));
size -= 4;
break;
case RPN_BANK_SECT:
{
char *name = (char *)rpn;
struct sSection *pSection = GetSectionByName(name);
if (pSection == NULL) {
errx(1, "Requested BANK() of section \"%s\", which was not found.\n",
name);
}
nBank = pSection->nBank;
rpnpush(getrealbankfrominternalbank(nBank));
int len = strlen(name);
size -= len + 1;
rpn += len + 1;
break;
}
case RPN_BANK_SELF:
nBank = pCurrentSection->nBank;
rpnpush(getrealbankfrominternalbank(nBank));
break;
default:
errx(1, "%s: Invalid command %d\n", __func__,
rpn_cmd);
break;
}
}
return rpnpop();

View File

@@ -1,4 +1,4 @@
.\" Copyright (c) 2017 Antonio Nino Diaz <antonio_nd@outlook.com>
.\" Copyright (c) 2017-2018 Antonio Nino Diaz <antonio_nd@outlook.com>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
@@ -12,7 +12,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd July 22, 2017
.Dd January 7, 2018
.Dt RGBDS 5
.Os RGBDS Manual
.Sh NAME
@@ -42,7 +42,7 @@ is a 0terminated string of
.Bd -literal
; Header
BYTE ID[4] ; "RGB5"
BYTE ID[4] ; "RGB6"
LONG NumberOfSymbols ; The number of symbols used in this file
LONG NumberOfSections ; The number of sections used in this file
@@ -155,25 +155,29 @@ special prefixes for integers and symbols.
.It Li $03 Ta Li / operator
.It Li $04 Ta Li % operator
.It Li $05 Ta Li unary -
.It Li $06 Ta Li | operator
.It Li $07 Ta Li & operator
.It Li $08 Ta Li ^ operator
.It Li $09 Ta Li unary ~
.It Li $0A Ta Li && comparison
.It Li $0B Ta Li || comparison
.It Li $0C Ta Li unary !
.It Li $0D Ta Li == comparison
.It Li $0E Ta Li != comparison
.It Li $0F Ta Li > comparison
.It Li $10 Ta Li < comparison
.It Li $11 Ta Li >= comparison
.It Li $12 Ta Li <= comparison
.It Li $13 Ta Li << comparison
.It Li $14 Ta Li >> comparison
.It Li $15 Ta Li BANK()
function.
A symbol ID follows.
.It Li $16 Ta Li HRAMCheck.
.It Li $10 Ta Li | operator
.It Li $11 Ta Li & operator
.It Li $12 Ta Li ^ operator
.It Li $13 Ta Li unary ~
.It Li $21 Ta Li && comparison
.It Li $22 Ta Li || comparison
.It Li $23 Ta Li unary !
.It Li $30 Ta Li == comparison
.It Li $31 Ta Li != comparison
.It Li $32 Ta Li > comparison
.It Li $33 Ta Li < comparison
.It Li $34 Ta Li >= comparison
.It Li $35 Ta Li <= comparison
.It Li $40 Ta Li << comparison
.It Li $41 Ta Li >> comparison
.It Li $50 Ta Li BANK(symbol),
a
.Ar LONG
Symbol ID follows.
.It Li $51 Ta Li BANK(section_name),
a null-terminated string follows.
.It Li $52 Ta Li Current BANK() .
.It Li $60 Ta Li HRAMCheck.
Check if the value is in HRAM, AND it with 0xFF.
.It Li $80 Ta Ar LONG
integer follows.