ARM Calling Standard

A calling standard or convention is a prefined way of using the registers and making subroutine calls. Following the convention allows your code to work with code produced by others and by the tools.

Each processor family has its own calling standard.

../_images/ARM_Calling_Convention.png

Table showing how registers are used in the Arm Calling Convention.

Argument registers

  • R0 - R3
  • Used to pass arguments to subroutines
  • Subroutines can use them as scratch registers
  • If they have important data before the call, the calling routine must save the data before the call.
  • Caller saved

Register Variables

  • R4 - R8, and R9 - R10
  • Callee saved
  • Subroutine must preserve their data
  • Return intact after the call

Stack Pointer

  • R13 (SP)
  • Typically pointer to full descending stack
  • Typically auto indexed
  • STMFD sp!, {regs, lr}
  • LDMFD sp!, {regs, pc}

Static Base

  • R9
  • Offset for position independent code
  • Used for re-entrant code ROM code, and shared libraries

Frame Pointer

  • R11
  • The frame pointer register, which is used to access automatic variables in the stack frame.

Argument Passing

  • Everything is organized as a list of words
  • The first four words are passed in R0-R3
  • The rest are pushed onto the stack in reverse order.

Return Result

  • Return is in R0 or R0-R4 depending on the size of the return value. Or pointer to memory in R0.
  • Simple results such as ints, are passed back in R0.
  • More complex values are written to memory at the address passed in through R0 as the first argument. The caller allocates the memory before the call.

Comments

  • Function calls with 4 or less parameters are more efficient because all the parameters are in registers.
  • Note that in C++ method calls add the ‘this’ pointer as the first parameter.

Possible optimizations

  • When functions require a lot of parameters pass a pointer to a struct with the parameters instead of passing the paramters directly.
  • Include the caller and the callee in the same C file so the compiler can improve the call depending on the the callee’s register use.
  • Use inline functions