From 28733fe312f55347d661c98cd4517532703543e0 Mon Sep 17 00:00:00 2001 From: ISSOtm Date: Wed, 14 Aug 2024 02:16:13 +0200 Subject: [PATCH] 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! --- man/rgblink.5 | 17 ++++++++++ src/link/script.y | 54 +++++++++++++++++++++++-------- test/link/script-syntax-error.out | 2 +- 3 files changed, 58 insertions(+), 15 deletions(-) diff --git a/man/rgblink.5 b/man/rgblink.5 index a2d8207c..fc60669f 100644 --- a/man/rgblink.5 +++ b/man/rgblink.5 @@ -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 diff --git a/src/link/script.y b/src/link/script.y index 53faf0eb..b854a8c4 100644 --- a/src/link/script.y +++ b/src/link/script.y @@ -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); @@ -106,11 +107,14 @@ line: directive: sect_type { - setSectionType($1); + setSectionType($1); } | 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,20 +649,24 @@ static void placeSection(std::string const &name, bool isOptional) { ); } - uint32_t bank = activeBankIdx + typeInfo.firstBank; - if (section->isBankFixed && bank != section->bank) { - scriptError( - context, - "The linker script places section \"%s\" in %s bank %" PRIu32 - ", but it was already defined in bank %" PRIu32, - name.c_str(), - sectionTypeInfo[section->type].name.c_str(), - bank, - section->bank - ); + if (activeBankIdx == UINT32_MAX) { + section->isBankFixed = false; + } else { + uint32_t bank = activeBankIdx + typeInfo.firstBank; + if (section->isBankFixed && bank != section->bank) { + scriptError( + context, + "The linker script places section \"%s\" in %s bank %" PRIu32 + ", but it was already defined in bank %" PRIu32, + 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) { uint16_t &org = curAddr[activeType][activeBankIdx]; diff --git a/test/link/script-syntax-error.out b/test/link/script-syntax-error.out index 758941a1..7ec4e680 100644 --- a/test/link/script-syntax-error.out +++ b/test/link/script-syntax-error.out @@ -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