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:
ISSOtm
2024-08-14 02:16:13 +02:00
committed by Eldred Habert
parent e45a422da3
commit 28733fe312
3 changed files with 58 additions and 15 deletions

View File

@@ -86,6 +86,22 @@ If the bank has never been active thus far, the
.Dq current address
defaults to the beginning of the bank
.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
A bank must be active for any of these directives to be used.
.Pp
@@ -104,6 +120,7 @@ causes all sections between it and the next
.Ic ORG
or bank specification to be placed at addresses automatically determined by
.Nm .
.Pq It is, however, compatible with Ic ALIGN No below.
.Pp
.Ql Ic ALIGN Ar addr , Ar offset
increases the

View File

@@ -35,6 +35,7 @@
static void includeFile(std::string &&path);
static void incLineNo();
static void setFloatingSectionType(SectionType type);
static void setSectionType(SectionType type);
static void setSectionType(SectionType type, uint32_t bank);
static void setAddr(uint32_t addr);
@@ -111,6 +112,9 @@ directive:
| sect_type number {
setSectionType($1, $2);
}
| sect_type FLOATING {
setFloatingSectionType($1);
}
| FLOATING {
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) {
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");
return;
}
if (activeBankIdx == UINT32_MAX) {
scriptError(context, "Cannot set the current address: the bank is floating");
return;
}
auto &pc = curAddr[activeType][activeBankIdx];
auto const &typeInfo = sectionTypeInfo[activeType];
@@ -627,6 +649,9 @@ static void placeSection(std::string const &name, bool isOptional) {
);
}
if (activeBankIdx == UINT32_MAX) {
section->isBankFixed = false;
} else {
uint32_t bank = activeBankIdx + typeInfo.firstBank;
if (section->isBankFixed && bank != section->bank) {
scriptError(
@@ -641,6 +666,7 @@ static void placeSection(std::string const &name, bool isOptional) {
}
section->isBankFixed = true;
section->bank = bank;
}
if (!isPcFloating) {
uint16_t &org = curAddr[activeType][activeBankIdx];

View File

@@ -1,3 +1,3 @@
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