AUPCS(7)

NAME
aupcs - ARM Unix procedure call standard

SYNOPSIS
#include <arm/frame.h>
typedef unsigned Instruction;
typedef int Register;
typedef Instruction *RSMPtr;
struct frame {
	struct frame	*fp;	/* Save frame pointer */
	void	*sp;	/* Saved stack pointer */
	Instruction	*lr;	/* Return link value */
};
typedef union {
	RSMPtr	*fprsm;	/* Actually twelve bytes beyond it */
	struct frame	*fpfp;	/* Frame is fpfp[-1] */
}   FramePtr;
struct arm_pc {
	unsigned	mode: 2;	/* Processor mode */
	unsigned	pc: 24;		/* Program counter (/4) */
	unsigned	F: 1;		/* FIQ disable */
	unsigned	I: 1;		/* IRQ disable */
	unsigned	V: 1;		/* overflow */
	unsigned	C: 1;		/* carry */
	unsigned	Z: 1;		/* zero */
	unsigned	N: 1;		/* negative */
};
#define FR_MODE_BITS 0xFC000003
#define FR_USER_MODE	0
#define FR_FIQ_MODE	1
#define FR_IRQ_MODE	2
#define FR_SVC_MODE	3
#define FR_rsm_instructions(maskp) 	((RSMPtr)( ((unsigned)(maskp) & ~FR_MODE_BITS) - 12 ) )
#define FR_savedreg(mask) ((mask) & 0x2FF)
#define FR_RSM_INSTRUCTION APCS_RSM_INSTRUCTION
#define FR_FPS_INSTRUCTION APCS_FPS_INSTRUCTION
#define FR_savedfpreg(mask) (((mask) & 0x3000) >> 12)

DESCRIPTION
The ARM instruction set does not include direct support for the procedure calls of a stack based language. Rather a convention is defined at a higher level which allows both inter-language procedure calls and interfaces to standard libraries. The convention governs what must happen within a procedure which calls other procedures which are imported from libraries or other languages. A given compiled or interpreted language is free to ignore the convention wherever it can guarantee not to execute code from other languages or from standard libraries.

In addition UNIX itself imposes constraints on the code which can be executed. The UNIX signal handling is asynchronous (as far as a process is concerned) and by default occurs on the same stack as normal execution. The procedure call standard does not address this problem, except that it can be implemented in such a way as to guarantee that no data below (numerically) the stack pointer is ever used - a language implementation which accepts signals on the normal execution stack must also guarantee never to use data below the stack pointer.

In addition UNIX signals may mean that a procedure executes at an arbitrary time - thus any procedure which runs with signals enabled and with signal handlers in place should ensure that it obeys the procedure call standard even though it does not intentionally call any other procedures.

The procedure call standard defines the appearance of the stack at the moment when another procedure is called. It also defines conventions for passing arguments and returning a result from a procedure.

EXTERNAL PROCEDURE ENTRY
At the moment when control arrives in an externally callable procedure the following must be true:

o   Arguments 1 to 4 are in registers 0 to 3.

o   Arguments 5+ are at address sp-4*(n-5) (for argument n) where “sp” - the stack pointer - is held in register 13.

o   The frame pointer - fp - register 11 - holds the address of a valid frame (as described below.)

o   The link register - lr - register 14 - holds the program counter and program status word required in the pc (register 15 - the program counter) when control returns to the caller.

It is manifestly obvious that the program counter must contain the entry pointer address of the procedure. What is less obvious is that the register save instruction which is pointed to by the top element of the stack frame must not be altered during the whole of the extent of the invocation of this particular instance of the procedure - see the description of the stack frame below.

Notice that floating point registers are passed in ARM machine registers or on the stack - not in the floating point registers.

EXTERNAL PROCEDURE EXIT
When the program counter is reset to the value passed in the link register to effect return from an external procedure it must be the case that the values in all registers except 0-3, 10, 12 and 14 (the link register itself) hold the values which they held on the corresponding entry to the procedure. Similarly the floating point registers 4-7 are expected to be unchanged - the first four may be changed.

The status of register 10 is unclear - this register is the stack link register, which is never actually used in the current UNIX implementation. It is likely that this register will be used in the future however, so it should not be modified.

If the external routine returns a word (or less) sized non floating point result this is expected to be in register 0. If it returns a floating point result this is expected to be in floating pointer register 0. Any other result is stored at the address passed in the first argument (register 0) - the caller is responsible for making sure that there is sufficient space for the result. Thus C functions which return a structure result of size greater than one word (four bytes) are actually implemented with an extra argument.

THE STACK FRAME
On entry to an external procedure the frame pointer must point to a valid stack frame. The typedefs included in the synopsis along with the following description may be used to access this data - the function __set_sigcontext(3) may be used to obtain the value of the frame pointer. The frame is laid out as follows (entities further down the page are at lower address.)

fp --> |  | save mask pointer |  | [fp]
 |  | return link pointer |  | [fp,#-4]
 |  | return sp value |  | [fp,#-8]
 |  | return fp value |  | [fp,#-12]
 | [ | saved r9 | ]
 | [ | saved r8 | ]
 | [ | saved r7 | ]
 | [ | saved r6 | ]
 | [ | saved r5 | ]
 | [ | saved r4 | ]
 | [ | saved f7 | ] | three words
 | [ | saved f6 | ] | three words
 | [ | saved f5 | ] | three words
 | [ | saved f4 | ] | three words

The above structures may be used by casting the frame pointer value as (struct frame *) and referencing fp[-1] or by casting it as (RSMPtr *) and examining *fp.

o   The return fp value is either 0 (meaning that there are no more stack frames) or a pointer to the save mask pointer of another stack frame.

o   The save mask pointer, when the bits corresponding to the program status word (0xfc000003) have been masked out, points 12 bytes beyond a stmfd instruction which corresponds to the cpu registers in the stack frame. The processor mode bits of the save mask pointer (0x3) are set only on the stack frame generated by the trampoline code - so a signal handler can be detected.

o   The items enclosed in [] are optional - they must be there only if the procedure alters any of the relevant registers during its execution.

The register save instruction indicated by the save mask pointer corresponds to an instruction of the form:

	stmfd sp!, {registers, fp, ip, lr, pc}

Although the registers r4-r9 are optional the remainder of the instruction must be exactly as specified. The instruction corresponds to the value 0xE92DD800, if none of r4-r9 are saved, so (instruction & ~0x3f0) must equal this value. This must be true for the whole of the time that this stack frame is in the list of stack frames indicated by the frame pointer.

Immediately after the stmfd instruction those floating point registers which are to be changed should be saved, in the order f7, f6, f5 then f4. This must be done using stfe instructions based on the sp value - the instruction has the value 0xED6D4103 when the bits 0x3000 have been cleared.

The expected procedure entry is thus:

	mov	ip, sp
	stmfd	sp!, {registers, fp, ip, lr, pc}
	stfe	f7, [sp, #-12]!
	stfe	f6, [sp, #-12]!
	stfe	f5, [sp, #-12]!
	stfe	f4, [sp, #-12]!
	sub	fp, ip, #4

Of couse this is only what the register save mask pointer should point to - any instructions may be used to set up the stack frame so long as it valid at the relevant times.

On examination of the save instruction and the optional stfe instructions following it it is possible to “unwind” the stack restoring the correct values in all the registers which must be defined on procedure exit. The procedure return can be accomplished using:

	ldmea	fp, {registers, fp, sp, pc}^

The floating point registers must be restored before this using ldfe instructions based on the fp.

REGISTER BINDINGS

The same basic procedure call standard is used on all ARM based computers, however the bindings of functionality to registers can vary - in particular different registers are used for ip/sl/sp/fp. The bindings described above are those for the AUPCS-U standard. The header file <arm/apcsreg.h> describes these bindings and is included by both <arm/frame.h> and <arm/apcs.h>, the latter file is suitable for use in assembler modules and is used indirectly when the assembler support header <arm/as_support.h> is used.

SEE ALSO
afp(7), __set_sigcontext(3), setjmp(3)
VL86C010 Risc Family Data Manual
(VLSI Technology Inc. Application Specific Logic Products Division, 8375 South River Parkway, Tempe, AZ 85284. USA [602-752-8574])

AUTHORS
Too many people have contributed to this standard for it to be reasonable to list them all.