https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94743
Bug ID: 94743 Summary: IRQ handler implementation wrong when using __attribute__ ((interrupt("IRQ"))) Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: clyon at gcc dot gnu.org Target Milestone: --- Hi, As described in https://bugs.linaro.org/show_bug.cgi?id=5614: IRQ implementation when using __attribute__ ((interrupt("IRQ"))) by GCC does not save/restore NEON scratch registers when using -mfloat-abi=hard -mfpu=neon-fp16. But if the handler calls a function that uses Neon scratch registers, this will corrupt the values seen by the program when the IRQ handler completes. An easy example uses memcpy in the handler: === irq_test.c === typedef struct { int data[32]; } dummy_t ; extern void foo(dummy_t d); __attribute__ ((interrupt("IRQ"))) void IRQ_HDLR_Test(void) { dummy_t d; d.data[3] = 3; foo(d); } === Compile with arm-none-eabi-gcc -mcpu=cortex-a9 -mtune=cortex-a9 -marm -mfloat-abi=hard -mfpu=neon-fp16 -Ofast irq_test.c The generated code looks like: 21 IRQ_HDLR_Test: 22 @ Interrupt Service Routine. 23 @ args = 0, pretend = 0, frame = 128 24 @ frame_needed = 0, uses_anonymous_args = 0 25 0000 04E04EE2 sub lr, lr, #4 26 0004 0F502DE9 push {r0, r1, r2, r3, ip, lr} 27 0008 F0D04DE2 sub sp, sp, #240 28 000c 0330A0E3 mov r3, #3 29 0010 80108DE2 add r1, sp, #128 30 0014 7020A0E3 mov r2, #112 31 0018 0D00A0E1 mov r0, sp 32 001c 7C308DE5 str r3, [sp, #124] 33 0020 FEFFFFEB bl memcpy 34 0024 70308DE2 add r3, sp, #112 35 0028 0F0093E8 ldm r3, {r0, r1, r2, r3} 36 002c FEFFFFEB bl foo 37 0030 F0D08DE2 add sp, sp, #240 38 @ sp needed 39 0034 0F90FDE8 ldmfd sp!, {r0, r1, r2, r3, ip, pc}^ In this case, the newlib version of memcpy uses NEON code and will clobber NEON registers. To be safe, the IRQ handler should push {d0-d7, d16-d31} This can be costly in terms of CPU cycles for an IRQ handler, so maybe we could think of adding another attribute but it would be hard for the end-user to guess that he might use Neon registers in an implicit way (like here where the compiler calls memcpy)