Calling Conventions for the Compiler
The following documentation discusses the calling conventions for the compiler for the NEC VR4300 family of processors.
The compiler passes arguments to a function using a combination of integer general registers, floating-point registers, and the stack. The number, type, and relative position of arguments in the calling functions argument list define the combination of registers and memory used. The general registers $4..$7 and the floating-point registers $f12 and $f13 pass the first few arguments.
If the function being called returns a structure or union, the calling function passes the address of an area large enough to hold the structure to the function in $4. The function being called copies the returned structure into this area before returning. The address in $4 becomes the first argument to the function for the purpose of argument register allocation. All user arguments are then shifted down by one.
The compiler always allocates space on the stack for all arguments even when some or all of the arguments to a function are passed in registers. This stack space is a large enough structure to contain all the arguments. After promotion and structure return pointer insertion, the arguments are aligned according to normal structure rules. Locations used for arguments within the stack frame are referred to as the home locations.
Whenever possible, arguments declared in variable argument lists, as with those defined using a va_list declaration, are passed in the integer registers, even when they are floating-point numbers.
If the first argument is an integer, remaining arguments are passed in the integer registers.
The compiler passes structures and unions as if they were very wide integers with their size rounded up to an integral number of words. The fill bits necessary for rounding up are undefined. A structure can be split so that a portion is passed in registers and the remainder passed on the stack. In this case, the first words are passed in $4, $5, $6, and $7 as needed, with additional words passed on the stack.
The rules for assigning which arguments go into registers and which arguments must be passed on the stack can be explained by considering the list of arguments itself as a structure, aligned according to normal structure rules. Mapping of this structure into the combination of registers and stack is as follows: up to two leading floating-point (but not va_list) arguments can be passed in $f12 and $f13; everything else with a structure offset greater than or equal to 32 is passed on the stack. The remainder of the arguments are passed in $4..$7 based on their structure offset. Any holes left in the structure for alignment are unused, whether in registers or on the stack.
A function can return no value, an integral or pointer value, a floating-point value (single or double precision), or a structure; unions are treated the same as structures.
A function that returns no value puts no particular value in any register.
A function that returns an integral or pointer value places its result in register $2.
A function that returns a floating-point value places its result in floating-point register $f0.
The caller to a function that returns a structure or a union passes the address of an area large enough to hold the structure in register $4. The function returns a pointer to the returned structure in register $2.
General Purpose (Integer)
Register
|
Usage |
Constant zero: |
$0 |
Volatile: |
$1-$15,
$24, $25 |
Saved: |
$16-$23,
$30 |
Parameters: |
$4-$7 |
Kernel Reserved: |
$26, $27
|
Global pointer: |
$28 |
Stack pointer: |
$29 |
Frame pointer: |
$30 |
Return address: |
$31 |
Floating Point Register
|
Usage |
Volatile: |
$f0-$f11,
$f14-$f19 |
Parameter: |
$f12, $f13
|
Saved: |
$f20-$f31
|
Note:
Do not depend on this order. Instead, use GCCs asm(
) extension and
allow the compiler to schedule registers.