diff --git a/.gitignore b/.gitignore index 44db582..2c8e6a8 100644 --- a/.gitignore +++ b/.gitignore @@ -42,6 +42,8 @@ intelFPGA_lite/ /imageconvert include/ generated/ +overlay +overlayhelper # Dumb QtCreator junk build-*/ diff --git a/build-tools.sh b/build-tools.sh index 05d0321..da44f29 100755 --- a/build-tools.sh +++ b/build-tools.sh @@ -35,3 +35,8 @@ popd pushd tools/imageconvert cc imageconvert.c ../shared/util.o -o ../../imageconvert -lm popd + + +pushd tools/overlay + cc overlay.c ../shared/util.o -o ../../overlay -lm +popd diff --git a/examples/overlay/build.sh b/examples/overlay/build.sh index 02e3e9d..e56abc8 100755 --- a/examples/overlay/build.sh +++ b/examples/overlay/build.sh @@ -25,15 +25,22 @@ PROJECT=overlay -F256=$(pwd)/../.. +F256=$(readlink -f $(pwd)/../..) LLVM=${F256}/llvm-mos PATH=${LLVM}/bin:${PATH} CLANG="mos-f256k-clang -I${F256}/include -I${F256}/f256lib -Os" +[[ -d .builddir ]] && rm -rf .builddir +mkdir -p .builddir + +# Do not use relative paths. +${F256}/overlay 5 ${F256}/examples/overlay/.builddir ${F256}/examples/overlay + +pushd .builddir ${CLANG} -c ${PROJECT}.c -${CLANG} -T f256.ld \ +${CLANG} -T ../f256.ld \ -Wl,-Map=overlay.map \ -o ${PROJECT} \ ${PROJECT}.o @@ -44,3 +51,6 @@ llvm-nm ${PROJECT}.elf > ${PROJECT}.sym llvm-objdump -d --print-imm-hex ${PROJECT}.elf > ${PROJECT}.lst hexdump -C ${PROJECT}.pgz > ${PROJECT}.hex python ${F256}/pgz-thunk.py ${PROJECT}.pgz + +mv ${PROJECT}.pgz ../. +popd diff --git a/examples/overlay/overlay.c b/examples/overlay/overlay.c index 3dc9754..b4be221 100644 --- a/examples/overlay/overlay.c +++ b/examples/overlay/overlay.c @@ -21,27 +21,47 @@ */ -#define SEGMENT_TEST +#include "f256.h" +#include "f256.c" -/* - */ - /* - Breaking things { with comments! - */ -const char *test(int arg1, int arg2) { - return "Pointers from a swapped bank is probably a bad idea."; +// This is the first segment we've defined. The linker will place this code in +// the first available far memory slot (default 0x10000). +#define SEGMENT_FIRST + +void firstSegment(int arg1, int arg2) { + printf("firstSegment = %d\n", arg1 + arg2); } -int test2(int arg1, int arg2) { - return 1; +// This is the second segment we've defined. The linker will place this code in +// the next available far memory slot (default 0x12000). +#define SEGMENT_SECOND + +void secondSegment(int arg1, int arg2) { + printf("secondSegment = %d\n", arg1 + arg2); } +// Back to the first segment. The linker will place this code immediately +// after the previous first segment code. +#define SEGMENT_FIRST +void moreFirstSegment(int arg1, int arg2) { + printf("moreFirstSegment = %d\n", arg1 + arg2); +} + +// Back to near memory, the 64k visible to the processor. By default, this +// segment begins at 0x300. #define SEGMENT_MAIN - int main(int argc, char *argv[]) { - test(1, 2); + // The overlay tool will generate trampoline macros for each function + // that is located in a far segment so no code changes are required. + firstSegment(1, 2); + secondSegment(3, 4); + moreFirstSegment(5, 6); + + // Spin. + for (;;); + return 0; } diff --git a/examples/overlay/run.sh b/examples/overlay/run.sh new file mode 100755 index 0000000..bfd9a2d --- /dev/null +++ b/examples/overlay/run.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# +# Copyright (c) 2024 Scott Duensing, scott@kangaroopunch.com +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + + +python ../../FoenixMgr/FoenixMgr/fnxmgr.py --run-pgz overlay.pgz diff --git a/tools/overlay/CMakeLists.txt b/tools/overlay/CMakeLists.txt deleted file mode 100644 index 7e31c9e..0000000 --- a/tools/overlay/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -cmake_minimum_required(VERSION 3.12) - -project(overlay LANGUAGES C) - -#set(HEADERS ) -#list(TRANSFORM HEADERS PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/include/") - -set(SOURCE - overlay.c -) -list(TRANSFORM SOURCE PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/src/") - -add_executable(${CMAKE_PROJECT_NAME} -# ${HEADERS} - ${SOURCE} - ../shared/util.c -) - -target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src - ${CMAKE_CURRENT_SOURCE_DIR}/../shared -) diff --git a/tools/overlay/src/overlay.c b/tools/overlay/overlay.c similarity index 95% rename from tools/overlay/src/overlay.c rename to tools/overlay/overlay.c index 222505c..6f3dd8e 100644 --- a/tools/overlay/src/overlay.c +++ b/tools/overlay/overlay.c @@ -27,7 +27,7 @@ #include #include -#include "util.h" +#include "../shared/util.h" #define BUFFER_SIZE 4096 // If you have a line of code longer than this, you deserve the crash. @@ -96,6 +96,8 @@ void parseCFile(char *filename, char *targetFile, FILE *trampoline, char *trampo * - It only handles C, not C++. * - It can only handle single-line function definitions with the opening '{' on the same line as the function. * - It always generates trampolines, not just when they're needed. + * - Comments after function definitions will probably break it. + * - Comments after SEGMENT defines WILL break it. * * Someone should fix it. :-) */ @@ -125,14 +127,16 @@ void parseCFile(char *filename, char *targetFile, FILE *trampoline, char *trampo // Read next byte from C input file. if ((c = fgetc(in)) == EOF) break; - // Look for '//' comments. - if ((c == '/') && (pos > 0) && (buffer[pos-1] == '/')) inComment = true; + if (pos > 0) { + // Look for '//' comments. + if ((c == '/') && (pos > 0) && (buffer[pos-1] == '/')) inComment = true; - // Look for '/*' comment start. - if ((c == '*') && (pos > 0) && (buffer[pos-1] == '/')) comments++; + // Look for '/*' comment start. + if ((c == '*') && (pos > 0) && (buffer[pos-1] == '/')) comments++; - // Look for '*/' comment end. - if ((c == '/') && (pos > 0) && (buffer[pos-1] == '*')) comments--; + // Look for '*/' comment end. + if ((c == '/') && (pos > 0) && (buffer[pos-1] == '*')) comments--; + } // Count brackets so we know if we're inside a function or not. if ((!inComment) && (comments == 0)) { @@ -186,7 +190,7 @@ void parseCFile(char *filename, char *targetFile, FILE *trampoline, char *trampo temp = strdup(start); *b = '('; // Write out new function definition. - fprintf(out, "%s%sFAR%d_%s {\n", buffer, found ? "*" : " ", 8, start); + fprintf(out, "%s%cFAR%d_%s {\n", buffer, found ? '*' : ' ', _currentBank, start); // Create trampoline macro. fprintf(trampoline, "#define %s(...) ({ \\\n" "\t\tunsigned char ___mmu = (unsigned char)*(volatile unsigned char *)%#06x; \\\n"