sub lr,lr,#4 ; 三级流水线
(一)这个算是讲清楚了
1: ARM3级流水线
由ARM7-TDMI-S技术参考手册P2可知,ARM的流水线结构为:
取指----->译码------>执行
ARM代码: PC PC- 4 PC - 8
0x1008 0x1004 0x1000
在此页,还注明,PC是指向被取指的指令,而不是正在执行的指令。(也就是说在此 PC值为0x1008 ?)
(即:书上摘录:由于ARM 体系结构采用了多级流水线技术,对于ARM 指令集而言,PC 总是指向当前指令的下两条指令的地址,PC 的值为当前指令的地址值加8 个字节)
2: 当发生BL跳转前,会在寄存器 R14 (即LR)中保存当前PC-4,即bl跳转指令的下一条指令的地址。所以在返回时只要 MOV pc,lr
3:中断
(1)当发生中断的时候,把是寄存器pc当前值存入LR(此时的LR是中断模式下的LR),所以返回时,应该是将LR-4赋值给PC。(0x1004)注:有些异常中断可能要将LR-8或LR赋值给PC。详细请仔细看ARM数据手册。
(2)当发生IRQ或FIQ后,系统要进入相应的异常模式进行处理,这些是由硬件实现的。
产生异常后,ARM核会做以下工作:
<1>. 将当前的地址加4或者加8存到LR寄存器里,即把当前状态下下一条指令的地址存入LR
<2>. 将CPSR复制到SPSR,
<3>. 然后将异常模式的状态强制写入CPSR
<4>. 强制PC从相关的异常向量处取指!!
中断结束后:
1. 将SPSR复制回CPSR
2. 开中断
3. 返回原程序,LDR PC,LR
4:因为每个模式下面都有LR,所以当返回原来模式时,原来模式下的LR并没有被破坏。
(二) http://blog.csdn.net/comwise/article/details/10490203
1. 首先要谈流水线,在arm执行过程中一般分为取指,译码,执行阶段
也就是假设当前 第一条指令在执行阶段
第二条指令在译码阶段
第三条指令在取指阶段
当前正在执行的指令地址为pc-8,第二条就为pc-4,而pc现在真正指向已处于pc位置
2. 一般pc在发生中断时lr保存的是当前的pc值,这里pc值是多少呢??
当发生中断肯定保存的pc是第三条指令,而我们从中断返回肯定不是执行第三条指令,而是紧接着的第二条指令,所以应该保存的 lr = pc - 4,但是当执行到此位置时pc值已经改变,肯定不对,还好发生中断时 mov lr,pc 所以这里就可以直接使用 sub lr,lr,#4
(三) http://www.cnblogs.com/zjfdbz/archive/2012/09/26/2704647.html
ARM处理器使用流水线来增加处理器指令流的速度,这样可使几个操作同时进行,并使处理与存储器系统之间的操作更加流畅,连续,能提供0.9MIPS/MHZ的指令执行速度。
PC 代表程序计数器,流水线使用三个阶段,因此指令分为三个阶段执行:1.取指(从存储器装载一条指令);2.译码(识别将要被执行的指令);3.执行(处理 指令并将结果写回寄存器)。而R15(PC)总是指向“正在取指”的指令,而不是指向“正在执行”的指令或正在“译码”的指令。一般来说,人们习惯性约定 将“正在执行的指令作为参考点”,称之为当前第一条指令,因此PC总是指向第三条指令。当ARM状态时,每条指令为4字节长,所以PC始终指向该指令地址 加8字节的地址,即:PC值=当前程序执行位置+8;
ARM指令是三级流水线,取 指,译指,执行时同时执行的,现在PC指向的是正在取指的地址,那么cpu正在译指的指令地址是PC-4(假设在ARM状态下,一个指令占4个字 节),cpu正在执行的指令地址是PC-8,也就是说PC所指向的地址和现在所执行的指令地址相差8。
当突然发生中断的时候,保存的是PC的地址
这样你就知道了,如果返回的时候返回PC,那么中间就有一个指令没有执行,所以用SUB pc lr-irq #4
但是在ADS中PC确实是指向即将执行的指令处,这个是软件处理后的结果,主要是为了用户调试程序方便.
需要注意的是,当前使用指令STM/STR保存R15时候,保存的可能是当前指令地址值+8字节,也可能保存的是当前的指令地址+12字节.到底是哪种,取决于芯片的具体的设计方式。无论如何,在同一芯片中,要么采用当前的指令地址+8,要么采用当前的指令地址+12。因此对于用户来讲,尽量避免使用STM/STR指令来保存R15的值。但是可以在开始的时候用一段程序对芯片的offset进行测试!
代码如下:
SUB R1, PC, #4 ;获得下面的存放下面存放STR指令的地址
STR PC,[R0]
LDR R0,[RO]
SUB R0, R0, R1
ARM7中断与PC、LR的问题:
1,假设当前是PC,PC-4,PC-8(三级流水)
2,发生IRQ异常,执行保护操作,LR中保存由于FIQ或IRQ占先而没有被执行的指令的地址(即有些资料上把这个地址写成PC或者当前地址,很费解甚至误解)的下一条地址
3,清空流水线
4,进入中断服务程序
5,待流水线填满,执行操作才被重新挂起(解释了ARM7为什么是0.9MIPS)
6,中断返回前,对LR处理,LR=LR-4,指向之前被清空的已译码但没被执行的指令的地址
7,清空流水线,返回
8,重新对丢弃的前一次已译码指令取指
9,待流水线满,开始继续执行