The libbase changes
Introduction
On m68k amiga
the A6 register was used for the pointer to the base address of a
library structure. This A6 register was also not used for other code so
anywhere in the code of a library you could access the libbase through
this register without explicitly passing it to the function as a
function argument.
The first i386 ABI put the libbase on the stack as last argument to the function. This approach has some disadvantages:
- When you want to use the libbase
in subfunctions of the library you need to pass the libbase to that
subfunction. In the end this means that the libbase has to be added as
an argument to all functions in a call chain of functions where the
libbase is needed in the bottom function.
- This
way only a libbase can be used in function that use amiga library style
argument passing. It is difficult to use the libbase in libraries that
use normal C argument passing like for example arosc.library.
- Current
way of passing argument on i386 is incompatible with vararg functions
as the libbase is put as last argument on the stack.
- There has been comments of this approach on the efficiency due to the stack usage by the extra argument.
The
goal for the ABI and the libbase would also to be compatible with
other compilers then gcc; for example the vbcc compiler.
Another goal should be to make it very easy to port of external libraries to AROS.
Implementation
The
current implementation in the ABI V1 branch (trunk/branches/ABI_V1)
uses the %ebx register to pass the libbase to the library function.
This register is also reserved for base relative addressing.
As this register is currently reserved and not used by code generated
by the compiler you could access it everywhere in the library code.
AROS_GET_LIBBASE
and AROS_SET_LIBBASE macros are defined to be able to access the
libbase. These are by default defined as resp AROS_GET_RELBASE and
AROS_SET_RELBASE when they are not provided by the cpu.h include file
for the cpu.
When no cpu specific versions of the AROS_L[HCPD]
macros are defined, default versions are defined in aros/libcall.h that
will use the AROS_GET_LIBBASE and AROS_SET_LIBBASE macros for
passing the library base to the functions of a library.
Other solutions
- Use relbase for passing libbase: in the description of the base pointer for relative addressing
different solutions are provided. These could all also be used for
libbase passing. They could also be used even another solution would be
used
- Use %eax register; two different approaches have been tried:
- A
first approach is to add a gcc attribute to the function for
putting the first argument into a register and then passing the libbase
as the first argument (the gcc attribute is __attribute((regparm(1)) ).
The big disadvantage is that now the libbase is the first argument.
This means that in warnings and errors the first normal parameter is
reported as the second parameter and so on. This is very confusing for
the programmer and that is why a better way was sought.
- A
second approach was to try to implement the AROS_LH macros fully in
inline asm code that would push the arguments on the stack and call the
function. This approach seemed to get very complex as now the rules for
sizes of arguments have to be implemented in the macro itself. This approach was not further developed when work with the %ebx was started.