[comp.sys.amiga.tech] Parameters to Librhcr

jvkelley@watcgl.waterloo.edu (Jeff Kelley) (08/10/88)

[ To reread the original article, use ^P in rn (is this hypertext?) ]

>Can anyone confirm/deny this hunch for me, or better yet tell me exactly 
>how parameters are handled?
>

Exec does not concern itself with the parameters, the mechanism by which
they are passed to the library is purely a convention between the 
assembler routine that you link with and the .library.  Traditionally,
the assembler routine takes the parameters off the stack (where they
were put when you called it from your C code) and puts them into the
registers the .library code is expecting them in (at the back of the
Exec RKM you can find the specifications for 1.1 library functions).
Another convention is that pointers should be passed in address registers,
everything else in data registers, but this isn't always followed (e.g.
dos.library).  Both these conventions were adopted, I presume, to optimize
the speed potential of the library code.

You can, however, define your own convention for passing arguments to your
.library.  If you are writing the .library in C, it may be convenient to decree
that all arguments will be passed on the stack.  Your assembler routine would
then only need to 'JMP' (not 'JSR') to the appropriate .library
vector.  That library vector could then 'JMP' directly to your .library
function written in C.  This avoids the wastage of time (and space) needlessly
taking parameters from the stack and putting them in registers only to push
the register values back on the stack again.

It would be nice if the Lattice C '#pragma libcall' feature would support this
method of passing parameters, as it currently only supports the pass-in-register
model (which is, admittedly, adequate for the system libraries).

--
Jeff Kelley    Graphics Lab, Dept. of Computer Science, University of Waterloo
   uunet!watmath!watcgl!jvkelley  	tel:   (519) 578-4514
"Remember, this is not a competition, only an exhibition. Please, no wagering."
	- David Letterman

ditto@cbmvax.UUCP (Michael "Ford" Ditto) (08/10/88)

In article <3716@hcr.UUCP> edwin@hcr.UUCP (Edwin Hoogerbeets) writes:
>I am working on interfacing C routines to Amiga shared librhcr, and I
>need some help. 

 [ describes function's paramters in C calling conventions ]

>However, if I have the routine _foo in my library, in which registers
>can I expect the Exec to put the parameters to _foo when calling it in
>the library? The reason I want to know this is so that I may push these
>values on to the stack again to call a C routine.

Exec doesn't do anything at all to the paramters to a library function.
In fact, Exec never even gets control during a library call: the calling
program just does a "jsr offset(basereg)" directly to the code (offset
defines which function in the library to call, basereg is a register
that points to the base of the library).

In other words, you, the designer of the library, determine the calling
conventions of each routine in the library.  If you want to just use
C conventions all the way, go ahead, but you will still need a "stub"
interface so that your compiler can jsr to _functionname which will
do something like "move yourlibbase,basereg; jmp offset(basereg)".

>I have looked in the RKM's and found nothing specific about that, but
>from observation it seems that pointers are in the a[0|1] registers and 
>values go in the d[0|1] registers. What happens if there are more than 4
>parameters?

This is a sort of "convention" which makes it easier to remember the
calling sequences of library function... if your function will only be
called from C, and you will be providing the "stubs" for other programmers
to use, then it really doesn't matter what conventions you choose.

-- 
					-=] Ford [=-

	.		.		(In Real Life: Mike Ditto)
.	    :	       ,		ford@kenobi.cts.com
This space under construction,		...!ucsd!elgar!ford
pardon our dust.			ditto@cbmvax.commodore.com

carolyn@cbmvax.UUCP (Carolyn Scheppner CATS) (08/11/88)

In article <3716@hcr.UUCP> edwin@hcr.UUCP (Edwin Hoogerbeets) writes:
>
>I am working on interfacing C routines to Amiga shared librhcr, and I
>need some help. 
>
>A certain function is declared like this in C:
>
>LONG foo (alpha, bravo, charlie, delta)
>LONG alpha, charlie;
>struct boing *bravo, *delta;
>
>where 'struct boing' is some random structure unimportant to this
>question. This function is actually an assembler routine in a library
>that will take parameters as this declaration suggests.
>
>However, if I have the routine _foo in my library, in which registers
>can I expect the Exec to put the parameters to _foo when calling it in
>the library? The reason I want to know this is so that I may push these
>values on to the stack again to call a C routine.
>
>I have looked in the RKM's and found nothing specific about that, but
>from observation it seems that pointers are in the a[0|1] registers and 
>values go in the d[0|1] registers. What happens if there are more than 4
>parameters?

1. A0|1 and D0|1 are used alot for parameter passing because these
   registers are allowed to be trashed when you call a system routine.
   Programs can count on D2-D7 and A2-A7 being preserved when they call
   a system routine.  Therefore, if any system routine requires args
   in any of these registers, the interface code in Amiga.lib must
   save these registers, pass the args in them, then restore them
   before returning.

2. It's kind of weird, but here's how it works if you have a C function
   calling a C routine in a run-time shared library:

   (hypothetical graphics.library BltOverEasy call)

   C program does OpenLibrary of graphics.library and stores Base address
      in globally visible GfxBase variable.

   C program calls BltOverEasy(lots,of,weird,things,and,more) which
      causes the args to be pushed on the stack as longs

   Assembler _BltOverEasy stub in Amiga.lib saves A6 and any untrashable
      registers needed for passing args to system BltOverEasy code,
      loads up the appropriate (individual to each function) registers
      with the arguments from the stack, puts GfxBase in A6, does
      jsr _LVOBltOverEasy(a6) (_LVOBltOverEasy being a negative hex
      word constant defined in Amiga.lib, and being the negative offset
      of the BltOverEasy entry in the GfxBase library jump table - note
      that these jump tables exist in memory preceding the library Base
      structure).

   The jsr hits the jump table which does (generally) a JMP to the
      rom (or ram) location of the actual library function code,
      at least the beginning of which is in assembler.
   
   Then, if the bulk of the library function happens to be in C, the
      assembler portion takes the args OUT of the registers, pushes
      them back on the stack, and jsr's to the C part of the
      library function.  Then fixes the stack pointer when it returns.

   When all is done, the library function does an RTS with the result
      in d0.

   This returns to the stub code in Amiga.lib, which restores all
      untrashable registers, leaving the result in d0, and does an
      RTS which returns you to the C program.

Note that this may seem like a lot of swapping around, but since the
library calls expect their parameters in registers, it means that
an assembler program calling a system function can just put the
library base in A6, the args in registers, and jsr _LVOBltOverEasy.


The current Amiga compilers provide methods for bypassing the Amiga.lib
step, instead generating inline code to put your args directly in the
appropriate registers and call the _LVO.  I believe Manx does this
via hard-coded interface code of their own, while Lattice does it
via pragma files which are similar to include files but define which
register should receive each argument.

   
NOTE - See the couple of pages of text right before the library
       autodocs in the RKM (any version) for an example of the
       type of stub code in Amiga.lib.  It's enough info to write
       your own mylib.lib linker lib for calling your own run-time
       library functions from C. 

-- 
==========================================================================
  Carolyn Scheppner -- CATS  Commodore Amiga Technical Support
  PHONE 215-431-9180   UUCP  ...{uunet,allegra,rutgers}!cbmvax!carolyn 

 Pad with zeros for a light, airy program.
==========================================================================