I am developing an embedded C application for my Cortex M3 microcontroller using the GNU arm-none-eabi toolchain.
I have plan to adopt an assembly subroutine that the vendor implemented into my C application. I plan to make a new C function, then within that, write an inline assembly block using the extended inline assembly protocol. In this post, I plan to treat this assembly subroutine as a black box, and plan to ask this forum about how to structure the inputs and clobber list; this routine has no outputs.
The assembly subroutine expects r0, r1, and r2 to be pre-set prior to the call. Further, the subroutine uses registers r4, r5, r6, r7, r8, r9 as scratch registers to do its function. It writes to a range of memory on the device, specified by r0 and r1 which are the start and stop addresses, respectively.
So, I am checking if my assumptions are correct. My questions follow.
- My function that I think I should write, is this right?:
void my_asm_ported_func(int reg_r0, int reg_r1, int reg_r2 {
__asm__ __volatile__ (
"ldr r0, %0 \n\t",
"ldr r1, %1 \n\t",
"ldr r2, %2 \n\t",
"<vendor code...> ",
: /* no outputs */
: "r" (reg_r0), "r" (reg_r1), "r" (reg_r2) /* inputs */
: "r0", "r1", "r2", "r4", "r5", "r6",
"r7", "r8", "r9", "memory" /* clobbers */
);
}
Since this asm subroutine writes to a range of other memory on the device, is adding "memory" to the clobber list enough? Seems too simple.
Is there a more elegant way to feed in r0 - r2 from the input parameters in the surrounding C function? I understand from AAPCS that the registers r0-r3 are input parameters 1-4, so this seems redundant to feed r0-r2 inputs manually like I did in the input list. Should I somehow just have this be a pure assembly function in a separater .S file?
Thank you in advance.
I tried the above but with the basic inline assembly protocol with terrible results - it crashed. I did it that way because I thought the assembly block would naturally take r0-r2 via the function prologue, which it evidently did because it wrote the memory correctly, but crashed once my breakpoint at the beginning of the asm block was kicked off (my vs code extension doesn't have the step-by-step disassembly view, so it just runs it as a block box and it crashed). I haven't tried the extended yet, I have been doing a lot of reading into this so I just wanted to make sure my black box approach should work and I'm not missing anything too big.