Code overlay example.
This commit is contained in:
parent
c7d21f850f
commit
d64a68da17
7 changed files with 89 additions and 44 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -42,6 +42,8 @@ intelFPGA_lite/
|
||||||
/imageconvert
|
/imageconvert
|
||||||
include/
|
include/
|
||||||
generated/
|
generated/
|
||||||
|
overlay
|
||||||
|
overlayhelper
|
||||||
|
|
||||||
# Dumb QtCreator junk
|
# Dumb QtCreator junk
|
||||||
build-*/
|
build-*/
|
||||||
|
|
|
@ -35,3 +35,8 @@ popd
|
||||||
pushd tools/imageconvert
|
pushd tools/imageconvert
|
||||||
cc imageconvert.c ../shared/util.o -o ../../imageconvert -lm
|
cc imageconvert.c ../shared/util.o -o ../../imageconvert -lm
|
||||||
popd
|
popd
|
||||||
|
|
||||||
|
|
||||||
|
pushd tools/overlay
|
||||||
|
cc overlay.c ../shared/util.o -o ../../overlay -lm
|
||||||
|
popd
|
||||||
|
|
|
@ -25,15 +25,22 @@
|
||||||
|
|
||||||
PROJECT=overlay
|
PROJECT=overlay
|
||||||
|
|
||||||
F256=$(pwd)/../..
|
F256=$(readlink -f $(pwd)/../..)
|
||||||
LLVM=${F256}/llvm-mos
|
LLVM=${F256}/llvm-mos
|
||||||
PATH=${LLVM}/bin:${PATH}
|
PATH=${LLVM}/bin:${PATH}
|
||||||
|
|
||||||
CLANG="mos-f256k-clang -I${F256}/include -I${F256}/f256lib -Os"
|
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} -c ${PROJECT}.c
|
||||||
|
|
||||||
${CLANG} -T f256.ld \
|
${CLANG} -T ../f256.ld \
|
||||||
-Wl,-Map=overlay.map \
|
-Wl,-Map=overlay.map \
|
||||||
-o ${PROJECT} \
|
-o ${PROJECT} \
|
||||||
${PROJECT}.o
|
${PROJECT}.o
|
||||||
|
@ -44,3 +51,6 @@ llvm-nm ${PROJECT}.elf > ${PROJECT}.sym
|
||||||
llvm-objdump -d --print-imm-hex ${PROJECT}.elf > ${PROJECT}.lst
|
llvm-objdump -d --print-imm-hex ${PROJECT}.elf > ${PROJECT}.lst
|
||||||
hexdump -C ${PROJECT}.pgz > ${PROJECT}.hex
|
hexdump -C ${PROJECT}.pgz > ${PROJECT}.hex
|
||||||
python ${F256}/pgz-thunk.py ${PROJECT}.pgz
|
python ${F256}/pgz-thunk.py ${PROJECT}.pgz
|
||||||
|
|
||||||
|
mv ${PROJECT}.pgz ../.
|
||||||
|
popd
|
||||||
|
|
|
@ -21,27 +21,47 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#define SEGMENT_TEST
|
#include "f256.h"
|
||||||
|
#include "f256.c"
|
||||||
|
|
||||||
/*
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
Breaking things { with comments!
|
|
||||||
*/
|
|
||||||
|
|
||||||
const char *test(int arg1, int arg2) {
|
// This is the first segment we've defined. The linker will place this code in
|
||||||
return "Pointers from a swapped bank is probably a bad idea.";
|
// 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) {
|
// This is the second segment we've defined. The linker will place this code in
|
||||||
return 1;
|
// 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
|
#define SEGMENT_MAIN
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
26
examples/overlay/run.sh
Executable file
26
examples/overlay/run.sh
Executable 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
|
|
@ -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
|
|
||||||
)
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <dirent.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.
|
#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 only handles C, not C++.
|
||||||
* - It can only handle single-line function definitions with the opening '{' on the same line as the function.
|
* - 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.
|
* - 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. :-)
|
* 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.
|
// Read next byte from C input file.
|
||||||
if ((c = fgetc(in)) == EOF) break;
|
if ((c = fgetc(in)) == EOF) break;
|
||||||
|
|
||||||
// Look for '//' comments.
|
if (pos > 0) {
|
||||||
if ((c == '/') && (pos > 0) && (buffer[pos-1] == '/')) inComment = true;
|
// Look for '//' comments.
|
||||||
|
if ((c == '/') && (pos > 0) && (buffer[pos-1] == '/')) inComment = true;
|
||||||
|
|
||||||
// Look for '/*' comment start.
|
// Look for '/*' comment start.
|
||||||
if ((c == '*') && (pos > 0) && (buffer[pos-1] == '/')) comments++;
|
if ((c == '*') && (pos > 0) && (buffer[pos-1] == '/')) comments++;
|
||||||
|
|
||||||
// Look for '*/' comment end.
|
// Look for '*/' comment end.
|
||||||
if ((c == '/') && (pos > 0) && (buffer[pos-1] == '*')) comments--;
|
if ((c == '/') && (pos > 0) && (buffer[pos-1] == '*')) comments--;
|
||||||
|
}
|
||||||
|
|
||||||
// Count brackets so we know if we're inside a function or not.
|
// Count brackets so we know if we're inside a function or not.
|
||||||
if ((!inComment) && (comments == 0)) {
|
if ((!inComment) && (comments == 0)) {
|
||||||
|
@ -186,7 +190,7 @@ void parseCFile(char *filename, char *targetFile, FILE *trampoline, char *trampo
|
||||||
temp = strdup(start);
|
temp = strdup(start);
|
||||||
*b = '(';
|
*b = '(';
|
||||||
// Write out new function definition.
|
// 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.
|
// Create trampoline macro.
|
||||||
fprintf(trampoline, "#define %s(...) ({ \\\n"
|
fprintf(trampoline, "#define %s(...) ({ \\\n"
|
||||||
"\t\tunsigned char ___mmu = (unsigned char)*(volatile unsigned char *)%#06x; \\\n"
|
"\t\tunsigned char ___mmu = (unsigned char)*(volatile unsigned char *)%#06x; \\\n"
|
Loading…
Add table
Reference in a new issue