SDCC4 for gbz80 Far call with transparent bank switching example
Features were implemented in the latest GBDK-2020 releases. You don't need this now, just use latest GBDK - everything is fixed automatically by the linker.
Link to GBDK-2020: https://github.com/Zal0/gbdk-2020
The description below explains the mechanism.
I was digging into the sdcc, and found out, that transparent bank switching is almost working! It was always! The only thing that was missing - a correct bank number in the structure, that is generated for every far call. The trampoline functions always existed in crt, and there is no problem with them. You may even call a subroutine in bank2 from a subroutine in bank1, and that all works perfectly, the banks are saved, switch is done at the proper moment, and banks restored after all correctly!
So, i wrote a very simple postprocessor, that identifies the bank number of a symbol and fills the compiler-magic structure with the correct values.
This postprocessor takes names of object files, which are passed through a command line, loads symbols from them, make a "name --> bank number" dict, then takes the last object file, parses it (it has a trivial structure) and patches the bank number in the object file and outputs the result to stdout.
The patch target is:
call banked_call
dw <far_function_offset>
dw 0 <--- HERE, the <bank_number>
Postprocessor identifies a call to banked_call, ensures that it is really a call, identifies that there is a
dw <far_function_offset>
after it (another reloc), finds a bank in the "name --> bank number" dict, patches the
dw <bank_number>
with a bank number. You may see the results of patching on the screenshot below:
This is the early alpha version of a postprocessor, it may contain some bugs, so i appriciate your help with testing and fixing it.
So. In your code, everything you should do is to declare a function, with a __banked keyword. Every call to such function is made by SDCC through a trampoline function call generated by it and is fixed by my postprocessor then. Watch through the make.bat script for the details on how it is done.
Your code in some .c file that is may be compiled, say, with -bo2 switch or a #pragma bank 2:
int some_bank2_proc(int a, int b, int c) __banked {
printf(" in %s\n", hello2);
return a + b + c;
}
and in the other place, say main(), you just call this function:
int somevar = some_bank2_proc(16, 32, 64);
Compile both files. Fix the object file from which the far call is made with far_fixer.py, by passing BOTH objects to it in the right order. You must fix EVERY object file, that contain far calls (only one in this example). If you forget one, there will be a crash. Then you just link patched files with the ye olde linker from 2000.
Thanks for reading this readme! Tony.
