Hi Peter and Frieder,
How do you propose this should be maintained? When someone uses a
different derivative or implements bank switching himself in his hardware
using a plain 8052 the SFR and maybe even the code needs to be changed.
Should the user then edit the linker and subsequently recompile the linker
for his purpose? And what if he uses several different derivatives? Should
he keep several versions of the linker around? This does not scale at all
Furthermore these methods without telling the compiler it is using a
banked call misalign parameters passed on the stack. This only works when
there are no parameters on stack or the xstack is used.
An alternative is to always preload some registers with the destination
function before a call is generated. Then the linker can substitute the
call destination with a trampoline function to do the bank switching. The
trampoline module pops the return address from the stack and pushes it
onto a different (software) stack. For simplicity for the user it also
pushes the current bank on this stack. Then it can switch the bank and
indirectly call the function using the registers. After return of the
function everything is restored again. It is much easier for the user to
edit and substitute this trampoline function.
This approach could use two versions of this function. Depending on the
used stack for parameter passing one of the two functions can be used. One
pushes on the xstack when parameters are passed on the internal stack. The
other pushes on the hardware stack when parameters are passed on the
xstack (--xstack option). A third version could be created for functions
that do not pass parameters on the stack and thus needs no unwinding of
The cost of this approach is several bytes per call to initialize the
registers and a fixed amount for the trampoline function(s) used.
In general I'm opposed to having the linker generate or modify any code. I
think only substitution of labels should be allowed.
> Hi Peter,
> Peter Kuhar schrieb:
>> Has anyone allready implemented the bankswitching technichue described
>> I'm currently adding a feature to the aslink to support that.
>> The codesegments are configured at compile time with:
>> --codeseg BANK2
>> linked with:
>> The linker finds(now it's a 3 pass linker) lcalls from one bank to
>> and generates proxy function in the common area bank. The crossbank
>> are then painted to the proxy.
>> Proxy then switheches the bank, calls the original function and restores
>> So there is no need to declare a banked call in source/header files.
>> an example proxy from CC2430 MCU looks like this( but could be modified
>> other hardware )
>> If we have void led() in BANK2;
>> the proxy looks like:
>> .globl _FMAL
>> .globl _led
>> push _FMAP ;save current bank
>> mov _FMAP, #0x02 ; select bank 2
>> lcall _led ;call _led in bank 2
>> pop _FMAP ;restore bank
>> FMAP is the bank selecting SFR on CC2430
>> the modifications are made in lkmain.c(making a 3 pass link) and
>> proxys and relocation lcall calls)
>> Any comments/suggestions.
> Nice!) I'm not aware that anyone has done that.
> One could do with one byte less stack space if the
> information from which bank the call originates would be
> used as well. A proxy could then look like this:
> mov _FMAP, #0x02 ; select bank 2
> lcall _led ; call _led in bank 2
> ajmp _bc_return_to_bank_1 ; ajmp/ljmp
> mov _FMAP, #0x00
> mov _FMAP, #0x01
> mov _FMAP, #0x02
> mov _FMAP, #0x03
> The number of instruction cycles would be the same, one byte
> less stack would be used. Depending on how the banked calls
> are intermixed it might need less or more code memory (as
> when called from bank3 a proxy _bc_led_called_from_bank3
> would be needed).
> (If you want to go fancy one could try "inc _FMAP" here
> shaving off one byte and one cycle:^)
> This SF.net email is sponsored by: Splunk Inc.
> Still grepping through log files to find problems? Stop.
> Now Search log events and configuration files using AJAX and a browser.
> Download your FREE copy of Splunk now >> http://get.splunk.com/
> Sdcc-user mailing list