> > The compiler piece is trivial but important because those extra two bytes
> > are essential in order to make bank unwinding work properly in all cases.  
> 
> Why do you need two bytes? I would have guessed that one should be enough.

To avoid magic wrappers everywhere.

The bank helper for that switch pushes the address of code that switches
back to the calling bank and then does a ret.

This means that the far function is completely unaware of any magic. It
does a ret, it ends up in the code that switches bank back, which does a
ret which ends up where expected.


> The approach of essentially treating all calls as banked is interesting.
> Maybe this could be implemented as a new memory model (e.g.
> --model-large, similar to how this is implemented for stm8, making
> function pointers 24 bits).
> 
> I'd still like to have banked calls in the normal memory model, handled
> differently from normal calls.

Yes - doing it as a generic thing has a performance impact. For my use
case that's fine and it would be unmanagable any other way. Something
like a game specific to one platform would want explicit banking in many
cases I think.

The explicit banking case is also very useful for the classic disk
overlays model. When you have your bank switches planned and few of them
it's an identical problem to the disk overlay model.

> 
> > 
> > The linker looks for calls that go between banks or banks and common
> > 
> > If a relocation is from code to code then it swaps the push af/call/pop af
> > with
> > 
> >             call __bank_n_m  ; where n/m are the banks
> >             .word funcaddr
> > 
> > and the platform provides specific banking functions according to need.
> > The extra push/pop af is removed and the extra 2 bytes on the stack are
> > needed by the bank switching code (it uses it to push the address of the
> > correct stub to switch back)
> >   
> 
> So you have one stub per bank?

One per combination although in fact most of them merge together because
every function calling into a bank has the same tail code, but a
different pushed value. The end result is one per combination for about 8
bytes then merging into one per bank, and one per bank for returns, plus
some for the stub stuff as it's a shade different.

In terms of them all being the same, the Rabbit is explicitly designed to
do it differently and the 'official' rabbit compiler generates code which
is designed to run in an 8K sliding window, and has long jump/call/ret
instructions including linker inserted ones for functions that cross an
8K boundary. That model is also doable on Z180 but a bit more clunky (and
I think came from some Z180 use cases and tools). In that model you don't
have to worry about dividing stuff into banks by hand. You have data and
common stuff, and a sliding 8K window for the rest.

Alan


_______________________________________________
Sdcc-user mailing list
Sdcc-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sdcc-user

Reply via email to