Re: [cc65] Segments and banking

Date view Thread view Subject view

From: Mike McCarty (jmccarty_at_ssd.usa.alcatel.com)
Date: 2001-05-25 17:03:02


On Fri, 25 May 2001, Ullrich von Bassewitz wrote:

> 
> On Fri, May 25, 2001 at 09:13:33AM -0400, shubel, paul wrote:
> > Question:  Can CC65 compile and link a segmented build?  For example,
> > can it call modules in "banked" areas of memory to exceed the 64K boundary?
> 
> cc65 cannot call functions in other banks by itself, because the banking
> mechanism is always hardware dependent. However, the linker is able to overlay
> memory areas. This means that it is possible to write programs for banked
> hardware with some help from the programmer.
> 
> > Is this what is meant by segments?
> 
> segments are just some hunks of code or data that have a name. The linker
> combines all pieces that have the same name to one large chunk, and places it
> into a memory area according to the rules in the configuration file.
> 
> This means that by placing a function f1() into a segment with the name CODE1,
> and a function named f2() into a segment CODE2, it is possible to tell the
> linker to relocate both segments CODE1 and CODE2 to the same address, but
> write it to different files. To support banking, the programmer has to supply
> a short stub in common memory for each such function that enables the correct
> bank and calls the function.

Excellent description, Ullrich. Having done banked memory switching
myself, I'd like to add to your statement.

Banked memory switching is both a blessing and a curse. It is a
blessing, in a sense, because it allows one to use much more memory
than the processor can directly access.

It is a curse for a multitude of reasons. One is the "short stub", also
sometimes called a "trampoline". This is the bane of programmers.
Debugging this stuff is a major pain. One has to be sure that the stack
appears in all banks. Initializing the memory (loading the program) is
a major pain. Single stepping in a debugger may or may not work. It may
be impossible to set a break in code not in the present bank, and it
may be impossible to step into it.

Oh, another way to do it is to have the trampolines appear in each bank,
rather than in common memory.

I prefer not to use trampolines at all, but rather to put a dispatcher
in common memory, along with a jump table and information on what bank
each destination lies in. Macroes can hide the interface. It's something
like this:

        #define SOME_FUNCTION           6
        #define SomeFunction(Arg1,Arg2) BankCall(SOME_FUNCTION,Arg1,Arg2)

where BankCall is a real routine in the common memory, the dispatcher.
Its prototype looks like this

        int     BankCall(int FunctionId,...);

It uses FunctionId as an index into a table of entries giving the
banked address (bank and offset) of the destination function.

SomeFunction looks like this:

        int     SomeFunction(SomeFunctionParmsStruct_t *Parms);

BankCall computes the address of the argument with the lowest address,
and passes that as the pointer to the parameter block accepted by the
function. One could use <stdarg.h> and make the functions receive a
va_list

        int     SomeFunction(va_list Parms);

similar to vfprintf().

BankCall looks in the function table, and checks the current hardware
state against the table entry. If necessary, it first enables the
chosen bank (or even just unconditionally enables it), saving the
current bank in a bank stack (or in a local variable on the stack).
Then it invokes the address in the table. On return, it re-enables the
bank called from if necessary (or even just unconditionally) and then
returns the value returned by the invoked routine.

In this way, no additional code need be written for multiple routines,
just add an entry in the table. Get the code right once, and then don't
change it.

Some prefer to do this

        #define SOME_BANK       3
        #define SOME_FUNCTION   0x1234
        int     BankCall(SOME_BANK,SOME_FUNCTION,...);

where the actual bank and function address get passed in. I don't like
this, as one has to edit a header file somewhere to put the banks and
addresses in. I prefer editing a jump table in a source file.

YMMV

Mike

----------------------------------------------------------------------
To unsubscribe from the list send mail to majordomo_at_musoftware.de with
the string "unsubscribe cc65" in the body(!) of the mail.


Date view Thread view Subject view

This archive was generated by hypermail 2.1.3 : 2001-12-14 22:05:40 CET