Linaro GCC的ARM GIC中断处理程序

时间:2016-08-31 09:49:42

标签: gcc arm interrupt-handling linaro

使用Linaro gcc编译ARM GIC的中断处理程序时会出现奇怪的结果。

代码是:

void foo1(void) __attribute__(( interrupt("IRQ") ));
void foo2(void) __attribute__(( interrupt("IRQ") ));

void foo1() {
  dummy();
  return;
}

void foo2() {
  return;
}

结果汇编代码:

foo1:
        sub     lr, lr, #4
        push    {r0, r1, r2, r3, r4, fp, ip, lr}
        add     fp, sp, #28
        bl      dummy
        nop
        sub     sp, fp, #28
        pop     {r0, r1, r2, r3, r4, fp, ip, pc}^

foo2:
        str     fp, [sp, #-4]!
        add     fp, sp, #0
        nop
        sub     sp, fp, #0
        ldr     fp, [sp], #4
        subs    pc, lr, #4

因此,如果有任何子程序,如果在处理程序代码和PUSH {lr} / POP {pc}中没有子程序,则SUBS用于从中断返回。

问题是SUBS自动从处理器IRQ模式切换到SVC模式,但POP {pc}没有。因此,应该使用SUBS,对于foo1,需要添加外部SUBS指令以从IRQ切换到SVC模式。

是功能还是错误?

有没有办法强制编译器每次都使用SUBS?

1 个答案:

答案 0 :(得分:1)

我找不到参考资料,但是IIRC,pop {}相当于LDM sp ..

对于LDM,ARM ARM(A4.1.22 LDM(3))声明:

  

^对于加载PC的LDM指令,这表示   当前模式的SPSR将复制到CPSR。

这就是生成的pop指令从SPSR恢复CPSR的原因,因此返回先前的CPU模式。