SLAA534A June 2013 – June 2020
For MSP430 and MSP430X, arguments whose size is greater than 32 bits and up to 64 bits use register quads. For example, R8::R11 is the notation used in this manual for a register quad consisting of the registers R8, R9, R10, and R11 in sequence. The lowest-numbered register holds the LSW. Register quads must be aligned. Therefore, only R8::R11 and R12::R15 are valid register quads. Register quads require special handling.
If there are enough argument registers remaining (all four) to pass the 64-bit value, all four will be used. Otherwise, the 64-bit value will be passed entirely on the stack. This may leave unused argument registers (in other words, a "hole"). The calling convention will try to back-fill the hole with subsequent arguments, but only if they fit entirely in registers (see example 2 that follows). That is, after any argument has been placed on the stack, no argument will be placed in a "split pair", as in Section 3.4.3.
MSP430 and MSP430X example 1:
C source code
void func1(long long a0, long long a1);
long long a0, a1;
func2(void)
{
func1(a0, a1);
}
Compiled in any model:
SUB.W #8,SP
MOV.W &a0+0,R12
MOV.W &a0+2,R13
MOV.W &a0+4,R14
MOV.W &a0+6,R15
MOV.W &a1+0,0(SP)
MOV.W &a1+2,2(SP)
MOV.W &a1+4,4(SP)
MOV.W &a1+6,6(SP)
MSP430 and MSP430X example 2:
This example shows a 64-bit argument that doesn't fit entirely in registers, so it is passed entirely on the stack, leaving unused registers which are then back-filled with arguments a2, a3, and a4.
C source code
void func1(int a0, long long a1, int a2, int a3, int a4);
int a0, a2, a3, a4;
long long a1;
func2(void)
{
func1(a0, a1, a2, a3, a4);
}
Compiled in any model:
SUB.W #8,SP
MOV.W &a0,R12
MOV.W &a1+0,0(SP)
MOV.W &a1+2,2(SP)
MOV.W &a1+4,4(SP)
MOV.W &a1+6,6(SP)
MOV.W &a2,R13
MOV.W &a3,R14
MOV.W &a4,R15
MSP430 and MSP430X example 3:
This example shows a 64-bit argument that doesn't fit entirely in registers, so it is passed entirely on the stack, leaving unused registers which are then back-filled. However, the last argument (a 32-bit type) does not fit entirely in registers, so it is passed entirely on the stack. This type would have been split and passed partially in R15 and partially on the stack if the 64-bit argument weren't already on the stack.
C source code
void func1(int a0, long long a1, long a2, long a3);
int a0;
long long a1;
long a2, a3;
func2(void)
{
func1(a0, a1, a2, a3);
}
Compiled in any model (note that R15 is unused):
SUB.W #12,SP
MOV.W &a0,R12
MOV.W &a1+0,0(SP)
MOV.W &a1+2,2(SP)
MOV.W &a1+4,4(SP)
MOV.W &a1+6,6(SP)
MOV.W &a2+0,R13
MOV.W &a2+2,R14
MOV.W &a3+0,8(SP)
MOV.W &a3+2,10(SP)
On MSP430 and MSP430X, holes and back-fill can only occur when register quads are used. If only singles and pairs are used, argument registers are used in order, there is no back-filling, and there are no holes.