ARM7中的中断返回地址和3级流水线问题
ARM7中的中断返回地址和3级流水线问题:
(1) ARM流水线
由ARM7-TDMI-S技术参考手册P2可知,ARM的流水线结构为:
取指----------------> 译码--------------------> 执行
ARM代码: PC PC- 4 PC - 8
0x1008 0x1004 0x1000
在此页,还注明,PC是指向被取指的指令,而不是正在执行的指令。(也就是说在此 PC值为0x1008 ?)
(2) 中断返回地址
在参考书上看到关于ARM异常响应。第一点:将下一条指令的地址存入相应的连接寄存器LR,以便程序在处理异常返回时能从正确的位置重新开始执行。若异常是从ARM状态进入,LR寄存器中保存的是下一条指令的地址(当前PC+4或PC+8,与异常类型有关)
问题:1
即使产生的中断,执行阶段的指令还是会被执行,流水线其它指令将会被放弃,而处理器将会从向量表的适当入口填充流水线。
要是这样的话,并且由人为的保存中断返回地址,应该是很有时间性的。或者说,所以有LR寄存器的出现,在清空流水线前,自动将下一条指令的地址保存到LR中,由(1)可以看出,就应该是PC - 4,即 0x1004。
但是参考第(2)部份,“若异常是从ARM状态进入,LR寄存器中保存的是下一条指令的地址(当前PC+4或PC+8,与异常类型有关)” 在此都说的是保存下一条指令的地址,直接地址应该是0X1004,算法也应该是当前PC - 4,为什么要加4(PC+4)?
问题:2
SUB LR,LR,#4 ;计算返回地址
在IRQ中断程序中,第一句话,都是这样。请问LR中的地址是什么,应该是由ARM core自动计算的吧。
问题:3
在很多参考资料上,都会有一个表,关于异常进入\退出。在这列出一项
以前状态
ARM R14_x Thumb R14_x
异常类型 返回指令
SWI MOVS PC, R14_svc PC+4 PC+2
FIQ SUBS PC, R14_fiq,#4 PC+4 PC+4
请问这里的以前状态是什么意思,在流水线里是什么了?
[解决办法]
1. pc=0x1008,因为要回去执行0x1004, 所以要-4
2. lr 是得理自动计算的。
3. 以前状态, 是指它是ARM状态,或是THUMB状态。
STMFD SP!, {R0-R3, R12, LR} ; 保存任务环境
这是按ATPCS来的。按ATPCS,子程序不保证这些寄存器在退出时仍为原来内容,
你的ISR如果要调用C写的子程序,就必须保护它们。
[解决办法]
2. lr 是处理器自动计算的。
[解决办法]
有些翻译可能会带来误解的,我不知道你那是什么书。
出现不同理解时,以ARM提供的范例代码为准。
------解决方案--------------------
普通的+8,有几种特殊的中断是+4的
[解决办法]
应该是这样的:
“将下一条指令的地址存入相应的连接寄存器LR,以便程序在处理异常返回时能从正确的位置重新开始执行。”这里的“将下一条指令的地址存入相应的连接寄存器LR”,说的把是寄存器pc当前值存入LR,也就是当前指令地址A+8存入了LR,那么如果处理完中断后照此返回的话,显然会跳过A+4这条指令而造成错误,因此需要人为将LR减4,也就是你在问题2中的这条语句:
SUB LR,LR,#4 ;计算返回地址
注意sub是减法不是加法……
另一方面,正如狗狗所说,某些异常是特殊的,对于这些特殊的异常而言,存入LR的值不是A+8而是A+4,那么这些异常处理函数就不需要再重新计算返回地址了。