Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2603847
  • 博文数量: 877
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 5920
  • 用 户 组: 普通用户
  • 注册时间: 2013-12-05 12:25
个人简介

技术的乐趣在于分享,欢迎多多交流,多多沟通。

文章分类

全部博文(877)

文章存档

2021年(2)

2016年(20)

2015年(471)

2014年(358)

2013年(26)

分类: LINUX

2014-06-19 16:19:50

转载地址    http://blog.csdn.net/sddzycnqjn/article/details/7691534
2.为何ARM9和ARM7一样,也是PC=PC+8

ARM7的三条流水线,PC=PC+8,很好理解,但是AMR9中,是五级流水线,为何还是PC=PC+8,而不是

PC

=PC+(5-1)*4

=PC + 16,

呢?


下面就需要好好解释一番了。


具体解释之前,先贴上ARM7和ARM9的流水线的区别和联系:


图表 26 ARM7三级流水线 vs ARM9五级流水线




图表 27 ARM7三级流水线到ARM9五级流水线的映射




下面开始对为何ARM9也是PC=PC+8进行解释。



先列出ARM9的五级流水线的示例:

图表 28 ARM9的五级流水线示例





然后我们以下面uboot中的start.S的最开始的汇编代码为例来进行解释:


  1. 00000000 <_start>:
  2.    0:   ea000014   b   58
  3.    4:   e59ff014   ldr pc, [pc, #20] ; 20 <_undefined_instruction>
  4.    8:   e59ff014   ldr pc, [pc, #20] ; 24 <_software_interrupt>
  5.    c:   e59ff014   ldr pc, [pc, #20] ; 28 <_prefetch_abort>
  6.   10:   e59ff014   ldr pc, [pc, #20] ; 2c <_data_abort>
  7.   14:   e59ff014   ldr pc, [pc, #20] ; 30 <_not_used>
  8.   18:   e59ff014   ldr pc, [pc, #20] ; 34 <_irq>
  9.   1c:   e59ff014   ldr pc, [pc, #20] ; 38 <_fiq>

  10. 00000020 <_undefined_instruction>:
  11.   20:   00000120   .word  0x00000120
复制代码




下面对每一个指令周期,CPU做了哪些事情,分别详细进行阐述:

在看下面具体解释之前,有一句话要牢记,那就是:

PC不是指向你正在运行的指令,而是

PC始终指向你要取的指令的地址

认识清楚了这个前提,后面的举例讲解,就容易懂了。


指令周期Cycle1

(1)取指

PC总是指向将要读取的指令的地址(即我们常说的,指向下一条指令的地址),而当前PC=4,

所以去取物理地址为4对对应的指令“ldr pc, [pc, #20]”,其对应二进制代码为e59ff014。

此处取指完之后,自动更新PC的值,即PC=PC+4(单个指令占4字节,所以加4)=4+4=8

指令周期Cycle2

(1)译指:翻译指令e59ff014;

(2)同时再去取指

PC总是指向将要读取的指令的地址(即我们常说的,指向下一条指令的地址),而当前PC=8,

所以去物理地址为8所对应的指令“ldr pc, [pc, #20]” 其对应二进制代码为e59ff014。

此处取指完之后,自动更新PC的值,即PC=PC+4=8+4=12=0xc


指令周期Cycle3

(1)执行(指令):执行“e59ff014”,即“ldr pc,[pc, #20]”所对表达的含义,即

PC

= PC + 20

= 12 + 20

= 32

= 0x20

此处,只是计算出待会要赋值给PC的值是0x20,这个0x20还只是放在执行单元中内部的缓冲中。

(2)译指:翻译e59ff014。

(3)取指

此步骤由于是和上面(1)中的执行同步做的,所以,未受到影响,继续取指,而取指的那一时刻,PC为上一Cycle

更新后的值,即PC=0xc,所以是去取物理地址为0xc所对应的指令” ldr pc, [pc, #20]”,对应二进制为e59ff014。


其实,分析到这里,大家就可以看出:

在Cycle3的时候,PC的值,刚好已经在Cycle1和Cycle2,分别加了4,所以Cycle3的时候,PC=PC+8,而同样道理

,对于任何一条指令的,都是在Cycle3,指令的Execute执行阶段,如果用到PC的值,那么PC那一时刻,就是

PC=PC+8。

所以,此处虽然是五级流水线,但是却不是PC=PC+16,而是PC=PC+8。

进一步地,我们发现,其实PC=PC+N的N,是和指令的执行阶段所处于流水线的深度有关,即此处指令的执行

Execute阶段,是五级流水线中的第三个,而这个第三阶段的Execute和指令的第一个阶段的Fetch取指,相差的

值是 3 -1 =2,即两个CPU的Cycle,而每个Cycle都会导致PC=+PC+4,所以,指令到了Execute阶段,才会发现

,此时PC已经变成PC=PC+8了。

回过头来反观ARM7的三级流水线,也是同样的道理,指令的Execute执行阶段,是处于指令的第三个阶段,

同理,在指令计算数据的时候,如果用到PC,就会发现此时PC=PC+8。


同理,假如ARM9的五级流水线,把指令的Execute执行阶段,设计在了第四个阶段,那么就是

PC=PC+(第4阶段-1)*4个字节 = PC= PC+12了。






【总结】

ARM7的三级流水线,PC=PC+8,

ARM9的五级流水线,也是PC=PC+8,

根本的原因是,两者的流水线设计中,指令的Execute执行阶段,都是处于流水线的第三级,

所以使得PC=PC+8。

类似地,可以推导出:

假设,Execute阶段处于流水线中的第E阶段,每条指令是T个字节,那么

PC

= PC + N*T

= PC + (E - 1) * T


此处ARM7和ARM9:

Execute阶段都是第3阶段-> E=3

每条指令是4个字节-> T=4

所以:

PC

=PC + N* T

=PC + (3 -1 ) * 4

= PC + 8


【关于直接改变PC的值,会导致流水线清空的解释】

把PC的值直接赋值为0x20。而PC值更改,直接导致流水线的清空,即导致下一个cycle中的,对应的流水线中的

其他几个步骤,包括接下来的同一个Cycle中的取指的工作被取消。在PC跳转到0x20的位置之后,流水线重新计算

,重新一步步地按照流水线的逻辑,去一点点执行。当然要保证当前指令的执行完成,即执行之后,

还有两个cycle,分别做的Memory和Write,会继续执行完成。

阅读(1195) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~