From d4d32095d16a8929d157f00962ab705ed71fae4c Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Fri, 26 Jun 2020 19:13:47 +0200 Subject: [PATCH] build segment tool can now be instructed to always place routine above #E000 --- ...46k_50k.s => under_rom_routines_46k_50k.s} | 7 +- doc/Development.md | 3 + tools/build_segment.cc | 94 ++++++++++++++++++- 3 files changed, 96 insertions(+), 8 deletions(-) rename c64/basic/memory/{e107.under_rom_routines_46k_50k.s => under_rom_routines_46k_50k.s} (91%) diff --git a/c64/basic/memory/e107.under_rom_routines_46k_50k.s b/c64/basic/memory/under_rom_routines_46k_50k.s similarity index 91% rename from c64/basic/memory/e107.under_rom_routines_46k_50k.s rename to c64/basic/memory/under_rom_routines_46k_50k.s index b46a03d1..7ceb7a84 100644 --- a/c64/basic/memory/e107.under_rom_routines_46k_50k.s +++ b/c64/basic/memory/under_rom_routines_46k_50k.s @@ -1,9 +1,8 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# STD * #TAKE-HIGH +// #LAYOUT# * BASIC_0 #TAKE-HIGH // #LAYOUT# * * #IGNORE -// XXX This can be any address - but definitely $E000 or above -// XXX TODO: extend build_segment tool to allow to specify placement range +// This has to go $E000 or above - as the routines below bank out the main BASIC ROM! #if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K diff --git a/doc/Development.md b/doc/Development.md index 95054f28..2a834a22 100644 --- a/doc/Development.md +++ b/doc/Development.md @@ -132,6 +132,7 @@ where: | `#IGNORE` | ignore the file completely | | `#TAKE` | compile the file normally | | `#TAKE-FLOAT` | compile the file, but force it to be floating | +| `#TAKE-HIGH` | as above, but always place routine at `$E000` or above | | `#TAKE-OFFSET` | shifts the fixed-location address by hex offset given as parameter | The first match counts, all the remaining ones are dropped. Examples: @@ -184,6 +185,8 @@ ROUTINE_NAME: #endif ``` +Last, but not least - the `#TAKE-HIGH` is intended to be used for BASIC routines, which should still be available after the main BASIC ROM is banked out. + ### CPU-specific optimizations TODO diff --git a/tools/build_segment.cc b/tools/build_segment.cc index 422819ef..d160f055 100644 --- a/tools/build_segment.cc +++ b/tools/build_segment.cc @@ -88,6 +88,7 @@ public: bool ignore; bool floating; + bool high; std::vector content; std::string label; @@ -109,6 +110,7 @@ public: void addToProblem(SourceFile *routine); void fillGap(DualStream &logOutput, int gapAddress, const std::list &routines); + void placeHighRoutines(DualStream &logOutput); void performObviousSteps(DualStream &logOutput); void removeUselessGaps(DualStream &logOutput); void sortFloatingRoutinesBySize(); @@ -416,9 +418,22 @@ void prepareBinningProblem() { std::string spacing; spacing.resize(GLOBAL_maxFileNameLen + 4 - sourceFile.fileName.length(), ' '); - std::string floating = sourceFile.floating ? "(floating) " : " "; + std::string floating_high; - logOutput << "file: " << floating << sourceFile.fileName << spacing << "size: " << std::to_string(sourceFile.codeLength) << "\n"; + if (sourceFile.high) + { + floating_high = "(floating, high) "; + } + else if (sourceFile.floating) + { + floating_high = "(floating) "; + } + else + { + floating_high = " "; + } + + logOutput << "file: " << floating_high << sourceFile.fileName << spacing << "size: " << std::to_string(sourceFile.codeLength) << "\n"; } // Create the binning problem @@ -569,6 +584,7 @@ SourceFile::SourceFile(const std::string &fileName, const std::string &dirName) dirName(dirName), ignore(false), floating(false), + high(false), startAddr(-1), codeLength(-1), testAddrStart(-1), @@ -686,12 +702,17 @@ bool SourceFile::preprocessLine(const std::string &line) if (iter->compare("#IGNORE") == 0) { - ignore = true; + ignore = true; } else if (iter->compare("#TAKE-FLOAT") == 0) { floating = true; } + else if (iter->compare("#TAKE-HIGH") == 0) + { + floating = true; + high = true; + } else if (iter->compare("#TAKE-OFFSET") == 0) { if (++iter == tokens.end()) ERROR("syntax error, missing parameter for '#TAKE-OFFSET'"); @@ -844,10 +865,71 @@ void BinningProblem::fillGap(DualStream &logOutput, int gapAddress, const std::l gaps.erase(gapAddress); } +void BinningProblem::placeHighRoutines(DualStream &logOutput) +{ + // Place routines which has to be stored in the high ROM area + // It is expected there will be very few of them, so no complicated algorithms here + + std::string spacing; + + while (!floatingRoutines.empty()) + { + // Try to find any high routine + + auto iterRoutine = floatingRoutines.begin(); + while (iterRoutine != floatingRoutines.end() && !(*iterRoutine)->high) iterRoutine++; + + if (iterRoutine == floatingRoutines.end()) break; + + // Now we need to find a space to put it - just take the largest gap available, + // which is located in the high ROM area + + int routineSize = (*iterRoutine)->codeLength; + int gapAddress = -1; + + for (auto &gap : gaps) + { + if (gap.second < routineSize || gap.first < 0xE000) continue; + + if (gap.second == routineSize) + { + gapAddress = gap.first; + break; + } + + if (gapAddress < 0 || gap.second > gaps[gapAddress]) + { + gapAddress = gap.first; + } + } + + if (gapAddress < 0) ERROR("no suitable space for a high routine"); + + // Place routine in the gap found + + gaps[gapAddress] -= routineSize; + + int targetAddr = gapAddress + gaps[gapAddress]; + fixedRoutines[targetAddr] = *iterRoutine; + statFree -= routineSize; + + logOutput << "reducing gap $" << std::hex << gapAddress << std::dec << + " to size " << gaps[gapAddress] << "\n"; + + spacing.resize(GLOBAL_maxFileNameLen + 4 - (*iterRoutine)->fileName.length(), ' '); + logOutput << " $" << std::hex << targetAddr << std::dec << ": " << + (*iterRoutine)->fileName << spacing << "size: " << + (*iterRoutine)->codeLength << "\n"; + + floatingRoutines.erase(iterRoutine); + if (gaps[gapAddress] == 0) gaps.erase(gapAddress); + } +} + void BinningProblem::performObviousSteps(DualStream &logOutput) { // Get the size of the biggest routine; if there is just one gap which - // can handle it - put the roputine exactly there + // can handle it - put the routine exactly there std::string spacing; @@ -954,6 +1036,10 @@ void Solver::run() problem.sortFloatingRoutinesBySize(); + // Place routines which should be stored in high-ROM + + problem.placeHighRoutines(logOutput); + // Run the solver until all is done while (!problem.gaps.empty() && !problem.floatingRoutines.empty())