Everything
9.1.2 Setting and referencing arguments and return values

(1)

Passing arguments

Arguments can be passed via registers or the stack. The manner in which each argument is passed is determined by the procedure below.

(a)

A memory image to which each argument is assigned is created on the stack

<1>

Scalar values that are 2 bytes or smaller are promoted to 4-byte integers before being stored.

<2>

Each argument is essentially aligned on a 4-byte boundary.

<3>

If a return value is a structure or union, then the start of the memory image is set to the address at which to write the return-value data.

<4>

If the function prototype is unknown, then each scalar-type argument is stored as follows.

-

1-byte scalar integer ->Promoted to 4-byte integer, then stored

-

2-byte scalar integer ->Promoted to 4-byte integer, then stored

-

4-byte scalar integer ->Stored as-is

-

8-byte scalar integer ->Stored as-is

-

4-byte scalar floating-point number ->Promoted to 8-byte floating-point number, then stored

-

8-byte scalar floating-point number ->Stored as-is

Example 1.

Function prototype : f(ST1, ST2, ST16)
Example where STx represents a structure with a size of x[byte]

 

In the case of a structure or union whose size is not a multiple of 4, it is possible to add padding between the parameters. The contents of the padded area are undefined.

Example 2.

Function prototype : f(char, long, ...)
Example of accepting variable number of actual arguments

 

The "area of variable number of arguments from here" consumes memory for the number of actual arguments that are set.

Example 3.

Function prototype : ST4 f(char, char, char, char)

 

An address of the location to which to write the ST4 return value is passed through rtn.

(b)

The first 4 words (16 bytes) of the created memory image are passed via registers r6 to r9, and the portion that does not fit is passed on the stack

<1>

If the arguments passed via the registers, it's loaded by the word units to each register (r6-r9).
The byte units and the half-word units aren't loaded.

<2>

The arguments passed on the stack are set in the stack frame of the calling function.

<3>

Arguments passed on the stack are stored on the stack in order from right to left in the memory image. Thus the word data at the 16-byte offset location of the memory image is placed in the location closest to 0.

Remark

See "9.1.4 Stack frame" about how data is placed on the stack.

Example 1.

Function prototype : f(ST1, ST2, ST16)
Example where STx represents a structure with a size of x[byte]

 

Even if only part of a structure (in this case, ST16) can fit in the registers, that part is still passed via the registers.

Example 2.

Function prototype : f(char, long, ...)
Example of accepting variable number of actual arguments

 

Even if the number of arguments is variable, the arguments are passed via registers where this is possible.

Example 3.

Function prototype : ST4 f(char, char, char, char)

 

Even if only passing four arguments of type char, the fourth argument may be passed on the stack, depending on the return value.

(2)

How return values are passed

There are three ways to pass return values, as follows.

(a)

If value is scalar type 4 bytes or smaller

The return value is returned to the caller via r10.

If the value is a scalar type less than 4 bytes in size, data promoted to 4 bytes is set in r10.

Zero promotion is performed on unsigned return values, and signed promotion on signed return values.

(b)

If value is scalar type 8 bytes

The return value is returned to the caller via r10 and r11.

The lower 32 bits are set in r10, and the upper 32 bits in r11.

(c)

If the value is a structure or union

If the return value is a structure or union, then when the caller calls the function, it sets the address to which to write the return value in the argument register r6. The caller sets the return value in the address location indicated by parameter register r6, and returns to the calling function.

Upon return, r6 and r10 are undefined (same as Caller-Save registers) to the calling function.

All structures and unions are turned by the same method, regardless of size. The actual data of the structure or union is not returned in the register.