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)

Reply via email to