EDIT: I am fully aware that the function asmCopy might be not functionnal, my question is more about the behaviour of gcc regarding parameters passing in registers.
I'm working on STM32H7 using STM32CubeIDE whose builder is arm-none-eabi-gcc
The optimisation level is -Os
I see the following behaviour that I cannot explain. I took screen capture to get in parallel asm and C code.
My C code is calling 3 functions. The first and the third one have exactly the same parameters.
The second one takes no parameters. here is its code:
static void Reset_Cycle_Counter(void)
{
volatile unsigned long *DWT_CYCCNT = (unsigned long *)0xE0001004;
volatile unsigned long *DWT_CONTROL = (uint32_t *)0xE0001000;
// Reset cycle counter
*DWT_CONTROL = *DWT_CONTROL & ~0x00000001 ;
*DWT_CYCCNT = 0;
*DWT_CONTROL = *DWT_CONTROL | 1 ;
}
The third function is particular: I am trying to write some assembly code (that may very well be wrong right now).
static void __attribute__((noinline)) asmCopy(void *dst, void *src, uint32_t bytes)
{
while (bytes--)
{
asm("ldrb r12,[r1], #1"); // src param is stored in r1, r12 can be modified without being restored after
asm("strb r12,[r0], #1"); // dst paramis stored in r0
}
}
Before the first function call (to memcpy), r0, r1 and r2 are loaded with the right values.
Then before call to the third function, as you can see below the parameters in r1 and r2 are wrong (qspi_addr should be 0x90000000).
My understanding of AAPCS (procedure call standard on ARM) is that before calling a subroutine, the registers r0 to r3 should be loaded with the parameters of the functions (if any). And the subroutine does not need to preserve or restore these registers. It is then normal that the second function modifies r1 and r2. So I would expect the compiler to update r0, r1 and r2 before the third call.
If I change the optimisation code to -O0, I indeed get this expected behaviour.
What do you think ?