IAR Calling Convention

IAR provides two calling conventions — one old, which is used in version 1.x of the compiler, and one new, which is the default. For both calling conventions, the registers available for passing parameters are: R16–R23. Parameters are allocated to registers using a first-fit algorithm, using parameter alignment requirements according to Table 2-2.

Table 1. Registers Used for Passing Parameters
Parameters Alignment Passed in registers
8-bit values 1 R16, R17, R18, R19, R20, R21, R22, R23
16-bit values 2 R17:R16, R19:R18, R21:R20, R23:R22
24-bit values 4 R18:R17:R16, R22:R21:R20
32-bit values 4 R19:R18:R17:R16, R23:R22:R21:R20
64-bit values 8 R23:R22:R21:R20:R19:R18:R17:R16

In the default-calling convention, as many parameters as possible are passed in registers. The remaining parameters are passed on the stack. The compiler may change the order of the parameters in order to achieve the most efficient register usage. The algorithm for assigning parameters to registers is quite complex in the default-calling convention. Below are three examples of combinations of register assignments in the default-calling convention.

Example 1:

void function(char __far * a, int b, char c, int d) 

This would result in a being allocated to R18:R17:R16, b to R21:R20 (alignment requirement prevents R20:R19), c to R19 (first fit), and d to R23:R22 (first fit).

Example 2:

void function(char a, int b, long c, char d)

This would result in a being allocated to R16 (first fit), b to R19:R18 (alignment), c toR23:R22:R21:R20 (first fit), and d to R17 (first fit).

Example 3:

void function(char a, char __far * b, int c, int d)

This would result in a being allocated to R16, b to R22:R21:R20, c to R19:R18, and d to the stack.

In the old calling convention, the two left-most parameters are passed in registers if they are scalar and up to 32 bits in size. Table 2-3 shows some of the possible combinations:

Table 2. Register Assignment Using the Old Calling Convention
Parameters Parameter 1 Parameter 2
f(b1,b2,…) R16 R20
f(b1,w2,…) R16 R20, R21
f(w1,l1,…) R16, R17 R20, R21, R22, R23
f(l1,b2,…) R16, R17, R18, R19 R20
f(l1,l2,…) R16, R17, R18, R19 R20, R21, R22, R23
Note: Where b denotes an 8-bit data type, w denotes a 16-bit data type, and l denotes a 32-bit data type. If the first and/or second parameter is a 3-byte pointer, it will be passed in R16–R18 or R20–R22, respectively.

In the old calling convention, the registers available for returning values are R16-R19. The default-calling convention can use the registers R16-R23 for returning values.

Table 3. Registers Used for Returning Values
Return values Passed in registers
8-bit values R16
16-bit values R17:R16
24-bit values R18:R17:R16
32-bit values R19:R18:R17:R16
64-bit values R23:R22:R21:R20:R19:R18:R17:R16