This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi,
I'm using tiarmclang v3.2 and have a custom interrupt handler for C functions which is written in assembly. I can't use interrupt function attribute as this does not preserve FPU registers, which I need. I know how to do this but I don't understand how to ensure the stack is 8-byte aligned before executing the C ISR. From the tiarmclang manual interrupt attribute section:
> "The tiarmclang compiler will re-align the stack pointer to an 8-byte boundary on entry into a function marked with the interrupt attribute because the Arm Procedure Call Standard (AAPCS) requires this alignment for all public interfaces."
In that same section they demonstrate an example of the 8-byte stack alignment does:
> tiarmclang -mcpu=cortex-r4 -S interrupt_function_attr.c > cat interrupt_function_attr.s ... int2: .fnstart @ %bb.0: @ %entry push {r0, r1, r2, r3, r10, r11, r12, lr} add r11, sp, #20 bfc sp, #0, #3 bl do_something2 sub sp, r11, #20 pop {r0, r1, r2, r3, r10, r11, r12, lr} subs pc, lr, #4 ...
The problem is, the text explaining what's going on doesn't match the code:
> "When compiled with the -mcpu=cortex-r4 option, the compiler-generated assembly snippet shows general-purpose registers being preserved during the function’s entry and exit code, the re-alignment of the stack pointer via the “sub sp, sp, #8” and “bfc sp, #0, #3” instructions, and the addition of the “subs pc, lr, #4” instruction to effect the exception return."
(emphasis mine)
There is no `sub sp, sp, #8` instruction shown. Could someone clarify:
1. Why `r10` get's pushed to the stack when it's a) not being used, and b) the C Exception handler Calling Convention section only says `R0-R3, R-12, LR` need to be preserved? I'm guessing because the r1 reg is being used and we want to always push an even number of registers to the stack to maintain 8-byte alignment if we already have it?
2. How the add and bfc instructions are keeping the stack 8-byte aligned
3. How my general purpose interrupt handler code below can be modified to ensure the stack is aligned to 8 bytes before calling an ISR. This is inline assembly that I wrap around my ISRs in C instead of using the interrupt attribute. I already have the code to call the function and handle register stacking and exception return so I've omitted that.
push {r0, r1, r2, r3, r10, r11, r12, lr} vmrs ip, fpexc stmfd sp!, {ip} vmrs ip, fpscr stmfd sp!, {ip} vpush {d0-d7} <omitting code to call the function here, I have this already> <omitting code to handle register unstacking and exception return, I have this>
Thank you!
Hi Daniel,
I can respond to a part of your inquiry ...
You are correct that the documentation is not accurate on how the re-alignment of the stack pointer is being accomplished inside the interrupt function. I believe the documentation should be adjusted to read as follows:
the re-alignment of the stack pointer via a forced adjustment to the stack and a “bfc sp, #0, #3” instructions. In the example shown, the stack is adjusted prior to the "bfc sp,#0,#3" instruction by pushing an extra 2 registers (r10 and r11) onto the stack. In other cases, the compiler may use a "sub sp,sp,#8" instruction to force an adjustment to the stack prior to the "bfc sp,#0,#3" instruction.
Regarding question #3, I suspect you need to insert a "bfc sp,#0,#3" instruction (or a functionally equivalent code sequence) prior to the push of the fpexc instruction in your code.
Hope this helps.
Regards,
Todd Snider
TI Arm Clang Compiler Tools Team