Code overlay example.

This commit is contained in:
Scott Duensing 2024-02-21 18:05:22 -06:00
parent c7d21f850f
commit d64a68da17
7 changed files with 89 additions and 44 deletions

2
.gitignore vendored
View file

@ -42,6 +42,8 @@ intelFPGA_lite/
/imageconvert
include/
generated/
overlay
overlayhelper
# Dumb QtCreator junk
build-*/

View file

@ -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

View file

@ -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

View file

@ -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;
}

26
examples/overlay/run.sh Executable file
View file

@ -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

View file

@ -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
)

View file

@ -27,7 +27,7 @@
#include <stdbool.h>
#include <dirent.h>
#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"