diff --git a/include/asm/rpn.h b/include/asm/rpn.h index 1059b2ab..c16c4fb8 100644 --- a/include/asm/rpn.h +++ b/include/asm/rpn.h @@ -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); diff --git a/include/common.h b/include/common.h index 8c4bd395..d453bbb9 100644 --- a/include/common.h +++ b/include/common.h @@ -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 */ diff --git a/include/link/assign.h b/include/link/assign.h index 09c44d23..c362b542 100644 --- a/include/link/assign.h +++ b/include/link/assign.h @@ -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, diff --git a/include/linkdefs.h b/include/linkdefs.h index fb4837fd..d13d3c6a 100644 --- a/include/linkdefs.h +++ b/include/linkdefs.h @@ -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 */ diff --git a/src/asm/asmy.y b/src/asm/asmy.y index efb9da39..d44a4376 100644 --- a/src/asm/asmy.y +++ b/src/asm/asmy.y @@ -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 { diff --git a/src/asm/output.c b/src/asm/output.c index 0152962b..917a3496 100644 --- a/src/asm/output.c +++ b/src/asm/output.c @@ -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; diff --git a/src/asm/rgbasm.5 b/src/asm/rgbasm.5 index f25d5696..facc0871 100644 --- a/src/asm/rgbasm.5 +++ b/src/asm/rgbasm.5 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2017 Antonio Nino Diaz +.\" Copyright (c) 2017-2018 Antonio Nino Diaz .\" .\" 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. diff --git a/src/asm/rpn.c b/src/asm/rpn.c index bf3b56bd..b2c74a15 100644 --- a/src/asm/rpn.c +++ b/src/asm/rpn.c @@ -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; diff --git a/src/link/assign.c b/src/link/assign.c index 0c920c54..82936e0a 100644 --- a/src/link/assign.c +++ b/src/link/assign.c @@ -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) { diff --git a/src/link/patch.c b/src/link/patch.c index 678b1456..7ec61633 100644 --- a/src/link/patch.c +++ b/src/link/patch.c @@ -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(); diff --git a/src/rgbds.5 b/src/rgbds.5 index 81b87d52..79200ec8 100644 --- a/src/rgbds.5 +++ b/src/rgbds.5 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2017 Antonio Nino Diaz +.\" Copyright (c) 2017-2018 Antonio Nino Diaz .\" .\" 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 0‐terminated 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.