使用 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
因此,如果处理程序代码中没有子例程,则使用 SUBS 从中断返回,如果有任何子例程,则使用 PUSH{lr}/POP{pc}。
问题是 SUBS 会自动从处理器 IRQ 模式切换到 SVC 模式,但 POP{pc} 不会。因此,应该使用 SUBS,对于 foo1,需要添加外部 SUBS 指令才能从 IRQ 切换到 SVC 模式。
它是功能还是错误?
有什么方法可以强制编译器每次都使用 SUBS 吗?