I would like to call an assembly function from C. It is part of a basic example for calling conventions.
The function is a basic:
int mult(int A, int B){
return A*B
}
According to the Procedure Call Standard for the
ARM® Architecture the parameters A
and B
should be in registers r0
and r1
respectively for the function call. The return value should be in r0
.
Essentially then I would expect the function to be:
EXPORT mult
mult MULT r0, r0, r1
BX lr
With GCC 7.2.1 (none) -O1 -mcpu=cortex-m4 -mabi=aapcs, I get the following: (using Compiler Explorer)
mult:
mul r0, r1, r0
bx lr
Which is what I expected. However. If I disable optimizations (-O0) I get the following nonsense:
mult:
push {r7}
sub sp, sp, #12
add r7, sp, #0
str r0, [r7, #4]
str r1, [r7]
ldr r3, [r7, #4]
ldr r2, [r7]
mul r3, r2, r3
mov r0, r3
adds r7, r7, #12
mov sp, r7
pop {r7}
bx lr
Which means GCC is using r7
as a frame pointer I think and passing all of the parameters and return values via the stack. Which is not according to the AAPCS.
Is this a bug with Compiler Explorer, GCC or have I missed something in the AAPCS? Why would -O0 have a fundamentally different calling convention than specified in the AAPCS document?