mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Implement floating bank in linker script
Turns out that we can solve being unable to choose a bank to change the PC of, by simply refusing to choose!
This commit is contained in:
@@ -86,6 +86,22 @@ If the bank has never been active thus far, the
|
|||||||
.Dq current address
|
.Dq current address
|
||||||
defaults to the beginning of the bank
|
defaults to the beginning of the bank
|
||||||
.Pq e.g. Ad $4000 No for Ic ROMX No sections .
|
.Pq e.g. Ad $4000 No for Ic ROMX No sections .
|
||||||
|
.Pp
|
||||||
|
Instead of giving a bank number, the keyword
|
||||||
|
.Ic FLOATING
|
||||||
|
can be used instead; this sets the type of the subsequent sections without binding them to a particular bank.
|
||||||
|
(If the type only allows a single bank, e.g.
|
||||||
|
.Ic ROM0 ,
|
||||||
|
then
|
||||||
|
.Ic FLOATING
|
||||||
|
is valid but redundant and has no effect.)
|
||||||
|
Since no particular section is active, the
|
||||||
|
.Dq current address
|
||||||
|
is made floating (as if by a
|
||||||
|
.Ql Ic FLOATING
|
||||||
|
directive), and
|
||||||
|
.Ic ORG
|
||||||
|
is not allowed.
|
||||||
.It Changing the current address
|
.It Changing the current address
|
||||||
A bank must be active for any of these directives to be used.
|
A bank must be active for any of these directives to be used.
|
||||||
.Pp
|
.Pp
|
||||||
@@ -104,6 +120,7 @@ causes all sections between it and the next
|
|||||||
.Ic ORG
|
.Ic ORG
|
||||||
or bank specification to be placed at addresses automatically determined by
|
or bank specification to be placed at addresses automatically determined by
|
||||||
.Nm .
|
.Nm .
|
||||||
|
.Pq It is, however, compatible with Ic ALIGN No below.
|
||||||
.Pp
|
.Pp
|
||||||
.Ql Ic ALIGN Ar addr , Ar offset
|
.Ql Ic ALIGN Ar addr , Ar offset
|
||||||
increases the
|
increases the
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
static void includeFile(std::string &&path);
|
static void includeFile(std::string &&path);
|
||||||
static void incLineNo();
|
static void incLineNo();
|
||||||
|
|
||||||
|
static void setFloatingSectionType(SectionType type);
|
||||||
static void setSectionType(SectionType type);
|
static void setSectionType(SectionType type);
|
||||||
static void setSectionType(SectionType type, uint32_t bank);
|
static void setSectionType(SectionType type, uint32_t bank);
|
||||||
static void setAddr(uint32_t addr);
|
static void setAddr(uint32_t addr);
|
||||||
@@ -106,11 +107,14 @@ line:
|
|||||||
|
|
||||||
directive:
|
directive:
|
||||||
sect_type {
|
sect_type {
|
||||||
setSectionType($1);
|
setSectionType($1);
|
||||||
}
|
}
|
||||||
| sect_type number {
|
| sect_type number {
|
||||||
setSectionType($1, $2);
|
setSectionType($1, $2);
|
||||||
}
|
}
|
||||||
|
| sect_type FLOATING {
|
||||||
|
setFloatingSectionType($1);
|
||||||
|
}
|
||||||
| FLOATING {
|
| FLOATING {
|
||||||
makeAddrFloating();
|
makeAddrFloating();
|
||||||
}
|
}
|
||||||
@@ -388,6 +392,20 @@ static void setActiveTypeAndIdx(SectionType type, uint32_t idx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void setFloatingSectionType(SectionType type) {
|
||||||
|
if (nbbanks(type) == 1) {
|
||||||
|
setActiveTypeAndIdx(type, 0); // There is only a single bank anyway, so just set the index to 0.
|
||||||
|
} else {
|
||||||
|
activeType = type;
|
||||||
|
activeBankIdx = UINT32_MAX;
|
||||||
|
// Force PC to be floating for this kind of section.
|
||||||
|
// Because we wouldn't know how to index into `curAddr[activeType]`!
|
||||||
|
isPcFloating = true;
|
||||||
|
floatingAlignMask = 0;
|
||||||
|
floatingAlignOffset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void setSectionType(SectionType type) {
|
static void setSectionType(SectionType type) {
|
||||||
auto const &context = lexerStack.back();
|
auto const &context = lexerStack.back();
|
||||||
|
|
||||||
@@ -433,6 +451,10 @@ static void setAddr(uint32_t addr) {
|
|||||||
scriptError(context, "Cannot set the current address: no memory region is active");
|
scriptError(context, "Cannot set the current address: no memory region is active");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (activeBankIdx == UINT32_MAX) {
|
||||||
|
scriptError(context, "Cannot set the current address: the bank is floating");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto &pc = curAddr[activeType][activeBankIdx];
|
auto &pc = curAddr[activeType][activeBankIdx];
|
||||||
auto const &typeInfo = sectionTypeInfo[activeType];
|
auto const &typeInfo = sectionTypeInfo[activeType];
|
||||||
@@ -627,20 +649,24 @@ static void placeSection(std::string const &name, bool isOptional) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t bank = activeBankIdx + typeInfo.firstBank;
|
if (activeBankIdx == UINT32_MAX) {
|
||||||
if (section->isBankFixed && bank != section->bank) {
|
section->isBankFixed = false;
|
||||||
scriptError(
|
} else {
|
||||||
context,
|
uint32_t bank = activeBankIdx + typeInfo.firstBank;
|
||||||
"The linker script places section \"%s\" in %s bank %" PRIu32
|
if (section->isBankFixed && bank != section->bank) {
|
||||||
", but it was already defined in bank %" PRIu32,
|
scriptError(
|
||||||
name.c_str(),
|
context,
|
||||||
sectionTypeInfo[section->type].name.c_str(),
|
"The linker script places section \"%s\" in %s bank %" PRIu32
|
||||||
bank,
|
", but it was already defined in bank %" PRIu32,
|
||||||
section->bank
|
name.c_str(),
|
||||||
);
|
sectionTypeInfo[section->type].name.c_str(),
|
||||||
|
bank,
|
||||||
|
section->bank
|
||||||
|
);
|
||||||
|
}
|
||||||
|
section->isBankFixed = true;
|
||||||
|
section->bank = bank;
|
||||||
}
|
}
|
||||||
section->isBankFixed = true;
|
|
||||||
section->bank = bank;
|
|
||||||
|
|
||||||
if (!isPcFloating) {
|
if (!isPcFloating) {
|
||||||
uint16_t &org = curAddr[activeType][activeBankIdx];
|
uint16_t &org = curAddr[activeType][activeBankIdx];
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
error: script-syntax-error.link(2): syntax error, unexpected ORG, expecting newline or OPTIONAL
|
error: script-syntax-error.link(2): syntax error, unexpected ORG, expecting newline or OPTIONAL
|
||||||
error: script-syntax-error.link(5): syntax error, unexpected string, expecting newline or number
|
error: script-syntax-error.link(5): syntax error, unexpected string, expecting newline or FLOATING or number
|
||||||
Linking failed with 2 errors
|
Linking failed with 2 errors
|
||||||
|
|||||||
Reference in New Issue
Block a user